Skip to content

feat(cli): bash/zsh/fish shell completion via --completion - #2579

Merged
cliffhall merged 2 commits into
v2/mainfrom
v2/feat/2434-cli-shell-completion
Oct 5, 2026
Merged

cliffhall merged 2 commits into
v2/mainfrom
v2/feat/2434-cli-shell-completion

Conversation

@cliffhall

Copy link
Copy Markdown
Member

Closes #2434

What

mcp-inspector --cli --completion <bash|zsh|fish> prints a shell completion script on stdout and exits without connecting to anything.

source <(mcp-inspector --cli --completion bash)
source <(mcp-inspector --cli --completion zsh)      # or save as _mcp-inspector on $fpath
mcp-inspector --cli --completion fish > ~/.config/fish/completions/mcp-inspector.fish
  • The first word completes the launcher's mode flags (--cli, --web, --tui). Once that word is --cli, it completes every CLI flag (with descriptions in zsh and fish).
  • --method completes ONE_SHOT_METHODS (the same list parseArgs validates against), plus servers/list and servers/show.
  • --transport, --log-level, --format, --protocol-era and --completion complete their accepted values. Flags taking a <path> fall back to file completion, as does the stdio target command.
  • Only --cli mode is completed. Web and TUI flags are out of scope.

How: derived from the program definition

The flag list is read from the live commander program when the script is generated, so it can't drift from --help. The same goes for which flags take a value and which take a path, both read from each option's flags string. Flags that sibling PRs add to parseArgs, such as --quiet and --output, get picked up automatically with no edit to the completion module. The one hand-stated piece is VALUE_CHOICES, the finite value sets that the CLI validates in custom parsers rather than with commander choices. A test guards it by running every listed value through the real option parser.

Why a flag rather than a completion subcommand

The CLI treats leading bare words as the stdio target command (mcp-inspector --cli node server.js …). A completion bash subcommand would collide with a server command named completion. A flag also fits the other no-connect short-circuits (--list-stored-auth, --print-handoff) and is listed in --help.

Files

  • clients/cli/src/completion.ts: new module holding the whole feature (option registration, flag collection, the three renderers).
  • clients/cli/src/cli.ts: three lines around program.parse, kept minimal so sibling CLI branches merge cleanly.
  • clients/cli/__tests__/completion.test.ts: structural tests, plus tests that execute the generated scripts in real bash, zsh and fish when installed (each shell is skipped if absent). completion.ts coverage is 100% on all four dimensions.
  • clients/cli/README.md: new "Shell completion" section and an options-table row.

Gate

  • npm run format, then npm run local:gate, with the sandbox proxy env unset.
  • local:validate passed.
  • coverage:web had one failure, which is environmental and unrelated to this diff: secret-store-selection.test.ts > isOnMountPoint > is false when the path itself can't be resolved. It fails in this sandbox on any branch because the worktrees sit on a mounted volume, and it is web auth code this PR doesn't touch.
  • Because that failure aborted the chain, I ran the remaining stages individually:
    • coverage:cli, coverage:tui, coverage:launcher, verify:build-gate, verify:bundle-externals: all passed.
    • smoke, smoke:web:firefox, local:storybook: queued behind the machine-wide gate lease. I'll post the result as a comment.

🤖 Generated with Claude Code

…2434)

`mcp-inspector --cli --completion <bash|zsh|fish>` prints a completion
script and exits without connecting. The flag list, which flags take a
value, and which take a path are read from the CLI's own commander
program, so the scripts cannot drift from --help. --method completes the
same ONE_SHOT_METHODS list parseArgs validates, plus servers/list and
servers/show; --transport, --log-level, --format and --protocol-era
complete their accepted values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
@cliffhall cliffhall added the v2 Issues and PRs for v2 label Oct 5, 2026
@cliffhall cliffhall linked an issue Oct 5, 2026 that may be closed by this pull request
2 tasks done
@cliffhall
cliffhall requested a balanced review from Copilot October 5, 2026 06:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Bash and zsh completion do not handle accepted --option=value arguments correctly.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
What changed in this PR

Adds shell completion to the CLI without opening a server connection.

Changes:

  • Introduces --completion <bash|zsh|fish>.
  • Derives completion flags from Commander options.
  • Adds installation guidance and structural/shell tests.
File Description
clients/​cli/​src/​completion.ts Generates scripts for all three shells.
clients/​cli/​src/​cli.ts Registers completion and exits after generation.
clients/​cli/​README.md Documents completion setup and usage.
clients/​cli/​__tests__/​completion.test.ts Tests generation, metadata, and shell behavior.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread clients/cli/src/completion.ts
Comment thread clients/cli/src/completion.ts
Bash splits `--method=tools/` on '=' (COMP_WORDBREAKS), so the value
completes against the option two words back; zsh keeps it as one word,
so the option prefix moves into IPREFIX via compset. Fish already
handles the form natively; all three are covered by shell tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
@cliffhall

Copy link
Copy Markdown
Member Author

Copilot round 1 (2 findings), both fixed in 9a6edc3 and answered inline:

  • Bash completion of --opt=value (bash splits the word on =): the value now completes against the option.
  • Zsh completion of --opt=value: the word is split, and the option prefix moves into IPREFIX via compset.

Requesting round 2.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Cross-shell behavior warrants human verification because shell execution tests can be skipped when interpreters are unavailable.

Review effort: Balanced
Findings: None

Resolved since last review (2)

@cliffhall

Copy link
Copy Markdown
Member Author

Copilot review loop closed. Round 2 was clean: no findings, and both round-1 findings were resolved. Per the pr-flow skill, one clean round ends the loop.

On the round-2 note that the shell execution tests can skip when an interpreter is missing: this is by design, so the suite still passes on machines without zsh or fish. For this PR, all three suites ran rather than skipped. bash, zsh and fish were installed on the machine that ran the gate, and the bash, zsh and fish script suites all executed and passed (22/22 in completion.test.ts). The structural tests run everywhere regardless.

@cliffhall

Copy link
Copy Markdown
Member Author

Gate status (all runs with the sandbox proxy env unset):

  • local:validate: passed.
  • coverage:web: one failure, the known environmental one (secret-store-selection.test.ts > isOnMountPoint > is false when the path itself can't be resolved). It is caused by the worktree sitting on a mounted volume and is unrelated to this diff.
  • coverage:cli, coverage:tui, coverage:launcher, verify:build-gate, verify:bundle-externals: all passed. completion.ts is at 100% on all four dimensions.
  • smoke:launcher and smoke:cli: passed. These are the smokes that exercise the CLI path this PR touches. Neither binds the fixed web ports, so I ran them outside the lease.
  • Not run locally: the web smokes (smoke:web*, smoke:web:firefox) and local:storybook. Three attempts to take the machine-wide gate lease each hit its 45-minute wait cap behind 10–18 queued gates from parallel sessions. This diff touches no web code, so CI's run is the check for those.

@cliffhall
cliffhall merged commit 323798a into v2/main Oct 5, 2026
10 of 11 checks passed
@cliffhall
cliffhall deleted the v2/feat/2434-cli-shell-completion branch October 5, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI has no shell completion (bash/zsh/fish)

2 participants