Skip to content

feat(parse): parse Args without an enclosing CLI - #1419

Merged
jdx merged 2 commits into
mainfrom
codex/parse-nested-args
Sep 12, 2026
Merged

feat(parse): parse Args without an enclosing CLI#1419
jdx merged 2 commits into
mainfrom
codex/parse-nested-args

Conversation

@jdx

@jdx jdx commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Adapters and embedded command surfaces can now parse one derived Args type without constructing or parsing the application’s root CLI. This lets callers reuse the command’s compiled flags, positional arguments, defaults, validation, subcommand routing, and typed construction directly.

let install = usage::parse_args_from::<Install>(&args)?;
let install = usage::parse_args_from_argv::<Install>(&argv)?;

The second form follows the full-argv convention and strips argv0. Both return ordinary usage parse errors, including help requests, for the selected command.

Validation: mise run ci (Rust workspace tests and doctests, Clippy, formatting, semver checks, Prettier, and Go tests).

AI-assisted — Tool: Codex; model: openai/gpt-5; version: unavailable.


Note

Low Risk
Additive public API on the existing parser path; behavior is covered by new integration tests with no changes to root CLI parsing.

Overview
Adds parse_args_from and parse_args_from_argv so a derived CommandArgs / Args type can be parsed without a root Cli. Parsing starts at that command’s tables (flags, positionals, defaults, validation, nested subcommands) and returns the same Error variants as full-app parsing, including help, version, and missing-args help.

parse_args_from treats the slice as that command’s words only; parse_args_from_argv strips argv0 first. Both are re-exported from usage-rs (via usage_argv) behind the spec feature. Docs and facade tests cover success paths, choices, help, and subcommand routing.

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

Summary by CodeRabbit

  • New Features

    • Added standalone argument parsing for individual command definitions without requiring a complete CLI application.
    • Supports defaults, positional arguments, choice validation, help, version, required arguments, and nested subcommands.
    • Exposed public parsing entry points for adapter and integration use.
  • Documentation

    • Added guidance and examples for standalone argument parsing.
  • Tests

    • Added coverage for successful parsing, defaults, choices, positional arguments, nested commands, help, and invalid or missing input.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: f0c13639-b86b-4779-b91e-dbdb5f7830c4

📥 Commits

Reviewing files that changed from the base of the PR and between e924951 and 9149f89.

📒 Files selected for processing (2)
  • usage-rs/src/lib.rs
  • usage-rs/tests/facade.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • usage-rs/src/lib.rs

Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

The PR adds standalone parsing functions for derived argument types, re-exports them, documents their use, and tests successful parsing, subcommands, help, invalid choices, and missing required arguments.

Changes

Standalone argument parsing

Layer / File(s) Summary
Standalone parser API
argv/src/spec.rs, argv/src/lib.rs
Adds parse_args_from and parse_args_from_argv. The functions parse derived argument types, handle help, version, and missing-argument errors, then validate and build the result.
Standalone parsing validation
usage-rs/src/lib.rs, usage-rs/tests/facade.rs
Documents standalone parsing and tests defaults, choices, positional values, subcommand routing, invalid choices, help, and missing required arguments.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant parse_args_from
  participant Parser
  participant CommandArgs
  Caller->>parse_args_from: provide argv
  parse_args_from->>Parser: parse T::COMMAND
  Parser-->>parse_args_from: parsed arguments or error
  parse_args_from->>CommandArgs: run T::check and T::build
  CommandArgs-->>Caller: return parsed value or error
Loading

Merge Risk: ⚪ Minimal · up to 9149f

The new standalone parsing APIs are covered for normal values, subcommands, defaults, and standard errors, with no current merge-blocking risk identified.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding support to parse derived Args without an enclosing CLI.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 4 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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 Sep 12, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the changes since the previous review fully address both earlier findings without introducing a new actionable issue.

Summary

  • Re-exports parse_args_from and parse_args_from_argv behind the spec feature.
  • Preserves normal parsing, validation, help, version, defaults, and subcommand routing behavior.
  • Gates the facade doctest correctly and adds nested-subcommand routing and validation coverage.

Reviews (2) · Last reviewed commit: "test(facade): cover standalone subcomman..."

Comment thread usage-rs/src/lib.rs
Comment thread usage-rs/tests/facade.rs
@jdx
jdx merged commit d07e50e into main Sep 12, 2026
12 checks passed
@jdx
jdx deleted the codex/parse-nested-args branch September 12, 2026 14:35
@github-actions

Copy link
Copy Markdown
Contributor

Instruction counts

benchmark trend instructions Δ wall (min) Δ
markdown ████▁▁▁▁▁▁▁ 384,245,167 → 384,294,770 +0.01% 64.15 → 64.67ms +0.81%
startup █▂▂▂▂▂▂▂▂▁▂ 981,111 → 988,147 +0.72% 1.34 → 1.36ms +1.50%

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.

framework stripped binary, bytes
usage 1349840
bpaf 2493216
clap 3101656
framework instructions, cold parse vs usage
usage 8607
clap 6314338 733x
bpaf 21909171 2545x
                                              min       p01       p10    median
usage-rs: argv -> struct                      775       776       778       787  ns
clap: build tree + parse -> struct        1236057   1237003   1247522   1266089  ns
bpaf: build parser + parse -> struct      3387539   3387539   3403634   3487584  ns

usage: argv -> struct                             789 ns      0.79 µs
clap: build tree + parse -> struct            1264591 ns   1264.59 µs
clap: parse -> struct, tree reused              50358 ns     50.36 µs
clap: build tree only                          754707 ns    754.71 µs

9149f89ba439 vs cf2785296717 · measured on the runner, not pushed to the history.

jdx pushed a commit that referenced this pull request Sep 12, 2026
### 🚀 Features

- **(help)** allow remapping semantic colours on Style by
[@lu-zero](https://github.com/lu-zero) in
[#1414](#1414)
- **(parse)** add opt-in default-subcommand flag routing by
[@jdx](https://github.com/jdx) in
[#1413](#1413)
- **(parse)** parse Args without an enclosing CLI by
[@jdx](https://github.com/jdx) in
[#1419](#1419)

### 🐛 Bug Fixes

- **(bash)** preserve colon-prefixed completion words by
[@jdx](https://github.com/jdx) in
[#1405](#1405)

### 📚 Documentation

- write PR titles and descriptions for release notes by
[@jdx](https://github.com/jdx) in
[#1415](#1415)

### ⚡ Performance

- **(cli)** shrink help sorting without allocating cached keys by
[@jdx](https://github.com/jdx) in
[#1396](#1396)
- **(cli)** make advanced help and runtime spec serialization optional
by [@jdx](https://github.com/jdx) in
[#1399](#1399)
- **(cli)** share help sorting and skip unused rendering work by
[@jdx](https://github.com/jdx) in
[#1400](#1400)
- **(cli)** avoid color analysis for plain help by
[@jdx](https://github.com/jdx) in
[#1401](#1401)

### 🔍 Other Changes

- **(ci)** use self-repository workflow references by
[@jdx](https://github.com/jdx) in
[#1409](#1409)

### 📦️ Dependency Updates

- lock file maintenance by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1398](#1398)
- update jdx/renovate-config digest to 8cabc2e by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1406](#1406)
- update zizmorcore/zizmor-action action to v0.6.3 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1403](#1403)
- update dependency go to v1.27.1 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1407](#1407)
- update actions/deploy-pages action to v5 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1404](#1404)
- update communique to v1.4.0 by [@jdx](https://github.com/jdx) in
[#1416](#1416)

### New Contributors

- @lu-zero made their first contribution in
[#1414](#1414)
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