pnpm 11.28
pnpm 11.28 adds the forceIgnoresPlatform setting and pnpm update --peer,
and brings a large batch of fixes from pnpm 12 to the JavaScript CLI: pnpm deploy, --filter, nodeLinker: hoisted, and custom modulesDir setups all
behave better. It also carries security fixes for shell completion, bin shims
on Nix, lifecycle scripts inside a custom modulesDir, and userAgent
placeholders in pnpm-workspace.yaml.
Minor Changes
forceIgnoresPlatform
pnpm install --force installs every optional dependency, including those
built for another os, cpu, or libc. The new
forceIgnoresPlatform
setting turns that part off, so --force still refetches packages and lifts
engineStrict but skips optional dependencies for other platforms
(#6133):
forceIgnoresPlatform: false
The default stays true in pnpm 11. In pnpm 12, --force skips such
dependencies by default.
pnpm update --peer
pnpm update --peer also updates the ranges in
peerDependencies, which pnpm update otherwise leaves alone
(#8081):
pnpm update --peer react
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). - Packages inside a custom
modulesDirare no longer treated as workspace projects. With amodulesDirsuch asvendorand apackagespattern such as**, a repeat install ran lifecycle scripts thatallowBuildshad not approved (#15412). - 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. Install again to replace the shims already innode_modules(#14883). - Shell completion omits candidates containing control or invisible formatting characters, so package and script names can no longer inject completion records or terminal escape sequences.
pnpm runtime setandpnpm env useno longer run a script that another package installed under the namepnpmorpnas though it were pnpm.pnpm store pruneleaves adlxcache root that is a symlink or Windows junction untouched.
Notable fixes
Installing
- Requests to a server whose TLS certificate fails verification now fail at once, naming the certificate problem, instead of retrying for more than a minute (#9134).
- Git dependencies fetched over SSH no longer appear to hang on a hidden passphrase or host key prompt: pnpm runs ssh in batch mode, so load a key that needs a passphrase into an SSH agent first (#2227). Committed submodules of git dependencies are now fetched (#1470).
- bzip2-compressed tarballs can be installed (#6761).
- The root project's
preinstallscript now runs before dependencies are resolved and linked, so a guard such asnpx only-allow pnpmstops the install beforenode_modulesis populated (#3760). - Installs that skip
devDependencies, such aspnpm install --prod, no longer runpnpm:devPreinstallorprepare(#7065), and they no longer install a devDependency that only satisfies an optional peer of a production dependency (#15344). pnpm installno longer addsallowBuildsplaceholders topnpm-workspace.yamlin CI or without a terminal (#11574).pnpm install --engine-strictrespectsenginesrelaxed byreadPackagehooks (#15482), and the project's pnpmfile now runs after the pnpmfiles of config dependency plugins (#9891).pnpm installandpnpm runreinstall a project that was moved together with itsnode_modules(#9512), and relink a direct dependency whose link points to a missing target (#9758).pnpm fetchalso installs the pnpm version thatpnpm-lock.yamlpins, so a later offline install can switch to it (#11808).- pnpm no longer crashes when
TMPDIR,TEMP, orTMPpoints to a missing directory (#4960).
Resolving and linking
- A dependency that a package also declares as an optional peer, such as
lightningcssin some vite builds, is now installed (#8912). - Removing an
overridesentry 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). - Ranges resolve to the newest matching version that is not deprecated (#15128).
pnpm addfollowed bypnpm removeof the same package leavespnpm-lock.yamlunchanged; unrelated transitive dependencies no longer move (#11859).pnpm install --frozen-lockfilesucceeds when an optional dependency was unresolvable and skipped by the install that wrote the lockfile (#3960).hoistWorkspacePackagesworks withnodeLinker: hoisted(#7553), and hoisted workspace projects are hoisted on every install, not only afternode_modulesis deleted (#3642).- A workspace package's bin that a build script creates after install is now linked (#10007).
Workspaces and filtering
--filter "[<since>]"compares against the merge base with<since>(#9907), and selects projects that use a changed catalog entry (#8718).--filterselectors are applied in order, so a later inclusion can re-include a project that an earlier exclusion removed (#9354).pnpm --filter <project> <command>andpnpm -r <command>run a command installed in the projects' dependencies when none of them has a script by that name (#10151).- Workspace projects reached through a symlink are installed (#1044).
- A
catalog:dependency that points at a workspace project counts as a workspace dependency for ordering and filtering (#15587). workspace:ranges match projects whose version is not valid semver, such as1.0(#4567), or carries build metadata (#6483).pnpm install --filterwithnodeLinker: hoistedinstalls only the selected projects' dependencies (#8882).- pnpm warns when a workspace install covers a project with its own
pnpm-workspace.yaml, whose settings do not apply (#11724).
Custom modulesDir
pnpm run,pnpm exec,pnpm versionhooks, and install-time lifecycle scripts find commands in a custommodulesDir, and tools installed there can load CommonJS plugins installed next to them (#3604). SeeextendNodePath.- A repeat install in a workspace with a custom
modulesDirtakes the up-to-date fast path.
Adding, updating, and removing
pnpm removeruns the project's ownpreuninstall,uninstall, andpostuninstallscripts (#3276), andpnpm remove -rfails before changing any manifest if a dependency is absent from every selected project (#2319).pnpm unlinkremoves thelink:dependency thatpnpm link <dir>added (#4219).pnpm addsaves the requested exact version (#6040), writespackage.jsonbefore lifecycle scripts run (#8627), and keeps a specifier areadPackagehook rewrote (#15156).pnpm updatekeeps ranges such as<= 3.0.0that the new version still satisfies (#6714), updates auto-installed peers by name (#10486), and moves a package off a locked version the registry no longer serves (#9953).minimumReleaseAgeExcludePruneandtrustPolicyExcludePrunework withsharedWorkspaceLockfile: false(#14612).pnpm importconverts Yarnpatch:dependencies intopatchedDependencies(#10278).
Scripts
- A script run without a terminal ends when pnpm is killed, as Playwright's
webServerdoes (#15555). pnpm execandpnpm dlxsetnpm_execpath,INIT_CWD,npm_node_execpath, andNODE(#7037), andpnpm execsetsPWD(#1550).pnpm restartrunsstopandstartwhen there is norestartscript (#4750).pnpm install-testaccepts--no-bail(#3777).pnpm dlxkeeps a separate cache per Node.js major version (#8611).- A
runtime:range containing||or a space installs the runtime instead of the npm package of the same name (#14817).
Publishing, packing, and deploying
pnpm publishresolvesworkspace:dependencies withoutnode_modules(#6567) and honorspublishConfig["@scope:registry"](#12071).pnpm packincludes bundled dependencies with the isolated linker (#1643), keeps symlinks inside the package (#8208), and preserves executable permissions.pnpm deploycopies the rootpackageManagerfield (#9079), puts the virtual store atvirtualStoreDir(#8787), and no longer runs the deployed project'spreparescript (#7282).
Configuration and registries
.npmrcfiles support npm's${VAR?}placeholder (#14404), and_authtokens from the globalconfig.yamlorpnpm_config__authexpand environment variables (#12828).pnpm loginlogs back in to an existing user on registries without web login, such as verdaccio (#12055).pnpm doctorchecks the configured default registry (#15618).- pnpm preserves CRLF line endings when it modifies manifests.
Windows and WSL
pnpm installin WSL waits out Windows file locks on/mnt/cand similar drives (#6155), and savingpnpm-lock.yamlon Windows retries while another process holds it (#9461).pnpm addandpnpm updatewritefile:andlink:specifiers with forward slashes on Windows (#7497).- Node.js runtime resolution supports Windows ARM64 (#7123).
- Bin shims run from Git Bash, MSYS2, or Cygwin pass
NODE_PATHas Windows paths (#3360).
Inspecting dependencies
pnpm audithonors--filter(#10982), lists a path from every affected project (#12200), and--fix=updatefixes npm-aliased dependencies (#15155).pnpm listandpnpm licenses listinside a workspace package list only that package unless--recursiveor--filteris given (#14494, #5689).pnpm -r outdated --jsonincludes every outdated dependency when projects use different versions of the same package (#7693).- The ignored build scripts warning and the update notice print as plain lines in CI and non-terminal output (#9421).
For the complete list of changes, see the v11.28.0 release notes.
