{"id":18468671,"url":"https://github.com/schummar/runp","last_synced_at":"2025-04-08T10:32:30.513Z","repository":{"id":55524121,"uuid":"523113799","full_name":"schummar/runp","owner":"schummar","description":"Neat parallel task execution","archived":false,"fork":false,"pushed_at":"2025-04-04T15:12:08.000Z","size":1555,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-06T05:45:58.151Z","etag":null,"topics":["command","execution","job","nodejs","npm","parallel","run","task","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/schummar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-09T21:28:26.000Z","updated_at":"2025-03-21T10:47:30.000Z","dependencies_parsed_at":"2024-04-05T15:26:15.689Z","dependency_job_id":"25af5ab8-309a-4bf3-aed6-74cc79db7a22","html_url":"https://github.com/schummar/runp","commit_stats":{"total_commits":80,"total_committers":3,"mean_commits":"26.666666666666668","dds":"0.23750000000000004","last_synced_commit":"9a49acca9981f00897e63bc5523f1cfa30a18c9b"},"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schummar%2Frunp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schummar%2Frunp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schummar%2Frunp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schummar%2Frunp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schummar","download_url":"https://codeload.github.com/schummar/runp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247441004,"owners_count":20939235,"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":["command","execution","job","nodejs","npm","parallel","run","task","typescript"],"created_at":"2024-11-06T10:07:52.707Z","updated_at":"2025-04-08T10:32:28.471Z","avatar_url":"https://github.com/schummar.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# runp - Neat parallel task execution\n\n[![](https://badgen.net/npm/v/@schummar/runp)](https://www.npmjs.com/package/@schummar/runp)\n![](https://badgen.net/github/license/schummar/runp)\n![](https://badgen.net/npm/types/@schummar/runp)\n\n## Features\n\n- Run commands in parallel, in series or any combination\n- Reference npm scripts by name with glob support\n- Command outputs will be separated in their own blocks instead of all mixed together\n- Nested `runp` calls will be merged with indented sub commands\n- CLI and type-safe Node API\n\n[Try it on StackBlitz](https://stackblitz.com/edit/runp-demo?file=package.json)\n\n![](docs/img/demo1.gif)\n\n# Getting started\n\n## Install\n\n```bash\nnpm i @schummar/runp\n```\n\n## Execute commands\n\n```bash\nrunp clean :p \"build:*\" :s \"rm -rf .cache\"\n```\n\nAssuming the following `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"clean\": \"rimraf dist\",\n    \"build:esm\": \"some build command\",\n    \"build:cjs\": \"another build command\",\n    \"build:type\": \"tsc --emitDeclarationOnly\"\n  }\n}\n```\n\nEach parameter can be a program, npm script, a flag or a switch. Arguments for programs and scripts can be added by encapsulating them in quotes.\n\n- `clean` executes `npm run clean`\n\n- `:p` for \"parallel\": remaining commands will be executed after the previous and in parallel\n\n- `\"build:*\"` executes all script matching this glob (see [minimatch](https://github.com/isaacs/minimatch))  \n  Mind the quotes, otherwise your shell will try to resolve the wildcard!\n\n- `:s` for \"sequential\": remaining commands will be execute after the previous and in series\n\n- `\"rm -rf .cache\"` deletes the .cache folder\n\n# Options\n\n```\n❯ runp --help\nrunp v1.5.0\n\nUsage:\n  runp [flags...] \u003ccommands...\u003e\n\nFlags:\n  -f, --forever                       Task will run forever. It won't display a spinner but a different symbol instead\n  -h, --help                          Show help\n  -k, --keep-output                   Keep output of successful commands visible\n  -n, --output-length \u003cnumber\u003e        Maximum number of lines for each command output (default: 10)\n      --version                       Show version\n```\n\nOptions can either be used as flags (prefix \"-\") or switches (prefix \":\"). Flags generally apply to all commands while switches can be used to change behavior midway for the remaining commands.\n\n## Option: Forever\n\n**Flags** `-f`, `--forever` apply to all commands\n\n**Switches** `:f`, `:f=false` apply for all remaining commands\n\nYou might run commands in parallel that are supposed to run indefinitely, like a backend server and a frontend dev server. In this case instead of a spinner, `runp` can display an arrow icons instead. The effect is purely cosmetic:\n\n![](docs/img/demo2.gif)\n\n## Option: Keep output\n\n**Flag** `-k`, `--keep-output` apply to all commands\n\n**Switches** `:k`, `:k=false` apply to remaining commands\n\nUsually a command's output will disappear after is has successfully executed. When `--keep-output` is set, it will remain visible.\n\n## Option: Output length\n\n**Flags** `-n \u003cnumber\u003e`, `--output-length \u003cnumber\u003e` apply to all commands\n\n**Switches** `:n=\u003cnumber\u003e` apply to remaining commands\n\nDefines how many lines of output will be visible at maximum for each command.\n\n## Option: Parallel and sequential execution\n\n**Switches** `:p`, `:s` apply to remaining commands\n\nCommands after the `:p` switch will first wait for all commands before the switch to finish, then execute in parallel.\n\nCommands after the `:s` switch will first wait for all commands before the switch to finish, then execute in series.\n\nBoth apply to all commands until another `:p` or `:s` appears.\n\nIt's possible to have multiple `:p` switches in succession, forming multiple parallel blocks.\nFor example `runp :p task1 task2 :p task3 task4` will execute first task1 and task2 in parallel, then task3 and task4 in parallel.\n\nBefore the first `:p` or `:s` switch appears, all commands will be executed in parallel by default.\n\n## Combining switches\n\nFlags and switches can be combined. E.g. `-fk` or `:pfn=10k=false`\n\n# Error handling\n\nWhen an error occurs the command will be marked with a red x-symbol and the command output will remain visible.\nAny parallel tasks are allowed to continue but dependent commands will not be executed.\n\n![](docs/img/demo3.gif)\n\n# Nested execution\n\nWhen `runp` is executed as child process of another `runp` instance, it delegates its tasks to the parent instance.\nCommands will be shown as child commands to the parent instance's command.\n\nThat is useful for example for composing npm scripts.\nSay we have the following `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"lint\": \"eslint\",\n    \"clean\": \"rimraf dist\",\n    \"build\": \"build:*\",\n    \"build:esm\": \"some build command\",\n    \"build:cjs\": \"another build command\",\n    \"build:type\": \"tsc --emitDeclarationOnly\",\n    \"prepublishOnly\": \"runp :s lint build\"\n  }\n}\n```\n\nRunning `npm publish` will now execute the `prepublishOnly` script, which in turn has `runp` execute the `lint` and `build` scripts.\nThe `build` script executes another instance of `runp` with its `build:*` commands.\nThe output however looks seamless:\n\n![](docs/img/demo4.gif)\n\n# Node API\n\n```ts\nimport { runp } from '@schummar/runp';\n\nrunp({\n  keepOutput: true,\n  outputLength: 10,\n\n  commands: [\n    {\n      cmd: 'clean',\n      name: 'Clean',\n      keepOutput: false,\n    },\n\n    ':p',\n\n    {\n      cmd: 'build:*',\n      cwd: 'src',\n    },\n\n    ':s',\n\n    {\n      cmd: 'rm',\n      args: ['-rf', '.cache'],\n    },\n  ],\n});\n```\n\nThe Node API allows running `runp` programmatically with all the same options, plus a bit more fine grained control.\n\n## commands.cmd\n\nThe executable or npm script to run.\n\n## commands.args\n\nArguments to pass to executable or npm script.\n\n## commands.cwd\n\nExecute command in different working directory\n\n## commands.id\n\nGive a task an id that can be referenced as dependency.\n\n## commands.depdendsOn\n\nCommand will only start once all dependencies have finished.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschummar%2Frunp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschummar%2Frunp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschummar%2Frunp/lists"}