mrkeyoor.com_
Sat 08 Aug 21:02 UTC
npmCLI & Toolingupdated 08 Aug 2026

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.

Verdict

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.

API stability4/5The three executables, colon-based patterns, option flags, placeholder syntax, and promise-returning Node function have stayed unchanged since the 4.1.5 release in 2018. That makes existing build scripts predictable, though it is stability by dormancy and there is no current compatibility policy for new Node and package-manager behavior.
Docs4/5The repository has separate command references for `npm-run-all`, `run-s`, `run-p`, and the Node API, with examples for patterns, mixed execution modes, placeholders, output controls, errors, process killing, and listener warnings. The material is clear but tied to an older npm and Node era and lacks a migration note to maintained forks.
Maintenance1/5npm reports version 4.1.5 as the latest release and dates it to November 2018. GitHub reports a later repository push in August 2024 and the project is not archived or registry-deprecated, but no newer package reached users. The long release gap and old dependency ranges make new adoption difficult to recommend.
Ecosystem4/5The package recorded 4,698,986 downloads in the measured week, has 5,837 GitHub stars, supports npm and Yarn invocation, and became a common script in JavaScript projects. Familiar forks and alternatives ease migration, but its integration model stops at package scripts and a CommonJS API rather than plugins or task graphs.

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
Skip it if

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

PackageRegistryPick it when
npm-run-all2npmYou want a maintained fork with the same `run-s`, `run-p`, pattern, and Node API concepts
concurrentlynpmYou mainly run long-lived commands together and want richer prefixes, restart behavior, and process-success policies
task-runnernpmYou want a small programmatic task graph instead of composing only package script names