npm-run-all
npm-run-all is a development CLI and CommonJS Node API for composing scripts already declared in `package.json`. Its `run-s` command runs names sequentially, `run-p` runs them concurrently, and the full command can switch modes within one plan. It also expands colon-separated script-name patterns such as `build:*`, forwards arguments, labels output, limits concurrency, and handles child-process termination across Unix and Windows.
It still solves cross-platform script composition cleanly, but the eight-year release gap makes the maintained `npm-run-all2` fork the sensible default. Keep the original only where its frozen behavior is already proven in your build.
Use it if
- You maintain a package with several npm scripts and need the same sequential or parallel plan on Windows, macOS, and Linux
- You want `build:*` or `test:**` patterns to select related scripts without repeating every name
- You need a short `run-s` and `run-p` syntax in an established CommonJS-era toolchain
- You need to mix sequential preparation with a parallel group in one package script
- You want an actively released package: version 4.1.5 was published in November 2018, despite millions of current weekly downloads
- You are starting fresh and can use the maintained `npm-run-all2` fork, which preserves the familiar commands while tracking current Node releases
- You need readable live output from many long-running tasks: normal output interleaves, labels turn stdout into a pipe and can disable colors, while aggregate output withholds each task's logs until it exits
- You expect shell syntax or arbitrary commands: it launches names from the current package's `scripts` map and its pattern separator is `:`, not a general shell glob over files
- You need careful service supervision or automatic restarts: `--race` stops the group after one successful exit, default parallel failure kills sibling process trees, and this is a task combiner rather than a process manager
Setup reality
Install it as a development dependency with `npm install --save-dev npm-run-all`, then put `run-s`, `run-p`, or `npm-run-all` inside `package.json` scripts. There are no peer dependencies, native addons, credentials, or separate config files, but it brings nine direct runtime dependencies from an older Node toolchain. Commands operate on the `scripts` field in the package found from the current working directory. A single `*` matches one colon-delimited level, while `**` includes deeper names; quote patterns in a shell when wildcard expansion or embedded arguments could interfere. Sequential mode stops before later tasks after a nonzero exit. Parallel mode sends termination to other tasks and descendants after a failure unless `--continue-on-error` is set; even with that flag, the runner itself exits nonzero if anything failed. `--race` means stop after the first task exits successfully, which is useful for paired watchers but wrong for ordinary build jobs. `--print-label` pipes output so color-detection libraries may turn colors off, and `--aggregate-output` buffers each process's output until that process finishes, making it a poor choice for servers that never exit. Parallelism is unlimited unless `--max-parallel` is set. The Node API is CommonJS, returns a promise, and needs explicit stdin, stdout, and stderr streams if you want inherited interaction; using shared piped streams with many parallel jobs may also require raising EventEmitter listener limits, as its own API documentation warns.
Patterns
Run scripts in orderrun-sequential
{
"scripts": {
"clean": "rimraf dist",
"lint": "eslint .",
"compile": "tsc",
"build": "run-s clean lint compile"
}
}`run-s` stops at the first nonzero exit, so `compile` does not run if `lint` fails.
Run independent scripts togetherrun-parallel
{
"scripts": {
"typecheck": "tsc --noEmit",
"test": "vitest run",
"verify": "run-p typecheck test"
}
}On the first failure, parallel mode terminates the other task tree unless `--continue-on-error` is present.
Run a family of scriptsmatch-script-pattern
{
"scripts": {
"build:css": "postcss src.css -o dist.css",
"build:js": "rollup -c",
"build:js:types": "tsc --emitDeclarationOnly",
"build": "run-p build:**"
}
}`build:*` matches only one level; `build:**` also matches deeper names such as `build:js:types`.
Prepare sequentially, then build in parallelmix-execution-modes
{
"scripts": {
"release": "npm-run-all clean lint --parallel build:css build:js --sequential package"
}
}The full command changes mode at each flag; tasks before the first mode flag run sequentially.
Forward arguments to every matched scriptforward-arguments
{
"scripts": {
"watch": "run-p \"build:* -- --watch\""
}
}Keep the task plus its arguments quoted. The `--` belongs to the underlying npm script invocation.
Insert a caller argument into a taskuse-argument-placeholder
{
"scripts": {
"serve": "run-s build \"start-server -- --port {1}\" --"
}
}
// npm run serve 8080`{1}` is replaced by the first value after the final `--`; `{@}` expands all arguments separately and `{*}` combines them.
Prefix logs with task nameslabel-parallel-output
{
"scripts": {
"dev": "run-p --print-label dev:api dev:web"
}
}Labels require piped stdout, so tools that color only when attached to a TTY may stop emitting colors.
Cap concurrent jobslimit-parallelism
{
"scripts": {
"test:all": "run-p --max-parallel 2 test:unit test:integration test:e2e"
}
}Parallelism defaults to unlimited, which can overwhelm memory, CPUs, databases, or shared test ports.
Run every check before reporting failurecontinue-after-error
{
"scripts": {
"check": "run-p --continue-on-error lint typecheck test"
}
}Other tasks continue, but the overall command still exits nonzero when any child fails.
Stop a parallel group when one task succeedsrace-long-running-tasks
{
"scripts": {
"preview:test": "run-p --race preview wait-and-test"
}
}`--race` triggers on a successful task exit and then kills siblings; do not use it for jobs that must all complete.
Run package scripts from Nodecall-node-api
const runAll = require('npm-run-all');
runAll(['clean', 'build:*'], {
parallel: false,
stdout: process.stdout,
stderr: process.stderr,
}).then((results) => {
console.log(results.map(({ name, code }) => ({ name, code })));
});The API is CommonJS and does not attach output streams by default; pass the process streams when interactive logs are expected.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| npm-run-all2 | npm | You want a maintained fork with the same `run-s`, `run-p`, pattern, and Node API concepts |
| concurrently | npm | You mainly run long-lived commands together and want richer prefixes, restart behavior, and process-success policies |
| task-runner | npm | You want a small programmatic task graph instead of composing only package script names |