pnpm 11.25
pnpm 11.25 replaces topological batches with a task scheduler, adds configurable
workspace task dependencies and per-task concurrency, and makes interrupted
recursive runs resumable from the work that actually passed. It also introduces
registry revisions, signed build artifacts shared through pnpr, batch approval
for staged packages, automatic pruning of stale audit exceptions, and a
pnpm init pin that follows the latest released pnpm.
Minor Changes
Workspace task orchestration
pnpm -r run now schedules individual project/script tasks as soon as their
dependencies finish. Declare relationships under tasks in
pnpm-workspace.yaml:
tasks:
build:
dependsOn: ['^build']
concurrency: 2
test:
dependsOn: ['build']
lint: {}
^build means build in each workspace dependency; bare build means the
task in the same project. A configured task with no dependsOn has no
dependencies, while an unconfigured task retains the old default of depending
on the same task in workspace dependencies. Missing scripts pass their edges
through rather than cutting the graph.
Cycles now fail with ERR_PNPM_TASK_CYCLE unless
ignoreWorkspaceCycles is set. --no-bail
skips dependents of a failed task while independent work continues; the default
--bail stops dispatch and cancels work already running. Use
pnpm -r run --dry-run <script> to inspect the graph, and add --json for its
machine-readable nodes and edges. See Workspace task
orchestration.
The scheduler also replaces topological batches in workspace install, rebuild, pack, publish, stage, and lifecycle work: a project starts as soon as its dependencies finish instead of waiting for unrelated projects in the same group.
Resuming the work that passed
Recursive run and exec persist each successfully completed task. On a
matching retry, --resume-from
uses that record and skips exactly the work that passed, wherever it appears in
the graph. The record is accepted only for the same selected projects, command,
arguments, scripts, and execution-affecting settings.
Without a compatible record, pnpm falls back to the graph: it treats the named task's transitive dependencies as completed, while still running the named task, its dependents, and unrelated work.
Signed build artifacts shared through pnpr
The sideEffectsCache can now restore a
dependency's build output across machines from pnpr. The repository declares
which organization and packages are eligible; signing keys and all other
publisher trust material are accepted only from the global config or the
environment:
pnprServer: https://packages.example.com
allowBuilds:
native-addon: true
sideEffectsCache:
remote:
org: acme
packages: [native-addon]
Artifacts are P-256 signed and bound to the package, source integrity, build input, and platform. Linux/glibc, macOS, and Windows are supported on x64 and arm64. A restored artifact is persisted in the shared store with its signed origin and reverified under the current keys, policy, source, and platform before later reuse; a bad variant is quarantined for that server. A cache miss or any verification, network, compatibility, or blob failure falls back to the ordinary local build.
The experimental protocol now gives every candidate and signed payload a discriminated subject: dependency builds carry package and source-integrity identity, while the protocol's workspace-task subject carries project and task identity. This changes request bodies and signed envelopes, so the pnpm client and pnpr server must be on matching releases.
The new object form also unites the local cache controls:
sideEffectsCache:
read: true
write: true
It supports read-only and write-only caches. The older boolean
sideEffectsCache, sideEffectsCacheReadonly, remoteSideEffectsCache, and
organization spellings continue to work. See Shared side-effects
cache.
Registry revisions
A revision-aware registry can replace the artifact of an already-published
version without rewriting the canonical name@version URL. pnpm records a
selected replacement beside its integrity:
packages:
lodash@4.17.21:
resolution:
integrity: sha512-<replacement-digest>
revision: 1
No revision means revision 0, the immutable original, so lockfiles that use no
replacements retain their existing shape. A dependency or override can select
one explicitly with <version>+rN; +r0 pins the original. Run
pnpm update --patches to refresh the selected
artifacts without changing any package version or declared range. The refresh
may run through the configured pnpr server. See Registry
revisions.
Batch approval for staged publishing
pnpm stage approve accepts several stage ids, or opens
an interactive picker when none are passed. One OTP approves the whole batch
until the registry stops accepting it. Workspace packages are approved in
dependency order, and a dependent is skipped when its workspace dependency
could not be approved.
pnpm init follows latest
pnpm init now looks up the pnpm version
behind the latest tag and pins it when it is newer than the running pnpm. An
offline, unreachable, slow, policy-rejected, or older result falls back to the
running version and never fails or delays the scaffold indefinitely
(#7490).
Pruning stale audit exceptions
Set audit.ignorePrune: true to make
pnpm audit --fix remove ignored GHSA entries that no longer occur in the audit
report. An exception for an advisory still present in the report is kept.
A project cannot choose the login scope
A scope key in a project's pnpm-workspace.yaml is now ignored with a
warning. pnpm login turns its scope into a machine-wide registry route, so a
repository must not be able to choose it. Pass --scope, set
PNPM_CONFIG_SCOPE, or set scope in the global config instead
(#13557).
Patch Changes
Registry and update correctness
- A
registryorregistriesdeclaration now wins over a route inferred from global_auth; thepnpm_config__authenvironment setting deliberately remains higher priority for CI-controlled routing. pnpm updatepreserves a dependency's declared range orcatalog:reference when an override also matches it, including when the override repeats the range verbatim (#12115, #14224).pnpm update -gno longer downgrades a package whose installed version is newer thanlatest, and it leaves pnpm itself topnpm self-update(#14270).--productionis accepted again as the alias of--prodon install, fetch, prune, update, list, why, and sbom (#14147).
Installation and build fixes
- An install reached through a symlinked
node_modulesno longer rewrites the target checkout, andpnpm add --lockfile-onlyno longer links dependencies (#14286). - Incremental installs validate unused patches correctly, and
deploy --prodworks when an omitted dev dependency is also an optional peer (#13692, #14302). - Reusing a prepared git dependency from the shared store now enforces
allowBuilds, and approval suggestions use its canonical git resolution id. - Hoisted copies of a built package no longer replace a destination directory
and delete dependencies nested under its
node_modules(#12880). - The remote cache avoids downloading blobs already present in the store, uses
environment names under
PNPM_SIDE_EFFECTS_CACHE_REMOTE_*(the old names remain aliases), and pnpr resolution now receives patch hashes and package extensions.
Workspace and package-manager fixes
- Workspace project sorting is now linear-time, fixing long stalls on deep workspaces with thousands of projects (#14149, #14151).
- Recursive-run cleanup terminates sibling process trees correctly on Windows.
- A satisfied
devEngines.packageManagerrange is now recorded in the lockfile'spackageManagerDependencieswith the running version as its shared resolution. - Automatic pnpm switching no longer forces descendant pnpm processes to use the parent's version (#14309).
- Update guidance now points to
pnpm self-updateonly whenPNPM_HOMEmanages pnpm; Corepack and other package-manager installs point to the standalone installer.
For the complete list, see the v11.25.0 release notes.
