Skip to content

/flags/pnpm/pnpm-recursive

pnpm -r (--recursive): run a command in every workspace package

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
pnpm
command
pnpm
flag
-r, --recursive
default
off (the command applies to the current package only)

pnpm -r run build (long form --recursive) runs build in every package of the workspace, in dependency order: packages that others depend on are built first. -r works with most commands: pnpm -r exec, pnpm -r test, pnpm -r update, pnpm -r add, pnpm -r publish. In a workspace the root package is excluded unless you add --include-workspace-root, and packages without the script are skipped.

Example workspace

app depends on lib, so lib builds first:

bash
printf 'packages:\n  - "packages/*"\n' > pnpm-workspace.yaml
echo '{ "name": "root", "private": true }' > package.json
mkdir -p packages/lib packages/app packages/docs
echo '{ "name": "lib", "version": "1.0.0", "scripts": { "build": "node -e \"console.log(1)\"" } }' > packages/lib/package.json
echo '{ "name": "app", "version": "1.0.0", "dependencies": { "lib": "workspace:*" }, "scripts": { "build": "node -e \"console.log(2)\"" } }' > packages/app/package.json
echo '{ "name": "docs", "version": "1.0.0" }' > packages/docs/package.json
npx --yes pnpm@9 install >/dev/null 2>&1
npx --yes pnpm@9 -r --workspace-concurrency=1 run build 2>&1 | grep -E "^(Scope|> |[0-9]$)" | sed -E 's/^(> [a-z]+@1\.0\.0 build) .*/\1/'

Output

Scope: 3 of 4 workspace projects
> lib@1.0.0 build
> node -e "console.log(1)"
1
> app@1.0.0 build
> node -e "console.log(2)"
2

Scope: 3 of 4 workspace projects means three of the four projects were selected: the root is the fourth and is excluded. docs has no build script and is skipped without an error. The sed only removes the absolute package path that pnpm prints after the script name.

Options used with -r

OptionEffect
--filter PATTERNLimit the packages (name, glob, directory, changed since a git ref)
--include-workspace-rootAlso run in the root package
--workspace-concurrency=NRun at most N packages at a time (default 4; 1 = sequential)
--parallelIgnore order and concurrency, run everything at once (watch or dev servers)
--no-sortDo not sort packages topologically
--streamPrint output immediately, prefixed with the package directory
--no-bailKeep going when a package fails (default is to stop)
--report-summaryWrite pnpm-exec-summary.json with the result of each package

Typical commands

bash
pnpm -r run build                     # build everything in order
pnpm -r --parallel run dev            # start every dev server at once
pnpm -r exec rm -rf dist              # run a shell command in each package
pnpm -r update typescript@latest      # update a dependency everywhere it is used
pnpm --filter "./packages/**" -r test # combine with a filter

-r versus --filter

-r alone selects every workspace package; --filter selects some of them and implies recursion. Use filters for large monorepos and CI jobs that only build what changed: see pnpm --filter.

Pitfalls

  • Outside a workspace (no pnpm-workspace.yaml), -r looks for packages in subdirectories of the current folder, which can pick up stray package.json files in fixtures or examples.
  • pnpm add pkg at the root of a workspace fails with ERR_PNPM_ADDING_TO_ROOT; pnpm -r add pkg adds it to every package instead, which is rarely what you want for a single package.
  • A failing package stops the run; the error shows which directory failed. Use --no-bail in reports where you want every result.
  • Long-running scripts (dev, watch) never finish, so dependants would wait forever in topological mode: use --parallel for them.

FAQ

Does pnpm -r run build include the workspace root?

No. In a workspace, -r runs in every package matched by pnpm-workspace.yaml but skips the root package. Add --include-workspace-root to run it there too.

In which order does pnpm -r run scripts?

In topological order: a package runs after the workspace packages it depends on. Independent packages run in parallel, up to --workspace-concurrency (4 by default). --no-sort ignores the order.

How do I run a script only in some packages?

Use --filter instead of, or together with, -r: pnpm --filter "./packages/**" run build or pnpm --filter api... run build for a package and its dependencies.

Sources