npm pnpm 11.0.0-beta.0
pnpm 11 Beta 0

6 hours ago

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.

Platinum Sponsors

Bit

Gold Sponsors

Sanity Discord Vite
SerpApi CodeRabbit Stackblitz
Workleap Nx

Don't miss a new pnpm release

NewReleases is sending notifications on new releases.