Skip to main content

pnpm 12.5

· 5 min read
Zoltan Kochan
Lead maintainer of pnpm

pnpm 12.5 expands Python support with editable project packages, shared workspace environments, automatic interpreter downloads, and lockfiles for multiple platforms and Python versions. It also accepts Package URLs in pnpm add, adds machine-wide task concurrency groups, and cleans up obsolete registry metadata with pnpm cache prune.

Python projects and environments

Interpreters per project

pnpm install chooses an interpreter that satisfies each project's requires-python, preferring .python-version when present. Different projects can use different interpreters. Set python.executable to choose one interpreter for every project.

When no installed interpreter fits, pnpm downloads a shared python-build-standalone interpreter and reuses it on later installs. runtimeOnFail controls this behavior: download permits downloads, error fails, and warn or ignore use an available interpreter despite the version mismatch.

Environments now live under python-envs in the pnpm store. Each project keeps its .venv link, which the next install migrates from the old project-local layout. Old .pnpm/python-envs directories remain until you delete them after running programs stop using them. With frozenStore, environments remain local.

Wheel imports use packageImportMethod. Choose clone-or-copy or copy when installed files may be modified. Isolated build environments use clones or copies to keep backend writes private.

Editable packages and workspace sources

pnpm now installs a Python project's own package editable when it declares [build-system], so its imports and [project.scripts] commands work immediately. [tool.uv].package can override whether it is packaged. Dynamic metadata comes from the build backend, and projects with only requirements.txt can receive an environment and lockfile too.

Declare local dependencies through [tool.uv.sources]:

pyproject.toml
[tool.uv.sources]
shared = { workspace = true }
# Alternatively: shared = { path = "../shared", editable = true }

Build backends need approval through allowBuilds, using keys such as 'pkg:pypi/hatchling': true. Git dependencies and source distributions are also supported and require distribution approval. Direct wheel URLs are supported. A workspace dependency without a source declaration is refused instead of silently fetched from an index.

One environment for a uv workspace

Members can share one environment:

pyproject.toml
[tool.uv.workspace]
members = ["packages/*"]

[tool.pnpm.python]
shared-environment = true

pnpm resolves every member into one pylock.toml and one .venv at the root. Conflicting dependency requirements produce an error naming the members. Independent environments remain the default.

Each project can also select its own extras and dependency groups under [tool.pnpm.python]. Workspace defaults skip names a project does not define; explicit project selections must exist.

One lockfile for multiple environments

Combine platform targets with Python versions:

pnpm-workspace.yaml
supportedArchitectures:
- linux-x64-manylinux_2_28
- darwin-arm64
- win32-x64
python:
enabled: true
versions: ['3.12', '3.13']

Every platform is paired with every version. One pylock.toml pins wheels and conditional dependencies for all of them. Installs select their matching environment and reject interpreters outside the declared environments.

python.overrides and python.constraints control versions throughout the graph. uv overrides and constraints are read too. Python filtering now selects projects by name, path, and local-source dependency relationships; pnpm add --filter <selector> pypi:<package> updates every selected project.

Package URLs and ecosystem registries

pnpm add accepts Package URLs:

pnpm add pkg:npm/express@4.18.2
pnpm add pkg:cargo/serde@1.0.188
pnpm add pkg:pypi/requests@2.31.0

Each writes to its ecosystem's manifest. pkg is now a reserved registry alias, regardless of case.

registries entries can name ecosystem: npm, cargo, or pypi. Python searches indexes in declaration order and uses the first that contains the package. Cargo accepts one sparse index. Credentials come from .npmrc, matched by origin; registry URL keys cannot contain credentials.

This replaces python.indexUrl, python.extraIndexUrls, and cargo.indexUrl. Without ecosystem declarations, PyPI and crates.io remain the defaults.

Platforms, tasks, and tool mirrors

supportedArchitectures accepts a list of exact platforms, such as linux-x64, linux-x64-musl, and darwin-arm64, or Rust target triples. current names the install's platform. The existing os, cpu, and libc mapping still works.

concurrencyGroups limits tasks across pnpm processes on the same machine, including pipelines:

pnpm-workspace.yaml
tasks:
test:rust:
concurrencyGroup: cargo
concurrencyGroups:
cargo: 2

A nested pnpm run in the same group reuses its parent's slot.

tools configures mirrors for Node.js, Bun, and Python in global config.yaml or PNPM_CONFIG_TOOLS. Node.js also supports per-channel mirrors. Workspace tool mirrors are ignored, and pnpm pack-app uses tools.node for its embedded runtime.

Cache cleanup and other fixes

  • pnpm cache prune removes obsolete metadata directories left by the registry cache naming change. Use --dry-run to preview deletions. pnpm cache list-registries now prints full URLs instead of encoded names.
  • Downloads no longer reuse a tarball for another package whose resolution pins a different integrity hash to the same URL (#15021).
  • Production and development install filters keep the complete dependency graph in pnpm-lock.yaml, so a later frozen install accepts it (#14912).
  • Lockfile Git conflict markers are merged automatically (#14880).
  • Cargo lockfile generation supports path and Git source overrides, and vendoring includes recursive Git submodules at their pinned commits.
  • pnx and pnpm dlx prompt for dependency build approval in interactive terminals, including cached installs with pending builds.
  • Python projects prepare concurrently, and identical registry requirements share fresh resolutions. pnpm audit also avoids hangs on graphs with many shared dependencies.

See the v12.5.0 release notes for the complete list of changes.