Skip to content

Add self-maintaining shell completions for the cmux CLI (bash/zsh/fish) - #6814

Closed
austinywang wants to merge 14 commits into
mainfrom
issue-6616-self-maintaining-shell-completions-for-the
Closed

austinywang wants to merge 14 commits into
mainfrom
issue-6616-self-maintaining-shell-completions-for-the

Conversation

@austinywang

@austinywang austinywang commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #6616

What

The cmux CLI has ~150 top-level commands but no shell completions, which makes its large surface area hard to navigate. This adds bash/zsh/fish completions that are generated, never hand-maintained, so they can't rot.

How it stays in sync

  • Command names come from the authoritative topLevelCommandNames registry in CLI/cmux.swift.
  • Per-command flags, first-level subcommands (incl. a|b|c groups), enum flag values, and (alias: x) aliases are parsed best-effort from the usage() help heredoc in the same file. The generator reads straight from source, so no built binary is required — it runs in CI.
  • A contract test (tests/test_cli_completions_contract.py, sibling to tests/test_cli_contract_help.py) regenerates from source and fails on drift. Adding a command without regenerating turns CI red. It also runs a --check guard that fails if usage() documents a top-level command that isn't completable (absent from the registry or filtered as internal). That makes the "self-maintaining" promise cover the command registry itself.

What completes

Input Completes to
cmux <Tab> all 147 user-visible top-level commands
cmux send --<Tab> --surface --window --workspace
cmux auth <Tab> login logout status
cmux diff --source <Tab> unstaged staged branch last-turn (bash, zsh, fish)
cmux --socket /x send --<Tab> send's flags (global options are skipped)
cmux cloud <Tab> vm's subcommands (alias inherits the spec)

Files

  • scripts/generate-cli-completions.py — source-only generator (--write, --shell <bash\|zsh\|fish>, --list-commands, --check, --cmux-bin to probe a built binary instead).
  • completions/cmux.{bash,zsh,fish} + completions/README.md — generated scripts (marked auto-generated) and install/regenerate docs.
  • tests/test_cli_completions_contract.py — drift + coverage + registry-coverage + shell-syntax guard.
  • .github/workflows/ci.yml — runs the contract test in the always-on workflow-guard-tests job.
  • CLI/cmux.swift — adds remote, remotes, and simulate-sidebar-drag to topLevelCommandNames. These are dispatched (case \"remotes\", \"remote\", case \"simulate-sidebar-drag\") and documented in usage() but were missing from the registry, so completions (and shouldOpenAsPathArgument) did not know them. .github/swift-file-length-budget.tsv refreshed via the official script for the 3-line addition.

Review notes

Implements the reference design contributed by @bdmorin in #6616, regenerated against current CLI/cmux.swift and hardened through review: zsh enum parity with bash/fish, a|b|c subcommand groups, leading global-option handling in all three shells, fish command matched by position (not __fish_seen_subcommand_from anywhere), documented-alias spec inheritance, and the registry-coverage drift guard.

Built so the generator's input can later be swapped to ArgumentParser's --generate-completion-script once #3254 reaches the subcommand tree, after which the generator retires.

Localization: no app/web UI strings introduced — completion scripts contain literal CLI command tokens, the README is contributor docs, and the generator/test/CI are tooling; none are subject to the Localizable.xcstrings / web/messages requirement. The cmux.swift change adds command-name identifiers, not UI strings.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added shell tab-completion support for the CLI in Bash, Zsh, and Fish, with context-aware option/value suggestions.
    • Introduced an automated completion generator to keep completions aligned with the CLI’s documented commands.
  • Bug Fixes
    • Added a CI contract test to ensure committed completion scripts match regenerated output and pass shell syntax checks.
    • Updated command suggestions by adding/removing specific command names to improve matching.
  • Documentation
    • Added instructions for installing, verifying, and regenerating CLI completions.

The cmux CLI has ~150 top-level commands but no shell completions, making
its large surface area hard to navigate. Add bash/zsh/fish completions that
are *generated, never hand-maintained*, so they can't rot:

- Command names come from the authoritative `topLevelCommandNames` registry
  in `CLI/cmux.swift`.
- Per-command flags, first-level subcommands, and enum flag values are parsed
  best-effort from the `usage()` help heredoc in the same file (no built
  binary required, so it works in CI).
- `tests/test_cli_completions_contract.py` regenerates from source and fails
  on drift, so adding a command without regenerating turns CI red. This is
  what keeps the scripts in sync without anyone having to remember.

What completes: `cmux <Tab>` (all commands), `cmux send --<Tab>` (flags),
`cmux auth <Tab>` -> `login logout status`,
`cmux diff --source <Tab>` -> `unstaged staged branch last-turn`.

Touches no Swift. The generator's input can later be swapped to
ArgumentParser's `--generate-completion-script` once #3254 reaches the
subcommand tree, after which the generator retires.

Implements the reference design contributed in #6616.

Fixes #6616

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 26, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jul 5, 2026 6:42am
cmux-staging Building Building Preview, Comment Jul 5, 2026 6:42am

@coderabbitai

coderabbitai Bot commented Jun 26, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@austinywang, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d30422e4-ceaa-4c47-b648-a3ba2d7ad81c

📥 Commits

Reviewing files that changed from the base of the PR and between 6d7f7b6 and bad94a8.

📒 Files selected for processing (5)
  • completions/cmux.bash
  • completions/cmux.fish
  • completions/cmux.zsh
  • scripts/generate-cli-completions.py
  • tests/test_cli_completions_contract.py
📝 Walkthrough

Walkthrough

Adds generated bash, zsh, and fish completion scripts for cmux, a Python generator that derives them from CLI/cmux.swift, a contract test that compares regenerated output to committed scripts, a CI guard step, and documentation for installation and regeneration.

Changes

cmux shell completions

Layer / File(s) Summary
Source discovery
scripts/generate-cli-completions.py, CLI/CMUXCLI+CommandSuggestions.swift
Adds registry/help source lookup helpers, command filtering, help-region extraction, and command-name registry updates used by the generator.
Help parsing
scripts/generate-cli-completions.py
Builds per-command completion specs from the help text, including subcommands, flags, and enum-valued arguments.
Emitter wiring
scripts/generate-cli-completions.py
Renders bash, zsh, and fish outputs and handles shell selection, command listing, and file writing.
Bash and zsh outputs
completions/cmux.bash, completions/cmux.zsh
Updates the checked-in bash and zsh completion scripts with command and option completion cases.
Fish output
completions/cmux.fish
Updates the checked-in fish completion script with top-level command gating and per-subcommand completions.
Docs, validation, and CI
completions/README.md, tests/test_cli_completions_contract.py, .github/workflows/ci.yml
Adds regeneration instructions, a drift contract test, and a workflow step that runs the test.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Workflow as workflow-guard-tests job
  participant ContractTest as tests/test_cli_completions_contract.py
  participant Generator as scripts/generate-cli-completions.py
  participant SwiftSource as CLI/cmux.swift
  participant BashOut as completions/cmux.bash
  participant ZshOut as completions/cmux.zsh
  participant FishOut as completions/cmux.fish
  Workflow->>ContractTest: run contract test
  ContractTest->>Generator: regenerate bash, zsh, fish
  Generator->>SwiftSource: read topLevelCommandNames and usage()
  ContractTest->>BashOut: compare regenerated output
  ContractTest->>ZshOut: compare regenerated output
  ContractTest->>FishOut: compare regenerated output
Loading

Possibly related PRs

  • manaflow-ai/cmux#7329: Changes the same command-name registry that the completion generator and contract test read from, so it can affect generated coverage.
🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: self-maintaining shell completions for cmux across bash, zsh, and fish.
Description check ✅ Passed The description is detailed and covers the implementation, sync strategy, touched files, and review context.
Linked Issues check ✅ Passed The PR matches #6616 by adding generated bash/zsh/fish completions, a drift test, registry-based command sourcing, and a future ArgumentParser path.
Out of Scope Changes check ✅ Passed The changes stay within the completion feature scope, including generator code, checked-in scripts, docs, tests, CI, and registry updates.
Cmux Swift Actor Isolation ✅ Passed The only Swift change adds command strings to a static Set in CMUXCLI; it introduces no actor annotations, shared mutable state, or UI/background access patterns.
Cmux Swift Blocking Runtime ✅ Passed HEAD changes only completions/scripts/tests; no production Swift diff exists, so no blocking sync primitive was introduced.
Cmux Browser Automation Off-Main ✅ Passed PR only adds completion scripts, generator, docs, and a contract test; it doesn’t touch browser automation paths or routing policy files.
Cmux Expensive Synchronous Load ✅ Passed PASS: The only Swift diff is adding command-name strings in the suggestion registry; no expensive agent-history loads or main-actor interactive paths were added.
Cmux Cache Substitution Correctness ✅ Passed The only production Swift change extends topLevelCommandNames; no cache, persistence, history, undo, or snapshot substitution appears.
Cmux No Hacky Sleeps ✅ Passed PASS: The new shell/Python runtime files contain no sleeps, timers, polling, or retry backoff; the rule file also excludes workflow YAML sleeps from scope.
Cmux Algorithmic Complexity ✅ Passed PASS: Changes are static completion code and a Swift command-name registry; loops only scan fixed-size command lists/word arrays, with no scalable rescans or hot-path filtering.
Cmux Swift Concurrency ✅ Passed HEAD^..HEAD changes are only completions, generator, and tests; no Swift files changed, so no new legacy async pattern in cmux-owned Swift code.
Cmux Swift @Concurrent ✅ Passed No Swift files are changed in this diff, so the @concurrent/nonisolated async rule has nothing to flag.
Cmux Swift File And Package Boundaries ✅ Passed Only Swift change is a 3-line registry update in a 213-line CLI helper; no oversized file growth or mixed responsibilities.
Cmux Swiftpm Lockfiles ✅ Passed No SwiftPM/Xcode/.gitignore/workflow/package-resolved files changed in the PR diff, so the lockfile policy is not implicated.
Cmux Swift Logging ✅ Passed No production Swift logging was added: this commit has no Swift source changes, and the inspected Swift file only updates command names with no print/debugPrint/dump/NSLog/Logger calls.
Cmux User-Facing Error Privacy ✅ Passed Only completion scripts, a generator, and contract tests changed; no user-facing errors or sensitive payloads were added.
Cmux Full Internationalization ✅ Passed Diff only adds generated shell completions, generator/test tooling, and developer docs; no localized Swift/UI strings, xcstrings, or web message files were changed.
Cmux Swiftui State Layout ✅ Passed No SwiftUI state/layout changes in the diff; touched files are completions/tests/CLI registry only, with no @Observable/@Published/GeometryReader/lazy-row patterns.
Cmux Architecture Rethink ✅ Passed No Swift files changed in this commit; git diff HEAD^..HEAD for '*.swift' is empty, so the Swift architectural rethink rules don’t apply.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS: The Swift edit only changes top-level command names; no NSWindow/NSPanel/WindowGroup code or cmuxAuxiliaryWindowIdentifiers changes, so the aux-window rule doesn’t apply.
Cmux Source Artifacts ✅ Passed Changed files are intentional source/docs/test artifacts; the generated completions are documented, auto-generated, and enforced by CI, with no stray temp/build/cache paths.
Cmux No Test Or Debug Seam In Production Source ✅ Passed No production Sources/** Swift files changed in the PR diff, so no test/debug seam was introduced there.
Cmux No Ambient Global State ✅ Passed No production Swift changes are present in the checked diff; only completions/tooling files changed, so no new ambient Swift global state was added.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-6616-self-maintaining-shell-completions-for-the

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds self-maintaining bash/zsh/fish tab-completions for the cmux CLI by introducing a Python generator that reads the authoritative topLevelCommandNames registry and the usage() heredoc from source — no built binary required. A contract test regenerates all three scripts and fails CI on any drift, registry gap, or shell-syntax error.

  • Generator (scripts/generate-cli-completions.py): parses the Swift registry and help heredoc to emit per-command flags, first-level subcommands (including a|b|c groups), enum flag values, and (alias: x) inheritance; handles value-bearing global options in all three shells so cmux --socket /path cmd --<Tab> works correctly.
  • Contract test (tests/test_cli_completions_contract.py): byte-exact drift check, registry-coverage guard (--check), top-level command coverage assertion, subcommand regression fixtures, and shell-syntax validation — though syntax checks for zsh and fish silently skip when those binaries are absent.
  • Swift registry (CLI/CMUXCLI+CommandSuggestions.swift): adds remote, remotes, and simulate-sidebar-drag, which were dispatched and documented but missing from topLevelCommandNames.

Confidence Score: 4/5

Safe to merge with a straightforward follow-up to install zsh and fish in the CI step so syntax validation actually runs for those shells.

The generator logic, all three emitters, the drift check, the registry-coverage guard, and the Swift registry additions are all correct. The gap is that the CI contract step does not install zsh or fish, so shell-syntax checks for those two completion scripts silently no-op on ubuntu-latest. A bug introduced into the zsh or fish emitter after a --write regeneration would pass CI undetected.

tests/test_cli_completions_contract.py and .github/workflows/ci.yml — the CI step needs to install zsh and fish so syntax checks run rather than silently skip.

Important Files Changed

Filename Overview
scripts/generate-cli-completions.py New source-only generator; parser logic, alias propagation, enum-value extraction, and global-option skipping in all three emitters are correct.
tests/test_cli_completions_contract.py Drift guard, registry-coverage check, and subcommand regression fixtures are well-structured, but shell-syntax checks for zsh and fish silently no-op in CI because neither shell is pre-installed on ubuntu-latest.
.github/workflows/ci.yml Adds the contract test step without installing zsh or fish, so syntax checks for those shells are silently skipped on the ubuntu-latest runner.
CLI/CMUXCLI+CommandSuggestions.swift Adds remote, remotes, and simulate-sidebar-drag to topLevelCommandNames; straightforward and correct.
completions/cmux.bash Generated bash completion: global-option skipping, file-fallback, and per-command flag/enum-value completion are structurally correct.
completions/cmux.zsh Generated zsh completion: global-option skipping, CURRENT-1 prev-word enum branches, and _files fallback are correct; previous-thread issues resolved.
completions/cmux.fish Generated fish completion: position-based __cmux_command skips value-bearing global options; top-level completions lack -f so file completion is preserved.
.github/swift-file-length-budget.tsv Budget refreshed for the 3-line Swift addition.
completions/README.md Clear install and regeneration instructions; correctly marks scripts as auto-generated.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["CLI/CMUXCLI+CommandSuggestions.swift\ntopLevelCommandNames registry"] -->|parse_registry| G
    B["CLI/cmux.swift\nusage() heredoc"] -->|extract_usage_heredoc| G
    G["generate-cli-completions.py\nbuild()"]
    G -->|emit_bash| BA["completions/cmux.bash"]
    G -->|emit_zsh| ZS["completions/cmux.zsh"]
    G -->|emit_fish| FI["completions/cmux.fish"]
    CI["CI: workflow-guard-tests"] -->|python3| CT
    CT["test_cli_completions_contract.py"]
    CT -->|regenerate + byte-diff| BA
    CT -->|regenerate + byte-diff| ZS
    CT -->|regenerate + byte-diff| FI
    CT -->|"--check: registry coverage"| B
    CT -->|"bash -n always runs"| BA
    CT -->|"zsh -n skipped if absent"| ZS
    CT -->|"fish -n skipped if absent"| FI
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["CLI/CMUXCLI+CommandSuggestions.swift\ntopLevelCommandNames registry"] -->|parse_registry| G
    B["CLI/cmux.swift\nusage() heredoc"] -->|extract_usage_heredoc| G
    G["generate-cli-completions.py\nbuild()"]
    G -->|emit_bash| BA["completions/cmux.bash"]
    G -->|emit_zsh| ZS["completions/cmux.zsh"]
    G -->|emit_fish| FI["completions/cmux.fish"]
    CI["CI: workflow-guard-tests"] -->|python3| CT
    CT["test_cli_completions_contract.py"]
    CT -->|regenerate + byte-diff| BA
    CT -->|regenerate + byte-diff| ZS
    CT -->|regenerate + byte-diff| FI
    CT -->|"--check: registry coverage"| B
    CT -->|"bash -n always runs"| BA
    CT -->|"zsh -n skipped if absent"| ZS
    CT -->|"fish -n skipped if absent"| FI
Loading

Reviews (14): Last reviewed commit: "Preserve top-level path completion" | Re-trigger Greptile

Comment thread scripts/generate-cli-completions.py
Comment thread scripts/generate-cli-completions.py Outdated
Comment on lines +312 to +313
lines.append(" local context state line")
lines.append(" local -a commands")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 The local context state line declaration is left over from _arguments-style zsh completion that was never wired up. These three variables are never read or assigned after declaration, producing dead code in every generated cmux.zsh.

Suggested change
lines.append(" local context state line")
lines.append(" local -a commands")
lines.append(" local -a commands")

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 3ecdc40 — removed the dead local context state line declaration from the zsh emitter.

— Claude Code

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@completions/cmux.bash`:
- Around line 7-12: Remove the unused shell variables from the cmux.bash
completion generator: in the logic around _init_completion and the fallback
assignment, drop words and cword from the local declaration unless they are
actually referenced later. Keep the generator output consistent with the
variables it uses so the generated completion script only declares cur and prev,
avoiding shellcheck SC2034.
- Line 23: The completion generator in cmux.bash is emitting an unsafe unquoted
array assignment for COMPREPLY, which triggers shellcheck SC2207 and can break
with future completions containing spaces. Update the generator logic around the
compgen/COMPREPLY emission to use the safer mapfile -t pattern with process
substitution instead of COMPREPLY=( $(...) ), preserving the existing behavior
while avoiding word-splitting.

In `@scripts/generate-cli-completions.py`:
- Around line 310-336: The zsh completion generator in emit_zsh is missing the
flag-value enum completions that emit_bash and emit_fish already provide. Update
the _cmux case handling to also consult spec.flag_values for each command and,
when the user is completing a value for a value-bearing flag, offer those enum
values instead of only subcommands and flag names. Use the existing emit_zsh,
CommandSpec, and specs structures to keep behavior aligned with the other shell
emitters.
- Around line 230-235: The subcommand detection in generate-cli-completions.py
is scanning the full help line and can mistake the first word of a description
for a real subcommand. Update the subcommand logic in the same parsing flow that
handles the command portion, and reuse the double-space boundary used by the
alias parsing branch so only the actual command text is tokenized. Make this
change in the subcommand detection path near the tokens/sub branch, keeping the
existing METAVARS and regex checks but applying them only to the trimmed command
segment.
- Around line 191-202: The `help_commands_region` helper uses an ambiguous loop
variable name (`l`) in the `next(...)` lookup, which triggers Ruff E741. Rename
that variable to something clear like `line` so the `help_commands_region` logic
remains unchanged while satisfying linting in CI.
- Around line 164-179: Make the registry parsing in parse_registry more robust
by updating REGISTRY_RE to accept an optional trailing comma so the final
command name is still captured when the Swift array literal omits it. Also
rename the ambiguous loop variable in parse_registry from l to line for
readability and to avoid E741. If you touch the completion generators, keep
emit_zsh consistent with the Bash/Fish behavior by adding flag_values support
when the help output includes --flag <value>.

In `@tests/test_cli_completions_contract.py`:
- Around line 86-95: The completion contract check currently only scans the
regenerated bash script for token matches, so it can miss commands that are
absent from the actual top-level completion table and it ignores zsh/fish
entirely. Update the test logic around the regenerated shell outputs to validate
each shipped shell’s top-level command list directly, using the existing
regeneration structure in test_cli_completions_contract.py instead of a
full-script substring search, and make sure the visible command coverage
assertion runs against bash, zsh, and fish.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: fcb2624e-fdac-4dcf-a53f-846122210716

📥 Commits

Reviewing files that changed from the base of the PR and between a4fb35c and 053c59b.

📒 Files selected for processing (7)
  • .github/workflows/ci.yml
  • completions/README.md
  • completions/cmux.bash
  • completions/cmux.fish
  • completions/cmux.zsh
  • scripts/generate-cli-completions.py
  • tests/test_cli_completions_contract.py

Comment thread completions/cmux.bash Outdated
Comment thread completions/cmux.bash Outdated
Comment thread scripts/generate-cli-completions.py
Comment thread scripts/generate-cli-completions.py
Comment thread scripts/generate-cli-completions.py Outdated
Comment thread scripts/generate-cli-completions.py
Comment thread tests/test_cli_completions_contract.py Outdated
cmux and others added 5 commits June 26, 2026 02:08
Fixes raised by Codex/Greptile on the completions PR:

- zsh emitter now wires up flag-value enum completions (e.g. `diff --source
  <Tab>` -> unstaged/staged/branch/last-turn) to match bash/fish, and drops the
  dead `local context state line` left over from `_arguments`-style completion.
- parse_help now captures unbracketed `a|b|c` subcommand groups, so first-level
  subcommands like `feed tui|clear`, `browser goto|navigate`, and
  `browser url|get-url` are completed.
- help_commands_region now stops at the next section header regardless of
  indentation, so the source-heredoc and `cmux help` (binary) input modes agree
  on the Commands region (previously the heredoc path ran into Environment:).
- Added `remote`, `remotes`, and `simulate-sidebar-drag` to topLevelCommandNames
  — they are dispatched (`case "remotes", "remote"`, `case
  "simulate-sidebar-drag"`) and documented in usage() but were missing from the
  registry, so completions (and shouldOpenAsPathArgument) did not know them.
- Added a registry-coverage drift guard: `generate-cli-completions.py --check`
  fails if usage() documents a top-level command absent from
  topLevelCommandNames, and the contract test runs it. This makes the
  "self-maintaining" promise cover the command registry itself.

Budget refreshed via scripts/swift_file_length_budget.py --write-budget for the
3-line registry addition.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address two edge-case defects raised in review:

- All three emitters now locate the command word by scanning past cmux's
  value-bearing global options (`--socket`, `--id-format`, `--window`,
  `--password`) and their values, instead of taking the first non-option word
  (bash/fish) or a fixed `words[2]` position (zsh). So `cmux --socket <path>
  send --<Tab>` now completes `send`'s flags rather than treating the socket
  path as the command. Verified at runtime for bash.
- The fish emitter now resolves the active top-level command by position via a
  `__cmux_command` helper and matches it with `__cmux_command_is`, replacing
  `__fish_seen_subcommand_from` which matched a word anywhere on the line. So
  `cmux docs browser <Tab>` no longer also fires the top-level `browser`
  automation completions. The helpers use a quoted local var so an empty
  command substitution can't malform `test`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`set-hook` is a documented, dispatched tmux-compat command, but it was listed
in INTERNAL_COMMANDS and therefore filtered out of every generated completion
script. Remove it so `cmux set-hook <Tab>` works.

This also exposed that the registry-coverage guard only checked the raw
registry, so it could not catch a documented command that was filtered as
internal. Tighten `registry_coverage_gaps` to require every documented
top-level command to be in `visible_commands()` (i.e. actually completable),
catching both "absent from topLevelCommandNames" and "wrongly filtered as
internal". Verified the guard flags set-hook if it is re-filtered.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`vm ... (alias: cloud)` and `remotes ... (alias: remote)` listed the alias at
`cmux <Tab>` (it is in the registry) but `cmux cloud <Tab>` / `cmux remote
<Tab>` completed nothing, because parse_help only attached the parsed spec to
the line's leading command. Parse the `(alias: name)` form and copy the
canonical command's flags/subcommands/enum values to the alias, so the alias
completes identically. Verified at runtime: `cmux cloud <Tab>` now offers
vm's subcommands and `cmux remote <Tab>` offers remotes' subcommands + flags.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…aining-shell-completions-for-the

# Conflicts:
#	.github/swift-file-length-budget.tsv
`is_real_enum` rejected a whole `<a|b|c>` group if any token matched a metavar
name, so `config <doctor|check|validate|path|paths|docs|documentation|reload>`
produced no completions at all because `path` is a metavar name -- even though
`path` is a real `config` subcommand here. Same for `hooks <agent>
<install|uninstall|event>` and `browser find|get|frame`.

A token is only a placeholder when the *entire* group is type metavariables
(`<id|ref|index>`); a group with at least one literal is a real choice list and
is kept whole (`path`/`docs`/`text`/`title` are real subcommands in their
context). Pure-placeholder groups like `<id|ref|index>` are still dropped, so
`cmux send --workspace <Tab>` does not offer `id ref index`. Verified at
runtime: `cmux config <Tab>` now offers all eight subcommands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@blacksmith-sh

This comment has been minimized.

…aining-shell-completions-for-the

# Conflicts:
#	.github/swift-file-length-budget.tsv
#	CLI/cmux.swift

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_cli_completions_contract.py`:
- Around line 179-194: The first-level subcommand regression guard in
test_cli_completions_contract is hardcoded and can drift from the CLI spec.
Replace the literal expected_subcommands mapping with values derived from the
generator’s parsed command specs, using the same source of truth as the
top-level command check (for example via parse_help/build from
generate-cli-completions.py and the resulting spec subcommands). Keep the
existing command_completion_words loop, but compute each command’s expected
first-level subcommands dynamically so new subcommands are picked up
automatically.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 943fd3f8-21f0-48ed-908c-a066187ad550

📥 Commits

Reviewing files that changed from the base of the PR and between c4b34ca and 6d7f7b6.

📒 Files selected for processing (5)
  • completions/cmux.bash
  • completions/cmux.fish
  • completions/cmux.zsh
  • scripts/generate-cli-completions.py
  • tests/test_cli_completions_contract.py

Comment on lines +179 to +194
# Regression guard: first-level subcommands can be written as spaced pipe
# alternatives, optional single values, or nested optional choice groups.
expected_subcommands = {
"browser": {"disable", "enable", "status"},
"markdown": {"open"},
"settings": {"docs", "open", "path"},
}
for shell, text in regenerated.items():
for command, expected_words in expected_subcommands.items():
actual = command_completion_words(shell, text, command)
missing = sorted(expected_words - actual)
if missing:
failures.append(
f"{shell}: {command} completions missing first-level "
f"subcommand(s): {', '.join(missing)}"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded expected_subcommands can silently go stale.

This regression guard nicely fixes the earlier per-shell coverage gap, but the subcommand list itself is hand-maintained — the opposite of the "self-maintaining" goal for these completions. If a new subcommand is added to browser, markdown, settings, or a new multi-subcommand command is introduced, this dict won't be updated automatically and the guard silently stops covering it, unlike the top-level command check above which dynamically derives expected from --list-commands.

Consider deriving expected first-level subcommands from the generator's own parsed specs (e.g. importing parse_help/build from generate-cli-completions.py and inspecting the resulting spec's subcommands) instead of a hardcoded literal, so this guard stays in sync the same way the rest of the contract test does.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_cli_completions_contract.py` around lines 179 - 194, The
first-level subcommand regression guard in test_cli_completions_contract is
hardcoded and can drift from the CLI spec. Replace the literal
expected_subcommands mapping with values derived from the generator’s parsed
command specs, using the same source of truth as the top-level command check
(for example via parse_help/build from generate-cli-completions.py and the
resulting spec subcommands). Keep the existing command_completion_words loop,
but compute each command’s expected first-level subcommands dynamically so new
subcommands are picked up automatically.

@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in cmux backlog Sep 23, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — bad94a83 Deployed Jul 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Self-maintaining shell completions for the cmux CLI (bash/zsh/fish)

3 participants