* fix: handle verifyDepsBeforeRun prompt in non-TTY environments
In non-interactive environments like CI, verifyDepsBeforeRun: 'prompt' would
silently exit with code 0 even when node_modules were out of sync. This could
cause tests to pass when they should fail.
Now, pnpm throws an error in non-TTY environments, alerting users that they
need to run 'pnpm install' first.
Also handles Ctrl+C gracefully during the prompt - exits cleanly without
showing a stack trace.
Fixes#10889Fixes#10888
* fix: improve Ctrl+C handling and fix prompt TTY guard
- Replace brittle ERR_USE_AFTER_CLOSE check with generic catch for prompt
cancellation (enquirer rejects with empty string on Ctrl+C, not that error)
- Fix prompt test to mock isTTY=true since Jest runs in non-TTY environment
- Fix test description "noTTY" → "non-TTY"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: narrow try/catch to only wrap enquirer.prompt
Avoid catching errors from install() which should propagate normally.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: zubeyralmaho <zubeyralmaho@users.noreply.github.com>
Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add n/prefer-node-protocol rule and autofix all bare builtin imports
to use the node: prefix. Simplify the simple-import-sort builtins
pattern to just ^node: since all imports now use the prefix.
Add eslint-plugin-simple-import-sort to enforce consistent import ordering:
- Node.js builtins first
- External packages second
- Relative imports last
- Named imports sorted alphabetically within each statement
## Summary
Fixes intermittent failures in the `parallel dlx calls of the same package` test, especially on Windows CI. Multiple race conditions were discovered when concurrent `pnpm dlx` processes share the same Global Virtual Store (GVS):
- **Content-verified skip in GVS mode**: When `safeToSkip` is true and a rename fails because the target already exists (ENOTEMPTY/EEXIST/EPERM), verify all files match (inode or content comparison) before skipping. Falls through to `renameOverwriteSync` if content doesn't match.
- **Tolerate EPERM during bin creation on Windows**: `cmd-shim`'s `chmod` can fail with EPERM when another process holds the `.bin` file. Warn instead of crashing.
- **Handle EPERM in DLX cache symlink**: Added EPERM to the list of tolerated errors when creating the DLX cache symlink, as Windows can throw this when another process has the symlink open.
## Test plan
- [x] `parallel dlx calls of the same package` test passes on Windows CI
- [x] Full test suite passes on both Ubuntu and Windows
Update all packages from zkochan/packages to their latest major versions
and exclude them from minimumReleaseAge requirement. This includes
updating catalog entries, adapting to breaking API changes (default
exports replaced with named exports, sync functions renamed with Sync
suffix), and updating type declarations.
* feat: use global virtual store for global packages and dlx
* fix(config): remove unnecessary virtualStoreDir override for global installs
When the global virtual store is disabled, the default `node_modules/.pnpm`
path works fine — no need to explicitly override it to `.pnpm`.
**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
* fix(dlx): print help message on calling pnpm dlx without arguments
Running `pnpm dlx` with no arguments would crash Node.js with a
TypeError as it attempted to call `.indexOf()` on an undefined variable.
This commit adds a guard clause and displays the help message instead
and exits gracefully.
Fixes#10633
* refactor: dlx
---------
Co-authored-by: Zoltan Kochan <z@kochan.io>
* fix(run): fail when no packages have script in filtered recursive run
Previously, `pnpm run -r <script>` and `pnpm run --filter <filter> <script>`
would silently succeed with exit code 0 when no packages had the specified
script, as long as a filter was used. This was inconsistent with the
documentation which states "If none of the packages have the command, the
command fails."
This change makes the command fail with ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT in
all cases where no packages have the script, regardless of whether a filter
is used. The `--if-present` flag can be used to suppress this error.
close#6844