Avatar for the oxc-project user
oxc-project
oxc-resolver
BlogDocsChangelog

Performance History

Latest Results

chore: release v11.20.1
release-plz-2026-05-28T15-25-06Z
2 hours ago
chore(deps): update pnpm to v11.4.0 (#1194) > ā„¹ļø **Note** > > This PR body was truncated due to platform limits. This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [pnpm](https://pnpm.io) ([source](https://redirect.github.com/pnpm/pnpm/tree/HEAD/pnpm)) | [`11.0.4` → `11.4.0`](https://renovatebot.com/diffs/npm/pnpm/11.0.4/11.4.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/11.4.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/pnpm/11.4.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/pnpm/11.0.4/11.4.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/11.0.4/11.4.0?slim=true) | --- ### Release Notes <details> <summary>pnpm/pnpm (pnpm)</summary> ### [`v11.4.0`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1140) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.3.0...v11.4.0) ##### 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. - `pnpm runtime set <name> <version>` now saves the runtime to `devEngines.runtime` by default instead of `engines.runtime`. Pass `--save-prod` (or `-P`) to save it to `engines.runtime` instead [#&#8203;11948](https://redirect.github.com/pnpm/pnpm/issues/11948). ##### Patch Changes - Fix a credential disclosure issue where an unscoped `_authToken` (or `_auth`, or `username` + `_password`, or `tokenHelper`) defined in one source — `~/.npmrc`, `~/.config/pnpm/auth.ini`, a workspace `.npmrc`, CLI flags, etc. — would be sent as an `Authorization` header to whichever registry a different (potentially untrusted) source named. The same fix extends to client TLS credentials (`cert`, `key`) so they aren't presented to a registry their author didn't choose. pnpm now rewrites each unscoped per-registry setting (`_authToken`, `_auth`, `username`, `_password`, `tokenHelper`, `cert`, `key`) to its URL-scoped form at load time, using the `registry=` value declared in the same source (or the npmjs default registry if the source declares none). A later layer overriding `registry=` therefore cannot pull an unscoped credential along, because it is already pinned to the URL its author intended. `ca`/`cafile` are intentionally not rescoped — they're trust anchors, not credentials, and corporate MITM-proxy setups rely on them applying globally. Every rescope emits a deprecation warning telling the user where the setting was pinned and how to write it directly. npm has rejected unscoped credentials outright since `npm@9`, and pnpm intends to remove support in a future major release. To target a specific registry, write the setting URL-scoped (e.g. `//registry.example.com/:_authToken=...` or `//registry.example.com/:cert=...`). `@pnpm/network.auth-header`: removed the `defaultRegistry` parameter from `createGetAuthHeaderByURI` and `getAuthHeadersFromCreds`. Now that credentials are URL-scoped at load time, the merged `configByUri` never contains the empty-string "default registry" placeholder slot, so re-keying it onto the merged default registry is no longer needed. - Fix `pnpm deploy` crashing with `ENOENT: ... lstat '<deployDir>/node_modules'` when `configDependencies` declares pacquet (`pacquet` or `@pnpm/pacquet`). The deploy directory never installs config dependencies, so the install engine they designate isn't on disk to invoke; the nested install now skips them. - 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. - Limit concurrent project manifest reads while listing large workspaces to avoid `EMFILE` errors. - 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`. - Improve the log message that pnpm prints after auto-adding entries to `minimumReleaseAgeExclude` when `minimumReleaseAge` is set without `minimumReleaseAgeStrict`. The message previously referred to the internal "loose mode" terminology, which wasn't searchable in the docs; it now tells the user to set `minimumReleaseAgeStrict` to `true` if they want these updates gated behind a prompt instead [#&#8203;11747](https://redirect.github.com/pnpm/pnpm/issues/11747). - 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. - 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. - Validate `devEngines.runtime` and `engines.runtime` version ranges for `node`, `deno`, and `bun` when `onFail` is set to `error` or `warn`. Previously these settings only had an effect with `onFail: 'download'` — the `error` and `warn` modes silently did nothing [#&#8203;11818](https://redirect.github.com/pnpm/pnpm/issues/11818). Violations now throw `ERR_PNPM_BAD_RUNTIME_VERSION`. - Require provenance before treating trusted publisher metadata as the strongest trust evidence. ### [`v11.3.0`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1130) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.2.2...v11.3.0) ##### Minor Changes - Added `pnpm stage` with `publish`, `list`, `view`, `approve`, `reject`, and `download` subcommands for npm staged publishing. - Added a new setting `trustLockfile`. When `true`, `pnpm install` skips the supply-chain verification pass that re-applies `minimumReleaseAge` / `trustPolicy='no-downgrade'` to every entry in the loaded lockfile. The install treats the lockfile as already-trusted — useful for closed-source projects where every commit comes from a trusted author. Defaults to `false`; verification stays on by default. Set in `pnpm-workspace.yaml`. Also cut the memory footprint of the verification pass itself: the per-(registry, name) trust-meta cache previously retained the full packument — dependency graphs, scripts, README, and per-version manifests — for the entire install. On large workspaces (`~4k` lockfile entries with `minimumReleaseAge` + `trustPolicy: no-downgrade` enabled) this could OOM CI runners with a 2GB heap cap. The cache now stores only the fields the trust check actually reads (`time`, per-version `_npmUser.trustedPublisher`, `dist.attestations.provenance`). The abbreviated-metadata cache is similarly projected to just the package-level `modified` field and the set of currently-listed version names. Fixes [#&#8203;11860](https://redirect.github.com/pnpm/pnpm/issues/11860). - Implemented `pnpm pkg` command natively, following `npm pkg` standards. - Implemented `pnpm repo` command natively, following `npm repo` standards. - Implemented `pnpm set-script` (alias `ss`) natively. Adds or updates an entry in the `scripts` field of the project manifest, supporting `package.json`, `package.json5`, and `package.yaml` formats. - Add a `skip-manifest-obfuscation` option for `pnpm pack` and `pnpm publish`. When enabled, the original `packageManager` field and publish lifecycle scripts are kept in the packed/published manifest instead of being stripped. The pnpm-specific `pnpm` field continues to be omitted. ##### Patch Changes - Fixed `pnpm dlx` failing with `ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND` when the installed package's CAS slot is missing its `package.json`. Observed in the wild for `pnpm dlx node@runtime:<version>` when the GVS slot was populated without the synthesized manifest runtime archives need (they don't ship a `package.json` of their own, so the synthesized one is the only way it gets there; an existing slot from an earlier code path that skipped the synthesis stays incomplete). The bin link itself is wired up from the resolution and remains valid, so `dlx` now falls back to the scopeless package name when the slot's manifest is unreadable — for single-bin packages (the dlx common case, including every `runtime:` spec) this matches what `manifest.bin` would have named. Multi-bin packages already require `--package=<spec> <bin>` to disambiguate and don't enter this code path. - Fixed non-determinism in `pnpm dedupe` and `pnpm install` when a dependency graph contains packages with transitive peer dependencies on each other (e.g. `@aws-sdk/client-sts` and `@aws-sdk/client-sso-oidc`) and `auto-install-peers` is enabled. The lockfile no longer flips between two equally-valid forms across consecutive runs. The root cause was that `resolveDependencies` pushed onto its `pkgAddresses` / `postponedResolutionsQueue` arrays from inside `Promise.all`-spawned callbacks, so completion-order timing leaked into the array order and downstream cyclic-peer suffix assignment. Fixes [#&#8203;8155](https://redirect.github.com/pnpm/pnpm/issues/8155). - Fixed a regression introduced by [#&#8203;11711](https://redirect.github.com/pnpm/pnpm/pull/11711) where `pnpm add <github-shorthand>` (and any other wanted-dependency whose alias can't be parsed from the user-supplied spec, e.g. tarball URLs or `pnpm/test-git-fetch#sha`) was silently dropped from the manifest update and from `pendingBuilds`. The alias-keyed lookup added in that PR couldn't find a `wantedDependency` whose `alias` was `undefined` at parse time but resolved to a package name only after fetching, so the entry never made it into `specsToUpsert`. Restored the original index-based pairing between `directDependencies` and `wantedDependencies`; the catalog-protocol preservation that PR was originally fixing is unaffected because it's driven by `rdd.catalogLookup.userSpecifiedBareSpecifier`, not by the lookup. Fixes the three `rebuilds dependencies` / `rebuilds specific dependencies` / `rebuild with pending option` failures in `building/commands/test/build/index.ts`. - Fixed `pnpm add --config` leaving orphan entries in `pnpm-lock.env.yaml` (the optional subdependencies of the previously resolved version of the updated config dependency). ### [`v11.2.2`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1122) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.2.1...v11.2.2) ##### Patch Changes - When the install engine is delegated to pacquet via `configDependencies`, the user's CLI flags passed to `pnpm install` (e.g. `--no-runtime`, `--prod`, `--dev`, `--no-optional`, `--node-linker`, `--cpu`/`--os`/`--libc`, `--offline`, `--prefer-offline`) are now forwarded to pacquet's `install` subcommand verbatim. Previously pacquet was invoked with a fixed argument list, so flags like `--no-runtime` were silently dropped. Flag forwarding is gated on the command being `install`/`i`; `add`, `update`, and `dedupe` still don't forward (their flag surface doesn't line up with pacquet's `install`). - Fixed `pnpm up` (and `pnpm add` / `pnpm remove`) failing with `pacquet_package_manager::outdated_lockfile` when pacquet is declared in `configDependencies`. pnpm now passes `--ignore-manifest-check` to pacquet so its `--frozen-lockfile` check doesn't fire against the (pre-mutation) `package.json` pnpm hasn't written yet [#&#8203;11797](https://redirect.github.com/pnpm/pnpm/issues/11797). Requires a pacquet release that supports the flag — bump `PACQUET_VERSION` in the e2e tests once it ships. ### [`v11.2.1`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1121) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.2.0...v11.2.1) ##### Patch Changes - Mark optional subdependency snapshots of config dependencies with `optional: true` in the env lockfile, matching how optional dependencies are recorded elsewhere in `pnpm-lock.yaml`. Previously, snapshots for the platform-specific subdeps pulled in via a config dep's `optionalDependencies` were written as empty objects, which was inconsistent with the rest of the lockfile and made it look like those non-host platform variants were required. - Fix `pickRegistryForPackage` returning the wrong registry for an unscoped `npm:` alias under a scoped local name. A manifest entry like `"@&#8203;private/foo": "npm:lodash@^1"` was routing the `lodash` fetch through `registries["@&#8203;private"]`, even though `lodash` is unscoped and doesn't live on that registry. The npm-alias branch now returns the alias target's own scope (or `null` for an unscoped target, falling through to `registries.default`) instead of leaking into the local key's scope. - Don't print "Installing config dependencies..." when config dependencies are already installed and nothing needs to be fetched, re-linked, or removed. ### [`v11.2.0`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1120) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.1.3...v11.2.0) ##### Minor Changes - **Experimental:** Adding [`@pnpm/pacquet`](https://npmx.dev/package/@&#8203;pnpm/pacquet) (the Rust port of pnpm) to `configDependencies` in `pnpm-workspace.yaml` now delegates the materialization phase of `pnpm install` to the pacquet binary. pnpm still owns dependency resolution; pacquet only fetches and imports from the freshly-written lockfile. This is an opt-in preview of the Rust install engine [#&#8203;11723](https://redirect.github.com/pnpm/pnpm/issues/11723). To configure pacquet in a project, run: ``` pnpm add @&#8203;pnpm/pacquet --config ``` You'll see changes in `pnpm-workspace.yaml` and `pnpm-lock.yaml` that should be committed. If you experience any issues with pacquet, please let us know by mentioning this in the GitHub issue you create. - `configDependencies` now resolve and install one level of `optionalDependencies` declared by the config dependency, with `os`/`cpu`/`libc` platform filtering applied at install time. This unlocks the esbuild/swc-style pattern where a package ships platform-specific binaries via `optionalDependencies` — a config dependency can now do the same and have the matching binary symlinked next to it in the global virtual store, so `require('pkg-platform-arch')` from inside the config dependency resolves correctly. The env lockfile records all platform variants regardless of host platform, so it remains portable across machines. Each entry in a config dependency's `optionalDependencies` must declare an exact version — ranges and tags are rejected to keep installs reproducible. - Implement the documented `pnpm login --scope <scope>` flag. The scope is normalized (a leading `@` is added if missing; blank values are ignored) and an `@<scope>:registry=<registry>` mapping is written to the pnpm auth file alongside the auth token. Subsequent installs of `@<scope>/*` packages then route to the chosen registry. Previously `pnpm login --scope foo` errored with `Unknown option: 'scope'` despite the flag being listed in the online documentation [#&#8203;11716](https://redirect.github.com/pnpm/pnpm/issues/11716). - `pnpm outdated` and `pnpm update --interactive` now report Node.js, Deno, and Bun runtimes installed as project dependencies (`runtime:` specifiers). Previously these were silently skipped. ##### Patch Changes - Fix `cafile=<relative-path>` in `.npmrc` being read from the wrong directory when pnpm is invoked from a different cwd (e.g. `pnpm --dir <project> install` from a CI wrapper or monorepo script). The path is now resolved against the directory of the `.npmrc` that declared it, not `process.cwd()`. Before this fix the CA file silently failed to load — the install proceeded without the configured CA and the user only saw TLS errors against a private registry, with no log line tying back to the wrongly resolved path [#&#8203;11624](https://redirect.github.com/pnpm/pnpm/issues/11624). - Fix `config.registry` getting a trailing slash appended when `registry` is set in `.npmrc` and no `registries.default` is provided by `pnpm-workspace.yaml`. The sync from `registries.default` to `config.registry` introduced in [#&#8203;11744](https://redirect.github.com/pnpm/pnpm/issues/11744) now only fires when the workspace manifest actually contributes a different default. - Fix global add/update to handle minimumReleaseAge policy violations instead of surfacing an internal resolver guardrail error. - Fix two crashes with `injectWorkspacePackages: true` when the lockfile has been pruned (e.g. by `turbo prune --docker`): - `Cannot use 'in' operator to search for 'directory' in undefined`: a peer-dependency-variant injected snapshot inherits its `resolution` from the base `packages:` entry; when a pruner drops that base entry the readers crash. `convertToLockfileObject` now reconstructs the directory resolution from the `file:` depPath at load time — a single normalization point, so every reader sees a fully-formed snapshot. - `ERR_PNPM_ENOENT` on `node_modules/.bin/<tool>`: after `prepare`/`postinstall`, `runLifecycleHooksConcurrently` re-imported each injected workspace package; the `scanDir`-into-`filesMap` workaround fed target-internal paths to the importer, which the `makeEmptyDir` fast path ([#&#8203;11088](https://redirect.github.com/pnpm/pnpm/issues/11088)) then wiped. Drop the workaround and pass `keepModulesDir: true` so the importer preserves the target's existing `node_modules` (bin links + transitive deps) and source files keep their hardlinks. - Fixed `pnpm login` and `pnpm logout` ignoring `registries.default` from `pnpm-workspace.yaml` [#&#8203;10099](https://redirect.github.com/pnpm/pnpm/issues/10099). - Fix the `minimumReleaseAge` (publishedBy) maturity shortcut to be inclusive at the cutoff. Previously, abbreviated metadata whose `modified` field equalled the cutoff fell off the fast path and triggered a full-metadata re-fetch (or a `MISSING_TIME` error when full metadata wasn't permitted). Since `modified` is an upper bound on every version's publish time, `modified == publishedBy` already implies every version passes the per-version `<=` filter in `filterPkgMetadataByPublishDate`, so the shortcut now accepts the boundary case directly. Strictly `>` (was `>=`) at the rejection branch. - Honor `publishConfig.access` when publishing packages. ### [`v11.1.3`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1113) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.1.2...v11.1.3) ##### Patch Changes - `pnpm install` now re-validates `pnpm-lock.yaml` entries against the active `minimumReleaseAge` and `trustPolicy: 'no-downgrade'` policies before any tarball is fetched. Lockfiles resolved elsewhere (committed to the repo, restored from a CI cache, produced by an older pnpm) under a weaker or absent policy can no longer install a freshly-published or trust-downgraded version silently. Violating entries abort the install with `ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION`, `ERR_PNPM_TRUST_DOWNGRADE`, or the generic `ERR_PNPM_LOCKFILE_RESOLUTION_VERIFICATION` when both policies trip in the same batch; `minimumReleaseAgeExclude` and `trustPolicyExclude` are honored. Verification results are cached so repeat installs against an unchanged lockfile take a fast path, and pnpm shows a transient progress line while the registry round-trip runs. When fresh resolution picks an immature version, the behavior depends on `minimumReleaseAgeStrict`: - **Loose mode** — the default, in effect whenever `minimumReleaseAge` keeps its built-in 24-hour value — auto-adds the immature picks to `minimumReleaseAgeExclude` in `pnpm-workspace.yaml` and lets the install proceed. A single info message lists what was persisted. - **Strict mode** in an interactive terminal collects every immature direct AND transitive pick in one pass and prompts once with the full list. Approving adds them to `minimumReleaseAgeExclude` and the install continues; declining aborts before the lockfile, `package.json`, or `node_modules` is touched. - **Strict mode** in CI (or any non-TTY context) aborts with `ERR_PNPM_NO_MATURE_MATCHING_VERSION` listing every offending entry, instead of failing on the first one the resolver hit. `minimumReleaseAgeStrict` auto-enables whenever the user explicitly sets `minimumReleaseAge` (CLI flag, env var, global `config.yaml`, or `pnpm-workspace.yaml`); set `minimumReleaseAgeStrict: false` to keep loose-mode auto-collect even with an explicit `minimumReleaseAge` value. Closes [#&#8203;10438](https://redirect.github.com/pnpm/pnpm/issues/10438), [#&#8203;10488](https://redirect.github.com/pnpm/pnpm/issues/10488), [#&#8203;11687](https://redirect.github.com/pnpm/pnpm/issues/11687). - Allow redundant trailing base64 padding in `.npmrc` auth values and report invalid auth base64 with a pnpm error. - Make `pnpm self-update` respect `minimumReleaseAge` (and `minimumReleaseAgeExclude`) when resolving which pnpm version to install. When the `latest` dist-tag points to a version newer than the configured age threshold, `self-update` now selects the newest mature version instead unless excluded by `minimumReleaseAgeExclude`. Also makes `dlx` and `outdated` surface invalid `minimumReleaseAgeExclude` patterns under the same `ERR_PNPM_INVALID_MINIMUM_RELEASE_AGE_EXCLUDE` error code already used by `install`, instead of leaking the internal `ERR_PNPM_INVALID_VERSION_UNION` / `ERR_PNPM_NAME_PATTERN_IN_VERSION_UNION` codes. - Global installs respect global config build policy (e.g., `dangerouslyAllowAllBuilds` from config.yaml) when GVS is enabled [#&#8203;9249](https://redirect.github.com/pnpm/pnpm/issues/9249). The global virtual-store (GVS) default `allowBuilds = {}` was applied before workspace manifest settings were read and before global config values (stripped by `extractAndRemoveDependencyBuildOptions`) were re-applied via `globalDepsBuildConfig`. This caused `hasDependencyBuildOptions` to return `true` (because `{}` is not null), blocking restoration of global config values like `dangerouslyAllowAllBuilds`. As a result, global installs skipped all build scripts even when the config explicitly allowed them. This fix moves the GVS default to **after** workspace manifest reading and `globalDepsBuildConfig` re-application, so that: 1. Workspace manifest `allowBuilds` takes precedence (if present) 2. Global config `dangerouslyAllowAllBuilds` is properly restored (if set and no workspace policy exists) 3. Empty `{}` is only applied as a last resort when no policy is configured anywhere - Honor `--silent` when `verifyDepsBeforeRun: install` auto-installs dependencies before `pnpm run` or `pnpm exec`, preventing install output from being written to stdout [#&#8203;11636](https://redirect.github.com/pnpm/pnpm/issues/11636). - Fix lockfile parsing failures when `pnpm-lock.yaml` contains CRLF line endings and multiple YAML documents [#&#8203;11612](https://redirect.github.com/pnpm/pnpm/issues/11612). - Anchor the side-effects-cache key and global-virtual-store hash to the project's script-runner Node — `engines.runtime` pin when present, shell `node` otherwise — instead of pnpm's own runtime. `ENGINE_NAME` (the `<platform>;<arch>;node<major>` prefix used as the side-effects-cache key and the engine portion of the GVS hash) was computed from `process.version` — the Node that runs pnpm itself. That was wrong in two situations: 1. **`@pnpm/exe` SEA bundle.** The bundle has its own embedded Node, not the `node` on the user's `PATH` that actually spawns lifecycle scripts. Two pnpm installations on the same machine (one SEA, one npm-package) therefore disagreed on the cache key, partitioning the side-effects cache and the global virtual store across two Node majors even though both installs would run scripts on the same shell `node`. 2. **`engines.runtime` / `devEngines.runtime` pin.** When a project pins a Node version via `devEngines.runtime` (pnpm v11+), pnpm downloads that Node into `node_modules/node/` and uses it to run lifecycle scripts. But the hash still anchored to whichever Node ran pnpm itself, not to the pinned Node — so two installs of the same project with two different runner Nodes would still disagree on the GVS slot path even though scripts run on the same pinned Node. Three changes: - `@pnpm/engine.runtime.system-node-version` now exports `engineName(nodeVersion?)`. Resolves the version in this order: explicit override → `getSystemNodeVersion()` (which already prefers `node --version` over `process.version` in SEA contexts) → `process.version`. - `@pnpm/deps.graph-hasher` now exports `findRuntimeNodeVersion(snapshotKeys)` — scans an iterable of lockfile snapshot keys for a `node@runtime:<version>` entry and returns its bare version string. `calcDepState` and `calcGraphNodeHash`/`iterateHashedGraphNodes` accept a `nodeVersion?` (in the options bag for the first, as a trailing parameter / ctx field for the others), forwarded to `engineName()`. The default (no override) preserves the pre-change behaviour. The legacy `ENGINE_NAME` constant in `@pnpm/constants` is unchanged so external consumers and existing tests keep working; in non-SEA, non-pinned contexts every value lines up. - Every install-side caller of the graph-hasher (`@pnpm/installing.deps-resolver`, `@pnpm/installing.deps-restorer`, `@pnpm/installing.deps-installer`, `@pnpm/building.during-install`, `@pnpm/building.after-install`, `@pnpm/deps.graph-builder`) now derives the project's pinned runtime via `findRuntimeNodeVersion(Object.keys(graph))` once per invocation and threads it through. On upgrade, two one-time GVS slot churns are possible: - **SEA-pnpm users** without a runtime pin: slots that previously hashed under the embedded-Node major (e.g. `node26`) now hash under the shell-Node major (e.g. `node24`), matching what pacquet, the npm-published `pnpm` package, and any other pnpm-compatible tool already produce. - **Projects with a `devEngines.runtime` pin**: slots that previously hashed under the runner's Node major now hash under the pinned Node major, matching what the lifecycle scripts will actually run on. In both cases the old slots become prune-eligible. - Resolve the GVS hash's engine portion per-snapshot when a dependency declares its own `engines.runtime`, instead of using an install-wide value. Pnpm's resolver desugars a dep's `engines.runtime` into `dependencies.node: 'runtime:<version>'`, and the bin linker spawns that dep's lifecycle scripts through the pinned Node downloaded into `<pkgDir>/node_modules/node/`. The GVS hash and the side-effects-cache key prefix were still anchored to the install-wide runtime — so a pinning snapshot's slot encoded the wrong Node major, and a reinstall on the same host could read the cached side-effects under a key whose `<platform>;<arch>;node<major>` triple disagreed with the Node the build actually ran on. Per-snapshot resolution now matches what `bins/linker` already does on a per-package basis: - `@pnpm/deps.graph-hasher` adds `readSnapshotRuntimePin(children)` — reads the `node` entry from one snapshot's graph children and extracts the version from a `node@runtime:` value. Pairs with the existing `findRuntimeNodeVersion(snapshotKeys)` install-wide fallback (also now exported from `@pnpm/deps.graph-hasher` rather than `@pnpm/engine.runtime.system-node-version`, where it was a poor fit — `system-node-version` is about probing the host Node, not parsing lockfile-derived strings). - `calcDepState` and `calcGraphNodeHash` consult `readSnapshotRuntimePin(graph[depPath].children)` first and only fall back to the install-wide `nodeVersion` parameter when the snapshot doesn't pin its own Node. Pacquet mirrors the same precedence at the `calc_graph_node_hash` call site in `package-manager/src/virtual_store_layout.rs` — a new `find_own_runtime_node_major(snapshot)` helper reads each snapshot's `dependencies` for a `node` entry with `Prefix::Runtime` and overrides the install-wide engine when present. On upgrade, snapshots of dependencies that declare their own `engines.runtime` re-hash under that dep's pinned Node instead of the install-wide value. The old slots become prune-eligible. Closes [#&#8203;11690](https://redirect.github.com/pnpm/pnpm/issues/11690). - Fixed `pnpm publish` failing with a 404 when authentication relied on OIDC trusted publishing alongside an `.npmrc` written by `actions/setup-node` (`_authToken=${NODE_AUTH_TOKEN}`) without `NODE_AUTH_TOKEN` being set. Unresolved `${VAR}` placeholders in auth values are now treated as empty rather than passed through verbatim, so the literal placeholder no longer surfaces as a bearer token when OIDC fallback is the intended auth source [#&#8203;11513](https://redirect.github.com/pnpm/pnpm/issues/11513). - Fix `devEngines.packageManager` (singular form, without `onFail`) defaulting to `onFail: "error"` instead of the documented `pmOnFail: "download"`. As a result, a project that pinned a different pnpm version via `devEngines.packageManager` and ran `pnpm install` from a mismatched pnpm version failed with a hard error, even though the migration table from `managePackageManagerVersions: true` to `pmOnFail: download (default)` promises the install would auto-download the wanted version [#&#8203;11676](https://redirect.github.com/pnpm/pnpm/issues/11676). The array form of `devEngines.packageManager` keeps its existing per-element defaults (`error` for the last entry, `ignore` for the rest), since those reflect explicit prioritization by the user. Explicit `onFail` values continue to win. - Fix `devEngines.packageManager` not writing `packageManagerDependencies` to `pnpm-lock.yaml` when the lockfile lacks an env-doc entry. Previously the lockfile sync skipped resolution unless an existing `packageManagerDependencies.pnpm` entry needed refreshing, so a fresh install without `onFail: "download"` left the resolved pnpm version unrecorded — contradicting the documented behavior that the resolved version is stored in `pnpm-lock.yaml` [#&#8203;11674](https://redirect.github.com/pnpm/pnpm/issues/11674). - Warn when `package.json` contains a legacy `pnpm` field with settings pnpm no longer reads from `package.json` (e.g. `pnpm.overrides`, `pnpm.patchedDependencies`). Previously these were silently ignored after the upgrade from v10, leaving users unaware that their overrides/patched dependencies had stopped taking effect [#&#8203;11677](https://redirect.github.com/pnpm/pnpm/issues/11677). ### [`v11.1.2`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1112) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.1.1...v11.1.2) ##### Patch Changes - `convertEnginesRuntimeToDependencies`: switch the runtime-dependency write to `Object.defineProperty` so the CodeQL `js/prototype-polluting-assignment` rule treats the assignment as safe regardless of the property name (follow-up to [#&#8203;11609](https://redirect.github.com/pnpm/pnpm/pull/11609)). - Address CodeQL static-analysis findings: guard manifest dependency writes against prototype-polluting keys (`__proto__`, `constructor`, `prototype`), and replace a potentially super-linear semver-detection regex in registry 404 hints with an O(n) parser. - Strip `sec-fetch-*` headers from outgoing HTTP requests. These headers are automatically added by undici's `fetch()` implementation per the Fetch spec but cause Azure DevOps Artifacts to return HTTP 400 for uncached upstream packages, as ADO interprets them as browser requests [#&#8203;11572](https://redirect.github.com/pnpm/pnpm/issues/11572). - Fix `minimumReleaseAge` handling for cached abbreviated metadata. The version-spec cache fast path no longer rethrows `ERR_PNPM_MISSING_TIME` under `strictPublishedByCheck`; it now falls through to the registry-fetch path, consistent with the adjacent mtime-gated cache block. When the registry returns 304 Not Modified for a package whose cached metadata is abbreviated (no per-version `time`), pnpm now re-fetches with `fullMetadata: true` if `minimumReleaseAge` is active and the package was modified after the cutoff. The upgraded metadata is persisted to disk so subsequent installs don't repeat the fetch. Previously the abbreviated meta was used as-is and the maturity check fell back to its warn-and-skip path, silently bypassing the quarantine and emitting a misleading "metadata is missing the time field" warning. Closes [#&#8203;11619](https://redirect.github.com/pnpm/pnpm/issues/11619). - Fix `pnpm upgrade --interactive --latest -r` not respecting named catalog groups. Previously, upgrading a dependency using a named catalog (e.g. `"catalog:foo"`) would incorrectly rewrite `package.json` to `"catalog:"` and place the updated version in the default catalog instead of the named one [#&#8203;10115](https://redirect.github.com/pnpm/pnpm/issues/10115). - Fixed `optimisticRepeatInstall` skipping `pnpm-lock.yaml` merge conflict resolution when the existing `node_modules` state appears up to date. - Fix `minimumReleaseAge` / `resolutionMode: time-based` installs failing on lockfiles whose `time:` block is missing entries. The npm-resolver's peek-from-store fast path now surfaces `publishedAt` from the lockfile rather than discarding it, and falls through to a registry metadata fetch when the time-based cutoff can't be computed from the data on hand. ### [`v11.1.1`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1111) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.1.0...v11.1.1) ##### Patch Changes - Skip installability validation when scanning workspace projects in `checkDepsStatus` (run by `verifyDepsBeforeRun`). Previously the status check called `findWorkspaceProjects`, which validates each project's `engines` and `os`/`cpu`/`libc` and warns about useless fields in non-root manifests — work that the install pipeline already performs. With no `nodeVersion` threaded through, the engine check also fell back to the system Node from `PATH` and emitted spurious "Unsupported engine" warnings before scripts ran. Status-only callers now use `findWorkspaceProjectsNoCheck`; install paths continue to validate. - Fixed `pnpm add <alias>:@&#8203;scope/pkg` for [named registries](https://redirect.github.com/pnpm/pnpm/pull/11324). The local resolver was claiming any specifier containing `/` as a local directory, so `pnpm add bit:@&#8203;teambit/bit` (with `bit` configured under `namedRegistries`) installed a bogus link to `bit:@&#8203;teambit/bit/` instead of resolving from the configured registry. The local resolver now runs after the named-registry resolver in the resolution chain. - Updated `@zkochan/cmd-shim` to 9.0.3. The sh shim it writes for `.cmd` / `.bat` targets now escapes the `/C` switch as `//C`, so it survives the path translation Git Bash applies when launching `cmd.exe`. Without this, a bare `/C` was rewritten to `C:\` before reaching cmd.exe — the switch was dropped, cmd started interactively, and the calling script saw the cmd banner instead of the wrapped command's output. Affects any cmd-shim-wrapped batch script invoked from Git Bash / MSYS / Cygwin on Windows. See [pnpm/cmd-shim#55](https://redirect.github.com/pnpm/cmd-shim/pull/55). ### [`v11.1.0`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1110) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.0.9...v11.1.0) ##### Minor Changes - Added `pnpm audit signatures` to verify ECDSA registry signatures for installed packages against keys from `/-/npm/v1/keys` [#&#8203;7909](https://redirect.github.com/pnpm/pnpm/issues/7909). Scoped registries are respected, and registries without signing keys are skipped. - Added support for installing packages from the [GitHub Packages npm registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry) via a built-in `gh:` prefix (e.g. `pnpm add gh:@&#8203;acme/private`), and, more broadly, for arbitrary named registries in the style of [vlt's named-registry aliases](https://docs.vlt.sh/cli/registries). Authentication is picked up from the existing per-URL `.npmrc` entries (e.g. `//npm.pkg.github.com/:_authToken=...`), so no separate auth mechanism is required. Additional aliases — or an override for the built-in `gh` alias, for GitHub Enterprise Server — can be configured under `namedRegistries` in `pnpm-workspace.yaml`: ```yaml namedRegistries: gh: https://npm.pkg.github.example.com/ work: https://npm.work.example.com/ ``` With this, `work:@&#8203;corp/lib@^2.0.0` resolves against `https://npm.work.example.com/`. [#&#8203;8941](https://redirect.github.com/pnpm/pnpm/issues/8941). - Allow setting sbom spec version using `--sbom-spec-version` [#&#8203;11389](https://redirect.github.com/pnpm/pnpm/pull/11389). - Add `--no-runtime` flag (config: `runtime=false`) to skip installing runtime entries (e.g. Node.js downloaded via `devEngines.runtime`) without modifying the lockfile. The lockfile keeps the runtime entry so frozen-lockfile validation still passes; only the runtime fetch and `.bin` linking are skipped. Useful in CI matrices where the runtime is provisioned externally (e.g. via `pnpm runtime -g set node <version>`) before `pnpm install` runs. - Added the `pnpm bugs` command that opens a package's bug tracker URL in the browser. With no arguments, it reads the current project's `package.json`; with one or more package names, it fetches each package's metadata from the registry and opens its bug tracker. Falls back to `<repository>/issues` when the `bugs` field is missing [#&#8203;11279](https://redirect.github.com/pnpm/pnpm/pull/11279). - Added `pnpm owner` command to manage package owners on the registry. ##### Patch Changes - Added "published X ago by Y" information to the `pnpm view` command output, similar to `npm view`. This is useful when comparing against `minimumReleaseAge`. For example, `pnpm view pnpm` now shows: ``` published 17 hours ago by GitHub Actions ``` - `pnpm publish` now honors the configured HTTP/HTTPS proxy (including `https_proxy`/`http_proxy`/`no_proxy` environment variables) when polling the registry's `doneUrl` during the web-based authentication flow. Previously the poll bypassed the proxy, causing the registry to respond `403` from a different source IP and the login to never complete [#&#8203;11561](https://redirect.github.com/pnpm/pnpm/issues/11561). - `pnpm add -g` now installs each space-separated package into its own isolated directory by default. To bundle multiple packages into the same isolated install (so that they share dependencies and are removed together), pass them as a comma-separated list. For example: - `pnpm add -g foo bar` installs `foo` and `bar` as two independent globals — removing one does not affect the other. - `pnpm add -g foo,bar qar` bundles `foo` and `bar` into a single isolated install while `qar` is installed on its own. Related: [#&#8203;11587](https://redirect.github.com/pnpm/pnpm/issues/11587). - `pnpm runtime set <name> <version>` no longer fails in the root of a multi-package workspace with the `ADDING_TO_ROOT` error. Installing the workspace root is a valid target for a runtime, so the command now bypasses that safety check. - Fix `pnpm --version` hanging for the lifetime of the worker pool after the version was printed. `main.ts`'s `--version` short-circuit returned before reaching the command-handler `finally` that calls `finishWorkers()`, so the worker pool that `switchCliVersion` had spawned during integrity resolution stayed alive and held the Node event loop open. The CLI entry now runs `finishWorkers()` from its own `finally`, so every exit path tears the pool down. Repro: `pnpm --version` in a workspace whose `devEngines.packageManager` version already matches the running pnpm + `onFail: "download"`. `switchCliVersion` resolves the integrity (spawning workers), finds nothing to swap, returns. The version prints, then the process hangs. ### [`v11.0.9`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1109) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.0.8...v11.0.9) ##### Patch Changes - Fixed installation of GitLab-hosted dependencies. pnpm now downloads the tarball from `https://gitlab.com/<user>/<project>/-/archive/<sha>/<project>-<sha>.tar.gz` instead of the GitLab API endpoint that contained an encoded slash (`%2F`) between user and project. The encoded slash both triggered `406 Not Acceptable` responses from GitLab and produced virtual store directory names that Node refused to import (`ERR_INVALID_MODULE_SPECIFIER`) [#&#8203;11533](https://redirect.github.com/pnpm/pnpm/issues/11533). - Honor `NPM_CONFIG_USERCONFIG` (and its lowercase `npm_config_userconfig` form) as a low-priority fallback when locating the user-level `.npmrc`. This restores compatibility with environments that point npm at a custom auth file via that env var — most notably `actions/setup-node`, which writes registry credentials to `${runner.temp}/.npmrc` and exports `NPM_CONFIG_USERCONFIG` to reference it. Without this, GitHub Actions workflows using `actions/setup-node` to authenticate to private registries broke after upgrading to pnpm v11. PNPM-prefixed env vars and `npmrcAuthFile` from the global `config.yaml` continue to take precedence [#&#8203;11539](https://redirect.github.com/pnpm/pnpm/issues/11539). - Fix `pnpm pack` not bundling dependencies listed in `bundleDependencies` (or `bundledDependencies`). The npm-packlist upgrade in pnpm 11 changed its API to require the caller to pre-populate the dependency tree, which the wrapper was not doing — `bundleDependencies` were silently dropped from the tarball [#&#8203;11519](https://redirect.github.com/pnpm/pnpm/issues/11519). - Fixed the pnpm CLI crashing with a confusing `SyntaxError: Invalid regular expression flags` instead of printing a clear "requires Node.js v22.13" error when launched on an unsupported Node.js version. The Node.js version check in `bin/pnpm.mjs` was effectively dead code because the static `import` of the bundled `dist/pnpm.mjs` was hoisted by the ES module loader and parsed before the check could run [#&#8203;11546](https://redirect.github.com/pnpm/pnpm/issues/11546). - Fixed `pnpm --prefix=<dir> install` overwriting the existing `pnpm-workspace.yaml` in `<dir>` with `set this to true or false` placeholders. The renamed `--prefix` option (which maps to `dir`) was not honored when locating the workspace root, so the workspace manifest's `allowBuilds` settings were not loaded into config and got clobbered when ignored builds were auto-populated [#&#8203;11535](https://redirect.github.com/pnpm/pnpm/issues/11535). - Fixed `pnpm publish --provenance` failing with a 422 from the registry when the package version contained semver build metadata (e.g. `1.0.0-canary.0+abc1234`). The `+<build>` segment is now stripped before packing so that the version embedded in the tarball, the metadata sent to the registry, and the sigstore provenance subject all agree [#&#8203;11518](https://redirect.github.com/pnpm/pnpm/issues/11518). ### [`v11.0.8`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1108) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.0.7...v11.0.8) ##### Patch Changes - Restored the heuristic that preserves tarball URLs in `pnpm-lock.yaml` when they cannot be derived from name+version+registry, even with the default `lockfileIncludeTarballUrl: false`. Without this, `pnpm install --frozen-lockfile` from an empty store fails with `ERR_PNPM_FETCH_404` for packages on registries that serve tarballs from a non-standard path — most notably GitHub Packages (`https://npm.pkg.github.com/download/<scope>/<name>/<version>/<hash>`) and JSR. `lockfileIncludeTarballUrl: true` continues to force the URL into the lockfile for every package [#&#8203;11276](https://redirect.github.com/pnpm/pnpm/issues/11276). - Run `preversion`, `version`, and `postversion` lifecycle scripts for `pnpm version`. - Fixed `ERR_PNPM_BAD_TARBALL_SIZE` when a registry serves tarballs with an end-to-end `Content-Encoding` (e.g. `gzip`). Tarballs are already compressed, so the fetcher now requests them with `Accept-Encoding: identity` (matching pnpm v10's effective behavior) and, as defense in depth against misbehaving servers, no longer enforces the strict `Content-Length` check when the response declares a `Content-Encoding` — `Content-Length` in that case refers to the encoded payload, not the decoded bytes the fetch implementation yields [#&#8203;11506](https://redirect.github.com/pnpm/pnpm/issues/11506). ### [`v11.0.7`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1107) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.0.6...v11.0.7) ##### Patch Changes - Restore the execute bit on the `node-gyp` shims packed inside `@pnpm/exe` (`dist/node-gyp-bin/node-gyp`, `dist/node-gyp-bin/node-gyp.cmd`, and `dist/node_modules/node-gyp/bin/node-gyp.js`). Without this, `pnpm/action-setup`'s standalone path (used on runners with Node.js < 22.13) failed any install whose lifecycle script invoked `node-gyp rebuild` with `sh: 1: node-gyp: Permission denied` [#&#8203;11483](https://redirect.github.com/pnpm/pnpm/issues/11483). - Fixed the `pn`, `pnpx`, and `pnx` aliases failing in Git Bash / MSYS2 on Windows when pnpm was installed via `@pnpm/exe` (or after `pnpm self-update`) [#&#8203;11486](https://redirect.github.com/pnpm/pnpm/issues/11486). Running `pnpx` (or `pnx`) printed the cmd.exe banner and dropped the user into an interactive command prompt instead of running `pnpm dlx`. The `bin` field rewrite on Windows was pointing those aliases at `.cmd` files; cmd-shim's Bash shim for a `.cmd` target wraps it in `exec cmd /C ...`, and MSYS2 mangles `/C` into a Windows path before cmd.exe sees it. The aliases are now `.exe` hardlinks of the SEA binary, which detects which name it was launched as via `process.execPath` and prepends `dlx` for `pnpx` / `pnx`. - Fix `pnpm install` recreating `node_modules` after `pnpm fetch`. `pnpm fetch` records empty `hoistPattern` and `publicHoistPattern` in `.modules.yaml`; since v11 removed the explicit-config gate, the follow-up install treated those as a hoist-pattern change and purged the modules directory. The fetch step now flags the modules manifest with `virtualStoreOnly: true` so the next install skips the hoist-pattern comparison and completes the missing post-import linking in place [#&#8203;11488](https://redirect.github.com/pnpm/pnpm/issues/11488). - 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. - Allow user-level preferences in the global `config.yaml`. The following settings can now be set in `~/.config/pnpm/config.yaml` (or via `pnpm config set --location global`) instead of being restricted to `pnpm-workspace.yaml`: `agent`, `globalVirtualStoreDir`, `initPackageManager`, `initType`, `registrySupportsTimeField`, `scriptShell`, `shellEmulator`, `sideEffectsCache`, `sideEffectsCacheReadonly`, `stateDir`, `strictDepBuilds`, `trustPolicy`, `trustPolicyExclude`, `trustPolicyIgnoreAfter`, `updateNotifier`, `useStderr`, `verifyDepsBeforeRun`, `verifyStoreIntegrity`, `virtualStoreDir`, `virtualStoreDirMaxLength` [#&#8203;11474](https://redirect.github.com/pnpm/pnpm/issues/11474). - Make trusted publishing (OIDC) take precedence over a configured static `_authToken` in `pnpm publish`, mirroring the npm CLI's behavior. When OIDC succeeds, the OIDC-derived token overrides any pre-configured `_authToken`; when OIDC is not applicable (no CI environment, exchange fails, registry has no trusted publisher configured), the static token is used as a fallback. This applies on every package during recursive publish, so each workspace package independently attempts trusted publishing. Additionally, the `NPM_ID_TOKEN` env var is now honored as a CI-agnostic injection point for an OIDC ID token. Previously OIDC was only attempted on GitHub Actions or GitLab; now any CI provider that exposes its own OIDC mechanism (e.g. CircleCI's `CIRCLE_OIDC_TOKEN_V2`, Buildkite, etc.) can forward its token via `NPM_ID_TOKEN` and trusted publishing will work without pnpm needing to recognize the provider explicitly. - `--pm-on-fail=ignore` (and other universal options like `--loglevel`, `--reporter`) is now honored when combined with `--help` or `--version`. Previously the CLI argument parser short-circuited those flags before universal options were preserved, so `pnpm audit --pm-on-fail=ignore --help` and `pnpm --pm-on-fail=ignore --version` reported the strict packageManager mismatch instead of running the requested action [#&#8203;11487](https://redirect.github.com/pnpm/pnpm/issues/11487). - 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](https://pnpm.io/cli/recursive). To include the root, pass `--include-workspace-root` [#&#8203;11341](https://redirect.github.com/pnpm/pnpm/issues/11341). - Restore npm-CLI-compatible `--json` stdout output for `pnpm publish` ([#&#8203;11476](https://redirect.github.com/pnpm/pnpm/issues/11476)). pnpm 11 reimplemented publish natively ([#&#8203;10591](https://redirect.github.com/pnpm/pnpm/pull/10591)) and inadvertently dropped the per-package JSON object that pnpm 10 emitted transitively via the npm CLI, silently breaking downstream tooling — most notably `nx release publish`, which parses stdout JSON to confirm success ([nrwl/nx#35575](https://redirect.github.com/nrwl/nx/issues/35575)). On success, the output is now: - `pnpm publish --json` → single object `{ id, name, version, size, unpackedSize, shasum, integrity, filename, files, entryCount, bundled }`, mirroring `npm publish --json`. - `pnpm publish -r --json` → array of those objects, mirroring `pnpm pack --json`'s shape choice. - `pnpm publish -r --report-summary` → existing `pnpm-publish-summary.json` envelope `{ publishedPackages: [...] }` is preserved, but each entry is upgraded to the same per-package shape (additive — `name` and `version` are still present). - `pnpm config get @&#8203;<scope>:registry` now reports the same URL that `pnpm publish` and the resolvers actually use. Previously, `config get` only consulted `.npmrc`, while `publish`/install used the merged map that includes `pnpm-workspace.yaml`'s `registries` block — so the two could diverge silently and a publish could go to the wrong registry [#&#8203;11492](https://redirect.github.com/pnpm/pnpm/issues/11492). ### [`v11.0.6`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1106) [Compare Source](https://redirect.github.com/pnpm/pnpm/compare/v11.0.5...v11.0.6) ##### Patch Changes - Fix `pnpm_config_npmrc_auth_file` and `pnpm_config_userconfig` env vars not actually loading the custom `.npmrc`. The env vars were parsed and assigned to the resolved config, but only after `loadNpmrcConfig` had already read the default `~/.npmrc` — so the custom file path was set but never read. The relevant env vars are now consulted before the user-level `.npmrc` is loaded [#&#8203;11465](https://redirect.github.com/pnpm/pnpm/issues/11465). - Preserve the original key order in `pnpm-workspace.yaml` when updating it. Existing keys keep their position, and new keys are inserted in alphabetical position when the existing keys are already sorted (with a leading `packages` key allowed) or appended at the end otherwise. - Fixed `pnpm self-update` on installations originally set up by pnpm v10. v10 added `PNPM_HOME` directly to PATH and wrote a `pnpm` bootstrap shim there. v11 setup writes shims under `PNPM_HOME/bin` instead, so when a v10 user upgrades to v11 the legacy shim at `PNPM_HOME` keeps pointing into the old `.tools/<version>` install — `pnpm --version` continues to report the pre-update version even though the new version was installed under `global/v11`. Self-update now detects this layout, refreshes the legacy shims so the upgrade actually takes effect, and prints a hint suggesting `pnpm setup` to migrate PATH to the v11 layout. [#&#8203;11464](https://redirect.github.com/pnpm/pnpm/issues/11464). - Print a warning when settings that are not allowed in the global config file (e.g. `nodeLinker`, `hoistPattern`) are present in `config.yaml` and silently ignored. Previously these settings were dropped without any feedback, leaving users unsure why their global configuration had no effect. The warning suggests moving those settings to a project-level `pnpm-workspace.yaml`, or sharing them across projects via [config dependencies](https://pnpm.io/11.x/config-dependencies). - Throw a pnpm error when `overrides` has an invalid shape or contains a non-string value. - Validate all `readPackage` dependency map fields, including `devDependencies`, and reject falsy non-object invalid values instead of silently accepting them. - Prevent crashes during `pnpm config`, `pnpm set`, and `pnpm get` by tolerating `configDependencies` install failures. For these commands, a failure to install `configDependencies` (for example because the registry auth token has not been written yet) is now logged at debug level and the command proceeds. All other commands still surface the install error [#&#8203;10684](https://redirect.github.com/pnpm/pnpm/issues/10684). - Treat `allowBuilds` as an install-state input and clear previously ignored builds when they are explicitly disallowed. - Fixes [#&#8203;10594](https://redirect.github.com/pnpm/pnpm/issues/10594), catalogs not being read from the workspace when using the `catalog:` protocol with the `pnpm dlx` / `pnpx` command, resulting in a catalog entry not found error. - Accept `PNPM_CONFIG_*` (uppercase) environment variables in addition to `pnpm_config_*`. Previously, only the lowercase form was honored, so env var > āœ‚ **Note** > > PR body was truncated to here. </details> --- ### Configuration šŸ“… **Schedule**: (in timezone Asia/Shanghai) - Branch creation - "before 10am on the first day of the month" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ā™» **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. šŸ”• **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc-resolver). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIwMi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
main
2 hours ago
chore(deps): update pnpm to v11.4.0
renovate/pnpm-package-manager
2 hours ago
chore: release v11.20.1
release-plz-2026-05-28T15-25-06Z
6 hours ago
chore(deps): update github actions (#1191) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [oxc-project/security-action](https://redirect.github.com/oxc-project/security-action) | action | patch | `v1.0.5` → `v1.0.7` | | [oxc-project/setup-rust](https://redirect.github.com/oxc-project/setup-rust) | action | patch | `v1.0.16` → `v1.0.17` | --- ### Release Notes <details> <summary>oxc-project/security-action (oxc-project/security-action)</summary> ### [`v1.0.7`](https://redirect.github.com/oxc-project/security-action/compare/v1.0.6...v1.0.7) [Compare Source](https://redirect.github.com/oxc-project/security-action/compare/v1.0.6...v1.0.7) ### [`v1.0.6`](https://redirect.github.com/oxc-project/security-action/compare/v1.0.5...v1.0.6) [Compare Source](https://redirect.github.com/oxc-project/security-action/compare/v1.0.5...v1.0.6) </details> <details> <summary>oxc-project/setup-rust (oxc-project/setup-rust)</summary> ### [`v1.0.17`](https://redirect.github.com/oxc-project/setup-rust/compare/v1.0.16...v1.0.17) [Compare Source](https://redirect.github.com/oxc-project/setup-rust/compare/v1.0.16...v1.0.17) </details> --- ### Configuration šŸ“… **Schedule**: (in timezone Asia/Shanghai) - Branch creation - "before 10am on monday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ā™» **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. šŸ‘» **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc-resolver). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIwMi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
main
6 hours ago
chore(deps): update github actions
renovate/github-actions
6 hours ago
chore(deps): update rust crates (#1192) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [compact_str](https://redirect.github.com/ParkMyCar/compact_str) | dependencies | patch | `0.9.0` → `0.9.1` | | [mimalloc-safe](https://redirect.github.com/napi-rs/mimalloc-safe) | dependencies | patch | `0.1.61` → `0.1.62` | --- ### Release Notes <details> <summary>ParkMyCar/compact_str (compact_str)</summary> ### [`v0.9.1`](https://redirect.github.com/ParkMyCar/compact_str/compare/v0.9.0...v0.9.1) [Compare Source](https://redirect.github.com/ParkMyCar/compact_str/compare/v0.9.0...v0.9.1) </details> <details> <summary>napi-rs/mimalloc-safe (mimalloc-safe)</summary> ### [`v0.1.62`](https://redirect.github.com/napi-rs/mimalloc-safe/blob/HEAD/CHANGELOG.md#0162---2026-05-26) [Compare Source](https://redirect.github.com/napi-rs/mimalloc-safe/compare/mimalloc-safe-v0.1.61...mimalloc-safe-v0.1.62) ##### Bug Fixes - *(sys)* Vendor Apple THREAD\_LOCAL patch in napi-rs/mimalloc fork ([#&#8203;71](https://redirect.github.com/napi-rs/mimalloc-safe/pull/71)) ##### Chore - *(deps)* Update yarn to v4.15.0 ([#&#8203;70](https://redirect.github.com/napi-rs/mimalloc-safe/pull/70)) </details> --- ### Configuration šŸ“… **Schedule**: (in timezone Asia/Shanghai) - Branch creation - "before 10am on monday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ā™» **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. šŸ‘» **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc-resolver). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIwMi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
main
6 hours ago
chore(deps): update dependency bun to v1.3.14 (#1190) This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [bun](https://bun.com) ([source](https://redirect.github.com/oven-sh/bun)) | `1.3.9` → `1.3.14` | ![age](https://developer.mend.io/api/mc/badges/age/npm/bun/1.3.14?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/bun/1.3.14?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/bun/1.3.9/1.3.14?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/bun/1.3.9/1.3.14?slim=true) | --- ### Release Notes <details> <summary>oven-sh/bun (bun)</summary> ### [`v1.3.14`](https://redirect.github.com/oven-sh/bun/releases/tag/bun-v1.3.14): Bun v1.3.14 [Compare Source](https://redirect.github.com/oven-sh/bun/compare/bun-v1.3.13...bun-v1.3.14) To install Bun v1.3.14 ```bash curl -fsSL https://bun.sh/install | bash # or you can use npm # npm install -g bun ``` Windows: ```bash powershell -c "irm bun.sh/install.ps1|iex" ``` To upgrade to Bun v1.3.14: ```bash bun upgrade ``` ##### [Read Bun v1.3.14's release notes on Bun's blog](https://bun.com/blog/bun-v1.3.14) ##### Thanks to 11 contributors! - [@&#8203;190n](https://redirect.github.com/190n) - [@&#8203;alii](https://redirect.github.com/alii) - [@&#8203;carlsmedstad](https://redirect.github.com/carlsmedstad) - [@&#8203;cirospaciari](https://redirect.github.com/cirospaciari) - [@&#8203;coleleavitt](https://redirect.github.com/coleleavitt) - [@&#8203;djs5008](https://redirect.github.com/djs5008) - [@&#8203;dylan-conway](https://redirect.github.com/dylan-conway) - [@&#8203;ig-ant](https://redirect.github.com/ig-ant) - [@&#8203;Jarred-Sumner](https://redirect.github.com/Jarred-Sumner) - [@&#8203;robobun](https://redirect.github.com/robobun) - [@&#8203;sosukesuzuki](https://redirect.github.com/sosukesuzuki) ### [`v1.3.13`](https://redirect.github.com/oven-sh/bun/releases/tag/bun-v1.3.13): Bun v1.3.13 [Compare Source](https://redirect.github.com/oven-sh/bun/compare/bun-v1.3.12...bun-v1.3.13) To install Bun v1.3.13 ```bash curl -fsSL https://bun.sh/install | bash # or you can use npm # npm install -g bun ``` Windows: ```bash powershell -c "irm bun.sh/install.ps1|iex" ``` To upgrade to Bun v1.3.13: ```bash bun upgrade ``` ##### [Read Bun v1.3.13's release notes on Bun's blog](https://bun.com/blog/bun-v1.3.13) ##### Thanks to 8 contributors! - [@&#8203;alii](https://redirect.github.com/alii) - [@&#8203;ant-kurt](https://redirect.github.com/ant-kurt) - [@&#8203;chrislloyd](https://redirect.github.com/chrislloyd) - [@&#8203;cirospaciari](https://redirect.github.com/cirospaciari) - [@&#8203;dylan-conway](https://redirect.github.com/dylan-conway) - [@&#8203;jarred-sumner](https://redirect.github.com/jarred-sumner) - [@&#8203;robobun](https://redirect.github.com/robobun) - [@&#8203;sosukesuzuki](https://redirect.github.com/sosukesuzuki) ### [`v1.3.12`](https://redirect.github.com/oven-sh/bun/releases/tag/bun-v1.3.12): Bun v1.3.12 [Compare Source](https://redirect.github.com/oven-sh/bun/compare/bun-v1.3.11...bun-v1.3.12) To install Bun v1.3.12 ```bash curl -fsSL https://bun.sh/install | bash # or you can use npm # npm install -g bun ``` Windows: ```bash powershell -c "irm bun.sh/install.ps1|iex" ``` To upgrade to Bun v1.3.12: ```bash bun upgrade ``` ##### [Read Bun v1.3.12's release notes on Bun's blog](https://bun.sh/blog/bun-v1.3.12) ##### Thanks to 8 contributors! - [@&#8203;alii](https://redirect.github.com/alii) - [@&#8203;ant-kurt](https://redirect.github.com/ant-kurt) - [@&#8203;cirospaciari](https://redirect.github.com/cirospaciari) - [@&#8203;dylan-conway](https://redirect.github.com/dylan-conway) - [@&#8203;gameroman](https://redirect.github.com/gameroman) - [@&#8203;jarred-sumner](https://redirect.github.com/jarred-sumner) - [@&#8203;robobun](https://redirect.github.com/robobun) - [@&#8203;sosukesuzuki](https://redirect.github.com/sosukesuzuki) ### [`v1.3.11`](https://redirect.github.com/oven-sh/bun/releases/tag/bun-v1.3.11): Bun v1.3.11 [Compare Source](https://redirect.github.com/oven-sh/bun/compare/bun-v1.3.10...bun-v1.3.11) To install Bun v1.3.11 ```bash curl -fsSL https://bun.sh/install | bash # or you can use npm # npm install -g bun ``` Windows: ```bash powershell -c "irm bun.sh/install.ps1|iex" ``` To upgrade to Bun v1.3.11: ```bash bun upgrade ``` ##### [Read Bun v1.3.11's release notes on Bun's blog](https://bun.com/blog/bun-v1.3.11) ##### Thanks to 15 contributors! - [@&#8203;alii](https://redirect.github.com/alii) - [@&#8203;anthonybaldwin](https://redirect.github.com/anthonybaldwin) - [@&#8203;baboon-king](https://redirect.github.com/baboon-king) - [@&#8203;c-stoeckl](https://redirect.github.com/c-stoeckl) - [@&#8203;cirospaciari](https://redirect.github.com/cirospaciari) - [@&#8203;dylan-conway](https://redirect.github.com/dylan-conway) - [@&#8203;gaowhen](https://redirect.github.com/gaowhen) - [@&#8203;hona](https://redirect.github.com/hona) - [@&#8203;igorkofman](https://redirect.github.com/igorkofman) - [@&#8203;jarred-sumner](https://redirect.github.com/jarred-sumner) - [@&#8203;km-anthropic](https://redirect.github.com/km-anthropic) - [@&#8203;robobun](https://redirect.github.com/robobun) - [@&#8203;sosukesuzuki](https://redirect.github.com/sosukesuzuki) - [@&#8203;ssing2](https://redirect.github.com/ssing2) - [@&#8203;whiteminds](https://redirect.github.com/whiteminds) ### [`v1.3.10`](https://redirect.github.com/oven-sh/bun/releases/tag/bun-v1.3.10): Bun v1.3.10 [Compare Source](https://redirect.github.com/oven-sh/bun/compare/bun-v1.3.9...bun-v1.3.10) To install Bun v1.3.10 ```bash curl -fsSL https://bun.sh/install | bash # or you can use npm # npm install -g bun ``` Windows: ```bash powershell -c "irm bun.sh/install.ps1|iex" ``` To upgrade to Bun v1.3.10: ```bash bun upgrade ``` ##### [Read Bun v1.3.10's release notes on Bun's blog](https://bun.com/blog/bun-v1.3.10) ##### Thanks to 11 contributors! - [@&#8203;alanstott](https://redirect.github.com/alanstott) - [@&#8203;alii](https://redirect.github.com/alii) - [@&#8203;cirospaciari](https://redirect.github.com/cirospaciari) - [@&#8203;dylan-conway](https://redirect.github.com/dylan-conway) - [@&#8203;hk-shao](https://redirect.github.com/hk-shao) - [@&#8203;hona](https://redirect.github.com/hona) - [@&#8203;jarred-sumner](https://redirect.github.com/jarred-sumner) - [@&#8203;martinamps](https://redirect.github.com/martinamps) - [@&#8203;prekucki](https://redirect.github.com/prekucki) - [@&#8203;robobun](https://redirect.github.com/robobun) - [@&#8203;sosukesuzuki](https://redirect.github.com/sosukesuzuki) </details> --- ### Configuration šŸ“… **Schedule**: (in timezone Asia/Shanghai) - Branch creation - "before 10am on monday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ā™» **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. šŸ”• **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc-resolver). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIwMi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
main
6 hours ago

Latest Branches

CodSpeed Performance Gauge
+5%
chore: release v11.20.1#1178
2 hours ago
0c05490
release-plz-2026-05-28T15-25-06Z
CodSpeed Performance Gauge
-2%
chore(deps): update pnpm to v11.4.0#1194
2 hours ago
72fa022
renovate/pnpm-package-manager
CodSpeed Performance Gauge
-1%
6 hours ago
88b632b
renovate/github-actions
Ā© 2026 CodSpeed Technology
Home Terms Privacy Docs