pnpm 12.7
pnpm 12.7 lets the global node shim follow .nvmrc and .node-version,
adds pnpm install --allow-build and pnpm publish --publish-wait-timeout,
and creates pnpm-workspace.yaml from the workspaces field of package.json.
pnpm install --force no longer installs optional dependencies built for other
platforms. This release also carries security fixes and a long list of bug
fixes.
Minor Changes
.nvmrc and .node-version in the node shim
The project-aware global node
shim now uses the Node.js version from the nearest .nvmrc or .node-version
file when the project does not declare a Node.js runtime in
devEngines.runtime or engines.runtime
(#4471). A project set up for nvm,
fnm, or n gets the right node without further setup:
cd ~/projects/legacy-app
cat .nvmrc # 20
node --version # v20.x.x
The nearest directory with a Node.js runtime declaration decides the version.
Within one directory, package.json takes precedence over .node-version,
which takes precedence over .nvmrc. An .nvmrc value that only nvm can act
on, such as system or a custom alias, is ignored. See
.nvmrc and .node-version.
pnpm install --allow-build
pnpm install --allow-build allows or denies a
package's lifecycle scripts and records the decision in allowBuilds, as
pnpm add --allow-build already did
(#15388):
pnpm install --allow-build=esbuild --allow-build='!core-js'
Waiting for published packages
pnpm publish --publish-wait-timeout <milliseconds>
waits for the published versions and their tarballs to become available from
the registry. A recursive publish confirms each package before it publishes the
packages that depend on it, so a dependent never points at a version its
consumers cannot fetch yet. If confirmation times out, the command fails. Set
a default in pnpm-workspace.yaml:
publishWaitTimeout: 60000
When pnpm publish -r --report-summary fails after some uploads were accepted,
the summary file now lists those packages.
pnpm-workspace.yaml from the workspaces field
In a repository with no pnpm-workspace.yaml, pnpm install now creates one
from the workspaces field of the root package.json and links the listed
projects on that same install
(#2255). An existing
pnpm-workspace.yaml is never changed, and nothing is created with
--ignore-workspace. If the workspaces field later differs from packages
in pnpm-workspace.yaml, pnpm prints a warning. See
Converting from the workspaces field.
--force keeps skipping foreign optional dependencies
pnpm install --force now keeps skipping optional dependencies whose os,
cpu, or libc do not match the host
(#6133). It still refetches every
package and lifts engineStrict. The new
forceIgnoresPlatform
setting restores the previous behaviour:
forceIgnoresPlatform: true
Other changes
- When a project pins a pnpm version or a runtime that another pnpm process is
installing at that moment, pnpm now waits a few seconds and then installs and
runs a private copy. It used to wait up to five minutes and then use the
shared install directory without the lock.
pnpm store pruneremoves any private copy a killed process left behind (#15413). - pnpm now keeps the blank lines between entries of
package.jsonwhen it updates the file (#5602). - pnpm now reads and updates
package.json5manifests, keeping their comments. Workspace discovery preferspackage.json, thenpackage.json5, thenpackage.yaml(#15129). pnpm init --barecreates apackage.jsonwith only the required fields (#15538).- The
reportersetting is now honored frompnpm-workspace.yaml, the global configuration, andPNPM_CONFIG_REPORTER(#4879). - Configuration files support npm's
${VAR?}placeholder, which expands to an empty string without a warning whenVARis unset (#14404). publishConfig["@scope:registry"]now sets the publish registry of a scoped package (#12071).- Node.js runtime resolution supports Windows ARM64 (#7123).
Security
- pnpm no longer expands environment variables in a
userAgentset in a project'spnpm-workspace.yaml. Such auserAgentis ignored. Before, pnpm sent the variable's value to the configured registry (#15415). - On Nix, a dependency's bin named like a system utility such as
sedcan no longer redirect a POSIX bin shim or thepnpm,pn,pnpx, andpnxlaunchers. Installing again replaces the shims already innode_modules(#14883). - pnpm no longer treats manifests inside its store, cache, state, or modules
directories as workspace projects. A
storeDirinside the workspace could let lifecycle scripts of packages in the store run withoutallowBuildsapproval (#15033). - Packages that run a lifecycle script are no longer hard-linked into the virtual store, so a build script can no longer rewrite the workspace source of an injected package or the store copy it was imported from (#15483).
Patch Changes
Installing
- Fixed running out of memory when many packages share a missing peer
dependency, mostly with
autoInstallPeers: false(#15362). - pnpm no longer hangs for up to 5 minutes after a pnpm process was killed while setting up the pinned pnpm version. A lock whose owner is gone is taken over at once (#15360).
- Requests to a server whose TLS certificate fails verification now fail at once instead of being retried for more than a minute (#9134).
- On macOS, pnpm falls back to its bundled CA roots when system trust evaluation is unavailable, such as in a sandbox (#15329).
- A warm install uses less CPU while linking packages. On Windows, it could take several times longer than with pnpm 11 (#15439).
pnpm installnow fetches committed submodules of git dependencies (#1470).- A local tarball replaced at the same path is reinstalled, and
--frozen-lockfilerejects it (#2437, #1889). - Installs that skip
devDependenciesno longer runpnpm:devPreinstallorpreparescripts (#7065). --prodinstalls no longer install a devDependency that only satisfies an optional peer of a production dependency (#15344).pnpm fetchalso installs the pnpm versionpnpm-lock.yamlpins, so a laterpnpm install --offlinecan switch to it (#11808).pnpm installno longer addsallowBuildsplaceholders topnpm-workspace.yamlin CI or without a terminal (#11574).- pnpm detects the same CI environments as pnpm 11, including AWS CodeBuild.
Resolving and linking
- A dependency that a package also declares as an optional peer dependency is
installed again, for example
lightningcssin some vite builds (#8912). - Removing an entry from
overridesnow re-resolves the packages it targeted (#4587). - With
trustPolicy: no-downgrade, pnpm resolves the newest matching version that is not a trust downgrade instead of failing (#14176). autoDedupeandpnpm dedupemove transitive dependencies to the version acatalog:dependency pins, andpnpm dedupeno longer alternates between two lockfiles when annpm:alias is involved (#15588).pnpm install --ignore-pnpmfilekeepspnpmfileChecksumin an up-to-date lockfile (#10944).- With
nodeLinker: hoisted,hoistWorkspacePackageslinks selected workspace projects and their bins into the rootnode_modules(#7553), and removed packages' commands are removed fromnode_modules/.bin(#7568). - Installing the
nodepackage on Windows works again (#15501).
Workspaces and filtering
- Workspace projects reached through a symlink are installed (#1044).
- A
catalog:dependency whose entry points at a workspace project counts as a workspace dependency for ordering and filtering (#15587). workspace:ranges match projects with non-semver versions such as1.0(#4567) and with build metadata (#6483).--frozen-lockfilefails when the lockfile lists a workspace project that is missing (#7667).- Injected workspace packages get the output of their own
prepare,install, andpostinstallscripts (#9464). - A custom
modulesDirworks with several path segments, withnodeLinker: hoisted, and on the up-to-date fast path (#15484). - pnpm warns when a workspace install covers a project that has its own
pnpm-workspace.yaml(#11724). [<since>]compares against the merge base, and selects projects whose catalog versions changed (#9907, #8718).--filterselectors are evaluated in order, so a later inclusion can re-include an excluded project (#9354).
Adding, updating, and removing
pnpm addsavespackage.jsonbefore running lifecycle scripts (#8627) and saves a requested exact version (#6040).pnpm add <pkg>@<version>andpnpm update <pkg>@<version>move a catalog entry onto the named version (#13715).pnpm updatekeeps a range without a save prefix, such as<= 3.0.0, when the new version still satisfies it (#6714).pnpm update <pkg>can move off a locked version the registry no longer serves (#9953).pnpm unlinkremoves thelink:dependency thatpnpm link <dir>added (#4219).pnpm installprunes unreferenced catalog entries whencatalogPrune: trueis set (#15273).pnpm importconverts Yarn'spatch:protocol (#10278).pnpm patchandpnpm patch-commitwork withsharedWorkspaceLockfile: false(#9926).
Running scripts
- A script run without a terminal ends when pnpm is killed, for example by
Playwright's
webServer(#15555). pnpm --filter <project> <command>andpnpm -r <command>run a command from the projects' dependencies when no script has that name (#10151).pnpm execandpnpm dlxsetnpm_execpath,INIT_CWD,npm_node_execpath, andNODE(#7037), andpnpm execsetsPWD(#1550).pnpm restartrunsstopandstartwhen there is norestartscript (#4750).pnpm dlxkeeps a separate cache entry per Node.js major version (#8611).pnpm pipelineruns outside a Git work tree, without caching (#15601).- A
runtime:range such as^22.18.0 || ^24.0.0installs the runtime instead of thenodenpm package (#14817).
Publishing and deploying
pnpm publishresolvesworkspace:dependencies withoutnode_modules(#6567).pnpm packandpnpm publishinclude bundled dependencies with the isolated linker (#1643), keep symlinks inside the package (#8208), and preserve executable permissions.pnpm deploycopies the rootpackageManagerfield (#9079), honorsvirtualStoreDir(#8787), and skips the deployed project'spreparescript (#7282).
Global packages and pnpm versions
- Global commands run with the pnpm you invoked, even in a project that pins another version (#14531).
pnpm self-updateinside a project that pins pnpm also updates the global pnpm (#14747) and no longer leaves the previous@pnpm/exebehind (#14709).pnpm setupno longer fails withText file busy(#15494) and no longer deletes lines near the pnpm block of a shell startup file (#7067).
Windows and WSL
- Installs and
pnpm cleanwait for a file held open by another process instead of failing at once, on Windows (#15081) and on Windows drives under WSL (#6155). - Saving
pnpm-lock.yamlis retried while another process holds it open (#9461). - Trailing dots and spaces are escaped in
node_modules/.pnpmdirectory names (#8101). - Bin shims run from Git Bash, MSYS2, or Cygwin pass
NODE_PATHas Windows paths (#3360).
Inspecting dependencies
pnpm audithonors--filter(#10982) and lists a dependency path from every affected workspace project (#12200).pnpm listandpnpm licenses listinside a workspace project list only that project (#14494, #5689).pnpm list --only-projectsprints every selected project (#9770).pnpm licenses listworks withsharedWorkspaceLockfile: false(#10140) and withnodeLinker: hoisted(#8589).pnpm store statusno longer reports packages with build scripts as modified (#15383).
See the v12.7.0 release notes for the complete list of changes.
