pnpm 11.11-11.14
pnpm 11.11 through 11.14 add native workspace release management (pnpm change, pnpm lane, and a bare pnpm version -r), a pnpm doctor command that diagnoses your installation end to end, the pnpm access and pnpm team commands for managing packages and organizations on the registry, convergence overrides, and scheme-carrying peerDependencies specifiers. They also fix a path-traversal vulnerability, cut peak memory during cold-cache resolution by roughly 30%, and resolve a peer dependency deadlock.
次要更改
Native workspace release management
pnpm can now version and release a workspace on its own, without a separate release tool (#12952). The new pnpm change command records change intents — changesets-compatible .changeset/*.md files naming the affected packages, their bump types, and a summary that becomes the changelog entry:
pnpm change
pnpm change status # show the pending release plan
At release time, the bare pnpm version -r consumes them, bumping versions across the workspace with dependent propagation through workspace: ranges, writing changelogs, and recording what it consumed in a committed ledger (.changeset/ledger.yaml) that keeps cherry-picks and merge-backs between release branches safe.
Packages can be moved onto per-package release lanes with pnpm lane, releasing X.Y.Z-lane.N prereleases from the same runs that release stable versions of everything else:
pnpm lane alpha --filter @example/cli # move onto a lane
pnpm lane main --filter @example/cli # graduate back to stable
Configuration lives under the new versioning key of pnpm-workspace.yaml — fixed, ignore, maxBump, lanes, epics, and changelog. Release changelogs default to registry storage: no CHANGELOG.md is committed, and each release's section is composed at publish time and packed into the published tarball. Set versioning.changelog.storage: repository to keep committed changelog files instead.
11.13 also added versioning.epics, which ties a group of member packages to a lead package, constraining every member's major version to a band derived from the lead's: while the lead is on major M, members live in M*100 … M*100+99. When a release plan takes the lead to a new stable major, every member re-bases to the band floor in the same plan.
See Release management for the whole workflow.
pnpm doctor
The new pnpm doctor command diagnoses the pnpm installation and the environment it runs in: the versions and install method, whether the global bin directory is on PATH, whether the store and cache are writable, which link strategies (reflink, hardlink, symlink) the store's filesystem supports, registry connectivity, and an offline file: install that exercises the resolve/store/link path end to end.
✓ Versions: pnpm 11.14.0, Node.js 22.20.0
✓ Install method: pnpm
✓ Global bin directory: /Users/example/Library/pnpm/bin
✓ Cache directory: /Users/example/Library/Caches/pnpm
✓ Store directory: /Users/example/Library/pnpm/store/v10
✓ Filesystem: available: reflink, hardlink, symlink
✓ Registry connectivity: https://registry.npmjs.org/ (128ms)
✓ Install smoke test: offline "file:" install linked its dependency
All checks passed
Each check reports how to fix what it finds, and the command exits non-zero when any check fails. Use --offline to skip the checks that need network access, --json for machine-readable output, and --benchmark to time the filesystem and install checks.
pnpm access and pnpm team
pnpm access manages package access and visibility on the registry — listing packages and collaborators, getting and setting package status and MFA requirements, and granting or revoking team access:
pnpm access list packages @myorg
pnpm access set status=public @myorg/pkg
pnpm access grant read-write @myorg:developers @myorg/pkg
pnpm team manages organization teams and memberships, with create, destroy, add, rm, and ls subcommands:
pnpm team create @myorg:developers
pnpm team add @myorg:developers alice
pnpm team ls @myorg
Convergence overrides
A new override selector form with an empty range — "pkg@": "<version>" — rewrites a dependency edge only when its exact version satisfies the edge's declared range, so compatible consumers converge on one version while incompatible consumers keep their own resolution, now and for any dependent added in the future (#12794):
overrides:
"form-data@": 4.0.6
The value must be an exact version. When a full resolution detects that every declared range also admits a newer version, pnpm warns that the override is stale and names the version to converge on. Previously an empty range in an override selector was undocumented and behaved like a bare (unscoped) override.
peerDependencies accept scheme-carrying specifiers
peerDependencies now accept dependency specifiers that carry a scheme — a named-registry spec (<registry>:<version>), an npm: alias, or a file:/git/URL spec — instead of rejecting them with ERR_PNPM_INVALID_PEER_DEPENDENCY_SPECIFICATION (#13095). Such a peer is matched against the semver range carried by the specifier (work:5.x.x is checked as 5.x.x, npm:bar@^5 as ^5), or against * when it carries no version, while the original specifier still selects the package to auto-install. Bare name@version values, which are almost always a mistake, are still rejected.
RegExp script selectors and --sequential for pnpm run
pnpm run again supports executing multiple scripts matching a RegExp (e.g. pnpm run "/^build:.*/"), now running matched scripts in deterministic lexicographical order. The --sequential (-s) option is restored as well, forcing workspaceConcurrency to 1 so matched scripts run one by one across and within packages.
Portable delegation for custom fetchers
Custom fetchers exported from a pnpmfile can now delegate by returning a { delegate: <resolution> } envelope: pnpm rewrites the package's resolution to the delegated shape and runs the built-in fetcher on it. This is the portable delegation form that also works in pacquet, where cafs and fetchers cannot be passed to the hook.
Other minor changes
allowBuildsentries for git-hosted packages can now match by repository URL without pinning the resolved commit hash, so trusted git repositories keep running their build scripts after branch updates without approving each new commit. Package-name-only rules still do not approve git-hosted artifacts.registriesandnamedRegistriescan now be configured in the globalconfig.yamlfile.
Security
- Fixed a path traversal vulnerability where a dependency whose manifest
namewas a scoped path traversal (e.g.@x/../../../<path>) could be written outsidenode_modulesto an attacker-controlled location duringpnpm install, even with--ignore-scripts. - Prevented a crafted
pnpm-lock.yamlfrom writing package content outside the virtual store. Dependency path keys that reconstruct to a path-traversal sequence are now rejected by the isolated linker and the Plug'n'Play resolver map, and traversals in the version-derived path segment are rejected under the global virtual store. - Updated
adm-zipto prevent crafted ZIP archives from causing excessive memory allocation. ${...}environment-variable placeholders in thehttpProxy,httpsProxy,noProxy,proxy, andnoproxysettings are no longer expanded when these settings come from a project'spnpm-workspace.yaml.pnpm publishno longer prints credentials when the target registry is configured with inlineuser:pass@credentials.pnpm runtime set <name> <version>now validates its arguments, so an unsupported name or a comma can no longer be misread as a list of packages.- Broken-lockfile errors no longer include snippets of the lockfile's contents.
- Rejected symlinked
pnpm-lock.yamlfiles when reading or writing the env lockfile document. pnpm self-updatenow honorstrustPolicy=no-downgrade, and checks that the version it installed can run before making it the active pnpm.
补丁更改
- Reduced peak memory usage during cold-cache dependency resolution by roughly 30%, back in line with pnpm 10. The memoized metadata cache no longer retains each package's raw registry response body for the whole resolution phase.
- Fixed an out-of-memory regression when workspace projects concurrently resolve a package with large registry metadata (#13077).
- Fixed a deadlock in peer dependency resolution:
pnpm installhung forever when a peer dependency cycle spanned a project's own dependencies and auto-installed peer providers, for example when installingelectron-builder@26.15.3(#12921). - Fixed peer dependency auto-install picking a version the peer range rejects. Peers are now deduplicated onto the highest preferred version that satisfies the declared range, and when none does, the range is resolved from the registry.
- Fixed peer dependency resolution with
autoInstallPeerswhen a workspace package depends on a version of a package that a transitive dependency's self-contained closure also provides for itself (#4993). - Fixed
pnpm installfailing withERR_PNPM_LOCKFILE_IS_SYMLINKwhenpnpm-lock.yamlis a symlink, as build sandboxes such as Bazel and Nix stage it (#13073). An install that leaves the lockfile unchanged no longer rewrites it, so--frozen-lockfileno longer needs to write at all. - Fixed frozen installs incorrectly treating equivalent Git dependency specifiers as a stale lockfile (#13039).
- Fixed
pnpm updaterewriting exact version pins that use the=operator (for example=3.5.1) to a caret range. - Fixed
pnpm updateremoving transitive lockfile entries whendedupePeerDependentsis disabled and the selected package is absent (#12456). - Failed instead of silently removing an optional dependency's locked entries from
pnpm-lock.yamlwhen the registry cannot resolve it (#12853). - Retried package metadata requests when a registry or proxy returns
304 Not Modifiedto an unconditional request, and recovered from a metadata cache entry that disappears after a304(#12882). - Fixed the dependency status check wrongly reporting "up to date" when a
package.json,.pnpmfile.cjs, or patch file was edited in the same second as the previous install, on filesystems that record mtimes at whole-second resolution. pnpm deploynow supports workspaces that use catalogs, and localfile:tarball dependencies keep their package name in the generated deploy lockfile.pnpm packnow respects workspace-root.npmignoreand.gitignorefiles, and no longer applies workspace-root ignore rules when a workspace package has its own.npmignore.pnpm publishagain sends the package's README to the registry as metadata, and--otpis now sent correctly for bothpnpm publish --otpandpnpm publish --batch --otp.pnpm outdatedno longer checks the registry for dependencies resolved from locallink:,file:, orworkspace:references (#12827).pnpm listandpnpm whyno longer crash withEMFILE: too many open fileswhen a project has a large number of unsaved dependencies.pnpm cache deletenow removes a package's metadata from every metadata cache directory (#12753).- Fixed orphaned child processes on Windows when pnpm exits on an error while commands spawned by
pnpm execorpnpm dlxare still running (#12406). - Kept the interactive
minimumReleaseAgeapproval prompt visible duringpnpm install, so the install no longer hangs on a question the user cannot see (#13019). - A
tokenHelperset in the global pnpmauth.iniis no longer rejected as project-level configuration, and a helper that hangs is now killed after 60 seconds instead of leaving the command waiting forever. pnpm add -g,pnpm update -g,pnpm setup, and the self-updater no longer fail withERR_PNPM_MISSING_TIMEwhentrustPolicy: no-downgradeorresolutionMode: time-basedis set in the global config (#12883).- A project pinned to a broken pnpm release via
packageManagerordevEngines.packageManagernow reports which release is broken and what to do about it, instead of failing inside the installer. - The published
pnpmpackage no longer declaresdependenciesordevDependencies, sonpm installof the tarball no longer tries to resolve internal-only packages (#12955). - Fixed an injected workspace dependency incorrectly staying as
file:instead of deduping back tolink:(#10433). pnpm owner lsnow reports authentication and authorization failures as dedicated errors that include the registry's response body.- Options that follow
create,exec, ortestappearing as a subcommand of another command are now parsed instead of being silently treated as positional parameters. - The changed-packages filter (
--filter "...[<since>]") no longer allows an option-like<since>value to be interpreted as a git option, and the repository root is resolved to the nearest.gitentry so the filter works in a git worktree. verify-deps-before-runno longer spawns apnpm installwhen pnpm is executed in a directory that has nopackage.json.pnpm stage listnow stops paginating after a fail-safe cap of 1000 pages.- Registered the
pnalias in generated shell completion scripts, and fixed standalone installer downgrades from pnpm v12 to v11.
