* feat: install config dependencies into the global virtual store
Config dependencies are now imported into {storeDir}/links/ following the
same path convention as regular packages (@scope/name/version/hash), then
symlinked into node_modules/.pnpm-config/. When the package already exists
in the GVS, the fetch and import are skipped entirely.
* refactor: extract shared GVS path computation into @pnpm/calc-dep-state
Move the leaf node hash computation from config deps-installer into
calcLeafGlobalVirtualStorePath in @pnpm/calc-dep-state to avoid
duplicating the hash logic.
When running `pnpm add -g .`, the linked-from path equals the cwd,
so path.relative() returns an empty string which is falsy, causing
the fallback to '???'. Use the absolute path as fallback instead.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Hide the ugly temporary directory path prefix from progress output
for global installs (same approach as dlx). Show a proper install
summary with "global:" heading instead of the temp directory path.
* fix: prefer .pnpmfile.mjs by default
* fix: handle ERR_MODULE_NOT_FOUND for missing optional .pnpmfile.mjs
Node's dynamic import() throws ERR_MODULE_NOT_FOUND (not MODULE_NOT_FOUND
like require()) when a file doesn't exist. This caused a hard error when
tryLoadDefaultPnpmfile was enabled and .pnpmfile.mjs was absent.
* fix: load only .pnpmfile.mjs when it exists, not both .mjs and .cjs
When both .pnpmfile.mjs and .pnpmfile.cjs exist, only the .mjs file
is now loaded. Previously both were loaded and their hooks combined.
Also adds .mjs support for config dependency plugins.
* feat: switch from pkg to Node.js SEA for creating standalone executables
Replace @yao-pkg/pkg with Node.js native Single Executable Applications
(--build-sea, Node.js 25.5+). The SEA binary embeds only pnpm.cjs (CJS
bootstrap), while pnpm.mjs and all assets live in a dist/ directory
shipped alongside the binary in platform-specific tarballs.
* refactor: move dist/ from platform packages to @pnpm/exe
The dist/ directory (pnpm.mjs, worker.js, templates, etc.) is identical
across all platforms, so ship it once in @pnpm/exe instead of duplicating
it in each platform package. Platform packages now only contain the
binary. The self-updater installs @pnpm/exe (not the platform package)
so it gets both dist/ and the binary via optionalDependencies.
* refactor: externalize @reflink/reflink in esbuild bundle
Make @reflink/reflink external in both the main and worker esbuild
bundles so the require() calls resolve at runtime from dist/node_modules
instead of being inlined. Add @reflink/reflink as a production dependency
of both pnpm (bundled into dist/node_modules by bundle-deps.ts) and
@pnpm/exe (installed by npm alongside the binary).
For GitHub release tarballs, only the target platform's reflink package
is kept. For @pnpm/exe npm publishing, all reflink platform packages
are stripped from dist/ since npm installs the right one automatically.
* chore: update cspell list
* test: update system-node-version tests for SEA detection
Mock @pnpm/cli-meta's detectIfCurrentPkgIsExecutable instead of
setting process.pkg, which is no longer used for SEA detection.
* test: improve cli-meta test coverage for SEA migration
Add tests for detectIfCurrentPkgIsExecutable() (non-SEA path) and
isExecutedByCorepack() which were previously untested. The SEA=true
path of detectIfCurrentPkgIsExecutable() cannot be unit tested since
node:sea is unavailable in an ESM test environment.
* refactor: move GitHub tarball assembly to copy-artifacts.ts
build-artifacts.ts (prepublishOnly of @pnpm/exe) now only builds the
SEA executables and prepares the exe npm dist/. The per-target dist/
assembly for GitHub release tarballs moves to copy-artifacts.ts, which
is the natural owner of that concern.
Other changes:
- Extract getReflinkKeepPackages/stripReflinkPackages to reflink-utils.ts
with tests using node:test
- Move --force from top-level pnpm install in release.yml to the pnpm
deploy in bundle-deps.ts, where it is actually needed to install all
@reflink/reflink-* platform packages into dist/node_modules
- Change @pnpm/exe prepublishOnly to run pnpm's full prepublishOnly
(compile + bundle-deps) so dist/node_modules is populated before
build-artifacts.ts and copy-artifacts.ts read from pnpm/dist
* fix: copy dist/ alongside binary when running pnpm setup for SEA
When the pnpm CLI is a Node.js SEA binary, it requires a dist/ directory
adjacent to the executable at runtime (containing pnpm.mjs and bundled
node_modules). The copyCli function in plugin-commands-setup now copies
dist/ from alongside the current binary into the tools directory so that
the installed pnpm works correctly after `pnpm setup`.
* fix: avoid argument list too long when creating Windows zip archives
* fix: propagate errors in copy-artifacts script
Previously errors in createArtifactTarball were swallowed, causing the
script to exit 0 even when artifact creation failed. Now errors are
re-thrown with a descriptive message, and the top-level IIFE has a
.catch() handler that sets a non-zero exit code.
* refactor: remove reflink-utils.ts from @pnpm/exe
The stripReflinkPackages call in build-artifacts.ts stripped all platform
packages while keeping @reflink/reflink. Instead, just remove the entire
@reflink directory from dist/ — @pnpm/exe already declares @reflink/reflink
as a runtime dependency, so npm installs it (along with the right platform
package via optionalDependencies) automatically.
This eliminates reflink-utils.ts, its tests, and the code duplication with
copy-artifacts.ts.
* feat: add --yes command line option
* feat: skip confirm modules purge prompt if --yes is passed
* refactor: factor out `ExecPnpmSyncOpts`
* test: add end-to-end test for --yes flag
* fix: `shamefullyHoist` set via `updateConfig` in `.pnpmfile.cjs`
* refactor: consolidate derived config processing to cli-utils
Move shamefullyHoist → publicHoistPattern conversion from
config/config to cli-utils/getConfig.ts as suggested in review.
* test(config): update tests for derived config processing move
* refactor: move applyDerivedConfig to cli-utils
* refactor: move applyDerivedConfig to cli-utils
* test: use unit test for hoist: false in cli-utils
* revert: not needed changes
close#10271