You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
pnpm login no longer requires an interactive terminal when the registry supports web-based login: without a TTY it prints the authentication URL (skipping the QR code and the "Press ENTER to open the URL in your browser" prompt) and polls the registry until the browser approval completes. Only the classic username/password login still fails with ERR_PNPM_LOGIN_NON_INTERACTIVE in a non-interactive terminal.
The save-prefix setting now accepts =: newly added dependencies are saved with an explicit = operator (=1.2.3) instead of the setting being silently treated as the default ^.
Patch Changes
allowBuilds entries can now approve git-hosted packages that pnpm downloads as a tarball, such as github: dependencies (which are fetched from codeload.github.com rather than cloned), by their repository URL without the resolved commit hash. This matches the hashless git+ matching already supported for cloned git dependencies. For example:
This approves the package whether pnpm clones it or downloads a tarball, so the entry no longer has to be updated every time the pinned commit changes. GitLab and Bitbucket tarball downloads are matched the same way. Approving or denying a specific resolved commit by its full tarball dep path continues to work.
pnpm outdated --include-github-actions no longer blocks on an interactive git credential prompt when a workflow uses a private action repo.
Prevented minimumReleaseAge from replacing latest with a SemVer-greater version than the registry tag target #13034.
Fixed empty bundledDependencies and bundleDependencies arrays causing nondeterministic lockfile changes. See #13123.
The install summary no longer prints (X is available) when the registry's dist-tags.latest is still held back by the active minimumReleaseAge policy. The hint only ever names the actual latest tag, so an immature latest suppresses the hint instead of advertising the version pnpm just refused to install #11698.
pnpm update keeps the explicit = operator of an exact version pin: a dependency saved as =3.5.1 now updates to =3.5.2 instead of the bare 3.5.2. See #13168.
Preserve a workspace dependency's link: entry when a run does not target it — e.g. pnpm update <other-pkg> (with or without --recursive), or a plain install after a root/catalog dependency change — with injectWorkspacePackages, instead of spuriously rewriting it to a peer-suffixed file: protocol. See #10433.
Workspace dependencies declared with a relative path (e.g. "foo": "workspace:../foo") are no longer silently dropped from the workspace projects graph, so --filter selection and the topological order of recursive commands take them into account.
Fixed an installed optional dependency being left without one of its own required dependencies. When a package reached through optionalDependencies is installable on the current system but one of its regular dependencies is not, a lockfile-based install skipped that dependency and installed the parent anyway, so importing the parent failed with MODULE_NOT_FOUND. The dependency is now installed, and an install-check warning reports the incompatibility. A dependency is still only skipped when every path to it is optional, or when the package that pulls it in was itself skipped #13286.
pnpm setup now appends PNPM_HOME and the global bin directory to the GitHub Actions environment files (GITHUB_ENV and GITHUB_PATH), so later steps in the same job can run pnpm add --global and other global commands #9191.
Added support for publishConfig.name, which publishes a package under a different name than the one its manifest carries in the workspace. It is for a project whose published name is already taken by a sibling project, which otherwise has to be renamed by a build step just before publishing. Only the published artifact is renamed — dependents, pnpm-lock.yaml, and release tooling keep addressing the project by its manifest name — and the new name reaches the packed manifest, the tarball filename, and everything that addresses the package at the registry: the already-published check of pnpm publish -r, its registry selection, and the release-planning probes of pnpm change status and pnpm version -r#13345.
pnpm self-update no longer takes any instruction from the project it is run in:
pnpm is fetched through the same trusted registry and auth configuration used when switching pnpm versions, so a project .npmrc or pnpm-workspace.yaml can no longer redirect the download or attach credentials to it, and the project's default .pnpmfile.(c|m)js is no longer loaded. Pnpmfiles from trusted sources (the pnpmfile setting, the global pnpmfile, config dependencies) still apply.
The minimumReleaseAge settings in pnpm-workspace.yaml no longer affect self-update. They still govern the project's own dependencies; for self-update the cooldown now comes from the built-in default, your global config, a PNPM_CONFIG_* environment variable, or a command-line flag. This fixes self-update failing inside a workspace that raises the cutoff while succeeding everywhere else, and stops a repository from either waiving the cooldown or keeping you on an outdated pnpm by raising it.
The same applies to the trustPolicy settings and to ci: a project can no longer weaken the trust check that guards the pnpm download, nor re-enable the confirmation prompt that a CI run suppresses.
When self-update refuses a version that is younger than the cutoff, an interactive run now offers to update anyway; non-interactive runs still fail. CI never prompts, even on a runner that attaches a TTY.
Patch Changes
Fixed pnpm licenses list to report every version when the same package is installed under multiple aliases pnpm/pnpm#13438.
Sort pnpm dedupe --check snapshot changes for stable output across pnpm implementations.
Strip Unicode formatting characters from registry- and manifest-derived terminal output.
Speed up installs after compatible catalog or direct dependency range changes by retaining the locked version without resolving the dependency graph again.
Speed up installs after safe override changes by reusing unambiguous compatible dependency resolutions, pruning obsolete dependencies, applying independent replacements and removals together, and handling parent-scoped "-" overrides without full lockfile resolution.
Installing a local file: directory dependency with the global virtual store enabled no longer fails with TypeError: Cannot read properties of undefined (reading 'split')#13335.
Local directory dependencies — file: directories and injected workspace packages — now get a global-virtual-store slot of their own per project. They used to share one slot across every project that depended on a directory of the same name, so a project could end up linked to another project's copy of the dependency.
The Workspace column of pnpm update --interactive now falls back to the project's path when its name is only whitespace, as it already did for a missing or empty one — all three render an equally blank label otherwise.
Checking GitHub Actions dependencies for updates is now opt-in for every command. Neither pnpm outdated nor pnpm update reads the workflow files unless --include-github-actions is passed or update.githubActions is set to true in pnpm-workspace.yaml. Reading them runs git ls-remote against every referenced repository, which fails in environments where GitHub is not reachable the way pnpm assumes (a GitHub Enterprise Server, a custom certificate authority, or an offline network) #13254.
pnpm outdated accepts the --include-github-actions option too.
pnpm update --interactive now measures its table in terminal columns rather than in characters. A package name, workspace name, or version containing wide characters (CJK, most emoji) no longer knocks its row's columns out of line with the rest of the group, and a wide character in a version no longer aborts the command with Subject parameter value width cannot be greater than the container width#13357.
The Workspace column of pnpm update --interactive is more informative in two cases. A dependency outdated at the same version in several workspace projects is offered as one choice, since selecting it updates every project — that choice now names all of them instead of only the first. And a workspace project without a name is now labelled with its path rather than left blank, so several unnamed projects can be told apart.
An auto-installed optional peer is no longer hoisted at a version the workspace root's own dependency on that package excludes. resolvePeersFromWorkspaceRoot already made the workspace root's specifier decide which version a missing required peer is installed at; the optional-peer picker ignored it and always took the highest version present anywhere in the graph. In a workspace whose root pins postcss: 8.5.10, an importer that depends on webpack and declares no postcss of its own got postcss@8.5.22 hoisted for terser-webpack-plugin's optional postcss peer, leaving two postcss@8.5.x instances in the graph #13320.
overrides now also govern peers that pnpm auto-installs. Previously an override only rewrote dependencies declared in a manifest, so a peer nobody declares — installed because autoInstallPeers is on — resolved against its declared peer range and could bring in a second copy of the very package the override pinned. For example, with overrides: { react: npm:react@19.2.0 } and a lone lucide-react dependency, pnpm installed react@18.3.1; it now installs the pinned react@19.2.0#13320.
Under resolvePeersFromWorkspaceRoot, a workspace root dependency declared with link: or file: (or the path form of workspace:, such as workspace:../pkg) now satisfies another project's missing peer dependency at the linked package's own version, instead of being hoisted as a path. Those specifiers are relative to the project that declares them, so the same specifier reached a different directory — or none — from the project the peer was hoisted into, leaving a broken link. The root now has the same authority over the peer as it has when it declares the package with a version range #13373.
Installs through a pnpr server now apply the project's whole verification policy. minimumReleaseAgeExclude, minimumReleaseAgeIgnoreMissingTime, trustPolicy, trustPolicyExclude, trustPolicyIgnoreAfter, and trustLockfile were ignored, so excluded packages were still held back and a lockfile containing them could be rejected.
trustPolicy: no-downgrade no longer fails with TRUST_POLICY_INCOMPATIBLE_WITH_PNPR when a pnpr server is configured.
--frozen-lockfile and --no-prefer-frozen-lockfile are now honored on the pnpr path, instead of resolving and rewriting the lockfile anyway. Since frozenLockfile defaults to true on CI, a CI install through a pnpr server now fails on an out-of-date lockfile rather than updating it.
Workspace installs through a pnpr server no longer crash with Cannot read properties of undefined (reading 'filter') after linking, when minimumReleaseAge is active #13275.
Fixed pnpm dedupe updating valid catalog resolutions when another matching version exists in the lockfile.
pnpm -r run "/pattern/" --no-bail no longer exits zero when one of a project's matched scripts fails and a later one passes. The run summary carries a single status per project, and the passing script overwrote the recorded failure.
Restored the store block a first install prints, naming how packages were materialized and where the stores live #13315:
Packages are hard linked from the content-addressable store to the virtual store.
Content-addressable store is at: ~/.local/share/pnpm/store/v11
Virtual store is at: node_modules/.pnpm
The root project's pnpm:devPreinstall script now runs before resolution and linking, as it does in pnpm 11. It is skipped under --ignore-scripts, --lockfile-only and --dry-run, by pnpm fetch and pnpm rebuild, and by a repeat install that is already up to date. Workspaces that use the hook to prepare state the install depends on — such as next.js, which generates a placeholder next bin with it — were left with dependents linked against files that were never created #13313.
Prevented pnpm dedupe --check from removing an incompatible node_modules directory.
pnpm update --workspace no longer links dependencies the user never named:
Running it with updateConfig.ignoreDependencies configured no longer fails with ERR_PNPM_WORKSPACE_PACKAGE_NOT_FOUND for a dependency that is only published to the registry. Such dependencies keep their specifiers, as they already did when no dependencies were ignored.
Passing package selectors that match no direct dependency no longer falls back to linking every workspace dependency.
Added a new setting, update.githubActionsServer, for specifying the base URL of the GitHub server that hosts the repositories of the GitHub Actions referenced by the workflow files (for example, a GitHub Enterprise Server). When the setting is not defined, the URL is read from the GITHUB_SERVER_URL environment variable, falling back to https://github.com. The URL must use the https:// or http:// protocol #13220.
pnpm outdated and pnpm update no longer fail when the refs of a GitHub Action's repository cannot be read (for example, when the action's repository is private or hosted on a different GitHub server). Such actions are now skipped with a warning.
Setting update.githubActions to false now makes pnpm outdated and the interactive pnpm update skip GitHub Actions dependencies.
Patch Changes
The token poll for web-based authentication no longer reads the body of non-OK or still-pending (HTTP 202) responses, and caps the token response body it does read at 64 KiB, so a malicious or compromised registry cannot exhaust memory through the poll pnpm/pnpm#12721.
Fixed catalog: references in dependencies and overrides failing to resolve when installing through a pnpr server, which errored with "No catalog entry '' was found for catalog 'default'." even though the catalog entry existed. Also fixed a crash on Windows when installing a nested workspace member (e.g. packages/foo) through a pnpr server #13232.
Republished every package: the tarballs published by the v11.13.1 through v11.16.0 releases were missing most of their compiled files due to a packing bug #13164.
Revert script ordering change for pnpm run --sequential /regex/
Support the from-git argument in the pnpm version command.
When the authentication URL cannot be rendered as a QR code (for example when it exceeds the maximum QR data capacity), web-based login now displays the URL alone with a warning instead of aborting authentication pnpm/pnpm#12721.
The first release of a package now publishes the version written in its manifest verbatim, instead of bumping off it. pnpm version -r and pnpm change status check the registry for each release's current version; when that version is not yet published, the package debuts at it and its pending changesets apply only from the next release. A newly added package seeded at 1100.0.0 with a minor changeset is therefore published as 1100.0.0 rather than skipping straight to 1100.1.0.
Added a --changeset flag to pnpm update. Set update.changeset to true in pnpm-workspace.yaml to enable this behavior by default, and use --no-changeset to override the setting for one update. After the update completes, pnpm writes a .changeset/pnpm-update-<suffix>.md file declaring a patch bump for every workspace package whose dependencies or optionalDependencies were changed by the update and a major bump when peerDependencies changed, including packages that consume an updated catalog entry via the catalog: protocol. Private packages, packages without a name, and packages listed in the ignore array of .changeset/config.json are skipped. If .changeset/config.json does not exist, a warning is printed and no changeset is generated.
Added GitHub Actions dependencies to pnpm outdated and interactive pnpm update. Non-interactive updates can include them with --include-github-actions or by setting update.githubActions to true in pnpm-workspace.yaml. Updated actions are pinned to exact commit hashes with their release tags preserved in comments.
Added update and audit settings sections to pnpm-workspace.yaml, superseding the awkwardly named updateConfig, auditConfig, and top-level auditLevel settings:
update:
ignoreDeps: # was updateConfig.ignoreDependencies
- webpack
- "@​babel/*"audit:
level: high # was auditLevelignore: # was auditConfig.ignoreGhsas
- GHSA-xxxx-yyyy-zzzz
update.ignoreDeps lists dependency name patterns that pnpm update and pnpm outdated should skip. audit.level and audit.ignore tune pnpm audit.
The deprecated updateConfig, auditConfig, and auditLevel settings keep working until the next major version. When both a new section value and its deprecated counterpart are set, the new section takes precedence and a warning is printed. Both the TypeScript CLI and the Rust config surface (pacquet) recognize the new sections.
Patch Changes
Fixed pnpm add --save-exact/--save-prefix and pnpm update writing a package's version with the peerDependencies range's prefix (e.g. ^19.2.7 instead of the requested 19.2.7) whenever the same package also appeared in peerDependencies. A real dependencies/devDependencies/optionalDependencies entry now takes precedence over a same-named peerDependencies entry when computing the current specifiers #13108.
Optional peer dependencies declared only via peerDependenciesMeta (for example debug's supports-color peer) are now resolved from a satisfying version already present in the dependency graph, the same way explicitly declared optional peer dependencies are. Previously such peers were only resolved this way when the package's metadata was read back from the lockfile, so an unrelated dependency change could rewrite peer resolutions across the whole lockfile.
Patch Changes
Updated adm-zip to prevent crafted ZIP archives from causing excessive memory allocation.
pnpm version -r no longer writes a versioning-ledger entry with no consumed intents as a bare intents: key, which the next run failed to read with ERR_PNPM_INVALID_VERSIONING_LEDGER. Empty intent lists are now written as intents: [], and the ledger reader accepts the bare form left by earlier releases.
Fixed pnpr workspace resolution to preserve project names and versions for workspace: dependencies.
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.
Added pnpm doctor, which 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. 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.
Added support for executing multiple scripts matching a RegExp passed to pnpm run (e.g., pnpm run "/^build:.*/"), running matched scripts in deterministic lexicographical order. Restored the --sequential (-s) CLI option for pnpm run, which forces workspaceConcurrency to 1 so that matched scripts run sequentially one by one across and within packages.
Patch Changes
Fixed pnpm install failing with ERR_PNPM_LOCKFILE_IS_SYMLINK when pnpm-lock.yaml is a symlink, as build sandboxes such as Bazel and Nix stage it #13073. Reading a lockfile through a symlink is allowed again, and an install that leaves the lockfile unchanged no longer rewrites it, so --frozen-lockfile no longer needs to write at all. Writing a changed lockfile through a symlink is still refused, as that would redirect the write onto the symlink's target.
Fixed frozen installs incorrectly treating equivalent Git dependency specifiers as a stale lockfile. See #13039.
pnpm owner ls now reports authentication and authorization failures (401/403) as dedicated errors that include the registry's response body, matching pnpm owner add/rm, instead of a generic Failed to fetch owners message.
Recover from a metadata cache entry that disappears (concurrent cache cleanup, antivirus) after the registry has already answered the conditional request with 304 Not Modified. The metadata is re-requested once without cache validators instead of failing the install with ERR_PNPM_CACHE_MISSING_AFTER_304.
A project pinned to a broken pnpm release via packageManager or devEngines.packageManager now reports which release is broken and what to do about it, instead of failing inside the installer. pnpm self-update already refused these releases; the version switch does too.
Prevent broken-lockfile errors from including snippets of the lockfile's contents.
pnpm self-update now checks that the version it installed can run before making it the active pnpm. A release that installs but cannot execute is discarded with an error instead of replacing a working installation.
Fixed an out-of-memory regression when workspace projects concurrently resolve a package with large registry metadata pnpm/pnpm#13077.
Fixed pnpm update rewriting exact version pins that use the = operator (for example =3.5.1) to a caret range (^3.5.1). Exact pins are now preserved and written back as the bare version. See #12745.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748→11.19.0Release Notes
pnpm/pnpm (pnpm)
v11.19.0: pnpm 11.19Compare Source
Minor Changes
pnpm loginno longer requires an interactive terminal when the registry supports web-based login: without a TTY it prints the authentication URL (skipping the QR code and the "Press ENTER to open the URL in your browser" prompt) and polls the registry until the browser approval completes. Only the classic username/password login still fails withERR_PNPM_LOGIN_NON_INTERACTIVEin a non-interactive terminal.The
save-prefixsetting now accepts=: newly added dependencies are saved with an explicit=operator (=1.2.3) instead of the setting being silently treated as the default^.Patch Changes
allowBuildsentries can now approve git-hosted packages that pnpm downloads as a tarball, such asgithub:dependencies (which are fetched fromcodeload.github.comrather than cloned), by their repository URL without the resolved commit hash. This matches the hashlessgit+matching already supported for cloned git dependencies. For example:This approves the package whether pnpm clones it or downloads a tarball, so the entry no longer has to be updated every time the pinned commit changes. GitLab and Bitbucket tarball downloads are matched the same way. Approving or denying a specific resolved commit by its full tarball dep path continues to work.
pnpm outdated --include-github-actionsno longer blocks on an interactive git credential prompt when a workflow uses a private action repo.Prevented
minimumReleaseAgefrom replacinglatestwith a SemVer-greater version than the registry tag target #13034.Fixed empty
bundledDependenciesandbundleDependenciesarrays causing nondeterministic lockfile changes. See #13123.The install summary no longer prints
(X is available)when the registry'sdist-tags.latestis still held back by the activeminimumReleaseAgepolicy. The hint only ever names the actual latest tag, so an immature latest suppresses the hint instead of advertising the version pnpm just refused to install #11698.pnpm updatekeeps the explicit=operator of an exact version pin: a dependency saved as=3.5.1now updates to=3.5.2instead of the bare3.5.2. See #13168.Preserve a workspace dependency's
link:entry when a run does not target it — e.g.pnpm update <other-pkg>(with or without--recursive), or a plain install after a root/catalog dependency change — withinjectWorkspacePackages, instead of spuriously rewriting it to a peer-suffixedfile:protocol. See #10433.Workspace dependencies declared with a relative path (e.g.
"foo": "workspace:../foo") are no longer silently dropped from the workspace projects graph, so--filterselection and the topological order of recursive commands take them into account.Platinum Sponsors
Gold Sponsors
v11.18.0: pnpm 11.18Compare Source
Minor Changes
Fixed an installed optional dependency being left without one of its own required dependencies. When a package reached through
optionalDependenciesis installable on the current system but one of its regulardependenciesis not, a lockfile-based install skipped that dependency and installed the parent anyway, so importing the parent failed withMODULE_NOT_FOUND. The dependency is now installed, and an install-check warning reports the incompatibility. A dependency is still only skipped when every path to it is optional, or when the package that pulls it in was itself skipped #13286.pnpm setupnow appendsPNPM_HOMEand the global bin directory to the GitHub Actions environment files (GITHUB_ENVandGITHUB_PATH), so later steps in the same job can runpnpm add --globaland other global commands #9191.Added support for
publishConfig.name, which publishes a package under a different name than the one its manifest carries in the workspace. It is for a project whose published name is already taken by a sibling project, which otherwise has to be renamed by a build step just before publishing. Only the published artifact is renamed — dependents,pnpm-lock.yaml, and release tooling keep addressing the project by its manifest name — and the new name reaches the packed manifest, the tarball filename, and everything that addresses the package at the registry: the already-published check ofpnpm publish -r, its registry selection, and the release-planning probes ofpnpm change statusandpnpm version -r#13345.pnpm self-updateno longer takes any instruction from the project it is run in:.npmrcorpnpm-workspace.yamlcan no longer redirect the download or attach credentials to it, and the project's default.pnpmfile.(c|m)jsis no longer loaded. Pnpmfiles from trusted sources (thepnpmfilesetting, the global pnpmfile, config dependencies) still apply.minimumReleaseAgesettings inpnpm-workspace.yamlno longer affectself-update. They still govern the project's own dependencies; forself-updatethe cooldown now comes from the built-in default, your global config, aPNPM_CONFIG_*environment variable, or a command-line flag. This fixesself-updatefailing inside a workspace that raises the cutoff while succeeding everywhere else, and stops a repository from either waiving the cooldown or keeping you on an outdated pnpm by raising it.trustPolicysettings and toci: a project can no longer weaken the trust check that guards the pnpm download, nor re-enable the confirmation prompt that a CI run suppresses.When
self-updaterefuses a version that is younger than the cutoff, an interactive run now offers to update anyway; non-interactive runs still fail. CI never prompts, even on a runner that attaches a TTY.Patch Changes
Fixed
pnpm licenses listto report every version when the same package is installed under multiple aliases pnpm/pnpm#13438.Sort
pnpm dedupe --checksnapshot changes for stable output across pnpm implementations.Strip Unicode formatting characters from registry- and manifest-derived terminal output.
Speed up installs after compatible catalog or direct dependency range changes by retaining the locked version without resolving the dependency graph again.
Speed up installs after safe override changes by reusing unambiguous compatible dependency resolutions, pruning obsolete dependencies, applying independent replacements and removals together, and handling parent-scoped
"-"overrides without full lockfile resolution.Installing a local
file:directory dependency with the global virtual store enabled no longer fails withTypeError: Cannot read properties of undefined (reading 'split')#13335.Local directory dependencies —
file:directories and injected workspace packages — now get a global-virtual-store slot of their own per project. They used to share one slot across every project that depended on a directory of the same name, so a project could end up linked to another project's copy of the dependency.The
Workspacecolumn ofpnpm update --interactivenow falls back to the project's path when itsnameis only whitespace, as it already did for a missing or empty one — all three render an equally blank label otherwise.Checking GitHub Actions dependencies for updates is now opt-in for every command. Neither
pnpm outdatednorpnpm updatereads the workflow files unless--include-github-actionsis passed orupdate.githubActionsis set totrueinpnpm-workspace.yaml. Reading them runsgit ls-remoteagainst every referenced repository, which fails in environments where GitHub is not reachable the way pnpm assumes (a GitHub Enterprise Server, a custom certificate authority, or an offline network) #13254.pnpm outdatedaccepts the--include-github-actionsoption too.pnpm update --interactivenow measures its table in terminal columns rather than in characters. A package name, workspace name, or version containing wide characters (CJK, most emoji) no longer knocks its row's columns out of line with the rest of the group, and a wide character in a version no longer aborts the command withSubject parameter value width cannot be greater than the container width#13357.The
Workspacecolumn ofpnpm update --interactiveis more informative in two cases. A dependency outdated at the same version in several workspace projects is offered as one choice, since selecting it updates every project — that choice now names all of them instead of only the first. And a workspace project without anameis now labelled with its path rather than left blank, so several unnamed projects can be told apart.An auto-installed optional peer is no longer hoisted at a version the workspace root's own dependency on that package excludes.
resolvePeersFromWorkspaceRootalready made the workspace root's specifier decide which version a missing required peer is installed at; the optional-peer picker ignored it and always took the highest version present anywhere in the graph. In a workspace whose root pinspostcss: 8.5.10, an importer that depends onwebpackand declares nopostcssof its own gotpostcss@8.5.22hoisted forterser-webpack-plugin's optionalpostcsspeer, leaving twopostcss@8.5.xinstances in the graph #13320.overridesnow also govern peers that pnpm auto-installs. Previously an override only rewrote dependencies declared in a manifest, so a peer nobody declares — installed becauseautoInstallPeersis on — resolved against its declared peer range and could bring in a second copy of the very package the override pinned. For example, withoverrides: { react: npm:react@19.2.0 }and a lonelucide-reactdependency, pnpm installedreact@18.3.1; it now installs the pinnedreact@19.2.0#13320.Under
resolvePeersFromWorkspaceRoot, a workspace root dependency declared withlink:orfile:(or the path form ofworkspace:, such asworkspace:../pkg) now satisfies another project's missing peer dependency at the linked package's own version, instead of being hoisted as a path. Those specifiers are relative to the project that declares them, so the same specifier reached a different directory — or none — from the project the peer was hoisted into, leaving a broken link. The root now has the same authority over the peer as it has when it declares the package with a version range #13373.Installs through a pnpr server now apply the project's whole verification policy.
minimumReleaseAgeExclude,minimumReleaseAgeIgnoreMissingTime,trustPolicy,trustPolicyExclude,trustPolicyIgnoreAfter, andtrustLockfilewere ignored, so excluded packages were still held back and a lockfile containing them could be rejected.trustPolicy: no-downgradeno longer fails withTRUST_POLICY_INCOMPATIBLE_WITH_PNPRwhen a pnpr server is configured.--frozen-lockfileand--no-prefer-frozen-lockfileare now honored on the pnpr path, instead of resolving and rewriting the lockfile anyway. SincefrozenLockfiledefaults totrueon CI, a CI install through a pnpr server now fails on an out-of-date lockfile rather than updating it.Workspace installs through a pnpr server no longer crash with
Cannot read properties of undefined (reading 'filter')after linking, whenminimumReleaseAgeis active #13275.Fixed
pnpm dedupeupdating valid catalog resolutions when another matching version exists in the lockfile.pnpm -r run "/pattern/" --no-bailno longer exits zero when one of a project's matched scripts fails and a later one passes. The run summary carries a single status per project, and the passing script overwrote the recorded failure.Restored the store block a first install prints, naming how packages were materialized and where the stores live #13315:
The root project's
pnpm:devPreinstallscript now runs before resolution and linking, as it does in pnpm 11. It is skipped under--ignore-scripts,--lockfile-onlyand--dry-run, bypnpm fetchandpnpm rebuild, and by a repeat install that is already up to date. Workspaces that use the hook to prepare state the install depends on — such as next.js, which generates a placeholdernextbin with it — were left with dependents linked against files that were never created #13313.Prevented
pnpm dedupe --checkfrom removing an incompatiblenode_modulesdirectory.pnpm update --workspaceno longer links dependencies the user never named:updateConfig.ignoreDependenciesconfigured no longer fails withERR_PNPM_WORKSPACE_PACKAGE_NOT_FOUNDfor a dependency that is only published to the registry. Such dependencies keep their specifiers, as they already did when no dependencies were ignored.Platinum Sponsors
Gold Sponsors
v11.17.0: pnpm 11.17Compare Source
Minor Changes
Added a new setting,
update.githubActionsServer, for specifying the base URL of the GitHub server that hosts the repositories of the GitHub Actions referenced by the workflow files (for example, a GitHub Enterprise Server). When the setting is not defined, the URL is read from theGITHUB_SERVER_URLenvironment variable, falling back tohttps://github.com. The URL must use thehttps://orhttp://protocol #13220.pnpm outdatedandpnpm updateno longer fail when the refs of a GitHub Action's repository cannot be read (for example, when the action's repository is private or hosted on a different GitHub server). Such actions are now skipped with a warning.Setting
update.githubActionstofalsenow makespnpm outdatedand the interactivepnpm updateskip GitHub Actions dependencies.Patch Changes
The token poll for web-based authentication no longer reads the body of non-OK or still-pending (HTTP 202) responses, and caps the token response body it does read at 64 KiB, so a malicious or compromised registry cannot exhaust memory through the poll pnpm/pnpm#12721.
Fixed
catalog:references in dependencies and overrides failing to resolve when installing through a pnpr server, which errored with "No catalog entry '' was found for catalog 'default'." even though the catalog entry existed. Also fixed a crash on Windows when installing a nested workspace member (e.g.packages/foo) through a pnpr server #13232.Republished every package: the tarballs published by the v11.13.1 through v11.16.0 releases were missing most of their compiled files due to a packing bug #13164.
Revert script ordering change for
pnpm run --sequential /regex/Support the
from-gitargument in thepnpm versioncommand.When the authentication URL cannot be rendered as a QR code (for example when it exceeds the maximum QR data capacity), web-based login now displays the URL alone with a warning instead of aborting authentication pnpm/pnpm#12721.
Platinum Sponsors
Gold Sponsors
v11.16.0: pnpm 11.16Compare Source
Minor Changes
The first release of a package now publishes the version written in its manifest verbatim, instead of bumping off it.
pnpm version -randpnpm change statuscheck the registry for each release's current version; when that version is not yet published, the package debuts at it and its pending changesets apply only from the next release. A newly added package seeded at1100.0.0with aminorchangeset is therefore published as1100.0.0rather than skipping straight to1100.1.0.Added a
--changesetflag topnpm update. Setupdate.changesettotrueinpnpm-workspace.yamlto enable this behavior by default, and use--no-changesetto override the setting for one update. After the update completes, pnpm writes a.changeset/pnpm-update-<suffix>.mdfile declaring a patch bump for every workspace package whosedependenciesoroptionalDependencieswere changed by the update and a major bump whenpeerDependencieschanged, including packages that consume an updated catalog entry via thecatalog:protocol. Private packages, packages without a name, and packages listed in theignorearray of.changeset/config.jsonare skipped. If.changeset/config.jsondoes not exist, a warning is printed and no changeset is generated.Added GitHub Actions dependencies to
pnpm outdatedand interactivepnpm update. Non-interactive updates can include them with--include-github-actionsor by settingupdate.githubActionstotrueinpnpm-workspace.yaml. Updated actions are pinned to exact commit hashes with their release tags preserved in comments.Added
updateandauditsettings sections topnpm-workspace.yaml, superseding the awkwardly namedupdateConfig,auditConfig, and top-levelauditLevelsettings:update.ignoreDepslists dependency name patterns thatpnpm updateandpnpm outdatedshould skip.audit.levelandaudit.ignoretunepnpm audit.The deprecated
updateConfig,auditConfig, andauditLevelsettings keep working until the next major version. When both a new section value and its deprecated counterpart are set, the new section takes precedence and a warning is printed. Both the TypeScript CLI and the Rust config surface (pacquet) recognize the new sections.Patch Changes
pnpm add --save-exact/--save-prefixandpnpm updatewriting a package's version with thepeerDependenciesrange's prefix (e.g.^19.2.7instead of the requested19.2.7) whenever the same package also appeared inpeerDependencies. A realdependencies/devDependencies/optionalDependenciesentry now takes precedence over a same-namedpeerDependenciesentry when computing the current specifiers #13108.Platinum Sponsors
Gold Sponsors
v11.15.1Compare Source
v11.15.0: pnpm 11.15Compare Source
Minor Changes
peerDependenciesMeta(for exampledebug'ssupports-colorpeer) are now resolved from a satisfying version already present in the dependency graph, the same way explicitly declared optional peer dependencies are. Previously such peers were only resolved this way when the package's metadata was read back from the lockfile, so an unrelated dependency change could rewrite peer resolutions across the whole lockfile.Patch Changes
Updated
adm-zipto prevent crafted ZIP archives from causing excessive memory allocation.pnpm version -rno longer writes a versioning-ledger entry with no consumed intents as a bareintents:key, which the next run failed to read withERR_PNPM_INVALID_VERSIONING_LEDGER. Empty intent lists are now written asintents: [], and the ledger reader accepts the bare form left by earlier releases.Fixed pnpr workspace resolution to preserve project names and versions for
workspace:dependencies.Platinum Sponsors
Gold Sponsors
v11.14.0: pnpm 11.14Compare Source
Minor Changes
peerDependenciesnow accept dependency specifiers that carry a scheme — a named-registry spec (<registry>:<version>), annpm:alias, or afile:/git/URL spec — instead of rejecting them withERR_PNPM_INVALID_PEER_DEPENDENCY_SPECIFICATION#13095. Such a peer is matched against the semver range carried by the specifier (work:5.x.xis checked as5.x.x,npm:bar@^5as^5), or against*when it carries no version, while the original specifier still selects the package to auto-install. Barename@versionvalues, which are almost always a mistake, are still rejected.Added
pnpm doctor, which diagnoses the pnpm installation and the environment it runs in: the versions and install method, whether the global bin directory is onPATH, whether the store and cache are writable, which link strategies (reflink, hardlink, symlink) the store's filesystem supports, registry connectivity, and an offlinefile:install that exercises the resolve/store/link path end to end. Each check reports how to fix what it finds, and the command exits non-zero when any check fails.Use
--offlineto skip the checks that need network access,--jsonfor machine-readable output, and--benchmarkto time the filesystem and install checks.Added support for executing multiple scripts matching a RegExp passed to
pnpm run(e.g.,pnpm run "/^build:.*/"), running matched scripts in deterministic lexicographical order. Restored the--sequential(-s) CLI option forpnpm run, which forcesworkspaceConcurrencyto 1 so that matched scripts run sequentially one by one across and within packages.Patch Changes
Fixed
pnpm installfailing withERR_PNPM_LOCKFILE_IS_SYMLINKwhenpnpm-lock.yamlis a symlink, as build sandboxes such as Bazel and Nix stage it #13073. Reading a lockfile through a symlink is allowed again, and an install that leaves the lockfile unchanged no longer rewrites it, so--frozen-lockfileno longer needs to write at all. Writing a changed lockfile through a symlink is still refused, as that would redirect the write onto the symlink's target.Fixed frozen installs incorrectly treating equivalent Git dependency specifiers as a stale lockfile. See #13039.
pnpm owner lsnow reports authentication and authorization failures (401/403) as dedicated errors that include the registry's response body, matchingpnpm owner add/rm, instead of a genericFailed to fetch ownersmessage.Recover from a metadata cache entry that disappears (concurrent cache cleanup, antivirus) after the registry has already answered the conditional request with
304 Not Modified. The metadata is re-requested once without cache validators instead of failing the install withERR_PNPM_CACHE_MISSING_AFTER_304.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.pnpm self-updatealready refused these releases; the version switch does too.Prevent broken-lockfile errors from including snippets of the lockfile's contents.
pnpm self-updatenow checks that the version it installed can run before making it the active pnpm. A release that installs but cannot execute is discarded with an error instead of replacing a working installation.Fixed an out-of-memory regression when workspace projects concurrently resolve a package with large registry metadata pnpm/pnpm#13077.
Fixed
pnpm updaterewriting exact version pins that use the=operator (for example=3.5.1) to a caret range (^3.5.1). Exact pins are now preserved and written back as the bare version. See #12745.Platinum Sponsors
Gold Sponsors