PackageTrack

npm · #3965

@pnpm/linux-x64

11.24.0pnpm/pnpm

Release timeline

586 releases since 2021
20222023202420252026

Releases

  1. 11.0.0-beta.326 Mar 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.
    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.
    • Store version bumped to v11.
    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.
    • Use SQLite for storing package index in the content-addressable store. Instead of individual JSON files under $STORE/index/, package metadata is now stored in a single SQLite database at $STORE/index.db with MessagePack-encoded values. This reduces filesystem syscall overhead, improves space efficiency for small metadata entries, and enables concurrent access via SQLite's WAL mode. Packages missing from the new index are re-fetched on demand #10500 #10826.

    Global Packages

    • Global installs (pnpm add -g pkg) and pnpm dlx now use the global virtual store by default. Packages are stored at {storeDir}/links instead of per-project .pnpm directories. This can be disabled by setting enableGlobalVirtualStore: false #10694.

    • Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own package.json, node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.

      Key changes:

      • pnpm add -g <pkg> creates an isolated installation in {pnpmHomeDir}/global/v11/{hash}/
      • pnpm remove -g <pkg> removes the entire installation group containing the package
      • pnpm update -g [pkg] re-installs packages in new isolated directories
      • pnpm list -g scans isolated directories to show all installed global packages
      • pnpm install -g (no args) is no longer supported; use pnpm add -g <pkg> instead

    Configuration

    • Changed default values: optimisticRepeatInstall is now true and verifyDepsBeforeRun is now install.

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Lockfile

    • Simplified patchedDependencies lockfile format from Record<string, { path: string, hash: string }> to Record<string, string> (selector to hash). Existing lockfiles with the old format are automatically migrated #10911.

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      If the registry requests OTP and the user has not provided it via the PNPM_CONFIG_OTP environment variable or the --otp flag, pnpm will prompt the user directly for an OTP code.

      If the registry requests web-based authentication, pnpm will print a scannable QR code along with the URL.

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    • pnpm no longer reads settings from the pnpm field of package.json. Settings should be defined in pnpm-workspace.yaml #10086.

    • Breaking changes to pnpm link:

      • pnpm link <pkg-name> no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, use pnpm link ./foo instead of pnpm link foo.
      • pnpm link --global is removed. Use pnpm add -g . to register a local package's bins globally.
      • pnpm link (no arguments) is removed. Use pnpm link <dir> with an explicit path instead.
    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    • Stop falling back to the npm CLI. Commands that were previously passed through to npm (access, adduser, bugs, deprecate, dist-tag, docs, edit, find, home, info, issues, login, logout, owner, ping, prefix, profile, pkg, repo, search, set-script, show, star, stars, team, token, unpublish, unstar, version, view, whoami, xmas) and their aliases (s, se, v) now throw a "not implemented" error with a suggestion to use the npm CLI directly #10642.

    • Store globally installed binaries in a bin subdirectory of PNPM_HOME instead of directly in PNPM_HOME. This prevents internal directories like global/ and store/ from polluting shell autocompletion when PNPM_HOME is on PATH #10986. After upgrading, run pnpm setup to update your shell configuration.

    Minor Changes

    New Commands

    • Added pnpm sbom command for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088.
    • Added pnpm clean command that safely removes node_modules directories from all workspace projects #10707. Use --lockfile to also remove pnpm-lock.yaml files.
    • Added a new command pnpm runtime set <runtime name> <runtime version spec> [-g] for installing runtimes. Deprecated pnpm env use in favor of the new command.
    • Add the ability to fix vulnerabilities by updating packages in the lockfile instead of adding overrides. Use pnpm audit --fix=update #10341.
    • Added pnpm ci command for clean installs #6100. The command runs pnpm clean followed by pnpm install --frozen-lockfile. Designed for CI/CD environments where reproducible builds are critical. Aliases: pnpm clean-install, pnpm ic, pnpm install-clean #11003.
    • Added pnpm peers check command that checks for unmet and missing peer dependency issues by reading the lockfile #7087.
    • Implemented the version command natively in pnpm to support workspaces and workspace: protocols correctly. The new command allows bumping package versions (major, minor, patch, etc.) with full workspace support and git integration #10879.

    Configuration

    • Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    • Added a new setting virtualStoreOnly that populates the virtual store without creating importer symlinks, hoisting, bin links, or running lifecycle scripts. This is useful for pre-populating a store (e.g., in Nix builds) without creating unnecessary project-level artifacts. pnpm fetch now uses this mode internally #10840.

    • Support specifying the pnpm version via devEngines.packageManager in package.json. Unlike the packageManager field, this supports version ranges. The resolved version is stored in pnpm-lock.yaml and reused if it still satisfies the range #10932.

    • Added a new dedupePeers setting that reduces peer dependency duplication. When enabled, peer dependency suffixes use version-only identifiers (name@version) instead of full dep paths, eliminating nested suffixes like ([email protected]([email protected])). This dramatically reduces the number of package instances in projects with many recursive peer dependencies #11070.

    • Config dependencies are now installed into the global virtual store ({storeDir}/links/) and symlinked into node_modules/.pnpm-config/. This allows config dependencies to be shared across projects that use the same store, avoiding redundant fetches and imports #10910.

    • Store config dependency and package manager integrity info in pnpm-lock.yaml instead of inlining it in pnpm-workspace.yaml. The workspace manifest now contains only clean version specifiers for configDependencies, while the resolved versions, integrity hashes, and tarball URLs are recorded in the lockfile as a separate YAML document. The env lockfile section also stores packageManagerDependencies resolved during version switching and self-update. Projects using the old inline-hash format are automatically migrated on install #10912 #10964.

    Store

    • When the global virtual store is enabled, packages that are not allowed to build (and don't transitively depend on packages that are) now get hashes that don't include the engine name (platform, architecture, Node.js major version). This means ~95% of packages in the GVS survive Node.js upgrades and architecture changes without re-import #10837.

    Hooks & Pnpmfiles

    • Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.
    • Support .pnpmfile.mjs as the default pnpmfile. When .pnpmfile.mjs exists, it takes priority over .pnpmfile.cjs and only one is loaded.

    CLI & Other

    • Added -F as a short alias for the --filter option.
    • Added support for hidden scripts. Scripts starting with . are hidden and cannot be run directly via pnpm run. They can only be called from other scripts. Hidden scripts are also omitted from the pnpm run listing #11041.
    • Allow pnpm approve-builds to receive positional arguments for approving or denying packages without the interactive prompt. Prefix a package name with ! to deny it. Only mentioned packages are affected; the rest are left untouched #11030.
    • During install, packages with ignored builds that are not yet listed in allowBuilds are automatically added to pnpm-workspace.yaml with a placeholder value, so users can manually set them to true or false #11030.
    • Added pn and pnx short aliases for pnpm and pnpx (pnpm dlx) #11052.
    • pnpm store prune now displays the total size of removed files #11047.
    • Warn when optimisticRepeatInstall skips shouldRefreshResolution hooks #10995.

    Performance

    • Skip redundant internal linking during GVS warm reinstall when no packages were added #11073.
    • Skip the staging directory when importing packages into node_modules. This avoids the overhead of creating a temp dir and renaming per package #11088.
    • Write CAS files directly to their final content-addressed path instead of writing to a temp file and renaming. Eliminates ~30k rename syscalls per cold install #11087.
    • Optimize hot path string operations in content-addressable store and increase gunzipSync chunk size for fewer buffer allocations during tarball decompression #11086.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    • Fail on incompatible lockfiles in CI when frozen lockfile mode is enabled #10978.

    • Fixed strictDepBuilds and allowBuilds checks being bypassed when a package's build side-effects are cached in the store #11039.

    • In GVS mode, pnpm approve-builds now runs a full install instead of rebuild, ensuring that GVS hash directories and symlinks are updated correctly after changing allowBuilds #11043.

    • Fixed a crash in the lockfile merger when merging non-semver version strings (e.g. link:, file:, git URLs) #11102.

    • Handle ENOTSUP error in linkOrCopy during parallel imports #11103.

    • Skip linking bins that already reference the correct target. This avoids redundant I/O during repeated installs and prevents permission errors when the store is read-only (e.g. Docker layer caching, CI prewarm, NFS) #11069.

    • Fix _password handling for the default registry to decode from base64 before use, consistent with scoped registry behavior #11089.

    • Fix a bug where the CAS locker cache was not updated when a file already existed with correct integrity #11085.

    • Prevent catalog entries from being removed by cleanupUnusedCatalogs when they are referenced only from workspace overrides #11075.

    • Resolve patch file paths during pnpm fetch #11054.

    • Fixed invalid specifiers for peers on all non-exact version selectors #11049.

    • Fixed false "Command not found" error on Windows when the command exists but exits with a non-zero exit code #11000.

    • Prepended Bearer to the authorization token generated by tokenHelper if it is missing, aligning with npm's behavior #11097.

    • Propagate error cause when throwing PnpmError in @pnpm/npm-resolver #10990.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  2. 11.0.0-beta.221 Mar 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.
    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.
    • Store version bumped to v11.
    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.
    • Use SQLite for storing package index in the content-addressable store. Instead of individual JSON files under $STORE/index/, package metadata is now stored in a single SQLite database at $STORE/index.db with MessagePack-encoded values. This reduces filesystem syscall overhead, improves space efficiency for small metadata entries, and enables concurrent access via SQLite's WAL mode. Packages missing from the new index are re-fetched on demand #10500 #10826.

    Global Packages

    • Global installs (pnpm add -g pkg) and pnpm dlx now use the global virtual store by default. Packages are stored at {storeDir}/links instead of per-project .pnpm directories. This can be disabled by setting enableGlobalVirtualStore: false #10694.

    • Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own package.json, node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.

      Key changes:

      • pnpm add -g <pkg> creates an isolated installation in {pnpmHomeDir}/global/v11/{hash}/
      • pnpm remove -g <pkg> removes the entire installation group containing the package
      • pnpm update -g [pkg] re-installs packages in new isolated directories
      • pnpm list -g scans isolated directories to show all installed global packages
      • pnpm install -g (no args) is no longer supported; use pnpm add -g <pkg> instead

    Configuration

    • Changed default values: optimisticRepeatInstall is now true and verifyDepsBeforeRun is now install.

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Lockfile

    • Simplified patchedDependencies lockfile format from Record<string, { path: string, hash: string }> to Record<string, string> (selector to hash). Existing lockfiles with the old format are automatically migrated #10911.

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      If the registry requests OTP and the user has not provided it via the PNPM_CONFIG_OTP environment variable or the --otp flag, pnpm will prompt the user directly for an OTP code.

      If the registry requests web-based authentication, pnpm will print a scannable QR code along with the URL.

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    • pnpm no longer reads settings from the pnpm field of package.json. Settings should be defined in pnpm-workspace.yaml #10086.

    • Breaking changes to pnpm link:

      • pnpm link <pkg-name> no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, use pnpm link ./foo instead of pnpm link foo.
      • pnpm link --global is removed. Use pnpm add -g . to register a local package's bins globally.
      • pnpm link (no arguments) is removed. Use pnpm link <dir> with an explicit path instead.
    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    • Stop falling back to the npm CLI. Commands that were previously passed through to npm (access, adduser, bugs, deprecate, dist-tag, docs, edit, find, home, info, issues, login, logout, owner, ping, prefix, profile, pkg, repo, search, set-script, show, star, stars, team, token, unpublish, unstar, version, view, whoami, xmas) and their aliases (s, se, v) now throw a "not implemented" error with a suggestion to use the npm CLI directly #10642.

    • Store globally installed binaries in a bin subdirectory of PNPM_HOME instead of directly in PNPM_HOME. This prevents internal directories like global/ and store/ from polluting shell autocompletion when PNPM_HOME is on PATH #10986. After upgrading, run pnpm setup to update your shell configuration.

    Minor Changes

    New Commands

    • Added pnpm sbom command for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088.
    • Added pnpm clean command that safely removes node_modules directories from all workspace projects #10707. Use --lockfile to also remove pnpm-lock.yaml files.
    • Added a new command pnpm runtime set <runtime name> <runtime version spec> [-g] for installing runtimes. Deprecated pnpm env use in favor of the new command.
    • Add the ability to fix vulnerabilities by updating packages in the lockfile instead of adding overrides. Use pnpm audit --fix=update #10341.
    • Added pnpm ci command for clean installs #6100. The command runs pnpm clean followed by pnpm install --frozen-lockfile. Designed for CI/CD environments where reproducible builds are critical. Aliases: pnpm clean-install, pnpm ic, pnpm install-clean #11003.

    Configuration

    • Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    • Added a new setting virtualStoreOnly that populates the virtual store without creating importer symlinks, hoisting, bin links, or running lifecycle scripts. This is useful for pre-populating a store (e.g., in Nix builds) without creating unnecessary project-level artifacts. pnpm fetch now uses this mode internally #10840.

    • Support specifying the pnpm version via devEngines.packageManager in package.json. Unlike the packageManager field, this supports version ranges. The resolved version is stored in pnpm-lock.yaml and reused if it still satisfies the range #10932.

    • Config dependencies are now installed into the global virtual store ({storeDir}/links/) and symlinked into node_modules/.pnpm-config/. This allows config dependencies to be shared across projects that use the same store, avoiding redundant fetches and imports #10910.

    • Store config dependency and package manager integrity info in pnpm-lock.yaml instead of inlining it in pnpm-workspace.yaml. The workspace manifest now contains only clean version specifiers for configDependencies, while the resolved versions, integrity hashes, and tarball URLs are recorded in the lockfile as a separate YAML document. The env lockfile section also stores packageManagerDependencies resolved during version switching and self-update. Projects using the old inline-hash format are automatically migrated on install #10912 #10964.

    Store

    • When the global virtual store is enabled, packages that are not allowed to build (and don't transitively depend on packages that are) now get hashes that don't include the engine name (platform, architecture, Node.js major version). This means ~95% of packages in the GVS survive Node.js upgrades and architecture changes without re-import #10837.

    Hooks & Pnpmfiles

    • Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.
    • Support .pnpmfile.mjs as the default pnpmfile. When .pnpmfile.mjs exists, it takes priority over .pnpmfile.cjs and only one is loaded.

    CLI & Other

    • Added -F as a short alias for the --filter option.
    • Added support for hidden scripts. Scripts starting with . are hidden and cannot be run directly via pnpm run. They can only be called from other scripts. Hidden scripts are also omitted from the pnpm run listing #11041.
    • Allow pnpm approve-builds to receive positional arguments for approving or denying packages without the interactive prompt. Prefix a package name with ! to deny it. Only mentioned packages are affected; the rest are left untouched #11030.
    • During install, packages with ignored builds that are not yet listed in allowBuilds are automatically added to pnpm-workspace.yaml with a placeholder value, so users can manually set them to true or false #11030.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    • Fail on incompatible lockfiles in CI when frozen lockfile mode is enabled #10978.

    • Fixed strictDepBuilds and allowBuilds checks being bypassed when a package's build side-effects are cached in the store #11039.

    • In GVS mode, pnpm approve-builds now runs a full install instead of rebuild, ensuring that GVS hash directories and symlinks are updated correctly after changing allowBuilds #11043.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  3. 11.0.0-beta.121 Mar 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.
    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.
    • Store version bumped to v11.
    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.
    • Use SQLite for storing package index in the content-addressable store. Instead of individual JSON files under $STORE/index/, package metadata is now stored in a single SQLite database at $STORE/index.db with MessagePack-encoded values. This reduces filesystem syscall overhead, improves space efficiency for small metadata entries, and enables concurrent access via SQLite's WAL mode. Packages missing from the new index are re-fetched on demand #10500 #10826.

    Global Packages

    • Global installs (pnpm add -g pkg) and pnpm dlx now use the global virtual store by default. Packages are stored at {storeDir}/links instead of per-project .pnpm directories. This can be disabled by setting enableGlobalVirtualStore: false #10694.

    • Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own package.json, node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.

      Key changes:

      • pnpm add -g <pkg> creates an isolated installation in {pnpmHomeDir}/global/v11/{hash}/
      • pnpm remove -g <pkg> removes the entire installation group containing the package
      • pnpm update -g [pkg] re-installs packages in new isolated directories
      • pnpm list -g scans isolated directories to show all installed global packages
      • pnpm install -g (no args) is no longer supported; use pnpm add -g <pkg> instead

    Configuration

    • Changed default values: optimisticRepeatInstall is now true and verifyDepsBeforeRun is now install.

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Lockfile

    • Simplified patchedDependencies lockfile format from Record<string, { path: string, hash: string }> to Record<string, string> (selector to hash). Existing lockfiles with the old format are automatically migrated #10911.

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      If the registry requests OTP and the user has not provided it via the PNPM_CONFIG_OTP environment variable or the --otp flag, pnpm will prompt the user directly for an OTP code.

      If the registry requests web-based authentication, pnpm will print a scannable QR code along with the URL.

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    • pnpm no longer reads settings from the pnpm field of package.json. Settings should be defined in pnpm-workspace.yaml #10086.

    • Breaking changes to pnpm link:

      • pnpm link <pkg-name> no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, use pnpm link ./foo instead of pnpm link foo.
      • pnpm link --global is removed. Use pnpm add -g . to register a local package's bins globally.
      • pnpm link (no arguments) is removed. Use pnpm link <dir> with an explicit path instead.
    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    • Stop falling back to the npm CLI. Commands that were previously passed through to npm (access, adduser, bugs, deprecate, dist-tag, docs, edit, find, home, info, issues, login, logout, owner, ping, prefix, profile, pkg, repo, search, set-script, show, star, stars, team, token, unpublish, unstar, version, view, whoami, xmas) and their aliases (s, se, v) now throw a "not implemented" error with a suggestion to use the npm CLI directly #10642.

    • Store globally installed binaries in a bin subdirectory of PNPM_HOME instead of directly in PNPM_HOME. This prevents internal directories like global/ and store/ from polluting shell autocompletion when PNPM_HOME is on PATH #10986. After upgrading, run pnpm setup to update your shell configuration.

    Minor Changes

    New Commands

    • Added pnpm sbom command for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088.
    • Added pnpm clean command that safely removes node_modules directories from all workspace projects #10707. Use --lockfile to also remove pnpm-lock.yaml files.
    • Added a new command pnpm runtime set <runtime name> <runtime version spec> [-g] for installing runtimes. Deprecated pnpm env use in favor of the new command.
    • Add the ability to fix vulnerabilities by updating packages in the lockfile instead of adding overrides. Use pnpm audit --fix=update #10341.
    • Added pnpm ci command for clean installs #6100. The command runs pnpm clean followed by pnpm install --frozen-lockfile. Designed for CI/CD environments where reproducible builds are critical. Aliases: pnpm clean-install, pnpm ic, pnpm install-clean #11003.

    Configuration

    • Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    • Added a new setting virtualStoreOnly that populates the virtual store without creating importer symlinks, hoisting, bin links, or running lifecycle scripts. This is useful for pre-populating a store (e.g., in Nix builds) without creating unnecessary project-level artifacts. pnpm fetch now uses this mode internally #10840.

    • Support specifying the pnpm version via devEngines.packageManager in package.json. Unlike the packageManager field, this supports version ranges. The resolved version is stored in pnpm-lock.yaml and reused if it still satisfies the range #10932.

    • Config dependencies are now installed into the global virtual store ({storeDir}/links/) and symlinked into node_modules/.pnpm-config/. This allows config dependencies to be shared across projects that use the same store, avoiding redundant fetches and imports #10910.

    • Store config dependency and package manager integrity info in pnpm-lock.yaml instead of inlining it in pnpm-workspace.yaml. The workspace manifest now contains only clean version specifiers for configDependencies, while the resolved versions, integrity hashes, and tarball URLs are recorded in the lockfile as a separate YAML document. The env lockfile section also stores packageManagerDependencies resolved during version switching and self-update. Projects using the old inline-hash format are automatically migrated on install #10912 #10964.

    Store

    • When the global virtual store is enabled, packages that are not allowed to build (and don't transitively depend on packages that are) now get hashes that don't include the engine name (platform, architecture, Node.js major version). This means ~95% of packages in the GVS survive Node.js upgrades and architecture changes without re-import #10837.

    Hooks & Pnpmfiles

    • Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.
    • Support .pnpmfile.mjs as the default pnpmfile. When .pnpmfile.mjs exists, it takes priority over .pnpmfile.cjs and only one is loaded.

    CLI & Other

    • Added -F as a short alias for the --filter option.
    • Added support for hidden scripts. Scripts starting with . are hidden and cannot be run directly via pnpm run. They can only be called from other scripts. Hidden scripts are also omitted from the pnpm run listing #11041.
    • Allow pnpm approve-builds to receive positional arguments for approving or denying packages without the interactive prompt. Prefix a package name with ! to deny it. Only mentioned packages are affected; the rest are left untouched #11030.
    • During install, packages with ignored builds that are not yet listed in allowBuilds are automatically added to pnpm-workspace.yaml with a placeholder value, so users can manually set them to true or false #11030.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    • Fail on incompatible lockfiles in CI when frozen lockfile mode is enabled #10978.

    • Fixed strictDepBuilds and allowBuilds checks being bypassed when a package's build side-effects are cached in the store #11039.

    • In GVS mode, pnpm approve-builds now runs a full install instead of rebuild, ensuring that GVS hash directories and symlinks are updated correctly after changing allowBuilds #11043.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  4. 11.0.0-beta.019 Mar 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.
    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.
    • Store version bumped to v11.
    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.
    • Use SQLite for storing package index in the content-addressable store. Instead of individual JSON files under $STORE/index/, package metadata is now stored in a single SQLite database at $STORE/index.db with MessagePack-encoded values. This reduces filesystem syscall overhead, improves space efficiency for small metadata entries, and enables concurrent access via SQLite's WAL mode. Packages missing from the new index are re-fetched on demand #10500 #10826.

    Global Packages

    • Global installs (pnpm add -g pkg) and pnpm dlx now use the global virtual store by default. Packages are stored at {storeDir}/links instead of per-project .pnpm directories. This can be disabled by setting enableGlobalVirtualStore: false #10694.

    • Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own package.json, node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.

      Key changes:

      • pnpm add -g <pkg> creates an isolated installation in {pnpmHomeDir}/global/v11/{hash}/
      • pnpm remove -g <pkg> removes the entire installation group containing the package
      • pnpm update -g [pkg] re-installs packages in new isolated directories
      • pnpm list -g scans isolated directories to show all installed global packages
      • pnpm install -g (no args) is no longer supported; use pnpm add -g <pkg> instead

    Configuration

    • Changed default values: optimisticRepeatInstall is now true and verifyDepsBeforeRun is now install.

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Lockfile

    • Simplified patchedDependencies lockfile format from Record<string, { path: string, hash: string }> to Record<string, string> (selector to hash). Existing lockfiles with the old format are automatically migrated #10911.

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      If the registry requests OTP and the user has not provided it via the PNPM_CONFIG_OTP environment variable or the --otp flag, pnpm will prompt the user directly for an OTP code.

      If the registry requests web-based authentication, pnpm will print a scannable QR code along with the URL.

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    • pnpm no longer reads settings from the pnpm field of package.json. Settings should be defined in pnpm-workspace.yaml #10086.

    • Breaking changes to pnpm link:

      • pnpm link <pkg-name> no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, use pnpm link ./foo instead of pnpm link foo.
      • pnpm link --global is removed. Use pnpm add -g . to register a local package's bins globally.
      • pnpm link (no arguments) is removed. Use pnpm link <dir> with an explicit path instead.
    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    Minor Changes

    New Commands

    • Added pnpm sbom command for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088.
    • Added pnpm clean command that safely removes node_modules directories from all workspace projects #10707. Use --lockfile to also remove pnpm-lock.yaml files.
    • Added a new command pnpm runtime set <runtime name> <runtime version spec> [-g] for installing runtimes. Deprecated pnpm env use in favor of the new command.
    • Add the ability to fix vulnerabilities by updating packages in the lockfile instead of adding overrides. Use pnpm audit --fix=update #10341.

    Configuration

    • Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    • Added a new setting virtualStoreOnly that populates the virtual store without creating importer symlinks, hoisting, bin links, or running lifecycle scripts. This is useful for pre-populating a store (e.g., in Nix builds) without creating unnecessary project-level artifacts. pnpm fetch now uses this mode internally #10840.

    • Support specifying the pnpm version via devEngines.packageManager in package.json. Unlike the packageManager field, this supports version ranges. The resolved version is stored in pnpm-lock.yaml and reused if it still satisfies the range #10932.

    • Config dependencies are now installed into the global virtual store ({storeDir}/links/) and symlinked into node_modules/.pnpm-config/. This allows config dependencies to be shared across projects that use the same store, avoiding redundant fetches and imports #10910.

    • Store config dependency and package manager integrity info in pnpm-lock.yaml instead of inlining it in pnpm-workspace.yaml. The workspace manifest now contains only clean version specifiers for configDependencies, while the resolved versions, integrity hashes, and tarball URLs are recorded in the lockfile as a separate YAML document. The env lockfile section also stores packageManagerDependencies resolved during version switching and self-update. Projects using the old inline-hash format are automatically migrated on install #10912 #10964.

    Store

    • When the global virtual store is enabled, packages that are not allowed to build (and don't transitively depend on packages that are) now get hashes that don't include the engine name (platform, architecture, Node.js major version). This means ~95% of packages in the GVS survive Node.js upgrades and architecture changes without re-import #10837.

    Hooks & Pnpmfiles

    • Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.
    • Support .pnpmfile.mjs as the default pnpmfile. When .pnpmfile.mjs exists, it takes priority over .pnpmfile.cjs and only one is loaded.

    CLI & Other

    • Added -F as a short alias for the --filter option.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    • Fail on incompatible lockfiles in CI when frozen lockfile mode is enabled #10978.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  5. 11.0.0-alpha.1615 Mar 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.
    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.
    • Store version bumped to v11.
    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.
    • Use SQLite for storing package index in the content-addressable store. Instead of individual JSON files under $STORE/index/, package metadata is now stored in a single SQLite database at $STORE/index.db with MessagePack-encoded values. This reduces filesystem syscall overhead, improves space efficiency for small metadata entries, and enables concurrent access via SQLite's WAL mode. Packages missing from the new index are re-fetched on demand #10500 #10826.

    Global Packages

    • Global installs (pnpm add -g pkg) and pnpm dlx now use the global virtual store by default. Packages are stored at {storeDir}/links instead of per-project .pnpm directories. This can be disabled by setting enableGlobalVirtualStore: false #10694.

    • Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own package.json, node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.

      Key changes:

      • pnpm add -g <pkg> creates an isolated installation in {pnpmHomeDir}/global/v11/{hash}/
      • pnpm remove -g <pkg> removes the entire installation group containing the package
      • pnpm update -g [pkg] re-installs packages in new isolated directories
      • pnpm list -g scans isolated directories to show all installed global packages
      • pnpm install -g (no args) is no longer supported; use pnpm add -g <pkg> instead

    Configuration

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Lockfile

    • Simplified patchedDependencies lockfile format from Record<string, { path: string, hash: string }> to Record<string, string> (selector to hash). Existing lockfiles with the old format are automatically migrated #10911.

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    • Breaking changes to pnpm link:

      • pnpm link <pkg-name> no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, use pnpm link ./foo instead of pnpm link foo.
      • pnpm link --global is removed. Use pnpm add -g . to register a local package's bins globally.
      • pnpm link (no arguments) is removed. Use pnpm link <dir> with an explicit path instead.
    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    Minor Changes

    • Config dependencies are now installed into the global virtual store ({storeDir}/links/) and symlinked into node_modules/.pnpm-config/. This allows config dependencies to be shared across projects that use the same store, avoiding redundant fetches and imports #10910.

    • Store config dependency and package manager integrity info in pnpm-lock.yaml instead of inlining it in pnpm-workspace.yaml. The workspace manifest now contains only clean version specifiers for configDependencies, while the resolved versions, integrity hashes, and tarball URLs are recorded in the lockfile as a separate YAML document. The env lockfile section also stores packageManagerDependencies resolved during version switching and self-update. Projects using the old inline-hash format are automatically migrated on install #10912 #10964.

    • 7fab2a2: Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • cb367b9: Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • 075aa99: Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • e146e98: Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • 7d5ada0: pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    • 5bf7768: A new --yes flag can be passed to pnpm to automatically confirm prompts. This is useful when running pnpm in non-interactive script.

    • 2b14c74: When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    • Added pnpm sbom command for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088.

    • Allow loading certificates from cert, ca, and key for specific registry URLs. E.g., //registry.example.com/:ca=-----BEGIN CERTIFICATE-----.... Previously this was only working via certfile, cafile, and keyfile #10230.

    • Added --all flag to pnpm approve-builds that approves all pending builds without interactive prompts #10136.

    • Added a new setting blockExoticSubdeps that prevents the resolution of exotic protocols in transitive dependencies #10265.

    • Added trustPolicyIgnoreAfter, which allows you to ignore trust policy checks for packages published more than a specified time ago #10352.

    • Added a new flag called --bare to pnpm init for creating a package.json with the bare minimum of required fields #10226.

    • Added support for allowBuilds, which is a new field that can be used instead of onlyBuiltDependencies and ignoredBuiltDependencies #10311.

    • Added support for object type in configDependencies when the tarball URL returned from package metadata differs from the computed URL #10431.

    • The pnpm dlx / pnpx command now supports the catalog: protocol. Example: pnpm dlx shx@catalog:.

    • Add support for a hook called beforePacking that can be used to customize the package.json contents at publish time #3816.

    • On systems using the musl C library (e.g. Alpine Linux), pnpm env use now automatically downloads the musl variant of Node.js. pnpm env add and pnpm env remove subcommands have been removed. pnpm env list now only lists remote Node.js versions.

    • Added support for --dry-run to the pack command #10301.

    • Added mark-and-sweep garbage collection for global virtual store. pnpm store prune now removes unused packages from the global virtual store's links/ directory.

    • Semi-breaking. Changed the location of unscoped packages in the virtual global store. They will now be stored under a directory named @ to maintain a uniform 4-level directory depth.

    • Support configuring auditLevel in the pnpm-workspace.yaml file #10540.

    • Support bare workspace: protocol without version specifier. It is now treated as workspace:* and resolves to the concrete version during publish #10436.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    • Added a new command pnpm runtime set <runtime name> <runtime version spec> [-g] for installing runtimes. Deprecated pnpm env use in favor of the new command.

    • Added pnpm clean command that safely removes node_modules directories from all workspace projects #10707. Use --lockfile to also remove pnpm-lock.yaml files.

    • Increase the network concurrency on machines with many CPU cores #10068.

    • Added support for trustPolicyExclude #10164.

    • Compute integrity hash for HTTP tarball dependencies when fetching, storing it in the lockfile to prevent servers from serving altered content on subsequent installs #10287.

    • Added support for automatic Node.js runtime installation for dependencies. pnpm will now install the Node.js version required by a dependency if that dependency declares a Node.js runtime in the engines field #10141.

    • Allow overriding the engines field on publish by the publishConfig.engines field.

    • Changed default values: optimisticRepeatInstall is now true and verifyDepsBeforeRun is now install.

    • Added a new setting: trustPolicy. When set to no-downgrade, pnpm will fail installation if a package's trust level has decreased compared to previous releases #8889.

    • Support .pnpmfile.mjs as the default pnpmfile. When .pnpmfile.mjs exists, it takes priority over .pnpmfile.cjs and only one is loaded.

    • Added -F as a short alias for the --filter option.

    • When the global virtual store is enabled, packages that are not allowed to build (and don't transitively depend on packages that are) now get hashes that don't include the engine name (platform, architecture, Node.js major version). This means ~95% of packages in the GVS survive Node.js upgrades and architecture changes without re-import #10837.

    • Support specifying the pnpm version via devEngines.packageManager in package.json. Unlike the packageManager field, this supports version ranges. The resolved version is stored in pnpm-lock.yaml and reused if it still satisfies the range #10932.

    • Add the ability to fix vulnerabilities by updating packages in the lockfile instead of adding overrides. Use pnpm audit --fix --fix-mode=update #10341.

    Patch Changes

    • Fixed global install output showing ??? instead of the linked package path when linking from the current directory #10899.

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  6. 11.0.0-alpha.1515 Mar 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.
    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.
    • Store version bumped to v11.
    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.
    • Use SQLite for storing package index in the content-addressable store. Instead of individual JSON files under $STORE/index/, package metadata is now stored in a single SQLite database at $STORE/index.db with MessagePack-encoded values. This reduces filesystem syscall overhead, improves space efficiency for small metadata entries, and enables concurrent access via SQLite's WAL mode. Packages missing from the new index are re-fetched on demand #10500 #10826.

    Global Packages

    • Global installs (pnpm add -g pkg) and pnpm dlx now use the global virtual store by default. Packages are stored at {storeDir}/links instead of per-project .pnpm directories. This can be disabled by setting enableGlobalVirtualStore: false #10694.

    • Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own package.json, node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.

      Key changes:

      • pnpm add -g <pkg> creates an isolated installation in {pnpmHomeDir}/global/v11/{hash}/
      • pnpm remove -g <pkg> removes the entire installation group containing the package
      • pnpm update -g [pkg] re-installs packages in new isolated directories
      • pnpm list -g scans isolated directories to show all installed global packages
      • pnpm install -g (no args) is no longer supported; use pnpm add -g <pkg> instead

    Configuration

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Lockfile

    • Simplified patchedDependencies lockfile format from Record<string, { path: string, hash: string }> to Record<string, string> (selector to hash). Existing lockfiles with the old format are automatically migrated #10911.

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    • Breaking changes to pnpm link:

      • pnpm link <pkg-name> no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, use pnpm link ./foo instead of pnpm link foo.
      • pnpm link --global is removed. Use pnpm add -g . to register a local package's bins globally.
      • pnpm link (no arguments) is removed. Use pnpm link <dir> with an explicit path instead.
    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    Minor Changes

    • Config dependencies are now installed into the global virtual store ({storeDir}/links/) and symlinked into node_modules/.pnpm-config/. This allows config dependencies to be shared across projects that use the same store, avoiding redundant fetches and imports #10910.

    • Store config dependency and package manager integrity info in pnpm-lock.yaml instead of inlining it in pnpm-workspace.yaml. The workspace manifest now contains only clean version specifiers for configDependencies, while the resolved versions, integrity hashes, and tarball URLs are recorded in the lockfile as a separate YAML document. The env lockfile section also stores packageManagerDependencies resolved during version switching and self-update. Projects using the old inline-hash format are automatically migrated on install #10912 #10964.

    • 7fab2a2: Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • cb367b9: Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • 075aa99: Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • e146e98: Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • 7d5ada0: pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    • 5bf7768: A new --yes flag can be passed to pnpm to automatically confirm prompts. This is useful when running pnpm in non-interactive script.

    • 2b14c74: When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    • Added pnpm sbom command for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088.

    • Allow loading certificates from cert, ca, and key for specific registry URLs. E.g., //registry.example.com/:ca=-----BEGIN CERTIFICATE-----.... Previously this was only working via certfile, cafile, and keyfile #10230.

    • Added --all flag to pnpm approve-builds that approves all pending builds without interactive prompts #10136.

    • Added a new setting blockExoticSubdeps that prevents the resolution of exotic protocols in transitive dependencies #10265.

    • Added trustPolicyIgnoreAfter, which allows you to ignore trust policy checks for packages published more than a specified time ago #10352.

    • Added a new flag called --bare to pnpm init for creating a package.json with the bare minimum of required fields #10226.

    • Added support for allowBuilds, which is a new field that can be used instead of onlyBuiltDependencies and ignoredBuiltDependencies #10311.

    • Added support for object type in configDependencies when the tarball URL returned from package metadata differs from the computed URL #10431.

    • The pnpm dlx / pnpx command now supports the catalog: protocol. Example: pnpm dlx shx@catalog:.

    • Add support for a hook called beforePacking that can be used to customize the package.json contents at publish time #3816.

    • On systems using the musl C library (e.g. Alpine Linux), pnpm env use now automatically downloads the musl variant of Node.js. pnpm env add and pnpm env remove subcommands have been removed. pnpm env list now only lists remote Node.js versions.

    • Added support for --dry-run to the pack command #10301.

    • Added mark-and-sweep garbage collection for global virtual store. pnpm store prune now removes unused packages from the global virtual store's links/ directory.

    • Semi-breaking. Changed the location of unscoped packages in the virtual global store. They will now be stored under a directory named @ to maintain a uniform 4-level directory depth.

    • Support configuring auditLevel in the pnpm-workspace.yaml file #10540.

    • Support bare workspace: protocol without version specifier. It is now treated as workspace:* and resolves to the concrete version during publish #10436.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    • Added a new command pnpm runtime set <runtime name> <runtime version spec> [-g] for installing runtimes. Deprecated pnpm env use in favor of the new command.

    • Added pnpm clean command that safely removes node_modules directories from all workspace projects #10707. Use --lockfile to also remove pnpm-lock.yaml files.

    • Increase the network concurrency on machines with many CPU cores #10068.

    • Added support for trustPolicyExclude #10164.

    • Compute integrity hash for HTTP tarball dependencies when fetching, storing it in the lockfile to prevent servers from serving altered content on subsequent installs #10287.

    • Added support for automatic Node.js runtime installation for dependencies. pnpm will now install the Node.js version required by a dependency if that dependency declares a Node.js runtime in the engines field #10141.

    • Allow overriding the engines field on publish by the publishConfig.engines field.

    • Changed default values: optimisticRepeatInstall is now true and verifyDepsBeforeRun is now install.

    • Added a new setting: trustPolicy. When set to no-downgrade, pnpm will fail installation if a package's trust level has decreased compared to previous releases #8889.

    • Support .pnpmfile.mjs as the default pnpmfile. When .pnpmfile.mjs exists, it takes priority over .pnpmfile.cjs and only one is loaded.

    • Added -F as a short alias for the --filter option.

    • When the global virtual store is enabled, packages that are not allowed to build (and don't transitively depend on packages that are) now get hashes that don't include the engine name (platform, architecture, Node.js major version). This means ~95% of packages in the GVS survive Node.js upgrades and architecture changes without re-import #10837.

    • Support specifying the pnpm version via devEngines.packageManager in package.json. Unlike the packageManager field, this supports version ranges. The resolved version is stored in pnpm-lock.yaml and reused if it still satisfies the range #10932.

    • Add the ability to fix vulnerabilities by updating packages in the lockfile instead of adding overrides. Use pnpm audit --fix --fix-mode=update #10341.

    Patch Changes

    • Fixed global install output showing ??? instead of the linked package path when linking from the current directory #10899.

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  7. 11.0.0-alpha.1411 Mar 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.
    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.
    • Store version bumped to v11.
    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.
    • Use SQLite for storing package index in the content-addressable store. Instead of individual JSON files under $STORE/index/, package metadata is now stored in a single SQLite database at $STORE/index.db with MessagePack-encoded values. This reduces filesystem syscall overhead, improves space efficiency for small metadata entries, and enables concurrent access via SQLite's WAL mode. Packages missing from the new index are re-fetched on demand #10500 #10826.

    Global Packages

    • Global installs (pnpm add -g pkg) and pnpm dlx now use the global virtual store by default. Packages are stored at {storeDir}/links instead of per-project .pnpm directories. This can be disabled by setting enableGlobalVirtualStore: false #10694.

    • Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own package.json, node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.

      Key changes:

      • pnpm add -g <pkg> creates an isolated installation in {pnpmHomeDir}/global/v11/{hash}/
      • pnpm remove -g <pkg> removes the entire installation group containing the package
      • pnpm update -g [pkg] re-installs packages in new isolated directories
      • pnpm list -g scans isolated directories to show all installed global packages
      • pnpm install -g (no args) is no longer supported; use pnpm add -g <pkg> instead

    Configuration

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Lockfile

    • Simplified patchedDependencies lockfile format from Record<string, { path: string, hash: string }> to Record<string, string> (selector to hash). Existing lockfiles with the old format are automatically migrated #10911.

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    • Breaking changes to pnpm link:

      • pnpm link <pkg-name> no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, use pnpm link ./foo instead of pnpm link foo.
      • pnpm link --global is removed. Use pnpm add -g . to register a local package's bins globally.
      • pnpm link (no arguments) is removed. Use pnpm link <dir> with an explicit path instead.
    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    Minor Changes

    • Config dependencies are now installed into the global virtual store ({storeDir}/links/) and symlinked into node_modules/.pnpm-config/. This allows config dependencies to be shared across projects that use the same store, avoiding redundant fetches and imports #10910.

    • Store config dependency and package manager integrity info in a separate pnpm-lock.env.yaml lockfile instead of inlining it in pnpm-workspace.yaml. The workspace manifest now contains only clean version specifiers for configDependencies, while the resolved versions, integrity hashes, and tarball URLs are recorded in the new env lockfile. The env lockfile also stores packageManagerDependencies resolved during version switching and self-update. Projects using the old inline-hash format are automatically migrated on install #10912.

    • 7fab2a2: Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • cb367b9: Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • 075aa99: Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • e146e98: Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • 7d5ada0: pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    • 5bf7768: A new --yes flag can be passed to pnpm to automatically confirm prompts. This is useful when running pnpm in non-interactive script.

    • 2b14c74: When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    • Added pnpm sbom command for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088.

    • Allow loading certificates from cert, ca, and key for specific registry URLs. E.g., //registry.example.com/:ca=-----BEGIN CERTIFICATE-----.... Previously this was only working via certfile, cafile, and keyfile #10230.

    • Added --all flag to pnpm approve-builds that approves all pending builds without interactive prompts #10136.

    • Added a new setting blockExoticSubdeps that prevents the resolution of exotic protocols in transitive dependencies #10265.

    • Added trustPolicyIgnoreAfter, which allows you to ignore trust policy checks for packages published more than a specified time ago #10352.

    • Added a new flag called --bare to pnpm init for creating a package.json with the bare minimum of required fields #10226.

    • Added support for allowBuilds, which is a new field that can be used instead of onlyBuiltDependencies and ignoredBuiltDependencies #10311.

    • Added support for object type in configDependencies when the tarball URL returned from package metadata differs from the computed URL #10431.

    • The pnpm dlx / pnpx command now supports the catalog: protocol. Example: pnpm dlx shx@catalog:.

    • Add support for a hook called beforePacking that can be used to customize the package.json contents at publish time #3816.

    • On systems using the musl C library (e.g. Alpine Linux), pnpm env use now automatically downloads the musl variant of Node.js. pnpm env add and pnpm env remove subcommands have been removed. pnpm env list now only lists remote Node.js versions.

    • Added support for --dry-run to the pack command #10301.

    • Added mark-and-sweep garbage collection for global virtual store. pnpm store prune now removes unused packages from the global virtual store's links/ directory.

    • Semi-breaking. Changed the location of unscoped packages in the virtual global store. They will now be stored under a directory named @ to maintain a uniform 4-level directory depth.

    • Support configuring auditLevel in the pnpm-workspace.yaml file #10540.

    • Support bare workspace: protocol without version specifier. It is now treated as workspace:* and resolves to the concrete version during publish #10436.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    • Added a new command pnpm runtime set <runtime name> <runtime version spec> [-g] for installing runtimes. Deprecated pnpm env use in favor of the new command.

    • Added pnpm clean command that safely removes node_modules directories from all workspace projects #10707. Use --lockfile to also remove pnpm-lock.yaml files.

    • Increase the network concurrency on machines with many CPU cores #10068.

    • Added support for trustPolicyExclude #10164.

    • Compute integrity hash for HTTP tarball dependencies when fetching, storing it in the lockfile to prevent servers from serving altered content on subsequent installs #10287.

    • Added support for automatic Node.js runtime installation for dependencies. pnpm will now install the Node.js version required by a dependency if that dependency declares a Node.js runtime in the engines field #10141.

    • Allow overriding the engines field on publish by the publishConfig.engines field.

    • Changed default values: optimisticRepeatInstall is now true and verifyDepsBeforeRun is now install.

    • Added a new setting: trustPolicy. When set to no-downgrade, pnpm will fail installation if a package's trust level has decreased compared to previous releases #8889.

    • Support .pnpmfile.mjs as the default pnpmfile. When .pnpmfile.mjs exists, it takes priority over .pnpmfile.cjs and only one is loaded.

    • Added -F as a short alias for the --filter option.

    • When the global virtual store is enabled, packages that are not allowed to build (and don't transitively depend on packages that are) now get hashes that don't include the engine name (platform, architecture, Node.js major version). This means ~95% of packages in the GVS survive Node.js upgrades and architecture changes without re-import #10837.

    Patch Changes

    • Fixed global install output showing ??? instead of the linked package path when linking from the current directory #10899.

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  8. 11.0.0-alpha.137 Mar 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.
    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.
    • Store version bumped to v11.
    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.
    • Use SQLite for storing package index in the content-addressable store. Instead of individual JSON files under $STORE/index/, package metadata is now stored in a single SQLite database at $STORE/index.db with MessagePack-encoded values. This reduces filesystem syscall overhead, improves space efficiency for small metadata entries, and enables concurrent access via SQLite's WAL mode. Packages missing from the new index are re-fetched on demand #10500 #10826.

    Global Packages

    • Global installs (pnpm add -g pkg) and pnpm dlx now use the global virtual store by default. Packages are stored at {storeDir}/links instead of per-project .pnpm directories. This can be disabled by setting enableGlobalVirtualStore: false #10694.

    • Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own package.json, node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.

      Key changes:

      • pnpm add -g <pkg> creates an isolated installation in {pnpmHomeDir}/global/v11/{hash}/
      • pnpm remove -g <pkg> removes the entire installation group containing the package
      • pnpm update -g [pkg] re-installs packages in new isolated directories
      • pnpm list -g scans isolated directories to show all installed global packages
      • pnpm install -g (no args) is no longer supported; use pnpm add -g <pkg> instead

    Configuration

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    • Breaking changes to pnpm link:

      • pnpm link <pkg-name> no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, use pnpm link ./foo instead of pnpm link foo.
      • pnpm link --global is removed. Use pnpm add -g . to register a local package's bins globally.
      • pnpm link (no arguments) is removed. Use pnpm link <dir> with an explicit path instead.
    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    Minor Changes

    • 7fab2a2: Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • cb367b9: Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • 075aa99: Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • e146e98: Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • 7d5ada0: pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    • 5bf7768: A new --yes flag can be passed to pnpm to automatically confirm prompts. This is useful when running pnpm in non-interactive script.

    • 2b14c74: When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    • Added pnpm sbom command for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088.

    • Allow loading certificates from cert, ca, and key for specific registry URLs. E.g., //registry.example.com/:ca=-----BEGIN CERTIFICATE-----.... Previously this was only working via certfile, cafile, and keyfile #10230.

    • Added --all flag to pnpm approve-builds that approves all pending builds without interactive prompts #10136.

    • Added a new setting blockExoticSubdeps that prevents the resolution of exotic protocols in transitive dependencies #10265.

    • Added trustPolicyIgnoreAfter, which allows you to ignore trust policy checks for packages published more than a specified time ago #10352.

    • Added a new flag called --bare to pnpm init for creating a package.json with the bare minimum of required fields #10226.

    • Added support for allowBuilds, which is a new field that can be used instead of onlyBuiltDependencies and ignoredBuiltDependencies #10311.

    • Added support for object type in configDependencies when the tarball URL returned from package metadata differs from the computed URL #10431.

    • The pnpm dlx / pnpx command now supports the catalog: protocol. Example: pnpm dlx shx@catalog:.

    • Add support for a hook called beforePacking that can be used to customize the package.json contents at publish time #3816.

    • On systems using the musl C library (e.g. Alpine Linux), pnpm env use now automatically downloads the musl variant of Node.js. pnpm env add and pnpm env remove subcommands have been removed. pnpm env list now only lists remote Node.js versions.

    • Added support for --dry-run to the pack command #10301.

    • Added mark-and-sweep garbage collection for global virtual store. pnpm store prune now removes unused packages from the global virtual store's links/ directory.

    • Semi-breaking. Changed the location of unscoped packages in the virtual global store. They will now be stored under a directory named @ to maintain a uniform 4-level directory depth.

    • Support configuring auditLevel in the pnpm-workspace.yaml file #10540.

    • Support bare workspace: protocol without version specifier. It is now treated as workspace:* and resolves to the concrete version during publish #10436.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    • Added a new command pnpm runtime set <runtime name> <runtime version spec> [-g] for installing runtimes. Deprecated pnpm env use in favor of the new command.

    • Added pnpm clean command that safely removes node_modules directories from all workspace projects #10707. Use --lockfile to also remove pnpm-lock.yaml files.

    • Increase the network concurrency on machines with many CPU cores #10068.

    • Added support for trustPolicyExclude #10164.

    • Compute integrity hash for HTTP tarball dependencies when fetching, storing it in the lockfile to prevent servers from serving altered content on subsequent installs #10287.

    • Added support for automatic Node.js runtime installation for dependencies. pnpm will now install the Node.js version required by a dependency if that dependency declares a Node.js runtime in the engines field #10141.

    • Allow overriding the engines field on publish by the publishConfig.engines field.

    • Changed default values: optimisticRepeatInstall is now true and verifyDepsBeforeRun is now install.

    • Added a new setting: trustPolicy. When set to no-downgrade, pnpm will fail installation if a package's trust level has decreased compared to previous releases #8889.

    • Support .pnpmfile.mjs as the default pnpmfile. When .pnpmfile.mjs exists, it takes priority over .pnpmfile.cjs and only one is loaded.

    • Added -F as a short alias for the --filter option.

    • When the global virtual store is enabled, packages that are not allowed to build (and don't transitively depend on packages that are) now get hashes that don't include the engine name (platform, architecture, Node.js major version). This means ~95% of packages in the GVS survive Node.js upgrades and architecture changes without re-import #10837.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  9. 11.0.0-alpha.121 Mar 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.

    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.

    • Store version bumped to v11.

    • Switched internal store and cache files from JSON to MessagePack format for improved performance.

      This change migrates all internal index files and metadata cache files to use MessagePack serialization instead of JSON. MessagePack provides faster serialization/deserialization and more compact file sizes, resulting in improved installation performance.

      Related PR: #10500

    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.

    Global Packages

    • Global installs (pnpm add -g pkg) and pnpm dlx now use the global virtual store by default. Packages are stored at {storeDir}/links instead of per-project .pnpm directories. This can be disabled by setting enableGlobalVirtualStore: false #10694.

    • Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own package.json, node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.

      Key changes:

      • pnpm add -g <pkg> creates an isolated installation in {pnpmHomeDir}/global/v11/{hash}/
      • pnpm remove -g <pkg> removes the entire installation group containing the package
      • pnpm update -g [pkg] re-installs packages in new isolated directories
      • pnpm list -g scans isolated directories to show all installed global packages
      • pnpm install -g (no args) is no longer supported; use pnpm add -g <pkg> instead

    Configuration

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    • Breaking changes to pnpm link:

      • pnpm link <pkg-name> no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, use pnpm link ./foo instead of pnpm link foo.
      • pnpm link --global is removed. Use pnpm add -g . to register a local package's bins globally.
      • pnpm link (no arguments) is removed. Use pnpm link <dir> with an explicit path instead.
    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    Minor Changes

    • 7fab2a2: Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • cb367b9: Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • 075aa99: Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • e146e98: Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • 7d5ada0: pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    • 5bf7768: A new --yes flag can be passed to pnpm to automatically confirm prompts. This is useful when running pnpm in non-interactive script.

    • 2b14c74: When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    • Added pnpm sbom command for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088.

    • Allow loading certificates from cert, ca, and key for specific registry URLs. E.g., //registry.example.com/:ca=-----BEGIN CERTIFICATE-----.... Previously this was only working via certfile, cafile, and keyfile #10230.

    • Added --all flag to pnpm approve-builds that approves all pending builds without interactive prompts #10136.

    • Added a new setting blockExoticSubdeps that prevents the resolution of exotic protocols in transitive dependencies #10265.

    • Added trustPolicyIgnoreAfter, which allows you to ignore trust policy checks for packages published more than a specified time ago #10352.

    • Added a new flag called --bare to pnpm init for creating a package.json with the bare minimum of required fields #10226.

    • Added support for allowBuilds, which is a new field that can be used instead of onlyBuiltDependencies and ignoredBuiltDependencies #10311.

    • Added support for object type in configDependencies when the tarball URL returned from package metadata differs from the computed URL #10431.

    • The pnpm dlx / pnpx command now supports the catalog: protocol. Example: pnpm dlx shx@catalog:.

    • Add support for a hook called beforePacking that can be used to customize the package.json contents at publish time #3816.

    • On systems using the musl C library (e.g. Alpine Linux), pnpm env use now automatically downloads the musl variant of Node.js. pnpm env add and pnpm env remove subcommands have been removed. pnpm env list now only lists remote Node.js versions.

    • Added support for --dry-run to the pack command #10301.

    • Added mark-and-sweep garbage collection for global virtual store. pnpm store prune now removes unused packages from the global virtual store's links/ directory.

    • Semi-breaking. Changed the location of unscoped packages in the virtual global store. They will now be stored under a directory named @ to maintain a uniform 4-level directory depth.

    • Support configuring auditLevel in the pnpm-workspace.yaml file #10540.

    • Support bare workspace: protocol without version specifier. It is now treated as workspace:* and resolves to the concrete version during publish #10436.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    • Added a new command pnpm runtime set <runtime name> <runtime version spec> [-g] for installing runtimes. Deprecated pnpm env use in favor of the new command.

    • Added pnpm clean command that safely removes node_modules directories from all workspace projects #10707. Use --lockfile to also remove pnpm-lock.yaml files.

    • Increase the network concurrency on machines with many CPU cores #10068.

    • Added support for trustPolicyExclude #10164.

    • Compute integrity hash for HTTP tarball dependencies when fetching, storing it in the lockfile to prevent servers from serving altered content on subsequent installs #10287.

    • Added support for automatic Node.js runtime installation for dependencies. pnpm will now install the Node.js version required by a dependency if that dependency declares a Node.js runtime in the engines field #10141.

    • Allow overriding the engines field on publish by the publishConfig.engines field.

    • Changed default values: optimisticRepeatInstall is now true and verifyDepsBeforeRun is now install.

    • Added a new setting: trustPolicy. When set to no-downgrade, pnpm will fail installation if a package's trust level has decreased compared to previous releases #8889.

    • Support .pnpmfile.mjs as the default pnpmfile. When .pnpmfile.mjs exists, it takes priority over .pnpmfile.cjs and only one is loaded.

    • Added -F as a short alias for the --filter option.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  10. 11.0.0-alpha.1124 Feb 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.

    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.

    • Store version bumped to v11.

    • Switched internal store and cache files from JSON to MessagePack format for improved performance.

      This change migrates all internal index files and metadata cache files to use MessagePack serialization instead of JSON. MessagePack provides faster serialization/deserialization and more compact file sizes, resulting in improved installation performance.

      Related PR: #10500

    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.

    Configuration

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    Minor Changes

    • 7fab2a2: Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • cb367b9: Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • 075aa99: Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • e146e98: Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • 7d5ada0: pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    • 5bf7768: A new --yes flag can be passed to pnpm to automatically confirm prompts. This is useful when running pnpm in non-interactive script.

    • 2b14c74: When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  11. 11.0.0-alpha.1023 Feb 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.

    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.

    • Store version bumped to v11.

    • Switched internal store and cache files from JSON to MessagePack format for improved performance.

      This change migrates all internal index files and metadata cache files to use MessagePack serialization instead of JSON. MessagePack provides faster serialization/deserialization and more compact file sizes, resulting in improved installation performance.

      Related PR: #10500

    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.

    Configuration

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    Minor Changes

    • 7fab2a2: Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • cb367b9: Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • 075aa99: Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • e146e98: Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • 7d5ada0: pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    • 5bf7768: A new --yes flag can be passed to pnpm to automatically confirm prompts. This is useful when running pnpm in non-interactive script.

    • 2b14c74: When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  12. 11.0.0-alpha.923 Feb 2026pre-release

    Nothing published for this version

  13. 11.0.0-alpha.823 Feb 2026pre-release

    Nothing published for this version

  14. 11.0.0-alpha.722 Feb 2026pre-release

    Nothing published for this version

  15. 11.0.0-alpha.622 Feb 2026pre-release

    Nothing published for this version

  16. 11.0.0-alpha.517 Feb 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.

    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.

    • Store version bumped to v11.

    • Switched internal store and cache files from JSON to MessagePack format for improved performance.

      This change migrates all internal index files and metadata cache files to use MessagePack serialization instead of JSON. MessagePack provides faster serialization/deserialization and more compact file sizes, resulting in improved installation performance.

      Related PR: #10500

    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.

    Configuration

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    Minor Changes

    • Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    • A new --yes flag can be passed to pnpm to automatically confirm prompts. This is useful when running pnpm in non-interactive script.

    • When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  17. 11.0.0-alpha.417 Feb 2026pre-release
    Release notes

    Major Changes

    Store

    • Runtime dependencies are always linked from the global virtual store #10233.

    • Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups.

    • Store version bumped to v11.

    • Switched internal store and cache files from JSON to MessagePack format for improved performance.

      This change migrates all internal index files and metadata cache files to use MessagePack serialization instead of JSON. MessagePack provides faster serialization/deserialization and more compact file sizes, resulting in improved installation performance.

      Related PR: #10500

    • Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read package.json from the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473.

    Configuration

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config get <array> now prints a JSON array.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      

    Other

    • This package is now pure ESM.

    • Node.js v18, 19, 20, and 21 support discontinued.

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • strictDepBuilds is true by default.

    • blockExoticSubdeps is true by default.

    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      
    • Removed the deprecated allowNonAppliedPatches completely in favor of allowUnusedPatches. Remove ignorePatchFailures so all patch application failures should throw an error.

    • Removed the pnpm server command #10463.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Removed support for hooks.fetchers. We now have a new API for custom fetchers and resolvers via the fetchers field of pnpmfile.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • pnpm publish now works without the npm CLI.

      The One-time Password feature now reads from PNPM_CONFIG_OTP instead of NPM_CONFIG_OTP:

      export PNPM_CONFIG_OTP='<your OTP here>'
      pnpm publish --no-git-checks
      

      Since the new pnpm publish no longer calls npm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can use pnpm pack && npm publish *.tgz as a workaround.

    Minor Changes

    • Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • Support reading allowBuilds from pnpm-workspace.yaml in the global package directory for global installs.

    • Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    • A new --yes flag can be passed to pnpm to automatically confirm prompts. This is useful when running pnpm in non-interactive script.

    • When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    Patch Changes

    • Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.

    • Explicitly tell npm the path to the global rc config file.

    • Fix YAML formatting preservation in pnpm-workspace.yaml when running commands like pnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.

      Closes #10425

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  18. 11.0.0-alpha.313 Jan 2026pre-release
    Release notes

    Major Changes

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • Replace workspace project specific .npmrc with packageConfigs in pnpm-workspace.yaml.

      A workspace manifest with packageConfigs would look something like this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        "project-1":
          saveExact: true
        "project-2":
          savePrefix: "~"
      

      Or this:

      # File: pnpm-workspace.yaml
      packages:
        - "packages/project-1"
        - "packages/project-2"
      packageConfigs:
        - match: ["project-1", "project-2"]
          modulesDir: "node_modules"
          saveExact: true
      
    • strictDepBuilds is true by default.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • blockExoticSubdeps is true by default.

    • This package is now pure ESM.

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • The pnpm CLI now gets installed with a specific version of Node.js, which it uses for its runtime. This makes pnpm more stable and it doesn't rely on your globally install Node.js anymore.

    • Node.js v18 and 19 support discontinued.

    • pnpm config get <array> now prints a JSON array.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • Runtime dependencies are always linked from the global virtual store #10233.

    • Removed support for the useNodeVersion and executionEnv.nodeVersion fields. devEngines.runtime and engines.runtime should be used instead #10373.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info
    • Remove deprecated build dependency settings: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, and ignoredBuiltDependencies.

      Use the allowBuilds setting instead. It is a map where keys are package name patterns and values are booleans:

      • true means the package is allowed to run build scripts
      • false means the package is explicitly denied from running build scripts

      Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in allowBuilds, an error is printed.

      Before:

      onlyBuiltDependencies:
        - electron
      onlyBuiltDependenciesFile: "allowed-builds.json"
      neverBuiltDependencies:
        - core-js
      ignoredBuiltDependencies:
        - esbuild
      

      After:

      allowBuilds:
        electron: true
        core-js: false
        esbuild: false
      

    Minor Changes

    • Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    • When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  19. 11.0.0-alpha.215 Dec 2025pre-release
    Release notes

    Major Changes

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • This package is now pure ESM.

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • The pnpm CLI now gets installed with a specific version of Node.js, which it uses for its runtime. This makes pnpm more stable and it doesn't rely on your globally install Node.js anymore.

    • Node.js v18 and 19 support discontinued.

    • pnpm config get <array> now prints a JSON array.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • JSON files in the store and cache are replaced with binary files generated with v8.serialize.

      Reading and deserializing a binary file generated with v8.serialize appears to be about 23% faster than reading and parsing a JSON file. Other operations are similar in speed. Therefore, we have switched to V8 binary files for storing data in pnpm’s global store and cache. The disadvantage of this approach is that V8 files generated by newer versions of Node.js cannot be deserialized by older versions. In such cases, we ignore the cache.

      Related PR: #9971.

    • Runtime dependencies are always linked from the global virtual store #10233.

    • Support lowercase options in pnpm add: -d, -p, -o, -e #9197.

      When using pnpm add command only:

      • -p is now an alias for --save-prod instead of --parseable
      • -d is now an alias for --save-dev instead of --loglevel=info

    Minor Changes

    • Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    Patch Changes

    • Explicitly tell npm the path to the global rc config file.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  20. 11.0.0-alpha.113 Nov 2025pre-release

    Nothing published for this version

  21. 11.0.0-alpha.013 Nov 2025pre-release
    Release notes

    Major Changes

    • pnpm config get (without --json) no longer print INI formatted text. Instead, it would print JSON for both objects and arrays and raw string for strings, numbers, booleans, and nulls. pnpm config get --json would still print all types of values as JSON like before.

    • pnpm config list and pnpm config get (without argument) now hide auth-related settings.

    • This package is now pure ESM.

    • pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in pnpm-workspace.yaml.

    • The pnpm CLI now gets installed with a specific version of Node.js, which it uses for its runtime. This makes pnpm more stable and it doesn't rely on your globally install Node.js anymore.

    • Node.js v18 and 19 support discontinued.

    • pnpm config get <array> now prints a JSON array.

    • The default value of the type field in the package.json file of the project initialized by pnpm init command has been changed to module.

    • pnpm config list and pnpm config get (without argument) now show top-level keys as camelCase. Exception: Keys that start with @ or // would be preserved (their cases don't change).

    • The standalone exe version of pnpm requires at least glibc 2.27.

    • pnpm config list now prints a JSON object instead of INI formatted text.

    • pnpm config get and pnpm config list no longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml).

    • JSON files in the store and cache are replaced with binary files generated with v8.serialize.

      Reading and deserializing a binary file generated with v8.serialize appears to be about 23% faster than reading and parsing a JSON file. Other operations are similar in speed. Therefore, we have switched to V8 binary files for storing data in pnpm’s global store and cache. The disadvantage of this approach is that V8 files generated by newer versions of Node.js cannot be deserialized by older versions. In such cases, we ignore the cache.

      Related PR: #9971.

    Minor Changes

    • Load environment variables whose names start with pnpm_config_ into config. These environment variables override settings from pnpm-workspace.yaml but not the CLI arguments.

    • Add support for a global YAML config file named config.yaml.

      Now configurations are divided into 2 categories:

      • Registry and auth settings which can be stored in INI files such as global rc and local .npmrc.
      • pnpm-specific settings which can only be loaded from YAML files such as global config.yaml and local pnpm-workspace.yaml.
    • Added support for pnpmfiles written in ESM. They should have the .mjs extension: .pnpmfile.mjs #9730.

    Patch Changes

    • Explicitly tell npm the path to the global rc config file.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  22. 10.34.510 Jul 2026
    Release notes

    Patch Changes

    • 78e29fe: Prevent a crafted pnpm-lock.yaml from writing package content outside the virtual store. A dependency path key whose name reconstructs to a path-traversal sequence (e.g. ../../../tmp/[email protected]) is now rejected by the isolated (virtual-store) linker and the Plug'n'Play resolver map, matching the containment already applied to the hoisted linker. Under the global virtual store, a traversal in the version-derived path segment (e.g. a snapshot version: "../../x") is now rejected at iterateHashedGraphNodes, the single point every global-virtual-store slot path funnels through.
    • 78e29fe: Fixed a path traversal vulnerability where a dependency whose manifest name was a scoped path traversal (e.g. @x/../../../<path>) could be written outside node_modules to an attacker-controlled location during pnpm install, even with --ignore-scripts. The isolated linker now validates the package name before using it as a directory name, matching the existing protection in the hoisted linker.
    • 47ef6f0: Fixed switching to and self-updating to pnpm v12. pnpm v12 (the Rust port) ships as the pnpm and @pnpm/exe npm packages whose bins are placeholders replaced at install time by the host's native binary from a @pnpm/exe.<platform>-<arch>[-musl] optional dependency. Because pnpm installs its own engine with --ignore-scripts, that relinking never ran, leaving a non-executable placeholder. pnpm now relinks the native binary itself for v12 (recognizing the new platform-package naming scheme and the native pnpm package), and verifies the native binary's npm registry signature before running it.
    • 36928be: ${...} environment-variable placeholders in the httpProxy, httpsProxy, noProxy, proxy, and noproxy settings are no longer expanded when these settings come from a project's pnpm-workspace.yaml. They now receive the same protection already applied to registry.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  23. 10.34.418 Jun 2026
    Release notes

    Patch Changes

    • 352ae48: Security: validate config dependency names and versions before using them to build filesystem paths. A pnpm-workspace.yaml with a traversal-shaped configDependencies name (such as ../../PWNED) or version (such as ../../../PWNED) could previously cause pnpm install to create symlinks or write package files outside node_modules/.pnpm-config and the store. Names must now be valid npm package names and versions must be exact semver versions. See GHSA-qrv3-253h-g69c.

    • 352ae48: Reject path-traversal and reserved dependency aliases (such as ../../../escape, .bin, .pnpm, or node_modules) that come from a lockfile rather than a freshly resolved manifest. A crafted lockfile alias could otherwise be joined directly under a hoisted node_modules directory, letting package files be written outside the intended install root or overwrite pnpm-owned layout.

      The nodeLinker: hoisted graph builder now validates each alias at the directory sink (safeJoinModulesDir), matching the validation pnpm already performs when resolving aliases from manifests. See GHSA-fr4h-3cph-29xv.

    • 352ae48: Prevent pnpm patch-remove from removing files outside the configured patches directory.

    • 217fbe0: Hardened the warning printed when a project .npmrc uses environment variables in registry/auth settings: the suggested pnpm config set command is now only included for keys made up of shell-inert characters. Because the key comes from a repository-controlled .npmrc and a shell expands $(...), backticks, and $VAR even inside double quotes, a crafted key could otherwise have turned the suggested copy-paste command into command execution.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  24. 10.34.311 Jun 2026
    Release notes

    ⚠️ Security fix — environment variables in a project .npmrc (action may be required)

    Following GHSA-3qhv-2rgh-x77r, pnpm no longer expands ${ENV_VAR} placeholders that come from a repository-controlled config file, because a malicious repository could otherwise use them to leak your environment secrets (npm tokens, CI job tokens, etc.) to an attacker-controlled registry during install. This applies to:

    • the project/workspace .npmrcregistry, @scope:registry, proxy URLs, URL-scoped keys (//host/…), and credential values (_authToken, _auth, _password, username, tokenHelper, cert, key);
    • registry URLs in pnpm-workspace.yaml.

    This release also closes a bypass where a project .npmrc could set userconfig, globalconfig, or prefix to make pnpm load a repo-supplied file as trusted config (via @pnpm/[email protected]).

    Environment variables are still expanded in trusted config: your user-level ~/.npmrc, the global config, CLI options, and environment config.

    If your authentication broke after upgrading, move the token out of the committed .npmrc:

    # Writes to your user/global config, not the repository:
    pnpm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN"
    

    Or keep the ${NPM_TOKEN} line but put it in your user-level ~/.npmrc instead of the repo. In GitHub Actions, actions/setup-node with registry-url already writes a user-level .npmrc, so NODE_AUTH_TOKEN keeps working. For other CI where editing each pipeline is hard, set NPM_CONFIG_USERCONFIG=.npmrc in the CI environment to declare the project .npmrc trusted.

    See https://pnpm.io/npmrc for full migration details.

    Patch Changes

    • Improved the warning printed when a project .npmrc uses an environment variable in a registry/proxy URL or in registry credentials. The message now explains why the setting was ignored and how to migrate it to a trusted source — for example by running pnpm config set "<key>" <value> to store it in the global config, or by keeping the ${...} line in the user-level ~/.npmrc — with a link to https://pnpm.io/npmrc.
    • A repository-controlled project or workspace .npmrc can no longer redirect which files pnpm loads as its trusted user and global configuration. Previously such a file could set userconfig, globalconfig, or prefix to point at an attacker-supplied file shipped in the repository, and pnpm would load it as a trusted config source — bypassing the protection that prevents repository config from expanding environment variables into registry request destinations and credentials, and allowing it to set tokenHelper. The user/global config file locations are now resolved only from trusted sources (CLI options, environment config, the npm builtin config, and defaults) before the project and workspace .npmrc files are read. Fixed by upgrading @pnpm/npm-conf to 3.0.3.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  25. 10.34.210 Jun 2026
    Release notes

    ⚠️ Security fix — environment variables in a project .npmrc (action may be required)

    Following GHSA-3qhv-2rgh-x77r, pnpm no longer expands ${ENV_VAR} placeholders that come from a repository-controlled config file, because a malicious repository could otherwise use them to leak your environment secrets (npm tokens, CI job tokens, etc.) to an attacker-controlled registry during install. This applies to:

    • the project/workspace .npmrcregistry, @scope:registry, proxy URLs, URL-scoped keys (//host/…), and credential values (_authToken, _auth, _password, username, tokenHelper, cert, key);
    • registry URLs in pnpm-workspace.yaml.

    This release also closes a bypass where a project .npmrc could set userconfig, globalconfig, or prefix to make pnpm load a repo-supplied file as trusted config (via @pnpm/[email protected]).

    Environment variables are still expanded in trusted config: your user-level ~/.npmrc, the global config, CLI options, and environment config.

    If your authentication broke after upgrading, move the token out of the committed .npmrc:

    # Writes to your user/global config, not the repository:
    pnpm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN"
    

    Or keep the ${NPM_TOKEN} line but put it in your user-level ~/.npmrc instead of the repo. In GitHub Actions, actions/setup-node with registry-url already writes a user-level .npmrc, so NODE_AUTH_TOKEN keeps working. For other CI where editing each pipeline is hard, set NPM_CONFIG_USERCONFIG=.npmrc in the CI environment to declare the project .npmrc trusted.

    See https://pnpm.io/npmrc for full migration details.

    Patch Changes

    • Package-manager bootstrap traffic is now resolved through trusted registries and trusted network config. When pnpm downloads the pnpm version requested by a repository's packageManager field, the registry it fetches from (and the proxy/TLS settings used for that traffic) now come exclusively from trusted config sources — CLI options, env config, user and global .npmrc — defaulting to the public npm registry, instead of the repository's project/workspace settings.
    • pnpm now verifies the npm registry signature of a package-manager binary before spawning it. When the packageManager field (or pnpm self-update) makes pnpm download another pnpm version, the staged install is verified corepack-style: the integrity recorded in the staged lockfile must carry a valid npm registry signature for the exact name@version, validated against npm's public signing keys that ship embedded in the pnpm CLI. Verification fails closed — a tampered download, an unsigned package, or an unreachable registry refuses the version switch rather than running an unverified binary. It runs only when the wanted version is actually downloaded (a tools-directory cache miss), so repeated commands pay no extra network round trip.
    • Environment variable expansion is now trust-aware for registry/auth config and request destinations. Repository-controlled config files (the project and workspace .npmrc and pnpm-workspace.yaml) can no longer expand ${...} placeholders in registry/proxy request destinations, URL-scoped keys, or registry credential values, preventing repository-controlled configuration from exfiltrating environment secrets through request URLs. Trusted user/global/CLI/env config keeps full env expansion, so existing token and registry setup flows continue to work.
    • Reject reserved manifest bin names ("", ".", "..", and scoped forms such as @scope/..) when resolving a package's bins. These names previously passed the bin-name guard and, when joined to the global bin directory during global remove/update/add operations, could resolve to the global bin directory itself or its parent and have it recursively deleted.
    • Require trusted package identity before package-name onlyBuiltDependencies (and allowBuilds) entries can approve lifecycle scripts for git, git-hosted tarball, direct tarball, and local directory artifacts. To approve one of those artifacts explicitly, use its peer-suffix-free lockfile depPath as the key. Lockfile entries are now rejected when a registry-style dependency path (name@semver) is backed by a git, directory, or git-hosted tarball resolution (ERR_PNPM_RESOLUTION_SHAPE_MISMATCH), so the dependency path is a reliable artifact identity by the time scripts can run.
    • pnpm now verifies the detached OpenPGP signature of a Node.js release's SHASUMS256.txt against the Node.js release team's public keys (embedded in the pnpm CLI) before trusting its hashes. The Node.js download mirror is repository-configurable (node-mirror:<channel> in .npmrc), and the integrity check previously trusted a SHASUMS256.txt fetched from that same mirror — a circular check that a malicious mirror could satisfy with a tampered binary and matching hashes. A mirror that proxies the real signed SHASUMS keeps working unchanged. Only the release channel publishes signed SHASUMS files, so pre-release channels (rc, nightly, …) remain unverified.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  26. 10.34.127 May 2026
    Release notes

    Patch Changes

    • Reject pnpm-lock.yaml entries whose remote tarball resolution: block is missing the integrity field. Previously the worker that extracts a downloaded tarball skipped hash verification when no integrity was supplied and minted a fresh one from the unverified bytes, so an attacker who could both alter the lockfile (e.g. via a pull request that strips integrity:) and serve modified content at the referenced tarball URL could install a tampered package without any error — including under --frozen-lockfile. pnpm now fails closed at lockfile-read time with ERR_PNPM_MISSING_TARBALL_INTEGRITY. Git-hosted tarballs (gitHosted: true or a URL on codeload.github.com / bitbucket.org / gitlab.com) and file: tarballs are exempt — the commit SHA in a git-host URL and the user-controlled local path already anchor the bytes.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  27. 10.34.027 May 2026
    Release notes

    Minor Changes

    • Treat tarball-integrity mismatches against the lockfile as a hard failure by default. Previously, pnpm install (non-frozen) would log ERR_PNPM_TARBALL_INTEGRITY, silently re-resolve from the registry, and overwrite the locked integrity — which meant a compromised registry, proxy, or republished version could substitute attacker-controlled content on a clean machine even though the project shipped a committed lockfile.

      pnpm install now exits with ERR_PNPM_TARBALL_INTEGRITY and a hint pointing at the new opt-in flag.

      The only opt-in is pnpm install --update-checksums — narrowly scoped to refreshing the locked integrity values from what the registry currently serves. Mirrors yarn's flag of the same name. A warning still prints when the bypass takes effect so the operation is auditable.

      --force and pnpm update deliberately do not bypass the integrity check. They are routine refresh operations; silently overwriting a locked integrity in those flows would erase the protection a committed lockfile is supposed to provide. --frozen-lockfile behavior is unchanged. --fix-lockfile keeps its documented purpose (filling in missing lockfile entries) and is also not a bypass.

    Patch Changes

    • Pin unscoped per-registry settings (_authToken, _auth, username/_password, tokenHelper, inline cert/key) to the registry declared in the same config source at load time, so a later layer overriding registry= (workspace .npmrc, pnpm-workspace.yaml, CLI --registry) cannot redirect a credential or client certificate authored for a different host. A deprecation warning is emitted whenever an unscoped per-registry setting is encountered, naming the source and the URL it was pinned to. Reported by JUNYI LIU.
    • Fixed minimumReleaseAge handling when cached metadata is abbreviated. The npm registry returns abbreviated package metadata (without the per-version time field) by default, which made the maturity check throw ERR_PNPM_MISSING_TIME whenever cached abbreviated metadata was reused. pnpm now upgrades cached abbreviated metadata to the full document via a follow-up fetch when minimumReleaseAge is active, persists the upgrade to the on-disk cache so subsequent installs skip the extra fetch, and lets ERR_PNPM_MISSING_TIME from the cache fast-path fall through to the network fetch even under strict mode.
    • Reject git resolutions whose commit field is not a 40-character hexadecimal SHA before invoking git. A malicious lockfile could otherwise smuggle a value such as --upload-pack=<command> through git fetch / git checkout, which on SSH or local-file transports executes the supplied command.
    • Reject patch files whose diff --git headers reference paths outside the patched package directory. Previously a malicious .patch file added via a pull request could write, delete, or rename arbitrary files reachable by the user running pnpm install.
    • Fixed --prefix=<dir> not being honored when locating the workspace root. The --prefix → dir rename was applied after workspace detection, so workspace settings declared in <dir>/pnpm-workspace.yaml were not loaded when pnpm was invoked from outside <dir> #11535.
    • Reject dependency aliases that contain path-traversal segments (such as @x/../../../../../.git/hooks) when reading them from a package manifest or symlinking them into node_modules. A malicious registry package could otherwise use a transitive dependency key to make pnpm install create symlinks at attacker-chosen paths outside the intended node_modules directory.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  28. 10.33.46 May 2026
    Release notes

    Patch Changes

    • Pin the integrity of git-hosted tarballs (codeload.github.com, gitlab.com, bitbucket.org) in the lockfile so that subsequent installs detect a tampered or substituted tarball and refuse to install it. Previously the lockfile only stored the tarball URL for git dependencies, so a compromised git host or a man-in-the-middle could serve arbitrary code on later installs without lockfile changes.

      A new gitHosted: true field is recorded on git-hosted tarball resolutions in the lockfile, letting every reader/writer route them by a single typed check instead of pattern-matching the tarball URL in each call site. Lockfiles written by older pnpm versions are enriched on load (URL fallback) so the field can be relied on uniformly across the codebase.

    • Fix a regression where pnpm --recursive --filter '!<pkg>' run/exec/test/add would include the workspace root in the matched projects. The workspace root is now correctly excluded by default when only negative --filter arguments are provided, matching the documented behavior. To include the root, pass --include-workspace-root #11341.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  29. 10.33.34 May 2026
    Release notes

    Patch Changes

    • When self-updating from v10's @pnpm/exe to v11+ on Intel macOS (darwin-x64), pnpm self-update now transparently switches to the JS-only pnpm package on npm instead of installing @pnpm/exe@v11+ (which doesn't ship a working binary for Intel Macs because of an upstream Node.js SEA bug — see #11423 and nodejs/node#62893). Without this, the self-update would silently leave the user with no working pnpm binary. The new install requires Node.js to be available on PATH; a warning is printed when the swap happens. All other host/version combinations are unchanged.
    • pnpm self-update (with no version argument) no longer downgrades pnpm when the registry's latest dist-tag points to an older release than the currently active version. Run pnpm self-update latest to force a downgrade #11418.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  30. 10.33.223 Apr 2026
    Release notes

    Patch Changes

    • Globally-installed bins no longer fail with ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND when pnpm was installed via the standalone @pnpm/exe binary (e.g. curl -fsSL https://get.pnpm.io/install.sh | sh -) on a system without a separate Node.js installation. Previously, when which('node') failed during pnpm add --global, pnpm fell back to process.execPath, which in @pnpm/exe is the pnpm binary itself — and that path was baked into the generated bin shim, causing the shim to invoke pnpm instead of Node #11291, #4645.

    • Fix an infinite fork-bomb that could happen when pnpm was installed with one version (e.g. npm install -g pnpm@A) and run inside a project whose package.json selected a different pnpm version via the packageManager field (e.g. pnpm@B), while a pnpm-workspace.yaml also existed at the project root.

      The child's environment is now forced to manage-package-manager-versions=false (v10) and pm-on-fail=ignore (v11+), which disables the package-manager-version handling in whichever pnpm runs as the child.

      Fixes #11337.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  31. 10.33.122 Apr 2026
    Release notes

    Patch Changes

    • When a project's packageManager field selects pnpm v11 or newer, commands that v10 would have passed through to npm (version, login, logout, publish, unpublish, deprecate, dist-tag, docs, ping, search, star, stars, unstar, whoami, etc.) are now handed over to the wanted pnpm, which implements them natively. Previously they silently shelled out to npm — making, for example, pnpm version --help print npm's help on a project with packageManager: [email protected] #11328.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  32. 10.33.024 Mar 2026
    Release notes

    Minor Changes

    • Added a new dedupePeers setting that reduces peer dependency duplication. When enabled, peer dependency suffixes use version-only identifiers (name@version) instead of full dep paths, eliminating nested suffixes like ([email protected]([email protected])). This dramatically reduces the number of package instances in projects with many recursive peer dependencies #11070.

    Patch Changes

    • Fail on incompatible lockfiles in CI when frozen lockfile mode is enabled, while preserving non-frozen CI fallback behavior.

    • When package metadata is malformed or can't be fetched, the error thrown will now show the originating error.

    • Fixed intermittent failures when multiple pnpm dlx calls run concurrently for the same package. When the global virtual store is enabled, the importer now verifies file content before skipping a rename, avoiding destructive swap-renames that break concurrent processes. Also tolerates EPERM during bin creation on Windows and properly propagates enableGlobalVirtualStore through the install pipeline.

    • Fixed handling of non-string version selectors in hoistPeers, preventing invalid peer dependency specifiers.

    • Improve the non-interactive modules purge error hint to include the confirmModulesPurge=false workaround.

      When pnpm needs to recreate node_modules but no TTY is available, the error now suggests either setting CI=true or disabling the purge confirmation prompt via confirmModulesPurge=false.

      Adds a regression test for the non-TTY flow.

    • Fixed false "Command not found" errors on Windows when a command exists in PATH but exits with a non-zero code. Also fixed path resolution for --filter contexts where the command runs in a different package directory.

    • When a pnpm-lock.yaml contains two documents, ignore the first one. pnpm v11 will write two lockfile documents into pnpm-lock.yaml in order to store pnpm version integrities and config dependency resolutions.

    • Fixed a bug preventing the clearCache function returned by createNpmResolver from properly clearing metadata cache.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  33. 10.32.111 Mar 2026
    Release notes

    Patch Changes

    • Fix a regression where pnpm-workspace.yaml without a packages field caused all directories to be treated as workspace projects. This broke projects that use pnpm-workspace.yaml only for settings (e.g. minimumReleaseAge) without defining workspace packages #10909.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  34. 10.32.09 Mar 2026
    Release notes

    Minor Changes

    • Added --all flag to pnpm approve-builds that approves all pending builds without interactive prompts #10136.

    Patch Changes

    • Reverted change related to setting explicitly the npm config file path, which caused regressions.
    • Reverted fix related to lockfile-include-tarball-url. Fixes #10915.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  35. 10.31.07 Mar 2026
    Release notes

    Minor Changes

    • When pnpm updates the pnpm-workspace.yaml, comments, string formatting, and whitespace will be preserved.

    Patch Changes

    • Added -F as a short alias for the --filter option in the help output.

    • Handle undefined pkgSnapshot in pnpm why -r #10700.

    • Fix headless install not being used when a project has an injected self-referencing file: dependency that resolves to link: in the lockfile.

    • Fixed a race condition when multiple worker threads import the same package to the global virtual store concurrently. The rename operation now tolerates ENOTEMPTY/EEXIST errors if another thread already completed the import.

    • When lockfile-include-tarball-url is set to false, tarball URLs are now always excluded from the lockfile. Previously, tarball URLs could still appear for packages hosted under non-standard URLs, making the behavior flaky and inconsistent #6667.

    • Fixed optimisticRepeatInstall skipping install when overrides, packageExtensions, ignoredOptionalDependencies, patchedDependencies, or peersSuffixMaxLength changed.

    • Fixed pnpm patch-commit failing with "unable to access '/.config/git/attributes': Permission denied" error in environments where HOME is unset or non-standard (Docker containers, CI systems).

      The issue occurred because pnpm was setting HOME and the Windows user profile env var to empty strings to suppress user git configuration when running git diff. This caused git to resolve the home directory (~) as root (/), leading to permission errors when attempting to access /.config/git/attributes.

      Now uses GIT_CONFIG_GLOBAL: os.devNull instead, which is git's proper mechanism for bypassing user-level configuration without corrupting the home directory path resolution.

      Fixes #6537

    • Fix pnpm why -r --parseable missing dependents when multiple workspace packages share the same dependency #8100.

    • Fix link-workspace-packages=true incorrectly linking workspace packages when the requested version doesn't match the workspace package's version. Previously, on fresh installs the version constraint is overridden to * in the fallback resolution paths, causing any workspace package with a matching name to be linked regardless of version #10173.

    • Fixed pnpm update --interactive table breaking with long version strings (e.g., prerelease versions like 7.0.0-dev.20251209.1) by dynamically calculating column widths instead of using hardcoded values #10316.

    • Explicitly tell npm the path to the global rc config file.

    • The parameter set by the --allow-build flag is written to allowBuilds.

    • Fix a bug in which specifying filter on pnpm-workspace.yaml would cause pnpm to not detect any projects.

    • Print help message on running pnpm dlx without arguments and exit.

    <!-- sponsors -->

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    <!-- sponsors end -->

    Open source →
  36. 10.30.326 Feb 2026
    Release notes

    Patch Changes

    • Fixed version switching via packageManager field failing when pnpm is installed as a standalone executable in environments without a system Node.js #10687.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  37. 10.30.223 Feb 2026
    Release notes

    Patch Changes

    • Fix auto-installed peer dependencies ignoring overrides when a stale version exists in the lockfile.
    • Fixed "input line too long" error on Windows when running lifecycle scripts with the global virtual store enabled #10673.
    • Update @zkochan/js-yaml to fix moderate vulnerability.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  38. 10.30.120 Feb 2026
    Release notes

    Patch Changes

    • Use the /-/npm/v1/security/audits/quick endpoint as the primary audit endpoint, falling back to /-/npm/v1/security/audits when it fails #10649.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  39. 10.30.017 Feb 2026
    Release notes

    Minor Changes

    • pnpm why now shows a reverse dependency tree. The searched package appears at the root with its dependents as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.

    Patch Changes

    • Revert pnpm why dependency pruning to prefer correctness over memory consumption. Reverted PR: #7122.
    • Optimize pnpm why and pnpm list performance in workspaces with many importers by sharing the dependency graph and materialization cache across all importers instead of rebuilding them independently for each one #10596.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  40. 10.29.311 Feb 2026
    Release notes

    Patch Changes

    • Fixed an out-of-memory error in pnpm list (and pnpm why) on large dependency graphs by replacing the recursive tree builder with a two-phase approach: a BFS dependency graph followed by cached tree materialization. Duplicate subtrees are now deduplicated in the output, shown as "deduped (N deps hidden)" #10586.
    • Fixed allowBuilds not working when set via .pnpmfile.cjs #10516.
    • When the enableGlobalVirtualStore option is set, the pnpm deploy command would incorrectly create symlinks to the global virtual store. To keep the deploy directory self-contained, pnpm deploy now ignores this setting and always creates a localized virtual store within the deploy directory.
    • Fixed minimumReleaseAgeExclude not being respected by pnpm dlx #10338.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" /> <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" /> <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" /> <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" /> </picture> </a> </td> </tr> </tbody> </table>

    Open source →
  41. 10.29.29 Feb 2026
    Release notes

    Patch Changes

    • Reverted a fix shipped in v10.29.1, which caused another issue #10571. Reverted fix: Fixed pnpm run -r failing with "No projects matched the filters" when an empty pnpm-workspace.yaml exists #10497.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  42. 10.29.17 Feb 2026
    Release notes

    Minor Changes

    • The pnpm dlx / pnpx command now supports the catalog: protocol. Example: pnpm dlx shx@catalog:.
    • Support configuring auditLevel in the pnpm-workspace.yaml file #10540.
    • Support bare workspace: protocol without version specifier. It is now treated as workspace:* and resolves to the concrete version during publish #10436.

    Patch Changes

    • Fixed pnpm list --json returning incorrect paths when using global virtual store #10187.

    • Fix pnpm store path and pnpm store status using workspace root for path resolution when storeDir is relative #10290.

    • Fixed pnpm run -r failing with "No projects matched the filters" when an empty pnpm-workspace.yaml exists #10497.

    • Fixed a bug where catalogMode: strict would write the literal string "catalog:" to pnpm-workspace.yaml instead of the resolved version specifier when re-adding an existing catalog dependency #10176.

    • Fixed the documentation URL shown in pnpm completion --help to point to the correct page at https://pnpm.io/completion #10281.

    • Skip local file: protocol dependencies during pnpm fetch. This fixes an issue where pnpm fetch would fail in Docker builds when local directory dependencies were not available #10460.

    • Fixed pnpm audit --json to respect the --audit-level setting for both exit code and output filtering #10540.

    • update tar to version 7.5.7 to fix security issue

      Updating the version of dependency tar to 7.5.7 because the previous one have a security vulnerability reported here: <a href="https://github.com/advisories/GHSA-34x7-hfp2-rc4v">CVE-2026-24842</a>

    • Fix pnpm audit --fix replacing reference overrides (e.g. $foo) with concrete versions #10325.

    • Fix shamefullyHoist set via updateConfig in .pnpmfile.cjs not being converted to publicHoistPattern #10271.

    • pnpm help should correctly report if the currently running pnpm CLI is bundled with Node.js #10561.

    • Add a warning when the current directory contains the PATH delimiter character. On macOS, folder names containing forward slashes (/) appear as colons (:) at the Unix layer. Since colons are PATH separators in POSIX systems, this breaks PATH injection for node_modules/.bin, causing binaries to not be found when running commands like pnpm exec #10457.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  43. 10.29.07 Feb 2026
    Release notes

    Minor Changes

    • The pnpm dlx / pnpx command now supports the catalog: protocol. Example: pnpm dlx shx@catalog:.
    • Support configuring auditLevel in the pnpm-workspace.yaml file #10540.
    • Support bare workspace: protocol without version specifier. It is now treated as workspace:* and resolves to the concrete version during publish #10436.

    Patch Changes

    • Fixed pnpm list --json returning incorrect paths when using global virtual store #10187.

    • Fix pnpm store path and pnpm store status using workspace root for path resolution when storeDir is relative #10290.

    • Fixed pnpm run -r failing with "No projects matched the filters" when an empty pnpm-workspace.yaml exists #10497.

    • Fixed a bug where catalogMode: strict would write the literal string "catalog:" to pnpm-workspace.yaml instead of the resolved version specifier when re-adding an existing catalog dependency #10176.

    • Fixed the documentation URL shown in pnpm completion --help to point to the correct page at https://pnpm.io/completion #10281.

    • Skip local file: protocol dependencies during pnpm fetch. This fixes an issue where pnpm fetch would fail in Docker builds when local directory dependencies were not available #10460.

    • Fixed pnpm audit --json to respect the --audit-level setting for both exit code and output filtering #10540.

    • update tar to version 7.5.7 to fix security issue

      Updating the version of dependency tar to 7.5.7 because the previous one have a security vulnerability reported here: <a href="https://github.com/advisories/GHSA-34x7-hfp2-rc4v">CVE-2026-24842</a>

    • Fix pnpm audit --fix replacing reference overrides (e.g. $foo) with concrete versions #10325.

    • Fix shamefullyHoist set via updateConfig in .pnpmfile.cjs not being converted to publicHoistPattern #10271.

    • pnpm help should correctly report if the currently running pnpm CLI is bundled with Node.js #10561.

    • Add a warning when the current directory contains the PATH delimiter character. On macOS, folder names containing forward slashes (/) appear as colons (:) at the Unix layer. Since colons are PATH separators in POSIX systems, this breaks PATH injection for node_modules/.bin, causing binaries to not be found when running commands like pnpm exec #10457.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  44. 10.28.226 Jan 2026
    Release notes

    Patch Changes

    • Security fix: prevent path traversal in directories.bin field.

    • When pnpm installs a file: or git: dependency, it now validates that symlinks point within the package directory. Symlinks to paths outside the package root are skipped to prevent local data from being leaked into node_modules.

      This fixes a security issue where a malicious package could create symlinks to sensitive files (e.g., /etc/passwd, ~/.ssh/id_rsa) and have their contents copied when the package is installed.

      Note: This only affects file: and git: dependencies. Registry packages (npm) have symlinks stripped during publish and are not affected.

    • Fixed optional dependencies to request full metadata from the registry to get the libc field, which is required for proper platform compatibility checks #9950.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  45. 10.28.119 Jan 2026
    Release notes

    Patch Changes

    • Fixed installation of config dependencies from private registries.

      Added support for object type in configDependencies when the tarball URL returned from package metadata differs from the computed URL #10431.

    • Fix path traversal vulnerability in binary fetcher ZIP extraction

      • Validate ZIP entry paths before extraction to prevent writing files outside target directory
      • Validate BinaryResolution.prefix (basename) to prevent directory escape via crafted prefix
      • Both attack vectors now throw ERR_PNPM_PATH_TRAVERSAL error
    • Support plain http:// and https:// URLs ending with .git as git repository dependencies.

      Previously, URLs like https://gitea.example.org/user/repo.git#commit were not recognized as git repositories because they lacked the git+ prefix (e.g., git+https://). This caused issues when installing dependencies from self-hosted git servers like Gitea or Forgejo that don't provide tarball downloads.

      Changes:

      • The git resolver now runs before the tarball resolver, ensuring git URLs are handled by the correct resolver
      • The git resolver now recognizes plain http:// and https:// URLs ending in .git as git repositories
      • Removed the isRepository check from the tarball resolver since it's no longer needed with the new resolver order

      Fixes #10468

    • pnpm run -r and pnpm run --filter now fail with a non-zero exit code when no packages have the specified script. Previously, this only failed when all packages were selected. Use --if-present to suppress this error #6844.

    • Fixed a path traversal vulnerability in tarball extraction on Windows. The path normalization was only checking for ./ but not .\. Since backslashes are directory separators on Windows, malicious packages could use paths like foo\..\..\.npmrc to write files outside the package directory.

    • When running "pnpm exec" from a subdirectory of a project, don't change the current working directory to the root of the project #5759.

    • Fixed a path traversal vulnerability in pnpm's bin linking. Bin names starting with @ bypassed validation, and after scope normalization, path traversal sequences like ../../ remained intact.

    • Revert Try to avoid making network calls with preferOffline #10334.

    • Fix --save-peer to write valid semver ranges to peerDependencies for protocol-based installs (e.g. jsr:) by deriving from resolved versions when available and falling back to * if none is available #10417.

    • Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  46. 10.28.09 Jan 2026
    Release notes

    Minor Changes

    • Add support for a hook called beforePacking that can be used to customize the package.json contents at publish time #3816.
    • In some cases, a filtered install (i.e. pnpm install --filter ...) was slower than running pnpm install without any filter arguments. This performance regression is now fixed. Filtered installs should be as fast or faster than a full install #10408.

    Patch Changes

    • Do not add a symlink to the project into the store's project registry if the store is in a subdirectory of the project #10411.
    • It should be possible to declare the requiredScripts setting in pnpm-workspace.yaml #10261.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  47. 10.27.030 Dec 2025
    Release notes

    Minor Changes

    • Adding trustPolicyIgnoreAfter allows you to ignore trust policy checks for packages published more than a specified time ago#10352.

    • Added project registry for global virtual store prune support.

      Projects using the store are now registered via symlinks in {storeDir}/v10/projects/. This enables pnpm store prune to track which packages are still in use by active projects and safely remove unused packages from the global virtual store.

    • Semi-breaking. Changed the location of unscoped packages in the virtual global store. They will now be stored under a directory named @ to maintain a uniform 4-level directory depth.

    • Added mark-and-sweep garbage collection for global virtual store.

      pnpm store prune now removes unused packages from the global virtual store's links/ directory. The algorithm:

      1. Scans all registered projects for symlinks pointing to the store
      2. Walks transitive dependencies to mark reachable packages
      3. Removes any package directories not marked as reachable

      This includes support for workspace monorepos - all node_modules directories within a project (including those in workspace packages) are scanned.

    Patch Changes

    • Throw an error if the value of the tokenHelper or <url>:tokenHelper setting contains an environment variable.
    • Git dependencies with build scripts should respect the dangerouslyAllowAllBuilds settings #10376.
    • Skip the package manager check when running with --global and a project packageManager is configured, and warn that the check is skipped.
    • pnpm store prune should not fail if the dlx cache directory has files, not only directories #10384
    • Fixed a bug (#9759) where pnpm add would incorrectly modify a catalog entry in pnpm-workspace.yaml to its exact version.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  48. 10.26.223 Dec 2025
    Release notes

    Patch Changes

    • Improve error message when a package version exists but does not meet the minimumReleaseAge constraint. The error now clearly states that the version exists and shows a human-readable time since release (e.g., "released 6 hours ago") #10307.

    • Fix installation of Git dependencies using annotated tags #10335.

      Previously, pnpm would store the annotated tag object's SHA in the lockfile instead of the actual commit SHA. This caused ERR_PNPM_GIT_CHECKOUT_FAILED errors because the checked-out commit hash didn't match the stored tag object hash.

    • Binaries of runtime engines (Node.js, Deno, Bun) are written to node_modules/.bin before lifecycle scripts (install, postinstall, prepare) are executed #10244.

    • Try to avoid making network calls with preferOffline #10334.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  49. 10.26.119 Dec 2025
    Release notes

    Patch Changes

    • Don't fail on pnpm add, when blockExoticSubdeps is set to true #10324.
    • Always resolve git references to full commits and ensure HEAD points to the commit after checkout #10310.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  50. 10.26.015 Dec 2025
    Release notes

    Minor Changes

    • Semi-breaking. Block git-hosted dependencies from running prepare scripts unless explicitly allowed in onlyBuiltDependencies #10288.

    • Semi-breaking. Compute integrity hash for HTTP tarball dependencies when fetching, storing it in the lockfile to prevent servers from serving altered content on subsequent installs #10287.

    • Added a new setting blockExoticSubdeps that prevents the resolution of exotic protocols in transitive dependencies.

      When set to true, direct dependencies (those listed in your root package.json) may still use exotic sources, but all transitive dependencies must be resolved from a trusted source. Trusted sources include the configured registry, local file paths, workspace links, trusted GitHub repositories (node, bun, deno), and custom resolvers.

      This helps to secure the dependency supply chain. Packages from trusted sources are considered safer, as they are typically subject to more reliable verification and scanning for malware and vulnerabilities.

      Exotic sources are dependency locations that bypass the usual trusted resolution process. These protocols are specifically targeted and blocked: Git repositories (git+ssh://...) and direct URL links to tarballs (https://.../package.tgz).

      Related PR: #10265.

    • Added support for allowBuilds, which is a new field that can be used instead of onlyBuiltDependencies and ignoredBuiltDependencies. The new allowBuilds field in your pnpm-workspace.yaml uses a map of package matchers to explicitly allow (true) or disallow (false) script execution. This allows for a single, easy-to-manage source of truth for your build permissions.

      Example Usage. To explicitly allow all versions of esbuild to run scripts and prevent core-js from running them:

      allowBuilds:
        esbuild: true
        core-js: false
      

      The example above achieves the same result as the previous configuration:

      onlyBuiltDependencies:
        - esbuild
      ignoredBuiltDependencies:
        - core-js
      

      Related PR: #10311

    • Added support for --dry-run to the pack command #10301.

    Patch Changes

    • Show deprecation in table/list formats when latest version is deprecated #8658.
    • Remove the injectWorkspacePackages setting from the lockfile on the deploy command #10294.
    • Normalize the tarball URLs before saving them to the lockfile. URLs should not contain default ports, like :80 for http and :443 for https #10273.
    • When a dependency is installed via a direct URL that redirects to another URL and is immutable, the original URL is normalized and saved to package.json #10197.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  51. 10.25.08 Dec 2025
    Release notes

    Minor Changes

    • Allow loading certificates from cert, ca, and key for specific registry URLs. E.g., //registry.example.com/:ca=-----BEGIN CERTIFICATE-----.... Previously this was only working via certfile, cafile, and keyfile.

      These properties are supported in .npmrc, but were ignored by pnpm, this will make pnpm read and use them as well.

      Related PR: #10230.

    • Added a new flag called --bare to pnpm init for creating a package.json with the bare minimum of required fields #10226.

    Patch Changes

    • Improved reporting of ignored dependency scripts #10276.
    • pnpm install should build any dependencies that were added to onlyBuiltDependencies and were not built yet #10256.
    • pnpm publish -r --force should allow to run publish over already existing versions in the registry #10272.
    • Don't fail with a ERR_PNPM_MISSING_TIME error if a package that is excluded from trust policy checks is missing the time field in the metadata.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  52. 10.24.027 Nov 2025
    Release notes

    Minor Changes

    • Increased network concurrency on machines with many CPU cores. pnpm now automatically selects a network concurrency between 16 and 64, based on the number of pnpm workers (calculated as workers × 3). This improves performance on high-core systems #10068.

    Patch Changes

    • trustPolicy should ignore the trust evidences of prerelease versions, when installing a non-prerelease version.
    • Handle ENOENT errors thrown by fs.linkSync(), which can occur in containerized environments (OverlayFS) instead of EXDEV. The operation now gracefully falls back to fs.copyFileSync() in these cases #10217.
    • Reverted: pnpm self-update should download pnpm from the configured npm registry #10205.
    • Packages that don't have a package.json file (like Node.js) should not be reimported from the store on every install. Another file from the package should be checked in order to verify its presence in node_modules.
    • Correctly read auth tokens for URLs that contain underscores #17.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  53. 10.23.020 Nov 2025
    Release notes

    Minor Changes

    • Added --lockfile-only option to pnpm list #10020.

    Patch Changes

    • pnpm self-update should download pnpm from the configured npm registry #10205.
    • pnpm self-update should always install the non-executable pnpm package (pnpm in the registry) and never the @pnpm/exe package, when installing v11 or newer. We currently cannot ship @pnpm/exe as pkg doesn't work with ESM #10190.
    • Node.js runtime is not added to "dependencies" on pnpm add, if there's a engines.runtime setting declared in package.json #10209.
    • The installation should fail if an optional dependency cannot be installed due to a trust policy check failure #10208.
    • pnpm list and pnpm why now display npm: protocol for aliased packages (e.g., foo npm:[email protected]) #8660.
    • Don't add an extra slash to the Node.js mirror URL #10204.
    • pnpm store prune should not fail if the store contains Node.js packages #10131.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  54. 10.22.012 Nov 2025
    Release notes

    Minor Changes

    • Added support for trustPolicyExclude #10164.

      You can now list one or more specific packages or versions that pnpm should allow to install, even if those packages don't satisfy the trust policy requirement. For example:

      trustPolicy: no-downgrade
      trustPolicyExclude:
        - [email protected]
        - [email protected] || 5.102.1
      
    • Allow to override the engines field on publish by the publishConfig.engines field.

    Patch Changes

    • Don't crash when two processes of pnpm are hardlinking the contents of a directory to the same destination simultaneously #10179.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  55. 10.21.09 Nov 2025
    Release notes

    Minor Changes

    • Node.js Runtime Installation for Dependencies. Added support for automatic Node.js runtime installation for dependencies. pnpm will now install the Node.js version required by a dependency if that dependency declares a Node.js runtime in the "engines" field. For example:

      {
        "engines": {
          "runtime": {
            "name": "node",
            "version": "^24.11.0",
            "onFail": "download"
          }
        }
      }
      

      If the package with the Node.js runtime dependency is a CLI app, pnpm will bind the CLI app to the required Node.js version. This ensures that, regardless of the globally installed Node.js instance, the CLI will use the compatible version of Node.js.

      If the package has a postinstall script, that script will be executed using the specified Node.js version.

      Related PR: #10141

    • Added a new setting: trustPolicy.

      When set to no-downgrade, pnpm will fail installation if a package’s trust level has decreased compared to previous releases — for example, if it was previously published by a trusted publisher but now only has provenance or no trust evidence. This helps prevent installing potentially compromised versions of a package.

      Related issue: #8889.

    • Added support for pnpm config get globalconfig to retrieve the global config file path #9977.

    Patch Changes

    • When a user runs pnpm update on a dependency that is not directly listed in package.json, none of the direct dependencies should be updated #10155.
    • Don't crash when two processes of pnpm are hardlinking the contents of a directory to the same destination simultaneously #10160.
    • Setting gitBranchLockfile and related settings via pnpm-workspace.yaml should work #9651.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  56. 10.20.028 Oct 2025
    Release notes

    Minor Changes

    • Support --all option in pnpm --help to list all commands #8628.

    Patch Changes

    • When the latest version doesn't satisfy the maturity requirement configured by minimumReleaseAge, pick the highest version that is mature enough, even if it has a different major version #10100.
    • create command should not verify patch info.
    • Set managePackageManagerVersions to false, when switching to a different version of pnpm CLI, in order to avoid subsequent switches #10063.

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →
  57. 10.19.1-oidc-test.323 Oct 2025pre-release

    Nothing published for this version

  58. 10.19.1-oidc-test.223 Oct 2025pre-release

    Nothing published for this version

  59. 10.19.1-oidc-test.023 Oct 2025pre-release

    Nothing published for this version

  60. 10.19.021 Oct 2025
    Release notes

    Minor Changes

    • You can now allow specific versions of dependencies to run postinstall scripts. onlyBuiltDependencies now accepts package names with lists of trusted versions. For example:

      onlyBuiltDependencies:
        - [email protected] || 21.6.5
        - [email protected]
      

      Related PR: #10104.

    • Added support for exact versions in minimumReleaseAgeExclude #9985.

      You can now list one or more specific versions that pnpm should allow to install, even if those versions don’t satisfy the maturity requirement set by minimumReleaseAge. For example:

      minimumReleaseAge: 1440
      minimumReleaseAgeExclude:
        - [email protected]
        - [email protected] || 5.102.1
      

    Platinum Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a> </td> </tr> </tbody> </table>

    Gold Sponsors

    <table> <tbody> <tr> <td align="center" valign="middle"> <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" /> <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" /> <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" /> <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" /> </picture> </a> </td> </tr> <tr> <td align="center" valign="middle"> <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <picture> <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" /> <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" /> <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" /> </picture> </a> </td> <td align="center" valign="middle"> <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"> <img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"> </a> </td> </tr> </tbody> </table>

    Open source →