{"id":21496956,"url":"https://github.com/financial-times/nori","last_synced_at":"2025-07-15T19:32:56.862Z","repository":{"id":34878424,"uuid":"159402535","full_name":"Financial-Times/nori","owner":"Financial-Times","description":"🍙 exploratory command-line tool to make changes across multiple repositories \u0026 track their progress","archived":false,"fork":false,"pushed_at":"2024-10-24T19:52:45.000Z","size":12774,"stargazers_count":11,"open_issues_count":19,"forks_count":0,"subscribers_count":48,"default_branch":"main","last_synced_at":"2024-10-24T23:53:08.875Z","etag":null,"topics":["cli","command-line-tool","customer-products","enquirer","interactive","migrations","platforms-customer-products"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Financial-Times.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-27T21:36:41.000Z","updated_at":"2024-10-16T10:03:16.000Z","dependencies_parsed_at":"2024-07-31T01:09:55.832Z","dependency_job_id":"76539e8b-b031-4b1d-b401-28bcd123fb89","html_url":"https://github.com/Financial-Times/nori","commit_stats":null,"previous_names":["financial-times/transformation-runner"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Financial-Times%2Fnori","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Financial-Times%2Fnori/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Financial-Times%2Fnori/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Financial-Times%2Fnori/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Financial-Times","download_url":"https://codeload.github.com/Financial-Times/nori/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226065303,"owners_count":17568187,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","command-line-tool","customer-products","enquirer","interactive","migrations","platforms-customer-products"],"created_at":"2024-11-23T16:20:00.578Z","updated_at":"2024-11-23T16:20:02.372Z","avatar_url":"https://github.com/Financial-Times.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg alt=\"nori\" src=\"etc/logo.svg\" width=\"240\"\u003e\u003cbr\u003e\n\n  \u003ca href=\"https://npmjs.com/package/nori\"\u003e\n    \u003cimg alt=\"npm\" src=\"https://img.shields.io/npm/v/nori.svg?color=grey\u0026label=%20\u0026logo=npm\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://circleci.com/gh/Financial-Times/nori\"\u003e\n    \u003cimg alt=\"CircleCI\" src=\"https://circleci.com/gh/Financial-Times/nori.svg?style=svg\"\u003e\n  \u003c/a\u003e\n\u003c/h1\u003e\n\n_exploratory command-line tool to make changes across multiple repositories \u0026 track their progress_\n\n\u003cblockquote\u003e\u003csmall\u003e\u003cem\u003ewords defined by this readme are written in \u003cstrong\u003ebold\u003c/strong\u003e\u003c/em\u003e\u003c/small\u003e\u003c/blockquote\u003e\n\nNori is a command-line application for managing changes across multiple (usually Github) repositories. It allows you to build up a sequence of [**Operations**](#operations) to go through the process of discovering repositories to change, cloning them \u0026 making the changes, creating Pull Requests for the changes, and tracking the progress of the Pull Requests in a Github Project. The main interface for Nori is an interactive command-line wizard, which prompts you for which operations to run, and the arguments needed for each operation.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"etc/screencast.gif\" alt=\"nori screencast\" width=\"569\" height=\"480\"\u003e\n\u003c/p\u003e\n\n## Usage\n\n```sh\nnpx nori\n```\n\nThis temporarily installs Nori and runs the interactive wizard. The first time you run it, it will prompt you for various configuration variables, which are required only for certain operations. It'll then ask you to `Create a session`. Give the session a memorable name. The wizard takes you through the operations you can run. At any point you can exit by pressing \u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003eC\u003c/kbd\u003e or selecting `Done`. Your progress is saved under the name you gave when you started `nori`. Next time you run it, it will display a list of previous sessions that you can resume, most recent last.\n\nIf you'll be running `nori` frequently, install it globally:\n\n```sh\nnpm install -g nori\n```\n\n`nori` can run operations via the interactive prompt, or directly on the command line. Operations **output** a particular type of data, and some operations have one or more **inputs**, which are types of data that must be gathered before you can run the operation. The interactive prompt will only enable the operations you have the data for so far. When running from the command line, you can pass this data around by [**Piping**](#piping) the operations, or by using a [**State File**](#state-file).\n\nRun `nori` with the name of the operation, and any arguments it requires as double-dashed command line arguments (`nori` understands `--kebab-case` arguments and transforms them to `camelCase`). If you're running in an interactive shell, `nori` will prompt for any missing arguments.\n\nFor example, to consume repositories from `repos.txt` and output the formatted list:\n\n```sh\n⟩ nori file --file repos.txt\nhttps://github.com/financial-times-sandbox/Abandoned-Toothbrush\nhttps://github.com/financial-times-sandbox/Western-Storm\n```\n\nEvery operation supports the `--json` flag, which outputs all data found formatted as JSON:\n\n```sh\n⟩ nori file --file repos.txt --json\n[\n  {\n    \"owner\": \"financial-times-sandbox\",\n    \"name\": \"Abandoned-Toothbrush\"\n  },\n  {\n    \"owner\": \"financial-times-sandbox\",\n    \"name\": \"Western-Storm\"\n  }\n]\n```\n\n## Operations\n\n### File\n\n##### `nori file --file \u003cfile path\u003e`\n\nGet a list of repositories from a text file, structured as line-separated `owner/name` strings (optionally with leading `https://github.com/`).\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eArguments\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003efile\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003epath to the text file to read, relative to the current working directory\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003cem\u003enone\u003c/em\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003erepos\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Get repositories through Bizops\nBefore executing any of the two commands below, either through `npx nori` interactive mode, or directly through the command line, make sure you set the env variable `BIZ_OPS_API_KEY`. To get the key, request a key with a Biz Ops API policy from https://apigateway.in.ft.com/key-form/developer.\n\n##### `nori team-repos`\nThis operation gets all the repositories from the team you have selected.\nIt shows a list of teams in customer products (obtained from Bizops) which you can select. \n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eArguments\u003c/th\u003e\n    \u003ctd\u003eNone\u003c/td\u003e\n    \u003ctd\u003e\u003cem\u003eTeams to be selected when command is run\u003c/em\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003enone\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003erepos\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n##### `nori graphql-repos --file \u003cfile path\u003e`\nThis operation gets repositories by executing the file that you pass in containing your own graphql query. \n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eArguments\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003efile\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003epath to a .graphql | .txt file containing graphql query for repositories\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003cem\u003enone\u003c/em\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003erepos\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Filter repository name\n\n##### `nori filter-repo-name --filter \u003crepo name\u003e`\n\nFilter the list of repositories by their names.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eArguments\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003efilter\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003eregular expression to filter the names of the repos by\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003erepos\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003erepos\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Clone\n\n##### `nori clone`\n\nClone each of the list of repositories\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eArguments\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003cem\u003enone\u003c/em\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003erepos\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003eclones\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Run Script\n\n##### `nori run-script --script \u003cfile path\u003e --branch \u003cbranch name\u003e`\n\nCreate a branch and run a script on it. If the provided branch name already exists, Nori will append a number to it (e.g. `branch` → `branch-1`).\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\" rowspan=\"2\"\u003eArguments\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003escript\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003epath to the script to run, relative to the current working directory. should have executable permissions\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ccode\u003ebranch\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003ename of the branch to create\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003eclones\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003elocalBranches\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nThe script has the responsibility to:\n\n- Make changes to the files in a local clone of a git repository\n- Add those changes to git\n- Commit those changes to git\n\nNori will take care of creating branches. The main benefit\nof this approach is that scripts do not _need_\n`nori` for you to be able to run them. This makes development,\ndebugging and one-off runs of a script much simpler.\n\n### Push Branches\n\n##### `nori push-branches`\n\nPush each repository's local branch to the remote. If a branch already exists on the remote with the same name as the local branch, Nori will append a number to it (e.g. `branch` → `branch-1`).\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eArguments\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003cem\u003enone\u003c/em\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003eclones\u003c/code\u003e, \u003ccode\u003elocalBranches\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003eremoteBranches\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Pull Requests\nIf you are planning to raise PRs, please add your github personal access token to the githubAccessToken object in `~/.config/nori-workspace/config.json`. Authenticating increases the [secondary rate limit](https://docs.github.com/en/rest/guides/best-practices-for-integrators#dealing-with-secondary-rate-limits) of GitHub API, which increases your chance to raise multiple PRs without being blocked by the limit.\n\n##### `nori prs --templates.title \u003cPR title\u003e --templates.body \u003cPR body\u003e`\n\nCreate a Pull Request for each of the pushed branches.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\" rowspan=\"2\"\u003eArguments\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003etemplates.title\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003ethe title of the pull requests. you can use Javascript \u003ccode\u003e${}\u003c/code\u003e template string syntax. available variables are \u003ccode\u003erepo.owner\u003c/code\u003e, \u003ccode\u003erepo.name\u003c/code\u003e and \u003ccode\u003ebranch\u003c/code\u003e.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ccode\u003etemplates.body\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003ethe body of the pull requests. supports templates like \u003ccode\u003etitle\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eConfiguration\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003egithubAccessToken\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003e\n      Github \u003ca href=\"https://github.com/settings/tokens/new?scopes=repo\u0026description=Nori\" target=\"_blank\"\u003epersonal access token with \u003ccode\u003erepo\u003c/code\u003e scope\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003erepos\u003c/code\u003e, \u003ccode\u003ebranches\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003eprs\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Create Project\n\n##### `nori create-project --project-data.name \u003cname\u003e --project-data.org \u003corg\u003e`\n\nCreate a Github Project.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\" rowspan=\"2\"\u003eArguments\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003eprojectData.name\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003ethe name of the project to create\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ccode\u003eprojectData.org\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003ethe org to create the project in. this must be the same org as every repo that you've created a PR on.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eConfiguration\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003egithubAccessToken\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003e\n      Github \u003ca href=\"https://github.com/settings/tokens/new?scopes=repo\u0026description=Nori\" target=\"_blank\"\u003epersonal access token with \u003ccode\u003erepo\u003c/code\u003e scope\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003cem\u003enone\u003c/em\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003eproject\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n**NB** _we're considering what to do about repos from multiple orgs, see [#62](https://github.com/Financial-Times/nori/issue/62)_\n\n**NB** _the project will have `To Do`, `In Progress` and `Done` columns, but there's currently no way to set up automatic transitions using the Github API. you'll have to set that up manually if you want the project board to reflect the state of the PRs_\n\n### Get Project\n\n##### `nori get-project --project-url \u003cprojectURL\u003e`\n\nGet a project from Github.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eArguments\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003eprojectUrl\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003eURL of the Github project page\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eConfiguration\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003egithubAccessToken\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003e\n      Github \u003ca href=\"https://github.com/settings/tokens/new?scopes=repo\u0026description=Nori\" target=\"_blank\"\u003epersonal access token with \u003ccode\u003erepo\u003c/code\u003e scope\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003cem\u003enone\u003c/em\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003eproject\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n### Add to Project\n\n##### `nori add-to-project`\n\nAdd the [PRs](#pull-requests) to the project.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eArguments\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003cem\u003enoned\u003c/em\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eConfiguration\u003c/th\u003e\n    \u003ctd\u003e\u003ccode\u003egithubAccessToken\u003c/code\u003e\u003c/td\u003e\n    \u003ctd\u003e\n      Github \u003ca href=\"https://github.com/settings/tokens/new?scopes=repo\u0026description=Nori\" target=\"_blank\"\u003epersonal access token with \u003ccode\u003erepo\u003c/code\u003e scope\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eInputs\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003eprs\u003c/code\u003e, \u003ccode\u003eproject\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003cth align=\"right\"\u003eOutput\u003c/th\u003e\n    \u003ctd colspan=\"2\"\u003e\u003ccode\u003ecards\u003c/code\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## State Files\n\nWhen running the interactive prompt, your progress is automatically saved to a state file. It contains the list of operations you've run \u0026 the arguments given to them, and a cache of the data returned by the operations.\n\nState files are kept in the folder `~/.config/nori-workspace` (this is also where repositories are cloned to). When you start the interactive prompt, it will list any state files already in the workspace folder, allowing you to resume previous sessions.\n\nIndividual operations can also read and save to state files with the `--state-file path/to/file.json` option. When you run an operation with a path to a state file that doesn't exist, it will ask if you want to create it. When the operation completes, it'll have added itself and the data it returned to the state file.\n\nThe `--state-file` option can also be used with the interactive prompt, which will skip the step asking you to create a state file or use one from the `nori` workspace folder, and allow you to use a state file from any location. State files are compatible between individual operations and the interactive prompt, which lets you shuffle between the two modes.\n\n## Piping\n\nState can also be passed between operations using shell pipes. This is equivalent to running them in sequence and reusing the same state file.\n\n```sh\nnori file --file repos.txt | nori run-script --script script.sh --branch change\n```\n\nNote that interactive features, such as prompting for missing arguments, won't be available when piping. If any arguments are missing, the operation will error instead. The same goes for providing a state file via the command line argument; it's an error to use `--state-file` and pipe as well. To load or save a state file in a piped operation, use [shell redirection](https://www.tldp.org/LDP/abs/html/io-redirection.html):\n\n```sh\nnori file --file repos.txt \u003c input-state.json | nori run-script --script script.sh --branch change \u003e output-state.json\n#                         └─────────┬────────┘                                                    └─────────┬─────────┘\n#                    read input from input-state.json                                        write output to output-state.json\n```\n\n## Licence\n\nMIT. \u0026copy; 2019 Financial Times. Made with :green_heart: by FT.com Enabling Technologies Group\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinancial-times%2Fnori","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffinancial-times%2Fnori","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinancial-times%2Fnori/lists"}