Skip to content

fix(cli): list the flags each command registers in --usage - #122

Merged
2ynn merged 3 commits into
mainfrom
fix/cli-usage-flags-match-registered-flags
Oct 20, 2026
Merged

2ynn merged 3 commits into
mainfrom
fix/cli-usage-flags-match-registered-flags

Conversation

@2ynn

@2ynn 2ynn commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Why

--usage should list exactly the flags each command accepts. Three gaps remained:

  • Whole-body flag name. A body-only operation whose JSON/form body is not expanded into field flags (a union, map, array or scalar body) registers one flag named after the body (--request, --vehicle, …). --usage listed --body instead, which the command rejects with unknown flag: --body, and never listed the real, often required, flag. A multipart body-only operation without flag metadata had the same missing flag and no replacement. --usage used templateHasBodyFlag, while opcmd.go.stmpl decided the registered flag with separate inline logic. In the primary test CLI, 113 commands advertised a --body they reject.
  • completion <shell> --no-descriptions. Cobra registers it on bash/zsh/fish/powershell; the hand-written completion nodes in includes/usage.ts did not list it.
  • Flags added at runtime to a generated command (for example by custom.Register) appeared in --usage only when the command was also marked with usage.MarkDynamic, including on the root.

What changed

  • includes/metadata.ts: new side-effect-free operationUsesMetadataFlags, the request-strategy decision (flag metadata plus optional --body, or one whole-body flag). It replaces the inline logic in opcmd.go.stmpl and intentOperationHasMeta in includes/intents.ts; the now unused operationHasFlagMetadata is removed. Generated command files are byte-identical apart from the [required] change below.
  • includes/usage.ts: getOperationWholeBodyUsageFlag mirrors the flag opcmd.go.stmpl registers: --body with flag metadata; otherwise --<request body name> for body-only operations, with the same help text; otherwise --body. The four completion shell nodes list --no-descriptions.
  • includes/templating.ts, includes/metadata.ts: requestBodyDescription and bodyFlagDescription return unescaped help text for --usage; the template* wrappers escape it for Go source.
  • includes/templating.ts: the whole-body flag help says [required] only when the body is neither optional nor nullable, matching the requiredness the command enforces (templateRequestBodyRequired). This also corrects --help for nullable body-only operations.
  • usage.go.stmpl: every command rendered from its usageNodes entry, marked dynamic or not, takes its flags from cobra (usageFlagLines): generated flag lines for the flags it still shows (a flag hidden at runtime is dropped), then visible local flags added at runtime. MarkDynamic is now only needed when help, aliases or args change at runtime. usageFlagLines reads LocalFlags() first, which merges persistent flags into Flags() before the lookups, so a root marked dynamic before its first render keeps its generated flags.
  • usage_test.go.stmpl:
    • TestUsageSchema_FlagsMatchRegisteredFlags walks every command, root included, and asserts that each flag in its own --usage is registered and each visible registered flag is listed.
    • TestUsageSchema_RuntimeFlagsKeepGeneratedLines replaces TestUsageSchema_DynamicCommandKeepsGeneratedLines and runs with and without MarkDynamic, adding a flag on a generated command and a persistent flag on the root.
    • TestUsageSchema_RuntimeHiddenFlagDropped: a generated flag hidden at runtime leaves the command's --usage.
    • TestUsageSchema_DynamicRoot marks a fresh root dynamic before its first render.
  • pkg/generate/snapshots/cli_empty_body_go_test.go: the generated usageNodes entries of body-only operations list the whole-body flag the command registers (not --body), with [required] exactly when the command requires it, and the completion shell entries list --no-descriptions. These check the table itself; the runtime tests above check the rendered output, which also lists flags missing from the table.
  • README.md: --usage section describes the whole-body flag name, --no-descriptions and runtime-added flags.
  • Review SDK zSDKs/sdk-cli regenerated: chat lists --request instead of --body; completion <shell> lists --no-descriptions. All other --usage output is unchanged.
  • Changeset: core, cli, fix, patch.

Testing

  • TARGET=primary make test-cli: 2189 tests pass.
  • go test ./pkg/generate/snapshots -run TestSnapCLI: pass.
  • make lint: pass.
  • TARGET=review make build-cli: diff limited to internal/usage/schema.go, tests/usage_test.go and gen.lock; generated command files are byte-identical.
  • The new cli_empty_body_go_test.go assertions fail on the base branch templates (standaloneoptional lists --body <body>, not --empty-body) and pass with this change.
  • Against the previous review SDK schema.go, TestUsageSchema_FlagsMatchRegisteredFlags fails (chat --usage lists unregistered --body) and passes with this change.
  • --usage compared for every command path against the base branch:
    • review SDK: 7 of 90 paths differ (root, chat, completion and its four shells), only by the lines above;
    • primary test CLI: 129 of 688 paths differ, only by --body replaced with the registered whole-body flag and --no-descriptions; generated command files differ only where a nullable whole-body flag's help loses [required] (8 commands);
    • a generated CLI with no body-only, non-expanded operations: only completion and its shells differ.

Public-safety check

  • This change contains no credentials, customer documents, private repository URLs, private filesystem paths, or unredacted private logs.
  • Title, body, comments, and commit messages name no customers or customer-derived identifiers, private paths or trackers, or workflow provenance, and are understandable without private context (.claude/skills/public-repo-communication/SKILL.md).
  • Generated fixtures and review SDK changes are public-safe.
  • I reviewed git diff --check.

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 11 files

Shadow auto-approve: would not auto-approve because issues were found.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread templates/templates/cli/usage_test.go.stmpl
Comment thread zSDKs/sdk-cli/internal/usage/schema.go Outdated

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 12 files (changes from recent commits).

Shadow auto-approve: would not auto-approve because issues were found.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread templates/templates/cli/README.md Outdated

@cubic-dev-ai cubic-dev-ai 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.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Shadow auto-approve: would auto-approve. Fixes CLI --usage to list registered flags (whole-body flag name, completion --no-descriptions, runtime-added flags) and aligns help requiredness, with new runtime and snapshot tests pinning the corrected behavior.

View guided diff | Turn on auto-fix | Re-trigger cubic

@AshGodfrey AshGodfrey left a comment

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.

Verified locally: CLI snapshot tests and the review SDK usage tests pass at this head; operationUsesMetadataFlags matches the inline logic it replaced. No blocking issues.

Base automatically changed from fix/cli-usage-compose-runtime-commands to main October 20, 2026 19:36
@2ynn
2ynn force-pushed the fix/cli-usage-flags-match-registered-flags branch from d0464bd to 05be2f7 Compare October 20, 2026 19:37
@2ynn
2ynn marked this pull request as ready for review October 20, 2026 19:38
@2ynn
2ynn requested a review from a team as a code owner October 20, 2026 19:38
@2ynn
2ynn requested a review from simplesagar October 20, 2026 19:38
2ynn added 3 commits October 20, 2026 15:39
`--usage` disagreed with the flags commands accept in three ways:

- A body-only operation whose JSON/form body is not expanded into field
  flags (union, map, array or scalar body) registers one flag named after
  the request body (e.g. `--request`), but `--usage` listed `--body`,
  which the command rejects, and omitted the real flag. A multipart
  body-only operation without flag metadata also lacked its body flag.
  `--usage` decided the flag with `templateHasBodyFlag`, while
  `opcmd.go.stmpl` used separate inline logic.
- cobra's `completion bash|zsh|fish|powershell` accept `--no-descriptions`,
  which the `completion` nodes did not list.
- Flags added at runtime to a generated command were listed only when the
  command was marked with `usage.MarkDynamic`.

`operationUsesMetadataFlags` (side-effect free) now makes the request
strategy decision for both `opcmd.go.stmpl` and `--usage`;
`getOperationWholeBodyUsageFlag` lists the whole-body flag the command
registers, with its help text and `[required]` marker. The completion shell
nodes list `--no-descriptions`. A command rendered from its `usageNodes`
entry also lists visible local flags the entry does not have, so
`MarkDynamic` is only needed when help, aliases or args change at runtime.
Generated command files are unchanged.

Tests: `TestUsageSchema_FlagsMatchRegisteredFlags` checks every command's
own `--usage` against its registered flags in both directions;
`TestUsageSchema_RuntimeFlagsKeepGeneratedLines` replaces
`TestUsageSchema_DynamicCommandKeepsGeneratedLines` and runs with and
without `MarkDynamic`. README `--usage` section updated; review SDK
regenerated.
…only enforced bodies required

- Every command rendered from its `usageNodes` entry now takes its flags
  from cobra (`usageFlagLines`), marked dynamic or not: generated flag
  lines for the flags it still shows (a flag hidden at runtime is dropped),
  then visible local flags added at runtime. `usageFlagLines` reads
  `LocalFlags()` first, which merges persistent flags into `Flags()` before
  the lookups; without it a root marked dynamic before its first render
  dropped every generated root flag.
- The whole-body flag help says `[required]` only when the body is neither
  optional nor nullable, matching `templateRequestBodyRequired`. This also
  corrects `--help` for nullable body-only operations.
- `operationUsesMetadataFlags` replaces `intentOperationHasMeta`; the unused
  `operationHasFlagMetadata` is removed.
- `--usage` reads the unescaped `--body` help (`bodyFlagDescription`); the
  template wrapper still escapes it for Go source.

Tests: the empty-body snapshot test checks the generated `usageNodes`
entries of body-only operations (registered whole-body flag, no `--body`,
`[required]` exactly when the command requires it) and `--no-descriptions`
on the completion shells, since the rendered output also lists flags
missing from the table. `TestUsageSchema_FlagsMatchRegisteredFlags` covers
the root; new `TestUsageSchema_RuntimeHiddenFlagDropped`;
`TestUsageSchema_DynamicRoot` marks a fresh root dynamic before its first
render. README and review SDK updated.
@2ynn
2ynn force-pushed the fix/cli-usage-flags-match-registered-flags branch from 05be2f7 to a1103b5 Compare October 20, 2026 19:39
@2ynn
2ynn added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit 67f55b4 Oct 20, 2026
240 checks passed
@2ynn
2ynn deleted the fix/cli-usage-flags-match-registered-flags branch October 20, 2026 20:14
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants