**TLDR:** Global packages in pnpm v10 are annoying and slow because they all are installed to a single global package. Instead, we will now use a system that is similar to the one used by "pnpm dlx" (aka "pnpx").
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 or version resolution shifts.
## Changes
- Add `@pnpm/global-packages` shared utilities package for scanning, hashing, and managing isolated global installs
- `pnpm add -g` creates isolated installs in `{pnpmHomeDir}/global/v11/{hash}/`
- `pnpm remove -g` removes the entire installation group containing the package
- `pnpm update -g` re-installs into new isolated directories and swaps symlinks
- `pnpm list -g` scans isolated directories to show installed global packages
- `pnpm outdated -g` checks each isolated installation for outdated dependencies
- `pnpm store prune` cleans up orphaned global installation directories
## Breaking changes
- `pnpm install -g` (no args) is no longer supported — use `pnpm add -g <pkg>`
- `pnpm link <pkg-name>` no longer resolves packages from the global store — only relative or absolute paths are accepted
- `pnpm link --global` is removed — use `pnpm add -g .` to register a local package's bins globally
* feat: enhance `store prune` to clean global virtual store
`pnpm store prune` will now clean the global virtual store
via a new project registry and mark-and-sweep garbage collection.
* test: add store prune test for transitive dependency preservation
* refactor: extract global virtual store pruning logic to a new file
* fix: improve symlink handling in global virtual store pruning
* fix: optimize removal of unreachable packages in global virtual store
* fix: refine project registry error handling
Throw `PnpmError` for inaccessible projects
and specifically clean up stale symlinks for `ENOENT` errors.
* test: create virtual store with install command
* refactor: standardize global virtual store directory structure
by placing unscoped packages under an `@` scope.
* test: update store prune tests to use `toContain` and `not.toContain` assertions`
* fix: linting issues
* Apply suggestions from code review
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: implemented CR suggestions
* fix: revert not needed change
* fix: use `is-subdir` to accurately determine if symlink targets
are within the global virtual store.
* revert: changes in package.json files
* test: add `--config.ci=false` to store prune tests
* chore: `package.json` add type field
* chore: add type field to every package.json
* chore: add type field to every package.json
---------
Co-authored-by: Zoltan Kochan <z@kochan.io>