Skip to content

fix(clap): say what clap would do with an unknown flag - #899

Merged
jdx merged 1 commit into
mainfrom
agent/unknown-flags
Aug 16, 2026
Merged

fix(clap): say what clap would do with an unknown flag#899
jdx merged 1 commit into
mainfrom
agent/unknown-flags

Conversation

@jdx

@jdx jdx commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Stack created with GitHub Stacks CLIGive Feedback 💬


Note

Medium Risk
Changes default parsing semantics for specs generated from clap (stricter unknown-flag handling for most commands), which fixes real CLI bugs but could affect any consumer that relied on the old permissive default.

Overview
Clap → usage spec export now sets unknown_flags on every command (and on the root spec) instead of leaving it unset, so usage-based parsers match clap’s behavior for unrecognized dash-words.

Commands that reject unknown flags get unknown_flags=error. Commands that forward hyphenated tokens get unknown_flags=value, inferred from clap when external subcommands are allowed or any arg has allow_hyphen_values / trailing_var_arg.

Regenerated usage.usage.kdl, commands.json, and test snapshots reflect the new metadata. Unit tests cover the inference rules and KDL round-trip serialization.

Reviewed by Cursor Bugbot for commit 9fa97a8. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Warning

Review limit reached

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

Next review available in: 6 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

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: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 87b56b34-37d9-4b96-abed-aa1b9b841f22

📥 Commits

Reviewing files that changed from the base of the PR and between 4a05869 and 9fa97a8.

⛔ Files ignored due to path filters (1)
  • clap_usage/tests/snapshots/simple__simple.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • cli/usage.usage.kdl
  • docs/cli/reference/commands.json
  • lib/src/spec/cmd.rs
  • lib/src/spec/mod.rs

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 Aug 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR makes clap-derived specs explicitly serialize clap-like unknown-flag handling at root and subcommand levels.

  • Assigns error to ordinary clap commands and value to commands considered forwarding-capable.
  • Serializes the root policy into generated KDL and updates generated snapshots and reference JSON.
  • Adds conversion and round-trip coverage for the new field.

Confidence Score: 4/5

The PR does not yet appear safe to merge because per-argument clap forwarding settings still relax unknown-flag handling for an entire generated command.

A command containing any hyphen-enabled or trailing positional receives UnknownFlags::Value globally, and the usage parser consults that command-level policy before binding the token to whichever positional is currently active; therefore generated specs can accept mistyped flags that clap rejects.

Files Needing Attention: lib/src/spec/cmd.rs

Important Files Changed

Filename Overview
lib/src/spec/cmd.rs Adds clap-to-spec unknown-flag policy derivation and focused serialization tests.
lib/src/spec/mod.rs Copies the converted root command’s unknown-flag policy into the top-level Spec.
clap_usage/tests/snapshots/simple__simple.snap Updates the generated clap usage snapshot to include the explicit root policy.
cli/usage.usage.kdl Regenerates the usage CLI’s self-description with explicit root and command policies.

Reviews (3): Last reviewed commit: "fix(clap): say what clap would do with a..." | Re-trigger Greptile

Comment thread lib/src/spec/cmd.rs
Comment thread lib/src/spec/cmd.rs
let forwards = cmd.is_allow_external_subcommands_set()
|| cmd
.get_arguments()
.any(|arg| arg.is_allow_hyphen_values_set() || arg.is_trailing_var_arg_set());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Trailing arg heuristic too broad

Medium Severity

The clap-to-spec conversion treats any trailing_var_arg as forwarding and sets unknown_flags to value. Clap still rejects unknown dash-words unless allow_hyphen_values is also set, so commands that only use a trailing var arg become looser than clap and miss the typo errors this change aims to restore.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c0daf25. Configure here.

@github-actions

github-actions Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Instruction counts

benchmark trend instructions Δ wall (min) Δ
markdown ▁▃▃▃▃▃█ 175,733,337 → 177,380,189 +0.94% 15.79 → 16.54ms +4.70%
startup ██▁▁▅▁▅ 1,221,823 → 1,221,966 +0.01% 0.95 → 0.95ms -0.60%

No instruction-count regression above 1%.

Only instruction counts gate. Wall clock is shown for context — on identical hardware it moves 4-20% run to run.

Measured by tak — instruction-counted CLI benchmarks, stored in this repository's git notes.

Shadow comparison

Parsing mise use -g node@20 against a shadow of mise's committed spec.
Reported, not gated: the shadow grows as the derive learns to express more, so
what to watch is the ratio rather than either column.

usage clap ratio
instructions, cold parse 72158 5895173 81x
usage: argv -> struct                            1277 ns      1.28 µs
clap: build tree + parse -> struct             496450 ns    496.45 µs
clap: parse -> struct, tree reused              23662 ns     23.66 µs
clap: build tree only                          305776 ns    305.78 µs

9fa97a83d1f6 vs 228046e8ba03 · measured on the runner, not pushed to the history.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fabea27. Configure here.

Comment thread lib/src/spec/mod.rs Outdated
@jdx jdx changed the title agent/unknown flags fix(clap): say what clap would do with an unknown flag Aug 15, 2026
A spec generated from clap said nothing about `unknown_flags`, so every command it
described fell back to this spec's default — offer the token to the positionals —
while clap itself rejects one. mise's spec has 211 commands and not one of them
said it, which is why `mise use --globa` is an error under clap and a *tool named
`--globa`* under a usage parser.

The two defaults differ for a reason and both are right where they are: a spec also
describes wrappers, where a dash-word is data in transit. But a CLI generated from
clap is not one of those — clap already decided, and dropping the decision quietly
loosened the grammar.

Which commands forward is clap's own knowledge: an argument that takes hyphen
values or a trailing var-arg, or a command that accepts external subcommands.
Regenerating mise against this says `error` on 205 commands and `value` on five —
`run`, `watch`, `asdf`, `tool-stub`, and `tasks run` — which is the audit, and it
agrees with the five files in mise that set those clap attributes. The usage CLI's
own spec is a smaller check of the same rule: `bash`, `exec`, `fish` and
`complete-word` forward; `generate` does not.

The root's own answer had nowhere to go and was being dropped. A spec says this at
the top level, which is the field a reader puts it back into, so that is where it
goes — mise's root forwards (its implicit task arguments take hyphen values), so it
stays permissive, while a CLI whose root does not now gets the strict reading it
asked for.

What this buys, checked against the regenerated spec: `mise use --globa` now says
"Invalid flag `--globa`: no such flag" instead of parsing, and the same for
`mise current --forc` and `mise prune --dry-ru`. The forwarding commands are
unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jdx
jdx force-pushed the agent/unknown-flags branch from fabea27 to 9fa97a8 Compare August 15, 2026 15:14
@jdx
jdx merged commit f68fef4 into main Aug 16, 2026
9 checks passed
@jdx
jdx deleted the agent/unknown-flags branch August 16, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant