Release Notes
Minor Changes
Added support for alias-less Git dependency adds, preserved locked Git commits during unrelated dependency changes, and reported Git package versions in install logs.
pnpm listandpnpm whyare now feature complete and behaviorally identical to the TypeScript CLI.pnpm listgained--only-projects,--find-by(finders declared in.pnpmfile.cjs), search by version range (pnpm ls "foo@^2"), subtree deduplication with[deduped]markers, peer/skipped annotations, the package-count summary,--longmanifest details, resolved tarball URLs and absolute paths in--json/--parseableoutput, and--depthsupport for globally installed packages.pnpm whygained--json,--parseable,--long,--prod/--dev/--no-optional,--find-by, workspace project names in the reverse tree, dependency-field annotations,[circular]/[deduped]markers, peer-variant hashes, and theFound N versionssummary.Added support for the
cleanupUnusedCatalogssetting: when enabled,pnpm add,pnpm update, andpnpm removedrop catalog entries frompnpm-workspace.yamlthat no workspace project references.The
enableModulesDir: falsesetting is now honored: the install resolves and writespnpm-lock.yamlbut creates nonode_modulesdirectory (unless the global virtual store is enabled, in which case packages are still materialized into the store).Command shims now set
NODE_PATHthe way pnpm does: under the isolatednodeLinkerwith a hoist pattern, each shim lists the target package's ownnode_modulesdirectories followed by the hidden hoisted modules directory (node_modules/.pnpm/node_modules). The newextendNodePath: falsesetting turns this off.Added the
--forceflag topnpm installandpnpm add: optional dependencies whosecpu/os/libc/enginesdon't match the host are installed instead of skipped, and a forced install relinks packages that an earlier install already materialized #13142.sharedWorkspaceLockfile: falseis now supported by the install family #12042: a workspace install runs one dedicated install per project, each with its ownpnpm-lock.yaml,node_modules, and virtual store (a customvirtualStoreDirresolves per project), andpnpm add/update/removein a project operate on that project's own lockfile. Recursive and filtered install-family commands still require a shared lockfile.Added PnP install materialization and fixed recovery from expired module caches and broken private lockfiles.
Patch Changes
Fixed recovery from interrupted dependency builds in the global virtual store, and made
pnpm fetchpopulate the virtual store without linking dependencies into projects.Fixed workspace lifecycle ordering and bin linking across isolated and hoisted installs.
Auto-installed peer dependencies wanted by multiple packages under distinct but compatible ranges now resolve through the ranges' semver intersection (
2+^2.2.0install one provider matching>=2.2.0 <3.0.0-0), matching pnpm. Previously such peers were only auto-installed when every consumer declared the identical range orautoInstallPeersFromHighestMatchwas enabled.engineStrictnow fails the install when an incompatible package is reached through a regular dependency edge of an installable package, even if the package is also optionally reachable — matching pnpm. Packages reachable only through optional edges or skipped parents are still skipped #13143.Engine checks (
engines.node/engines.pnpm) now match npm-semver'sincludePrereleasesemantics exactly: a prerelease version no longer satisfies a fully specified>=bound (9.0.0-alpha.1does not satisfy>=9.0.0), while still satisfying expanded ranges like9,>=9, and^9.0.0.Fixed a rare hang where
pnpm installorpnpm addcould wait forever: when two tasks fetched the same tarball concurrently, the waiting task could miss the downloader's completion notification and never wake up.