Rust CLI (v12): `pnpm run <TAB>` no longer completes package.json scripts (completion-server ignores the manifest)
Last pnpm version that worked
11.9.0 (Node CLI, @pnpm/exe). Verified directly; presumably every Node-based release, since script completion for pnpm run was the behaviour behind #5426 and #7964 (both closed as completed).
pnpm version
12.4.2 (Rust CLI, installed via Homebrew, which builds pnpm/crates/cli from the v12.4.2 tag). Same on main as far as the source goes (see below).
Code to reproduce the issue
mkdir repro && cd repro
printf '{"name":"repro","version":"1.0.0","scripts":{"hello":"echo hi","build":"echo b"}}' > package.json
# This is exactly what the generated fish/bash/zsh completion scripts run for `pnpm run <TAB>`:
SHELL=fish COMP_LINE="pnpm run " COMP_POINT=9 pnpm completion-server -- pnpm run ""
# -> prints nothing, exit 0 (same with SHELL=bash / SHELL=zsh, and with COMP_CWORD=2 set)
# Control: command and option completion still work in the same directory
SHELL=fish COMP_LINE="pnpm " COMP_POINT=5 pnpm completion-server -- pnpm "" # access, add, ...
SHELL=fish COMP_LINE="pnpm run --" COMP_POINT=11 pnpm completion-server -- pnpm run -- # --if-present, ...Comparison with the Node CLI in the same directory (11.9.0 downloaded by pnpm 12 through packageManager):
SHELL=fish COMP_CWORD=2 COMP_LINE="pnpm run " COMP_POINT=9 <pnpm-11.9.0> completion-server -- pnpm run ""
# build
# helloThrough the shell itself (fish 4.9.3, completion file from pnpm completion fish of 12.4.2):
fish -c 'complete -C "pnpm run "' # empty
fish -c 'complete -C "pnpm "' # access, add, adduser, ...Expected behavior
pnpm run <TAB> (and pnpm run <prefix><TAB>) offers the script names from the nearest package.json, as the Node CLI does.
Actual behavior
completion-server returns nothing for the script position, so the shell offers no candidates. The generated completion scripts use complete -f / -o default off, so there is no fallback either.
Additional information
- Cause, as far as I can tell: in
pnpm/crates/cli/src/cli_args/completion.rs,complete_wordsderives candidates only from the clapCommandtree (visible_subcommands,visible_options,option_values,visible_possible_values). Nothing in the module reads a manifest or the current directory, so no dynamic completion (scripts) is possible. The file is identical in this respect onmainat the time of filing. - Pinning
packageManager: [email protected]in the project does not restore it:completion-serveris answered by the installed Rust binary before any delegation to the pinned version (consistent with #7959), so projects that are still on 11.x lose script completion as soon as the globally installed pnpm is 12. - Related: #14655 (asks for
pnpm execcompletion, which would need the same manifest/project awareness). - Environment: macOS 15 (Darwin 24.6.0), arm64, fish 4.9.3, pnpm 12.4.2 from Homebrew (
/opt/homebrew/Cellar/pnpm/12.4.2). - Workaround I am using: a fish completion that adds
jq -r '(.scripts // {}) | to_entries[] | "\(.key)\t\(.value)"'over the nearestpackage.jsonat the script position afterrun, on top ofpnpm completion-serverfor commands and flags.
Node.js version
22.23.1 (not involved: the Rust binary answers completion-server itself without spawning Node).
Operating System
macOS
Source: pnpm/pnpm