Skip to content

chore(deps): update dependency pnpm to v11.25.0 - #382

Open
renovate[bot] wants to merge 1 commit into
masterfrom
renovate/pnpm-11.x
Open

chore(deps): update dependency pnpm to v11.25.0#382
renovate[bot] wants to merge 1 commit into
masterfrom
renovate/pnpm-11.x

Conversation

@renovate

@renovate renovate Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
pnpm (source) 11.9.011.25.0 age confidence

Release Notes

pnpm/pnpm (pnpm)

v11.25.0: pnpm 11.25

Compare Source

Minor Changes
  • Added an opt-in proof of concept that lets installs reuse a dependency's build output across machines, by publishing and restoring signed, organization-scoped artifacts through pnpr instead of running the lifecycle scripts locally.

    Configure it with the new remoteSideEffectsCache setting. A workspace names the eligible organization and packages; everything describing the act of signing — publish, keyId, builderId, trustedKeys, privateKey and the provenance fields — is refused in pnpm-workspace.yaml and read from the global config file or the environment instead.

  • Added macOS and Windows x64 and arm64 support to remote shared build artifacts pnpm/pnpm#13771.

  • Added the audit.ignorePrune setting. When set to true, pnpm audit --fix removes ignored GHSA entries that no longer appear in the audit report.

  • Generalized the experimental shared-artifact protocol so candidates and signed payloads identify a discriminated subject. Dependency side effects use package and source-integrity subjects, while workspace tasks use project and task subjects.

    This changes shared-artifact request bodies and signed payloads. A pnpr server and its clients have to be on matching versions.

  • pnpm init now pins the latest pnpm version, instead of the version of pnpm that ran the command. A project scaffolded by an outdated pnpm therefore no longer inherits that staleness through its own devEngines.packageManager / packageManager pin #​7490.

    The version is read from the latest tag on the package-manager registries. When that lookup cannot answer — no network, an unreachable or slow registry, offline, or a latest that the minimumReleaseAge / trustPolicy settings reject — pnpm init pins the running version as before, and never fails or hangs on the lookup. A latest that is older than the running pnpm is never pinned either.

  • A scope set in a project's pnpm-workspace.yaml is now ignored, with a warning naming where to set it instead. pnpm login records the scope as a @scope:registry route in the machine-global auth.ini, which outranks ~/.npmrc in every project — so a repository-committed file could redirect a scope such as @acme for all of a user's other projects after one routine login. Use --scope, the PNPM_CONFIG_SCOPE environment variable, or the global config file instead #​13557.

  • Verified remote build artifacts are persisted in the shared store with their signed origin metadata. Later installs reverify the artifact against current trust, policy, platform, and source before reuse, while invalid remote variants are quarantined per channel (pnpm/pnpm#13771).

  • Persist completed recursive tasks so --resume-from skips exactly the work that passed during a matching interrupted or failed pnpm -r run / pnpm -r exec invocation. When no compatible state exists, pnpm retains its graph-based resume behavior.

  • Allowed pnpm update --patches to refresh registry revisions through a configured pnpr server while retaining locked package versions.

  • Added explicit registry revision selection with <version>+rN and pnpm update --patches for refreshing revision artifacts without changing package versions. Registry-backed lockfile policy checks recognize historical revisions, and pnpr now preserves safe revision histories from upstream registries.

  • Workspace install, rebuild, pack, publish, stage, and lifecycle work now starts as soon as its dependencies finish instead of waiting for an unrelated topological group.

  • pnpm stage approve now approves several staged packages at once. Run it without a stage id to pick from the staged versions interactively, or pass a list of stage ids. The whole batch is approved with a single one-time password, and pnpm asks for a new one only once the registry stops accepting it. Inside a workspace, the selected packages are approved in dependency order, and a package whose workspace dependency could not be approved is skipped instead of being published against a dependency that never reached the registry.

  • Added per-task concurrency limits to workspace task orchestration. Set tasks.<name>.concurrency in pnpm-workspace.yaml to limit how many instances of that task may run across workspace projects at once:

    tasks:
      build:
        concurrency: 2
  • Added support for registry replacement tarballs using standard integrity values, explicit revision fields, registry routing from the registries setting, non-redirecting integrity-addressed URLs, canonical safe-integer revision numbers, and pnpr proxying for immutable upstream revision artifacts.

  • sideEffectsCache now declares the whole of how a package's build output is reused — whether one is restored, whether one is saved, and the remote tier that shares it between machines:

    sideEffectsCache:
      read: true
      write: true
      remote:
        org: acme
        packages: ['native-addon']

    sideEffectsCache: true, sideEffectsCacheReadonly, remoteSideEffectsCache, and its organization field all keep working. Where a field is set under both spellings the one above wins; where it is set under only one, it is kept.

    Two behaviors change, both bringing this CLI in line with what the Rust one already did: sideEffectsCacheReadonly: true now blocks writing to the cache, and setting it alongside sideEffectsCache: false gives a read-only view rather than switching the cache off entirely. A cache can also be declared write-only now, to populate one the run does not read.

  • Workspace task orchestration (pnpm/rfcs#23). pnpm -r run and pnpm -r exec now schedule per task instead of in topological chunks: a task starts as soon as the tasks it depends on have finished, so a project no longer waits for unrelated projects that happen to share its chunk.

    A new tasks section in pnpm-workspace.yaml declares what a task depends on, using the ^ convention:

    tasks:
      build:
        dependsOn: ['^build']
      test:
        dependsOn: ['build']
      lint: {}

    ^name means the named task in each of the project's workspace dependencies; a bare name means the task in the same project; an entry with no dependsOn declares an empty dependency list. A task with no entry behaves as dependsOn: ['^<its own name>'], which is exactly what the previous chunked ordering implied — an unconfigured workspace gets the scheduler improvement and nothing else changes meaning. A project without the script is reported skipped and passes its edges through to its own dependencies, so a scriptless package does not sever a chain.

    Also part of this change:

    • A dependency cycle among the tasks of a run is now an error naming the participating tasks (ERR_PNPM_TASK_CYCLE) instead of silently running in an arbitrary order. Setting ignoreWorkspaceCycles: true downgrades the error to a warning: the cycle's tasks run in an arbitrary order relative to each other.
    • --resume-from now skips exactly the transitive dependencies of the anchor package; work unrelated to the anchor still runs.
    • Under --no-bail, tasks whose dependencies failed are reported as skipped, not failed, and do not add to the exit code.
    • With --bail (the default), the first failure still ends the run at once and nothing new is dispatched — including scripts already queued behind the concurrency limit.
    • pnpm -r run --dry-run <script> prints the task graph that would execute without running anything (including skipping the verifyDepsBeforeRun check); --json emits the tasks and their resolved dependency edges.
    • Output is inherited rather than piped only when at most one script can ever be in flight (--workspace-concurrency=1, or the graph forces the scripts to run one after another).
Patch Changes
  • An _auth entry in the global config file no longer decides which registry packages come from when something else says. A registry or registries declared in pnpm-workspace.yaml or the global config now wins over the route inferred from a stored credential, which still applies where nothing else declares one. The pnpm_config__auth environment variable is unchanged: it stays the way to point a CI runner at a mandated proxy, and still overrides what a repository declares.

  • Prevent installs through a symlinked node_modules directory from rewriting the target checkout pnpm/pnpm#14286.

  • Treat empty scripts selected by a regular expression as missing before running dependent tasks.

  • The options type of the fetch command now declares allowBuilds, a setting its handler already forwarded to the installer. Type-level only — what pnpm fetch does is unchanged.

  • Filter hidden scripts matched by a regular expression during recursive runs when a visible script also matches.

  • Fixed automatically switched pnpm versions forcing all descendant pnpm processes to use the same version pnpm/pnpm#14309.

  • Fixed ERR_PNPM_UNUSED_PATCH validation during incremental installs pnpm/pnpm#13692.

  • Fixed pnpm deploy --prod failing when an excluded dev dependency was also declared as an optional peer dependency pnpm/pnpm#14302.

  • pnpm update -g no longer downgrades a global package. --latest resolves the latest dist-tag, which can point at an older release than the one installed — after pnpm add -g <pkg>@next, for instance #​14270.

    pnpm update -g also no longer changes the pnpm version. pnpm's own global install belongs to pnpm self-update #​14270.

  • Copying a built package to its other hoisted locations no longer replaces the destination directory. With nodeLinker: hoisted, that replacement deleted the dependencies nested inside the destination's node_modules, and made concurrent copies of the same build chunk fail with ERR_PNPM_ENOENT: no such file or directory, rename '.../node_modules/_tmp_...' #​12880.

  • pnpm update no longer replaces the specifier a project declares for a dependency that is also listed in overrides. A catalog: reference stays a catalog: reference, and a declared range stays as written, instead of being rewritten to the version the override resolved to #​12115.

  • pnpm update no longer moves the range a project declares for a dependency that overrides also lists, even when the override repeats that range verbatim. Previously the updated package.json disagreed with the lockfile, so the next pnpm install --frozen-lockfile failed with a specifier mismatch #​14224.

  • Make pnpm add --lockfile-only skip dependency linking pnpm/pnpm#14286.

  • --production is accepted again as an alias of --prod on install, fetch, prune, update, list, why, and sbom, and the install that verifyDepsBeforeRun reproduces is now spelled with --prod. pnpm run no longer aborts with "unexpected argument '--production' found" after a production-only install #​14147.

  • The progress output no longer overwrites the lines above it once it grows taller than the terminal window #​14270.

  • Restoring a dependency's build from the remote side-effects cache no longer downloads files the store already holds.

  • Forward patchedDependencies hashes and packageExtensions to pnpr so server-side resolution preserves patches and package extensions in the lockfile and installed packages.

  • Published the workspace task graph and scheduler as @pnpm/workspace.task-scheduler so other workspace commands can use the same dependency-aware scheduling as recursive run and exec.

  • The environment variables for the remote side-effects cache are named for the setting they configure: PNPM_SIDE_EFFECTS_CACHE_REMOTE_KEY_ID, ..._BUILDER_ID, ..._IMAGE_DIGEST, ..._ARCHITECTURE_BASELINE, ..._PRIVATE_KEY, ..._BUILD_ENV, ..._TRUSTED_KEYS and ..._PUBLISH. The PNPM_REMOTE_SIDE_EFFECTS_CACHE_* names keep working, and the new one wins when both are set.

  • A devEngines.packageManager range pin on pnpm is now recorded in pnpm-lock.yaml's packageManagerDependencies when the running pnpm already satisfies it, using the running version and keeping the range as the recorded specifier. Previously only an exact pin — or a range resolved on the way through a version switch — reached the lockfile, so a range pin written by hand (or by any tool other than pnpm add / pnpm self-update) left the project without the shared resolution the pin exists to provide.

  • Fixed recursive run cleanup on Windows when a lifecycle script fails while another script's process tree is still running.

  • The update notification now suggests pnpm self-update when PNPM_HOME manages the pnpm in use, and the standalone install script otherwise — under Corepack, or when another package manager installed pnpm. pnpm self-update under Corepack names the standalone install script too.

  • Enforce allowBuilds when a prepared git dependency is reused from the shared store, and use the lockfile's canonical git resolution ID in approval suggestions.

  • Topologically sorting workspace projects now runs in linear time, fixing installs and lockfile updates that stalled for seconds on workspaces with thousands of projects forming deep dependency chains #​14149, #​14151.

Platinum Sponsors
Bit OpenAI Notion
Gold Sponsors
Sanity Discord Vite
SerpApi CodeRabbit Stackblitz
Workleap Nx Latitude

v11.24.0: pnpm 11.24

Compare Source

Minor Changes
Patch Changes
  • Fixed pnpm v11 incorrectly reporting confirmModulesPurge as unrecognized when set in pnpm-workspace.yaml. The Rust CLI now identifies the unsupported option as a pnpm v11 setting instead of suggesting an unrelated setting.

  • pnpm install --frozen-lockfile no longer fails with ERR_PNPM_FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE when the pinned pnpm version recorded in pnpm-lock.yaml has to be re-resolved before it can be installed. It runs the pnpm version the lockfile pins and leaves the lockfile unchanged #​14124.

  • Under nodeLinker: hoisted, peer-resolution variants of an injected directory dependency (a file: snapshot) are materialized as separate copies again instead of collapsing onto the first-seen variant. Each copy keeps its own peer-resolved dependency set, so a project pinning one peer version no longer resolves another project's variant — Bit root components with conflicting peers across injected copies rely on this.

  • Fixed pnpm install --merge-git-branch-lockfiles --frozen-lockfile failing with ERR_PNPM_OUTDATED_LOCKFILE when a branch lockfile predates the removal of a dependency, or its move to another dependency group #​13966. A dependency that no project declares anymore is no longer reinstated by the merge, and the packages it was the only path to are dropped with it.

  • Batch workspace publishing accepts a shared scope-specific credential, rejects mismatched credentials for a registry before publishing, and runs the publish and postpublish scripts after each completed registry group pnpm/pnpm#14101.

  • The Rust CLI now honors five settings it recognized but ignored: updateNotifier, legacyDirFiltering, initAuthorName / initAuthorEmail / initAuthorUrl, initLicense, and initVersion. pnpm install and pnpm add check once a day for a newer pnpm and print how to get it (turn it off with updateNotifier: false); a {<dir>} filter selector can go back to matching the subtree below the directory with legacyDirFiltering: true; and pnpm init writes the configured author, license, and version into the package.json it scaffolds. PNPM_CONFIG_INIT_VERSION is now read as well.

    maxsockets, npm's spelling of maxSockets, is no longer ignored: both spellings are read from pnpm-workspace.yaml, the global config file, the environment, and the command line, in that increasing order of precedence — a value passed on the command line now wins even when the two sides spelled the setting differently.

    A lastUpdateCheck timestamp dated in the future — after a clock change, a restored snapshot, or a hand-edited state file — no longer silences the update check until that time comes around.

    legacyDirFiltering no longer reaches the workspace-root selectors pnpm generates for itself: the !{<workspace-root>} exclusion a recursive run / exec / add / test appends, and the {<workspace-root>} inclusion --workspace-root appends. Read as subtree matches they named every project below the root, so a recursive command under the setting selected nothing at all, and --workspace-root pulled in every project below the root instead of the root alone #​14101.

  • pnpm install --frozen-lockfile no longer fails when pnpm-lock.yaml records the pinned pnpm version alongside an engine package the running pnpm does not install it from. An entry pinning another version is still refused, and a plain install rewrites the block #​14124.

v11.23.0: pnpm 11.23

Compare Source

Minor Changes

  • pnpm config get and pnpm config list now show the settings pnpm acts on under their documented names:

    • registries shows the registries pnpm resolves from, merged across every source (.npmrc, pnpm-workspace.yaml, the global config, CLI flags), in the shape the setting is written in: keyed by registry URL, with the default registry declared as the bare @ scope. Built-in routes are included — the @jsr scope and the npmjs and gh prefixes — unless pointed elsewhere. Previously pnpm config get registries printed undefined.
    • update and audit show the effective sections, whichever spelling set them. The deprecated internal spellings (updateConfig, auditConfig, auditLevel) are no longer listed.
    • catalogs shows the complete resolved catalog set — the singular catalog block is its default entry — whichever spelling declared it.
    • The registry and @scope:registry entries show the merged routes rather than raw .npmrc values, so they always agree with the registries view.
  • Settings that no supported pnpm version recognizes get their own warning. A key in the global config file that this version of pnpm does not read is no longer reported with advice to move it to a project-level pnpm-workspace.yaml (where it would be ignored too); the warning now says the setting is not recognized by this version of pnpm, names the pnpm version that does read it when there is one (for example, globalShims is a pnpm v12 setting), and suggests the closest real setting name when the key looks like a typo. Unrecognized and non-camelCase keys in a project's pnpm-workspace.yaml, previously ignored silently, are now reported the same way. pnpm config get <key> and pnpm get <key> no longer print config-load warnings, so a script capturing the value gets the value alone.

  • The importPackage pnpmfile hook is deprecated. pnpm now prints a warning when a pnpmfile defines it, and the hook will be removed in the next major version. It also opts the installation out of the parallel package importer, making installation slower. If you rely on this hook, comment on #​14101.

  • node_modules/.modules.yaml no longer records the registries an install resolved from, and the recorded copy is dropped from the file on the first install that rewrites it.

    It dated from the lockfile format that spelled a dependency's path relative to its registry, where reading an installed tree meant knowing the registries it was installed with. Dependency paths have not carried a registry for several major versions, and the recorded copy outlived its use: pnpm list, pnpm why, and single-project installs preferred it over the project's own configuration, so a project whose registry had changed since its last install was still read through the old one.

    They now use the configured registries, like every other command already did.

  • When enableGlobalVirtualStore is on, every process pnpm spawns for the project (pnpm run, pnpm exec, lifecycle scripts) now receives a NODE_PATH pointing at the project's hoisted node_modules, plus a NODE_OPTIONS --import flag that registers a resolve hook restoring NODE_PATH lookups for ESM imports. Dependencies that import undeclared ("phantom") packages keep resolving under the global virtual store — for both CommonJS and ESM — without installing the @pnpm/plugin-esm-node-path config dependency pnpm/pnpm#9618. Tools run by pnpm dlx resolve such dependencies too: the JS CLI passes them the same environment, while the Rust CLI's dlx cache is self-contained, so its layout already exposes them.

  • A registry can now declare that its abbreviated metadata carries the time field, so resolutionMode: time-based reads the full metadata document only from the registries that need it:

    resolutionMode: time-based
    registries:
      https://npm.internal.example/:
        supportsTimeField: true

    registry.npmjs.org omits time from abbreviated metadata, so a time-based resolution has to fall back to the much larger full document. That fallback used to be all-or-nothing: registrySupportsTimeField answered for every registry at once, so a project resolving from both the public registry and a Verdaccio instance either paid for full metadata everywhere or claimed a time field npmjs does not serve. The answer is now per registry, and registrySupportsTimeField remains the answer for every registry that does not declare one.

    The declaration is also sent to a pnpr server, which applies it to the resolution it runs on the client's behalf.

  • A pnpr resolve request now carries the client's registries the way the registries setting declares them — keyed by URL, with the scopes routed to each, the bare-specifier prefix each answers to, and each one's serverType — in place of the prefix map it used to send.

    The server routes them through the same inversion the config reader runs, so a pnpr-served install resolves a scoped dependency from the registry that scope is routed to, which it previously could not: only the default registry and the prefix-addressed ones reached the server. A declared serverType reaches it too, so the tarball URLs pnpr omits from the lockfile match the ones the client reconstructs.

    Built-in scope routes the project has not pointed elsewhere are not declared, so a pnpr server's allowlist is not asked about npm.jsr.io on requests that resolve no JSR package.

    A registry a request only declares is no longer refused up front for being off the server's allowlist — a client describes its whole configuration, including scopes a given resolve never reaches, so a stray @scope:registry in a developer's ~/.npmrc no longer fails every install against a pnpr server that does not serve it. The boundary moves to the fetch itself: an origin the resolve does reach is refused before the request leaves the server, with the same message.

    This changes the resolve and verify-lockfile request bodies. A pnpr server and its clients have to be on matching versions; the protocol is still experimental and unversioned.

  • The registries setting now declares a registry once, keyed by its URL, with everything about that registry in the entry: how it lays out tarball URLs, the scopes routed to it, and the bare-specifier prefix it answers to.

    registries:
      https://artifactory.example.com/artifactory/api/npm/npm-virtual/:
        serverType: artifactory
        scopes: ['@acme', '@acme-internal']
        prefix: work
    • serverType tells pnpm how the registry lays out its tarball URLs, which decides whether a URL can be omitted from pnpm-lock.yaml:
      • undeclared (the default) — strict. Only the exact canonical URL is treated as reconstructible.
      • npm — the registry behaves like registry.npmjs.org, which also serves a scoped package from its percent-encoded path. Declare this for a faithful mirror or caching proxy of the public registry so its tarball URLs can be omitted too.
      • artifactory — JFrog Artifactory repeats the scope in a scoped package's tarball filename (@acme/widget/-/@acme/widget-1.0.0.tgz) where the npm registry strips it (@acme/widget/-/widget-1.0.0.tgz). Declaring it lets pnpm rebuild that URL, so it is omitted from pnpm-lock.yaml instead of being written out for every scoped package pnpm/get-npm-tarball-url#16.
    • scopes lists the @-prefixed scopes that resolve from this registry. A bare '@' is the scope-less default registry, the one the registry setting names.
    • prefix is the alias a dependency addresses this registry by, as in "foo": "work:^1.0.0".

    The layout is never inferred from the registry URL, so nothing changes unless you declare it; registry.npmjs.org continues to behave as npm without being declared. Because the lockfile depends on serverType, it is read from pnpm-workspace.yaml only — a serverType in the global config.yaml is ignored, so one developer's machine cannot shape a lockfile their collaborators read back with a different layout. Credentials are rejected in this setting, in a key as well as in a field, and still belong in .npmrc. An entry that routes nothing to itself and matches no configured registry is reported as a warning rather than silently ignored.

Migrating

The older registries shape, a map of <scope>: <url> strings, still works and needs no change:

registries:
  '@acme': https://npm.acme.example/

namedRegistries is deprecated in favor of the prefix field, and is still read for prefixes registries does not declare.

toLockfileResolution and isCanonicalRegistryTarballUrl now take their registry and layout as an options object rather than positional arguments, so @pnpm/lockfile.utils and @pnpm/resolving.tarball-url get a major bump.

  • An install that had to re-hash store files to verify them now reports it. If that cost more than a second, it says how long — The integrity of N files was checked in 2.5s. — and if it was quick but covered more than a thousand files, it names the cause instead: their timestamps changed since the store recorded them, which a backup tool, an antivirus scan or a copied store can do.

  • Added virtualStoreType, which names where the virtual store lives — one store per machine, or one per project:

    virtualStoreType: global   # or: project

    It is the canonical spelling of enableGlobalVirtualStore, which keeps working. When a project sets both, virtualStoreType wins. It can also be set through PNPM_CONFIG_VIRTUAL_STORE_TYPE and read back with pnpm config get virtualStoreType. The default is unchanged — project, so the shared store stays opt-in.

    The setting is independent of nodeLinker. isolated and pnp both work with either store type, and hoisted writes no virtual store at all, so it is unaffected.

Patch Changes

  • pnpm add --allow-build now adds to the allowBuilds entries already in pnpm-workspace.yaml instead of replacing them #​13872.

  • Kept pending build approvals available after removing an unrelated dependency.

  • pnpm approve-builds now removes onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies from pnpm-workspace.yaml when it writes allowBuilds. Those settings were replaced by allowBuilds in pnpm 11 and silently ignored since, so a workspace migrated from pnpm 10 kept them around looking active.

  • pnpm audit no longer reports a patched version that was never published or is deprecated. The inferred patched range (e.g. >=4.17.24 from <=4.17.23) is now checked against the registry packument, and the report is corrected to the lowest non-deprecated published version that satisfies it (e.g. >=4.18.1 when 4.17.24 does not exist and 4.18.0 is deprecated). When no published version satisfies the range, the report shows Patched versions: None. This also prevents pnpm audit --fix from adding overrides or minimumReleaseAgeExclude entries for patches that do not exist #​13824.

    pnpm audit --fix and pnpm audit --fix update no longer add a minimumReleaseAgeExclude entry when the registry packument shows that the minimum patched version was never published. Previously such entries were written for versions that do not exist, which would have let a later publish of that version bypass the minimumReleaseAge gate #​11563.

    The --json output of pnpm audit now returns patched_versions: null for advisories whose inferred patch is not available (never published, skipped, yanked, or deprecated), making it easier for tooling to distinguish "no fix available" from "fix available at version X".

  • Fixed pnpm patch-commit in project and edit paths containing non-ASCII characters.

  • The package and bump pickers of pnpm change now size their page from the terminal height instead of always showing 7 rows. They fall back to 7 rows when the terminal height is unknown pnpm/pnpm#13815.

  • Canceling a pnpm change prompt with Ctrl-c no longer prints a stack trace. It reports Change canceled and exits with a success status, like the other interactive commands #​13814.

  • Re-fetch full registry metadata when minimumReleaseAge is enabled and an abbreviated packument's time map omits timestamps for some versions. This prevents mature versions from being filtered out and resolution from falling back to the lowest matching version pnpm/pnpm#13741.

  • A config dependency carrying an inline integrity (the <version>+<integrity> form, or the object form without a tarball) now takes its tarball URL from the registry's packument instead of deriving it from the registry URL, so migrating one costs an extra metadata request. On a registry that serves tarballs from a path pnpm cannot derive, GitLab's group endpoint for one, installing such a config dependency failed with a 404 while the same package installed fine as a regular dependency #​13765.

  • Fixed PNPM_CONFIG_NODE_VERSION being ignored when setting the Node.js version used for compatibility checks.

  • A custom fetcher can no longer replace the archive integrity that pnpm-lock.yaml pins: the locked value is restored after a canFetch or fetch hook rewrites the resolution, and delegating a locked archive to a directory or git source now fails instead of installing unverified content.

    The Rust CLI now also loads the pnpmfiles named by the pnpmfile setting (a single path or an ordered list), and hands custom fetchers native localTarball and remoteTarball callbacks — including on a fresh install that has to compute a missing tarball integrity, which is then reused by later offline installs. File maps a fetcher returns are accepted only when they match what those native callbacks extracted.

  • Fixed an issue where running pnpm dedupe --check in projects with nodeLinker: hoisted would cause dependencies to be moved out of node_modules into node_modules/.ignored.

  • pnpm deploy --prod and pnpm deploy --no-optional no longer list the excluded dependency groups in the deployed package.json and pnpm-lock.yaml. The deployed lockfile referenced packages that the deploy left out of its graph, so installing in the deploy directory afterwards created dangling symlinks #​13623.

  • Don't treat files like license16.json as a package license when deciding if the workspace LICENSE file should be included in the packed package.

  • pnpm exec --recursive --no-reporter-hide-prefix no longer prints a blank prefixed line after each chunk of a command's output, and no longer splits a line in two when it straddles a chunk boundary.

  • Fixed 404 errors when installing from a registry that serves scoped packages only from a percent-encoded path, such as GitHub Enterprise Server. Outside registry.npmjs.org, a tarball URL that encodes the scope separator as %2f or %2F is no longer mistaken for one that pnpm can rebuild from the package name, version, and registry, so it is kept in pnpm-lock.yaml and requested verbatim on the next install #​13534.

  • Fixed trustPolicyExclude and minimumReleaseAgeExclude being ignored when set to a single string instead of a list. The value was read one character at a time, so the exclusion never matched the package it named — and a * anywhere in it matched every package, silently switching the policy off.

  • pnpm init now pins the exact pnpm version instead of a ^ range, and records it in the packageManager field alongside devEngines.packageManager. Corepack reads only packageManager and accepts nothing but an exact version, so it rejected the generated package.json with "expected a semver version" pnpm/pnpm#13969. A package created inside an existing workspace is still left unpinned — it follows the pin at the workspace root — and --no-init-package-manager still scaffolds a manifest without any pin. In pnpm 12, pnpm init also honors initType and its --init-type flag, so the manifest it writes is the same one pnpm 11 writes.

  • Fixed an issue where package overrides were written into the metadata cache, causing removed overrides to keep applying on subsequent installs pnpm/pnpm#13918.

  • On Windows, upgrading pnpm no longer leaves a stale pnpm.ps1 behind. PowerShell resolves pnpm.ps1 ahead of pnpm.cmd, so a shim written by an older installation kept running the previous version. Linking the pnpm CLI's bins now deletes it #​13919.

  • Fixed an inconsistency where minimumReleaseAgeExclude (and trustPolicyExclude) wildcard/bare-name rules behaved differently in the evaluator and normalizer. A bare rule now consistently evaluates as matching every version, preventing unexpected behavior and silent widening of version policy exemptions when pnpm rewrites the workspace manifest pnpm/pnpm#13725.

  • A frozen install no longer rewrites the packageManagerDependencies block of pnpm-lock.yaml. When the pnpm version pinned by devEngines.packageManager (or by packageManager) is missing from the lockfile or no longer matches it, --frozen-lockfile now fails with ERR_PNPM_FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE instead of resolving the version and saving it, so a manifest whose pin was bumped without regenerating the lockfile can no longer pass CI #​14009.

  • A git dependency installed over HTTPS from a hosted repository now keeps its branch, tag, or version range in the specifier recorded in package.json. It was written back without one, so the next pnpm update moved the dependency to the repository's default branch #​13999.

  • Fixed pnpm update --global --latest failing with a 404 error when a globally installed package was not added from the registry by name. Packages installed from a local path (link:/file:), a git repository, a tarball URL, an npm: alias, or a named registry now keep their spec during a global update instead of being looked up by name in the default registry. See #​12854.

  • Fix recursive pnpm update <name>@<version> so an exact pinned update stays scoped to the requested version line: copies of the same package on another major line — or, for a 0.x request, another minor line — keep their locked resolution instead of being re-resolved along with the target.

  • Under nodeLinker: hoisted, a dependency declared against a peer-resolution variant of a package version is no longer dropped from the installed layout. All variants of a version share one hoisted copy, and edges pointing at any of them now resolve to it, so the depending project keeps the package in its .package-map.json and the depending package keeps it in its node_modules/.bin.

  • Fixed pnpm install --merge-git-branch-lockfiles deleting the per-branch lockfiles when the lockfile setting is false. Such an install never reads them, so it has nothing to merge them into and now leaves them alone.

  • Fixed pnpm install sometimes not exiting after printing Done in Xs #​12297.

  • Fixed pnpm failing to read .modules.yaml files containing long dependency paths #​13875. The manifest is now parsed as JSON (the format pnpm writes it in), falling back to the YAML parser only for manifests written by old pnpm versions.

  • With preferSymlinkedExecutables, NODE_PATH again points at the virtual store of the workspace root when pnpm is run from inside a workspace package, so scripts can resolve dependencies that live only in the hoisted store #​13912.

  • Reduced registry metadata requests during dependency resolution by reusing cached metadata when lockfile preferences prove that no uncached version can win pnpm/pnpm#13976.

  • pnpm pkg get and pnpm pkg set now accept hyphens inside a dot-notation property path, so pnpm pkg get dependencies.some-package-name reads the key instead of failing with ERR_PNPM_UNEXPECTED_TOKEN_IN_PROPERTY_PATH. The bracketed and quoted forms already worked and are unchanged.

  • A resolve request now carries the client's resolutionMode, so an install delegated to a pnpr server picks versions the way the client would. time-based and lowest-direct reached the server as nothing at all, leaving it on its highest default: the returned lockfile pinned the highest satisfying version of every dependency, and the setting appeared to be ignored.

    This adds a field to the resolve request body. A server older than its client ignores it and keeps resolving highest; the protocol is still experimental and unversioned.

  • Fixed pnpm installs using pnpr to honor the client's autoInstallPeers, dedupePeers, and excludeLinksFromLockfile settings pnpm/pnpm#13389.

  • pnpm remove now prunes undecided entries ("set this to true or false") from allowBuilds in pnpm-workspace.yaml when sharedWorkspaceLockfile: true and the corresponding packages are removed pnpm/pnpm#13892.

  • Fixed workspace discovery for pnpm-workspace.yaml files without a packages field so commands only consider the workspace root instead of recursively scanning nested projects #​14047.

  • A runtime installed through devEngines.runtime now matches the host when supportedArchitectures lists several platforms. Listing os: [darwin, linux] and cpu: [x64, arm64] used to install the runtime built for the first entry of each list, so a machine running Linux on arm64 got a macOS x64 Node.js that could not execute #​13898.

  • pnpm sbom now fails with ERR_PNPM_SBOM_MISSING_IMPORTERS when pnpm-lock.yaml has no entry for a selected project, instead of writing an SBOM that under-reports that project's dependencies. Previously this crashed with Cannot read properties of undefined (reading 'devDependencies').

  • pnpm self-update now rewrites a simple devEngines.packageManager.version range (^/~) to the newly installed version, keeping the operator — matching how pnpm update and pnpm runtime set rewrite ranges. Complex ranges such as >=8.0.0 that the new version satisfies are still left unchanged #​13935.

  • pnpm self-update <tag> no longer downgrades when the dist-tag points at the pnpm version already running and that version is younger than minimumReleaseAge. The maturity cutoff moved the tag back to the previous mature release, so pnpm self-update next-12 on v12.0.0-rc.4 switched to v12.0.0-rc.3.

  • pnpm set-script now updates package.json instead of failing with ERR_PNPM_NOT_IMPLEMENTED pnpm/pnpm#13956.

  • pnpm update now preserves the existing range operator when updating a prerelease dependency. See #​7002.

  • Installs are faster in workspaces that declare inter-workspace dependencies with plain ranges ("*", "^1.2.3") rather than the workspace: protocol. With preferWorkspacePackages enabled, linking such a dependency no longer makes a registry request that cannot change the outcome — and workspace packages that were never published no longer cost a 404 on every install.

  • Added fetchWarnTimeoutMs and fetchMinSpeedKiBps to the Rust pnpm CLI and its N-API bindings. Slow registry metadata requests and tarball downloads now emit pnpm-compatible warnings without exposing URL credentials, query parameters, fragments, or control characters pnpm/pnpm#12042.

  • An override change is now absorbed by the fast lockfile update even when another, unchanged override uses the catalog: protocol. Previously any catalog:-valued override forced a full re-resolution whenever the override list changed, which could move unrelated packages in the lockfile (for example after pnpm audit --fix added an override).

  • Packed workspace package manifests now preserve dependency order, making repeated pnpm pack output deterministic #​10167.

  • pnpm update <name>@<version> now fails with ERR_PNPM_UPDATE_VERSION_ON_INDIRECT_DEP when the package is not a direct dependency of any selected project, instead of quietly updating it to whatever a fresh install would resolve. There is nowhere to record the version in that case, so the request cannot be honored, and the error points at the overrides entry that does pin a transitive dependency. Ranges and tags are unaffected, and a package that any selected project declares directly still takes its version as before.

  • trustPolicy: no-downgrade no longer aborts the install with ERR_PNPM_MISSING_TIME on registries that serve no per-version time field when minimumReleaseAgeIgnoreMissingTime is set. The trust check reads the same publish dates the minimumReleaseAge check does, so it now honors the same opt-in and skips the affected package with a warning #​12446.

    minimumReleaseAgeIgnoreMissingTime no longer lets a lockfile entry the registry does not list pass the minimumReleaseAge check during lockfile verification. The opt-in covers a registry that cannot date its releases; a packument that does date every version it lists is saying it never published this one, which stays a hard failure.

    The missing-time warning now names the check it is reporting on, so a package whose minimumReleaseAge and trustPolicy checks are both skipped warns about both instead of only the first.

  • pnpm update <pkg>@<version> now updates only the selected packages and leaves unrelated dependencies unchanged. A selector that renames the package it installs — pnpm update <alias>@npm:<pkg>@<version> or the jsr: equivalent — now targets the package the alias installs rather than the alias.

  • Fixed verifyDepsBeforeRun being ignored when set to install, warn, error, or prompt through the PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN environment variable or the --config.verify-deps-before-run flag #​13816. Only the boolean values were accepted before, so a string value was silently dropped.

  • pnpm version <bump> with --dry-run no longer edits package.json files. It now only reports the bumps it would make, and skips the working tree check, the version lifecycle scripts, the commit, and the tag pnpm/pnpm#13953.

Platinum Sponsors

Bit
OpenAI

Gold Sponsors

Sanity Discord Vite
SerpApi CodeRabbit

Note

PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch 3 times, most recently from 5554140 to 66900e5 Compare July 9, 2026 13:56
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch 2 times, most recently from a744f40 to a6fcd9a Compare July 9, 2026 14:15
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.34%. Comparing base (45db68f) to head (10be927).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #382   +/-   ##
=======================================
  Coverage   98.34%   98.34%           
=======================================
  Files           5        5           
  Lines         121      121           
  Branches       31       31           
=======================================
  Hits          119      119           
  Misses          2        2           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from a6fcd9a to ee45fb8 Compare July 9, 2026 14:18
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch 3 times, most recently from 681075d to f820854 Compare July 9, 2026 23:00
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.10.0 chore(deps): update dependency pnpm to v11.11.0 Jul 9, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from f820854 to 55d04bc Compare July 11, 2026 22:12
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.11.0 chore(deps): update dependency pnpm to v11.12.0 Jul 11, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from 55d04bc to c3ce62e Compare July 13, 2026 23:56
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.12.0 chore(deps): update dependency pnpm to v11.13.0 Jul 13, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from c3ce62e to 7d17e79 Compare July 16, 2026 02:10
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.13.0 chore(deps): update dependency pnpm to v11.13.1 Jul 16, 2026
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.13.1 chore(deps): update dependency pnpm to v11.14.0 Jul 17, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from 7d17e79 to f1b3f6f Compare July 17, 2026 22:37
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.14.0 chore(deps): update dependency pnpm to v11.15.0 Jul 18, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch 2 times, most recently from e3980ec to 1d2c0d1 Compare July 20, 2026 05:33
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.15.0 chore(deps): update dependency pnpm to v11.15.1 Jul 20, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from 1d2c0d1 to 138b685 Compare July 22, 2026 21:59
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.15.1 chore(deps): update dependency pnpm to v11.16.0 Jul 22, 2026
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.16.0 chore(deps): update dependency pnpm to v11.17.0 Jul 23, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch 2 times, most recently from 6dcefe1 to ed5f8d1 Compare July 29, 2026 14:46
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.17.0 chore(deps): update dependency pnpm to v11.18.0 Jul 29, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from ed5f8d1 to 5f1c329 Compare August 3, 2026 16:04
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.18.0 chore(deps): update dependency pnpm to v11.20.0 Aug 3, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from 5f1c329 to a2fc896 Compare August 9, 2026 17:39
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.20.0 chore(deps): update dependency pnpm to v11.21.0 Aug 9, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from a2fc896 to e46faa6 Compare August 15, 2026 21:00
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.21.0 chore(deps): update dependency pnpm to v11.22.0 Aug 15, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from e46faa6 to de85e98 Compare August 23, 2026 19:06
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.22.0 chore(deps): update dependency pnpm to v11.23.0 Aug 23, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from de85e98 to 4f71774 Compare August 25, 2026 17:59
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.23.0 chore(deps): update dependency pnpm to v11.24.0 Aug 25, 2026
@renovate
renovate Bot force-pushed the renovate/pnpm-11.x branch from 4f71774 to 10be927 Compare September 1, 2026 02:30
@renovate renovate Bot changed the title chore(deps): update dependency pnpm to v11.24.0 chore(deps): update dependency pnpm to v11.25.0 Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants