Skip to content

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

Open
jdx wants to merge 1 commit into
mainfrom
agent/unknown-flags
Open

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

Conversation

@jdx

@jdxjdx 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

coderabbitaiBot 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-appsBot 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

FilenameOverview
lib/src/spec/cmd.rsAdds clap-to-spec unknown-flag policy derivation and focused serialization tests.
lib/src/spec/mod.rsCopies the converted root command’s unknown-flag policy into the top-level Spec.
clap_usage/tests/snapshots/simple__simple.snapUpdates the generated clap usage snapshot to include the explicit root policy.
cli/usage.usage.kdlRegenerates 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 threadlib/src/spec/cmd.rs
Comment threadlib/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 CursorFix in Web

Reviewed by Cursor Bugbot for commit c0daf25. Configure here.

@github-actions

github-actionsBot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Instruction counts

benchmarktrendinstructionsΔ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.

usageclapratio
instructions, cold parse72158589517381x
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.

@cursorcursorBot 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 threadlib/src/spec/mod.rs Outdated
@jdxjdx changed the title agent/unknown flagsfix(clap): say what clap would do with an unknown flagAug 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
jdxforce-pushed the agent/unknown-flags branch from fabea27 to 9fa97a8CompareAugust 15, 2026 15:14
Sign up for freeto 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

@jdx