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
Added interactive group selection to pnpm update --global --interactive.
Running pnpm setup, pnpm self-update, or a command that modifies the global installation (such as pnpm add --global) through sudo now prints a warning. pnpm keeps global packages and configuration in the invoking user's home directory, so running these commands as root silently operates on the root user's home directory instead of yours. They will fail with ERR_PNPM_SUDO_NOT_SUPPORTED in pnpm v12. Read-only global commands (such as pnpm bin --global) are unaffected.
Patch Changes
Fixed pnpm failing to start under asynchronous Node.js module loaders when no .pnpmfile.mjs exists pnpm/pnpm#11701.
Fixed minimumReleaseAge fallback for custom dist-tags so the selected version does not exceed the registry’s original tag target.
Removing a dependency from package.json and reinstalling no longer re-resolves the dependency graph. The importer's entry is dropped from pnpm-lock.yaml, anything it made unreachable is pruned, and a catalog entry that loses its last referent is removed — all without registry access. Installs still fall back to a full resolution when a package that stays resolves a peer dependency through the removed one, since that would change the surviving package's entry rather than only prune.
Changing a catalog entry to a different exact version no longer re-resolves the dependency graph. The package is replaced in pnpm-lock.yaml directly, reusing the same check the pnpm.overrides fast path applies: every locked dependency of the package must still satisfy the new version's manifest. Installs fall back to a full resolution when anything other than the catalog reaches the package — an importer that depends on it directly, or another package that depends on it — since the graph would then need both versions.
Fixed a CI regression where github:owner/repo dependencies (and other shorthand Git specifiers) would fail to install with Permission denied (publickey) on CI runners that lack SSH keys. The Git resolver no longer records an SSH URL unless the user explicitly wrote one (e.g. git+ssh:// or git@host:...):
The repository visibility probe (an HTTP HEAD request) now retries transient failures such as 429 Too Many Requests, so host throttling of CI runners is no longer mistaken for a private repository.
For non-SSH specifiers, anonymous HTTPS git ls-remote access is now tried before SSH, so a public repository whose visibility probe fails still resolves to a portable HTTPS URL instead of an SSH URL that only works where SSH keys are configured.
When every probe fails, the resolver falls back to HTTPS for shorthand and HTTPS-style specifiers, and only guesses SSH when the user explicitly provided an SSH URL.
A repository that could not be confirmed public is no longer resolved to the host's anonymous archive URL (e.g. codeload.github.com, which would fail to download for a private repository); it stays a regular git resolution so installs can use ambient Git credentials such as credential helpers and tokens.
Note that a private repository that is reachable both over authenticated HTTPS and over SSH now resolves to its HTTPS URL, where previous versions recorded the SSH URL.
ng build and nuxt build now work under the global virtual store: pnpm's built-in compatibility extensions add the tslib dependency that @angular/build uses without declaring and the unplugin dependency that @nuxt/vite-builder v4 uses without declaring.
Fixed link: dependencies under enableGlobalVirtualStore so linked children are materialized and slots remain isolated by their resolved link targets.
An install that skips resolution because pnpm-lock.yaml is already up to date now reacts fully to packages the lockfile removed — for example after pulling a lockfile in which a dependency was deleted. The hoist layer is recomputed, so a package that became hoistable when a direct dependency was removed is hoisted, and pendingBuilds entries for removed packages are dropped instead of staying pending forever.
The held-back-update warning printed by pnpm update no longer fires when minimumReleaseAge is the actual reason a newer version was not picked. The warning's baseline now applies the same maturity cutoff as the pick itself, so it no longer wrongly attributes the hold-back to "your manifests and already installed dependencies" or recommends an override that would defeat the age gate. See #13071.
Checking whether ignoredOptionalDependencies is up to date no longer reorders the configured patterns. The check sorted them in place, which could move an ! exclusion ahead of the pattern it excludes from and flip which optional dependencies were ignored.
Changing autoInstallPeers, dedupePeers, peersSuffixMaxLength, excludeLinksFromLockfile, or injectWorkspacePackages no longer re-resolves the dependency graph when the lockfile proves the setting cannot affect it: no package or project declares a peer dependency for the peer settings, and no project depends on a directory or on another workspace project for the link and injection settings. The new setting is recorded in pnpm-lock.yaml and the install proceeds from the existing resolution. Every other case still falls back to a full resolution.
Adding, editing, or removing an entry in patchedDependencies no longer re-resolves the dependency graph. Resolution never reads a patch — it only records the patch file's hash against the package it matches — so the install now rewrites the affected entries in pnpm-lock.yaml and materializes the patched package from the store instead. Installs still fall back to a full resolution when the patched package is reachable as a peer dependency, and when the new configuration would leave a patch unused while allowUnusedPatches is off, so ERR_PNPM_UNUSED_PATCH is still reported.
Resolving a private git repository no longer blocks on an interactive credential prompt: git ls-remote now fails fast with an authentication error when git has no credentials for the repository #13522.
Lockfile verification now honors offline mode by using cached registry metadata instead of reaching the registry. When the required metadata is not available locally, verification reports the same ERR_PNPM_NO_OFFLINE_META condition used by offline resolution.
POSIX shell shims now follow symbolic links before computing basedir, preventing execution failures when a shim is invoked via an external symlink on PATH#13405.
The automatic packageManager version switch works again on registries whose tarball URLs point at a different host than the registry itself (load-balanced feed proxies, Artifactory-style mirrors). Package-manager entries are now always recorded with integrity-only resolutions — the download URL is derived from the trusted bootstrap registry instead — and entries persisted in an invalid shape by an earlier pnpm are discarded and re-resolved instead of failing every command #13619.
Registries that serve no npm signature metadata (private mirrors and feed proxies commonly strip dist.signatures) no longer break the automatic packageManager version switch and pnpm self-update#13147. When the configured registry cannot provide a verifiable signature, pnpm now fetches the signature from registry.npmjs.org and verifies it against the same embedded npm keys over the installed integrity — which proves exactly the same thing. If no signature can be obtained from either source (for example, both are unreachable, or the registry publishes only a shasum), pnpm proceeds with a warning instead of failing, but only when the packages resolve through a registry configured in the user's own (non-project) configuration; the download stays pinned by the lockfile integrity, and a signature that exists but does not validate still fails the switch.
pnpm fetch, and any install run with virtualStoreOnly, no longer writes a .pnp.cjs loader under nodeLinker: pnp. These installs populate the virtual store without linking the project, so the loader would have claimed the project resolves out of a store it was never linked into. The importer links and node_modules/.package-map.json were already skipped; the PnP loader now follows the same rule.
Prevent pnpm from removing project files when modulesDir resolves to the project root.
Speed up installs after adding ignoredOptionalDependencies patterns by removing newly ignored optional dependencies and pruning packages that are no longer reachable without resolving the dependency graph again.
When a failed install re-copies a bin script from the store, rerunning pnpm install now reapplies the executable bit to the bin instead of leaving it non-executable #12742.
pnpm root -g and pnpm bin -g now print warnings to stderr instead of stdout, so their stdout stays a clean, machine-readable path. Previously, running either command with --global in a project that pins a package manager (e.g. via the packageManager field) printed a warning like [WARN] Using --global skips the package manager check for this project ahead of the path, breaking programs that capture the output as a path #13672.
In pnpm 12, pnpm root -g and pnpm prefix -g are now supported (they previously failed with ERR_PNPM_CLI_ROOT_GLOBAL_UNSUPPORTED / ERR_PNPM_CLI_PREFIX_GLOBAL_UNSUPPORTED), and the reporter output of dlx, create, config, sbom, with, store, prefix, root, and bin goes to stderr, matching pnpm 11.
pnpm setup no longer makes Node.js print a MODULE_TYPELESS_PACKAGE_JSON warning about dist/worker.js on every command. The package.json it writes next to a standalone executable now declares "type": "module".
pnpm update without saving no longer records a version that the manifest's range excludes. The kept range stays authoritative: a requested version outside it is skipped with a warning, and a requested range, a dist tag, or --latest resolves within it instead of past it. Previously each of these could write a lockfile entry that contradicted its own specifier, which the next pnpm install --frozen-lockfile rejected with ERR_PNPM_OUTDATED_LOCKFILE#12764.
pnpm version -r --json now outputs [] instead of human-readable text when no pending changes exist pnpm/pnpm#13217.
Security fix. Affects projects using namedRegistries on pnpm 11.1.0–11.19.x. It is semi-breaking for those projects — see "If you use named registries" below.
The lockfile recorded no marker for which registry a package came from. Packages were keyed by name@version alone, and entry lookup went through refToRelative(ref, name), so a dependency you declared against one registry could be satisfied by an entry that was actually resolved from another. When two registries served the same name and version, both collapsed onto a single packages: entry and whichever resolved first decided the tarball every consumer got.
That is a package-substitution risk: a package you expect from your private registry could be installed from a different registry that publishes the same name and version, and the lockfile recorded nothing that would let you tell.
Packages resolved from a named registry are now recorded under registry-qualified keys (<name>@<registryName>:<version>, e.g. foo@work:1.0.0), so each registry gets its own entry and the lockfile pins which one a dependency came from.
The lockfile format version is unchanged. Registry-qualified keys appear only for packages resolved from a named registry, so a project that does not use namedRegistries sees no difference, and older pnpm versions keep reading the file.
If you use named registries
Your next non-frozen install re-keys those entries, which shows up as a lockfile diff. Commit it — that diff is the fix being applied. Review it: an entry that moves to a registry you did not expect is worth investigating.
Everyone working on the project should be on this version or newer before you do. An older pnpm reads the re-keyed lockfile fine — frozen installs are unaffected — but it does not produce registry-qualified keys itself, so any install that updates the lockfile writes those entries back to the old shape, and the next install on a current pnpm re-qualifies them. The result is a lockfile that flips back and forth, and while it is in the old shape the project is exposed again. Because the lockfile format version is deliberately unchanged, pnpm cannot detect this and warn you about it.
There is no setting to keep the old behavior: the old shape is the vulnerability.
Tarball URLs that follow the standard registry layout are no longer written to the lockfile for named-registry packages; they are recomputed from the namedRegistries setting on demand.
To use named registries, map your aliases in pnpm-workspace.yaml:
npmjs: now resolves to https://registry.npmjs.org/ with no configuration, alongside the existing gh: alias for GitHub Packages. It pins a dependency to the public registry even when registry points elsewhere, such as an internal proxy:
Built-in registry URLs are also the prefixes a lockfile's recorded tarball URL is matched against when pnpm verifies a package. Without the override, an entry whose tarball URL is on registry.npmjs.org is verified against the public registry rather than your mirror. This only affects lockfiles that record such URLs — a canonical URL for your configured registry is omitted from the lockfile and unaffected — and only when a tarball-URL, minimumReleaseAge, or trustPolicy check runs. Overriding the alias is the same escape hatch GHES users already have for gh.
Every alias the lockfile references must stay in namedRegistries: reading an entry whose alias is gone fails with ERR_PNPM_MISSING_NAMED_REGISTRY rather than silently falling back to the default registry, since that would fetch a different package. Renaming an alias re-resolves the packages that used it.
Named registry aliases that shadow a reserved dependency specifier prefix (file, link, workspace, runtime, npm, jsr, ...) are now rejected with ERR_PNPM_RESERVED_NAMED_REGISTRY_NAME instead of being silently shadowed by the corresponding resolver.
pnpm licenses and pnpm sbom now keep the two artifacts apart as well: license records carry the registry alias, and SBOM components carry the purl repository_url qualifier.
Patch Changes
An empty http-proxy, https-proxy, proxy, or no-proxy value — from the .npmrc, pnpm-workspace.yaml, the CLI, or the HTTP_PROXY / HTTPS_PROXY / PROXY / NO_PROXY environment variables — no longer fails the install with ERR_PNPM_INVALID_PROXY. Empty settings read as unset, so a shell exporting HTTP_PROXY= disables the proxy, and an empty proxy= in the .npmrc no longer suppresses HTTPS_PROXY#13533.
proxy=false in the .npmrc or proxy: false in pnpm-workspace.yaml now turns proxying off instead of being read as a proxy host named false. false and null on https-proxy / http-proxy / no-proxy read as unset, and on the command line they are ordinary host names, since a flag carries its value verbatim.
The env lockfile no longer pins @pnpm/exe alongside pnpm when the wanted pnpm version is 12 or newer. From v12 the unscoped pnpm package is itself the native executable, so @pnpm/exe is not published for it and resolving it would fail. The engine identity check now verifies the native binary through whichever package ships it.
lexCompare and nerfDart are now published as @pnpm/text.ordinal-comparator and @pnpm/config.registry-auth-key. Use these instead of @pnpm/util.lex-comparator and @pnpm/config.nerf-dart.
Fixed the order in which pnpm matches a lockfile's recorded tarball URL against known registry URLs. Two registry URLs of equal length were previously ordered arbitrarily, so which one a tarball URL matched could differ between runs.
Dependency resolution is faster: package metadata is now filtered once per packument instead of once per dependency edge when minimumReleaseAge is active, and parsed semver versions and ranges are reused instead of re-parsed on every comparison.
Security: pnpm rebuild now refuses a lockfile whose packages key carries a path traversal in the package name (e.g. ../../../escaped@1.0.0), instead of running that package's lifecycle scripts and linking its bins in a directory outside the virtual store. Such a name is rejected with ERR_PNPM_INVALID_DEPENDENCY_NAME.
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.
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
This PR includes no changesets
When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types
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.20.0+sha256.47a3352808501b8d1ef20112273b6a5dcfa53d28a55bcce36d268e878bd6bfe9→11.21.0Release Notes
pnpm/pnpm (pnpm)
v11.21.0: pnpm 11.21Compare Source
Minor Changes
Added interactive group selection to
pnpm update --global --interactive.Running
pnpm setup,pnpm self-update, or a command that modifies the global installation (such aspnpm add --global) throughsudonow prints a warning. pnpm keeps global packages and configuration in the invoking user's home directory, so running these commands as root silently operates on the root user's home directory instead of yours. They will fail withERR_PNPM_SUDO_NOT_SUPPORTEDin pnpm v12. Read-only global commands (such aspnpm bin --global) are unaffected.Patch Changes
Fixed pnpm failing to start under asynchronous Node.js module loaders when no
.pnpmfile.mjsexists pnpm/pnpm#11701.Fixed
minimumReleaseAgefallback for custom dist-tags so the selected version does not exceed the registry’s original tag target.Removing a dependency from
package.jsonand reinstalling no longer re-resolves the dependency graph. The importer's entry is dropped frompnpm-lock.yaml, anything it made unreachable is pruned, and a catalog entry that loses its last referent is removed — all without registry access. Installs still fall back to a full resolution when a package that stays resolves a peer dependency through the removed one, since that would change the surviving package's entry rather than only prune.Changing a catalog entry to a different exact version no longer re-resolves the dependency graph. The package is replaced in
pnpm-lock.yamldirectly, reusing the same check thepnpm.overridesfast path applies: every locked dependency of the package must still satisfy the new version's manifest. Installs fall back to a full resolution when anything other than the catalog reaches the package — an importer that depends on it directly, or another package that depends on it — since the graph would then need both versions.Fixed a CI regression where
github:owner/repodependencies (and other shorthand Git specifiers) would fail to install withPermission denied (publickey)on CI runners that lack SSH keys. The Git resolver no longer records an SSH URL unless the user explicitly wrote one (e.g.git+ssh://orgit@host:...):429 Too Many Requests, so host throttling of CI runners is no longer mistaken for a private repository.git ls-remoteaccess is now tried before SSH, so a public repository whose visibility probe fails still resolves to a portable HTTPS URL instead of an SSH URL that only works where SSH keys are configured.codeload.github.com, which would fail to download for a private repository); it stays a regulargitresolution so installs can use ambient Git credentials such as credential helpers and tokens.Note that a private repository that is reachable both over authenticated HTTPS and over SSH now resolves to its HTTPS URL, where previous versions recorded the SSH URL.
Fixes pnpm/pnpm#13276.
ng buildandnuxt buildnow work under the global virtual store: pnpm's built-in compatibility extensions add thetslibdependency that@angular/builduses without declaring and theunplugindependency that@nuxt/vite-builderv4 uses without declaring.Fixed
link:dependencies underenableGlobalVirtualStoreso linked children are materialized and slots remain isolated by their resolved link targets.An install that skips resolution because
pnpm-lock.yamlis already up to date now reacts fully to packages the lockfile removed — for example after pulling a lockfile in which a dependency was deleted. The hoist layer is recomputed, so a package that became hoistable when a direct dependency was removed is hoisted, andpendingBuildsentries for removed packages are dropped instead of staying pending forever.The held-back-update warning printed by
pnpm updateno longer fires whenminimumReleaseAgeis the actual reason a newer version was not picked. The warning's baseline now applies the same maturity cutoff as the pick itself, so it no longer wrongly attributes the hold-back to "your manifests and already installed dependencies" or recommends an override that would defeat the age gate. See #13071.Checking whether
ignoredOptionalDependenciesis up to date no longer reorders the configured patterns. The check sorted them in place, which could move an!exclusion ahead of the pattern it excludes from and flip which optional dependencies were ignored.Changing
autoInstallPeers,dedupePeers,peersSuffixMaxLength,excludeLinksFromLockfile, orinjectWorkspacePackagesno longer re-resolves the dependency graph when the lockfile proves the setting cannot affect it: no package or project declares a peer dependency for the peer settings, and no project depends on a directory or on another workspace project for the link and injection settings. The new setting is recorded inpnpm-lock.yamland the install proceeds from the existing resolution. Every other case still falls back to a full resolution.Adding, editing, or removing an entry in
patchedDependenciesno longer re-resolves the dependency graph. Resolution never reads a patch — it only records the patch file's hash against the package it matches — so the install now rewrites the affected entries inpnpm-lock.yamland materializes the patched package from the store instead. Installs still fall back to a full resolution when the patched package is reachable as a peer dependency, and when the new configuration would leave a patch unused whileallowUnusedPatchesis off, soERR_PNPM_UNUSED_PATCHis still reported.Resolving a private git repository no longer blocks on an interactive credential prompt:
git ls-remotenow fails fast with an authentication error when git has no credentials for the repository #13522.Lockfile verification now honors offline mode by using cached registry metadata instead of reaching the registry. When the required metadata is not available locally, verification reports the same
ERR_PNPM_NO_OFFLINE_METAcondition used by offline resolution.POSIX shell shims now follow symbolic links before computing
basedir, preventing execution failures when a shim is invoked via an external symlink onPATH#13405.The automatic
packageManagerversion switch works again on registries whose tarball URLs point at a different host than the registry itself (load-balanced feed proxies, Artifactory-style mirrors). Package-manager entries are now always recorded with integrity-only resolutions — the download URL is derived from the trusted bootstrap registry instead — and entries persisted in an invalid shape by an earlier pnpm are discarded and re-resolved instead of failing every command #13619.Registries that serve no npm signature metadata (private mirrors and feed proxies commonly strip
dist.signatures) no longer break the automaticpackageManagerversion switch andpnpm self-update#13147. When the configured registry cannot provide a verifiable signature, pnpm now fetches the signature fromregistry.npmjs.organd verifies it against the same embedded npm keys over the installed integrity — which proves exactly the same thing. If no signature can be obtained from either source (for example, both are unreachable, or the registry publishes only ashasum), pnpm proceeds with a warning instead of failing, but only when the packages resolve through a registry configured in the user's own (non-project) configuration; the download stays pinned by the lockfile integrity, and a signature that exists but does not validate still fails the switch.pnpm fetch, and any install run withvirtualStoreOnly, no longer writes a.pnp.cjsloader undernodeLinker: pnp. These installs populate the virtual store without linking the project, so the loader would have claimed the project resolves out of a store it was never linked into. The importer links andnode_modules/.package-map.jsonwere already skipped; the PnP loader now follows the same rule.Prevent pnpm from removing project files when
modulesDirresolves to the project root.Speed up installs after adding
ignoredOptionalDependenciespatterns by removing newly ignored optional dependencies and pruning packages that are no longer reachable without resolving the dependency graph again.When a failed install re-copies a bin script from the store, rerunning
pnpm installnow reapplies the executable bit to the bin instead of leaving it non-executable #12742.pnpm root -gandpnpm bin -gnow print warnings to stderr instead of stdout, so their stdout stays a clean, machine-readable path. Previously, running either command with--globalin a project that pins a package manager (e.g. via thepackageManagerfield) printed a warning like[WARN] Using --global skips the package manager check for this projectahead of the path, breaking programs that capture the output as a path #13672.In pnpm 12,
pnpm root -gandpnpm prefix -gare now supported (they previously failed withERR_PNPM_CLI_ROOT_GLOBAL_UNSUPPORTED/ERR_PNPM_CLI_PREFIX_GLOBAL_UNSUPPORTED), and the reporter output ofdlx,create,config,sbom,with,store,prefix,root, andbingoes to stderr, matching pnpm 11.pnpm setupno longer makes Node.js print aMODULE_TYPELESS_PACKAGE_JSONwarning aboutdist/worker.json every command. Thepackage.jsonit writes next to a standalone executable now declares"type": "module".pnpm updatewithout saving no longer records a version that the manifest's range excludes. The kept range stays authoritative: a requested version outside it is skipped with a warning, and a requested range, a dist tag, or--latestresolves within it instead of past it. Previously each of these could write a lockfile entry that contradicted its own specifier, which the nextpnpm install --frozen-lockfilerejected withERR_PNPM_OUTDATED_LOCKFILE#12764.pnpm version -r --jsonnow outputs[]instead of human-readable text when no pending changes existpnpm/pnpm#13217.Platinum Sponsors
Gold Sponsors
v11.20.0: pnpm 11.20Compare Source
Minor Changes
Security fix. Affects projects using
namedRegistrieson pnpm 11.1.0–11.19.x. It is semi-breaking for those projects — see "If you use named registries" below.The lockfile recorded no marker for which registry a package came from. Packages were keyed by
name@versionalone, and entry lookup went throughrefToRelative(ref, name), so a dependency you declared against one registry could be satisfied by an entry that was actually resolved from another. When two registries served the same name and version, both collapsed onto a singlepackages:entry and whichever resolved first decided the tarball every consumer got.That is a package-substitution risk: a package you expect from your private registry could be installed from a different registry that publishes the same name and version, and the lockfile recorded nothing that would let you tell.
Packages resolved from a named registry are now recorded under registry-qualified keys (
<name>@<registryName>:<version>, e.g.foo@work:1.0.0), so each registry gets its own entry and the lockfile pins which one a dependency came from.The lockfile format version is unchanged. Registry-qualified keys appear only for packages resolved from a named registry, so a project that does not use
namedRegistriessees no difference, and older pnpm versions keep reading the file.If you use named registries
Your next non-frozen install re-keys those entries, which shows up as a lockfile diff. Commit it — that diff is the fix being applied. Review it: an entry that moves to a registry you did not expect is worth investigating.
Everyone working on the project should be on this version or newer before you do. An older pnpm reads the re-keyed lockfile fine — frozen installs are unaffected — but it does not produce registry-qualified keys itself, so any install that updates the lockfile writes those entries back to the old shape, and the next install on a current pnpm re-qualifies them. The result is a lockfile that flips back and forth, and while it is in the old shape the project is exposed again. Because the lockfile format version is deliberately unchanged, pnpm cannot detect this and warn you about it.
There is no setting to keep the old behavior: the old shape is the vulnerability.
Tarball URLs that follow the standard registry layout are no longer written to the lockfile for named-registry packages; they are recomputed from the
namedRegistriessetting on demand.To use named registries, map your aliases in
pnpm-workspace.yaml:New built-in
npmjs:aliasnpmjs:now resolves tohttps://registry.npmjs.org/with no configuration, alongside the existinggh:alias for GitHub Packages. It pins a dependency to the public registry even whenregistrypoints elsewhere, such as an internal proxy:{ "dependencies": { "left-pad": "npmjs:^1.3.0" } }npm:cannot do this — it is the alias protocol (npm:<name>@<range>) and resolves through whateverregistrypoints at.If you mirror or proxy npmjs, point the alias at your mirror:
Built-in registry URLs are also the prefixes a lockfile's recorded tarball URL is matched against when pnpm verifies a package. Without the override, an entry whose tarball URL is on
registry.npmjs.orgis verified against the public registry rather than your mirror. This only affects lockfiles that record such URLs — a canonical URL for your configured registry is omitted from the lockfile and unaffected — and only when a tarball-URL,minimumReleaseAge, ortrustPolicycheck runs. Overriding the alias is the same escape hatch GHES users already have forgh.Every alias the lockfile references must stay in
namedRegistries: reading an entry whose alias is gone fails withERR_PNPM_MISSING_NAMED_REGISTRYrather than silently falling back to the default registry, since that would fetch a different package. Renaming an alias re-resolves the packages that used it.Named registry aliases that shadow a reserved dependency specifier prefix (
file,link,workspace,runtime,npm,jsr, ...) are now rejected withERR_PNPM_RESERVED_NAMED_REGISTRY_NAMEinstead of being silently shadowed by the corresponding resolver.pnpm licensesandpnpm sbomnow keep the two artifacts apart as well: license records carry the registry alias, and SBOM components carry the purlrepository_urlqualifier.Patch Changes
An empty
http-proxy,https-proxy,proxy, orno-proxyvalue — from the.npmrc,pnpm-workspace.yaml, the CLI, or theHTTP_PROXY/HTTPS_PROXY/PROXY/NO_PROXYenvironment variables — no longer fails the install withERR_PNPM_INVALID_PROXY. Empty settings read as unset, so a shell exportingHTTP_PROXY=disables the proxy, and an emptyproxy=in the.npmrcno longer suppressesHTTPS_PROXY#13533.proxy=falsein the.npmrcorproxy: falseinpnpm-workspace.yamlnow turns proxying off instead of being read as a proxy host namedfalse.falseandnullonhttps-proxy/http-proxy/no-proxyread as unset, and on the command line they are ordinary host names, since a flag carries its value verbatim.The env lockfile no longer pins
@pnpm/exealongsidepnpmwhen the wanted pnpm version is 12 or newer. From v12 the unscopedpnpmpackage is itself the native executable, so@pnpm/exeis not published for it and resolving it would fail. The engine identity check now verifies the native binary through whichever package ships it.lexCompareandnerfDartare now published as@pnpm/text.ordinal-comparatorand@pnpm/config.registry-auth-key. Use these instead of@pnpm/util.lex-comparatorand@pnpm/config.nerf-dart.Fixed the order in which pnpm matches a lockfile's recorded tarball URL against known registry URLs. Two registry URLs of equal length were previously ordered arbitrarily, so which one a tarball URL matched could differ between runs.
Dependency resolution is faster: package metadata is now filtered once per packument instead of once per dependency edge when
minimumReleaseAgeis active, and parsed semver versions and ranges are reused instead of re-parsed on every comparison.Security:
pnpm rebuildnow refuses a lockfile whosepackageskey carries a path traversal in the package name (e.g.../../../escaped@1.0.0), instead of running that package's lifecycle scripts and linking its bins in a directory outside the virtual store. Such a name is rejected withERR_PNPM_INVALID_DEPENDENCY_NAME.Platinum Sponsors
Gold Sponsors
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