feat(cli): group the top-level help and lead with gateway/service/doctor - #5159
Conversation
`kirocrew --help` listed ~40 subcommands as one flat argparse block in
registration order, headed by a `{chat,doctor,gateway,...}` choice blob
that filled the usage line, with 17 `mcp-*` internals rendered as
literal `==SUPPRESS==` rows. The three commands a new install actually
needs sat in the middle of it, and nothing said how `gateway` differs
from `service install` or what port either one opens.
The taxonomy now lives in `cli_help.py`: ordered sections, `Start here`
first with exactly gateway, service and doctor, followed by notes on the
two lifetimes (foreground vs. systemd/launchd, one at a time) and on the
single loopback dashboard port. argparse's own listing is suppressed and
the grouped listing is rendered into the epilog.
Every user-facing command registers through `cli_help.add_command`,
which refuses a name that is in no section, so a new command cannot be
added without appearing in the help; the section summary becomes the
subparser `description`, which is what `kirocrew <cmd> --help` prints.
The `mcp-*` MCP servers the agent backend spawns are dropped from the
listing and from the `invalid choice: 'x' (choose from ...)` message,
which otherwise answered a typo with all 17 of them. Their `choices`
view filters iteration only: membership and `_name_parser_map` are
untouched, so `kirocrew mcp-core` still dispatches.
GPT 5.6 Review — ✅ no blocking findingsGPT 5.6 completed its review of This comment is updated in place on each push. Review detailsNo findings. False positive or not applicable? A repository writer can comment: |
Design Review (Fable 5) — ✅ PASSDesign-level review of Design-Verdict: PASS Real usability harm, solved at the right layer with a fail-loud guard ( The one genuine coupling — [DESIGN-REVIEWED] 1079b2d |
First Principles Review (Fable 5) — 🟡 CONCERNSPremise-level review of Both data files and the surrounding code are read; the review follows. First-Principles-Verdict: CONCERNS The grouped help earns its place; two small riders don't: a hand-duplicated port constant policed by a test, and a What this change shipsIntent: make
Watch
Subtractions
[FIRST-PRINCIPLES-REVIEWED] 1079b2d |
Opus 4.8 Review — ✅ no blocking findingsReviewed Review detailsNo candidates were supplied, and I independently verified the load-bearing mechanisms: No findings. [OPUS-REVIEWED] 1079b2d Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
…tor (#5159) (#5353) `kirocrew --help` listed ~40 subcommands as one flat argparse block in registration order, headed by a `{chat,doctor,gateway,...}` choice blob that filled the usage line, with 17 `mcp-*` internals rendered as literal `==SUPPRESS==` rows. The three commands a new install actually needs sat in the middle of it, and nothing said how `gateway` differs from `service install` or what port either one opens. The taxonomy now lives in `cli_help.py`: ordered sections, `Start here` first with exactly gateway, service and doctor, followed by notes on the two lifetimes (foreground vs. systemd/launchd, one at a time) and on the single loopback dashboard port. argparse's own listing is suppressed and the grouped listing is rendered into the epilog. Every user-facing command registers through `cli_help.add_command`, which refuses a name that is in no section, so a new command cannot be added without appearing in the help; the section summary becomes the subparser `description`, which is what `kirocrew <cmd> --help` prints. The `mcp-*` MCP servers the agent backend spawns are dropped from the listing and from the `invalid choice: 'x' (choose from ...)` message, which otherwise answered a typo with all 17 of them. Their `choices` view filters iteration only: membership and `_name_parser_map` are untouched, so `kirocrew mcp-core` still dispatches. (cherry picked from commit 55814a8)
What
kirocrew --helpwas a wall. It listed ~40 subcommands as one flat argparseblock in registration order, so the three commands a new install actually
needs —
gateway,service,doctor— sat in the middle of it. The usage linewas a ~400-character
{chat,doctor,gateway,…}choice blob, 17 internalmcp-*servers rendered as literal
==SUPPRESS==rows (passinghelp=argparse.SUPPRESSto
add_parserprints the sentinel — argparse only honours it on the parent'sown actions), and nothing anywhere said how
gatewaydiffers fromservice install, or what port either one opens.After
Nine sections follow:
Run the gateway,Set it up,Work with the agent,Memory and knowledge,Extend it,Security and privacy,Move it and back it up,Develop Kiro Crew itself.How
cli_help.pyowns the taxonomy.COMMAND_GROUPS— ordered sections of ordered(command, summary)pairs — is the single source of truth for the listing, soregistration order in
cli.pyno longer matters and no command block wasmoved (deliberately:
cli.pyis a hot file).cli.pysetshelp=argparse.SUPPRESSon the subparsers action to hideargparse's flat block, passes
cli_help.TOP_USAGEasusage=(the suppressedaction would otherwise drop the placeholder from the usage line), and pins
prog="kirocrew"on the action — without it argparse derives eachsubcommand's prog from the parent's
usage=, prefixing everykirocrew <cmd> --helpwith the whole top-level usage string.cli_help.add_command, whichraises
KeyErrorfor a name that is in no section: a new command cannot beadded without appearing in the help. The section summary becomes the
subparser's
description(whatkirocrew <cmd> --helpprints), so thesentence exists once. A caller may still pass a longer
description—benchdoes.
mcp-*register with nohelpat all, andhide_internal_commandsswaps theaction's
choicesfor a live Mapping view over the same parser map thatiterates only user-facing commands, in section order. So a typo now gets
choose from gateway, service, doctor, …instead of a list including 17 MCPservers. Membership is unfiltered and
_name_parser_mapis untouched, sokirocrew mcp-corestill dispatches — the filter changes what argparse prints,never what it accepts.
Behaviour change worth calling out
Each command's one-line summary moved from
help=todescription=, sokirocrew <cmd> --helpnow prints that sentence at the top. Previously itappeared only in the parent listing.
Tests
test/test_cli_help.py(11 tests): offered-vs-grouped parity read off argparse'sown invalid-choice message; no command in two sections;
add_commandrefuses anungrouped name;
mcp-*absent from both the help and the error but stilldispatchable;
Start hereleads with the three; no==SUPPRESS==/ choice blob;subcommand usage not prefixed with the top-level usage; and the help's spelled-out
port stays equal to
config.loader._DEFAULT_PORT.Local gates:
check_black_formatting.py,isort,flake8,mypy(1031 files),docs-lint.sh, brand and harness-parity gates, and 1140 existing CLI-adjacenttests.
docs/system-specs/modules/cli.mddocuments the contract under a new### Top-level help.