feat: add peer completion for bash, zsh, and fish - #16
Conversation
Adds `peer completion <bash|zsh|fish>`, a read-only generator that prints a shell completion script built from the command registry, so it tracks the live command tree without a hand-maintained second list. - src/completion/index.ts folds commandDefinitions into a completion tree and renders a per-shell script (bash case lookup, zsh #compdef + _describe, fish declarative completes behind a path-precise guard) - src/commands/global-options.ts extracts the program-level option list as data; src/cli.ts consumes it so the generator and the CLI describe one set - the command is passthrough + exposeInMcp:false, keeping the script emitter out of the MCP tool surface, matching `peer mcp` - regenerated agents/ catalogs; README, CHANGELOG, llms.txt, AGENTS.md updated - tests/completion.test.ts covers the model, all three renderers, and the command; npm run check and npm run test:e2e pass
|
Hey @ADWilkinson — heads up that I put this together on my own, it wasn't asked for, so genuinely no hard feelings if it's not something you want in the CLI. The reason I did it: I kept reaching for tab completion while poking around with If the approach isn't right, or you'd just rather not own this surface, tell me and I'll close it — no problem either way. |
Running
peerat a terminal today gives you nothing on tab — no command names, no flags. This addspeer completion <bash|zsh|fish>so you can wire up real completion:The script isn't hand-written. It's generated from
commandDefinitionsand the program-level option list, so it can't drift from the actual command tree — add a command, rebuild, the completion follows.How it's put together:
src/completion/index.tswalks the registry into a small tree (each node = its sub-commands + its long flags, with parent groups filled in from child paths), then renders per shell: acase "$path"lookup for bash,#compdef+_describefor zsh (keeps the command descriptions), and declarativecomplete -c peerlines behind a path-precise guard for fish.src/commands/global-options.tspulls the 15 global options out into a list.src/cli.tsnow loops over that list instead of 15 literalprogram.option(...)calls, so the CLI and the completion generator are reading the same source.It's a read-only command —
passthrough: trueso the raw script lands on stdout and stays source-able, errors still go out as the usual JSON envelope, and an unknown shell gets aVALIDATION_ERRORwith exit 1. It'sexposeInMcp: falsefor the same reasonpeer mcpis: a shell-script emitter doesn't belong in the MCP tool surface. MCP profile counts don't change.Regenerated
agents/tool-catalog.jsonandagents/runtime-manifest.json(CLI count 147 → 148). README gets a "Shell completion" section, plus updates toCHANGELOG.md,llms.txt, andAGENTS.md.npm run check(247 tests, lint, typecheck, build) andnpm run test:e2e(4/4) both pass;npm run auditis clean.tests/completion.test.tscovers the model builder, all three renderers, and the command including the error paths — the new files land at 100% coverage.