Skip to content

feat: add dynamic command catalogs - #1275

Merged
jdx merged 12 commits into
mainfrom
feat/dynamic-command-catalogs
Aug 24, 2026
Merged

feat: add dynamic command catalogs#1275
jdx merged 12 commits into
mainfrom
feat/dynamic-command-catalogs

Conversation

@jdx

@jdx jdx commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Summary

Add usage-dynamic: commands an application discovers at runtime, merged into a derived host's
help, completion, and parsing. Plugins attach to a static command that declared an
external_subcommand catch-all, via root(spec) or under(path, spec). The derive's parse
tables, the emitted KDL, and the ordinary parse path are untouched.

How the pieces fit

Completion has two answerers, split at the catch-all. Up to it the words are the host's and
the host's own engine answers for them, so registered sync/async completers, multicall
projections, and the --candidates half of the protocol keep working — with catalogued names
added wherever a subcommand belongs. Past it the plugin's own spec answers alone: its
subcommands, flags, and declared choices, under the same rules the static engine uses for when a
position is closed to the shell's path fallback.

Which required saying where a line leaves the static tables. walk discarded
Event::External, so a position past a catch-all looked like the declaring command's own — and
completion answered with that command's subcommands, flags, and working directory, all of them
answers about a CLI these tables do not describe. Position::external reports the boundary, and
both implementations now offer nothing past it. That is a behavior fix on main independent of
this crate, pinned by new corpus vectors (corpus/complete/03-external-boundary.json) that
needed a way to say "nothing is the claim" — an empty expectation stays refused otherwise.

Building the merged tree is lazy, and cheap when it happens. Dispatch reads only the entry
specs, never the merged tree, so assembling one waits for app(). The round trip that used to
follow insertion — writing the whole spec out as KDL and parsing it back, purely to fix
full_cmd, usage lines, and a memoized lookup — is now Spec::restamp, with a test pinning it
against the round trip it replaces.

Measured on benches/mise.usage.kdl (256 KB):

before after
build(), per dispatch ~230 ms 0
fixup after grafting 97 ms 97 µs

Hot path unchanged: 8,720 instructions cold parse, 490 ns median.

Also

  • CompletionRequest is argv's protocol parser made public, so the workspace has one fewer copy
    of it; App::complete_request is its answer before rendering.
  • Non-UTF-8 argv still errors — the spec model parses Strings — but the docs now say plainly
    that the argv is intact and belongs in the same fallback arm as an uncatalogued name.
  • A parent path spelled with a hidden static alias resolves, as under always said it would.
  • docs/rust/dynamic-commands.md is rewritten around one end-to-end main, which lives in
    usage-dynamic/examples/host.rs and compiles in CI. That is how two API shapes the prose
    would otherwise have got wrong surfaced: parse_from takes &[&OsStr], and rendering host
    help through the merged tree needs the command's path rather than its name. The page is in the
    sidebar now.
  • The catalog no longer clears mounts from a completion copy of the tree, so app().spec() is
    the host's spec as written.

Trade-off worth naming

usage-dynamic pulls usage-lib — kdl, tera, miette — into a derive-based binary. That is the
cost of a portable spec model at runtime, and it is confined to cold paths, but it is real and
an application that does not need runtime commands should not depend on this crate.

Validation

  • mise run ci
  • mise run perf:shadow — 8,720 instructions, 490 ns median
  • cargo +1.95 check --locked -p usage-dynamic --all-features
  • npm run docs:build

cargo package -p usage-dynamic still cannot verify until usage-lib's new cli-help feature
is published; Cargo resolves the 6.1.1 metadata, which predates it. The workspace build, tests,
clippy, and the 1.95 check all compile the packaged source against this PR's usage-lib.

This pull request was generated by Claude Code.


Note

Medium Risk
New public crate and completion-protocol APIs plus a behavior change: completions past an external_subcommand now offer nothing. Static parse hot path is unchanged, but help/completion merge and grafting are new surface area.

Overview
Adds usage-dynamic: applications discover plugin specs themselves and attach them to a static external_subcommand catch-all via Catalog::builder. Built-in commands still parse against derived tables only; parse_external dispatches captured argv against one spec; app() lazily merges the tree for help and completion.

Completion splits at the catch-all. Host engine (overlays, projections, --candidates) answers before it; the plugin spec answers after. Position::external records where words left the static tables. Past that boundary, both argv and usage-cli now offer nothing (no host flags, no path fallback). Corpus vectors use a new "nothing": true expectation.

Spec grafting is cheap. Spec::restamp restamps full_cmd, usage lines, and subcommand lookup instead of a KDL round-trip. From<SpecCommand> for Spec supports in-process command trees. CLI help is split onto a cli-help feature so the catalog can render pages without full docs.

Also publicizes CompletionRequest / complete_request so hosts share one protocol parser. Experimental docs and examples/host.rs show the intended parse_from + catalog help/completion flow.

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

Summary by CodeRabbit

  • New Features

    • Added runtime-discovered commands with merged help, completion, version information, and dispatch.
    • Added independent CLI help support and expanded completion request handling.
    • Added dynamic command documentation and a host integration example.
  • Bug Fixes

    • Suppressed host suggestions and file fallback after external subcommands.
    • Improved updates when commands are dynamically grafted into an existing tree.
  • Documentation

    • Clarified dynamic command catalogs, lazy loading, validation, and host integration.
  • Tests

    • Added coverage for dynamic commands, forwarding, help, completion, validation, and dispatch.

@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Review 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: Pro Plus

Run ID: 05b9f2cd-1e56-4874-96ab-13e74b049c11

📥 Commits

Reviewing files that changed from the base of the PR and between e140f26 and 2117915.

📒 Files selected for processing (4)
  • docs/rust/dynamic-commands.md
  • lib/src/spec/mod.rs
  • usage-dynamic/src/lib.rs
  • usage-dynamic/tests/catalog.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/rust/dynamic-commands.md

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


📝 Walkthrough

Walkthrough

This change adds the usage-dynamic crate for runtime command catalogs, parsing, help, and completion. It also tracks external-subcommand completion boundaries, adds specification restamping, separates CLI help features, and adds integration tests, documentation, and MSRV coverage.

Changes

Dynamic commands and completion

Layer / File(s) Summary
External-subcommand completion boundaries
argv/src/complete.rs, argv/src/help.rs, cli/src/cli/complete_word.rs, conformance/*, corpus/complete/*
Completion records external forwarding boundaries and returns no host candidates, overlays, or filesystem fallback after forwarding begins. The completion request API is public.
Specification features and grafted trees
lib/Cargo.toml, lib/src/docs/*, lib/src/lib.rs, lib/src/parse.rs, lib/src/spec/*
The cli-help feature is separate from docs. Spec::restamp recalculates paths, usage, and lookup caches after command grafting.
Runtime catalog and APIs
Cargo.toml, .github/workflows/test.yml, usage-dynamic/Cargo.toml, usage-dynamic/src/lib.rs
Adds the crate to the workspace and MSRV checks. Adds Catalog, Builder, and App APIs for validated runtime specs, lazy merged trees, external parsing, typed outcomes, help, and completion.
Catalog integration validation
usage-dynamic/tests/catalog.rs
Tests Rust-built runtime specifications with dispatch parsing, help, version handling, merged help, and completion.
Host example and documentation
usage-dynamic/examples/host.rs, docs/.vitepress/config.mts, docs/rust/dynamic-commands.md, docs/rust/index.md
Adds a plugin-aware host example and documents runtime command discovery, dispatch, help, completion, validation, and catalog usage.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟡 Moderate · up to 21179

The PR adds runtime command catalogs and changes completion behavior, but named completion requests can still return host candidates after an external-subcommand boundary, and nested plugin completers may be lost from merged specifications. These concrete correctness and integration issues should be fixed or explicitly accepted before merging.

Sequence Diagram(s)

sequenceDiagram
  participant Host
  participant Catalog
  participant PluginSpec
  Host->>Catalog: discover and register plugin specs
  Host->>Catalog: parse external arguments
  Catalog->>PluginSpec: resolve alias and parse plugin command
  PluginSpec-->>Catalog: return Parsed, Help, or Version
  Host->>Catalog: request help or completion
  Catalog->>PluginSpec: delegate selected plugin completion
  PluginSpec-->>Catalog: return plugin candidates
  Catalog-->>Host: render help or completion response
Loading

Poem

I’m a rabbit with plugins in tow,
Through catalog paths, new commands grow.
Past forwarded words, silence is clear,
No stray files or flags appear.
Restamped specs make the burrow bright!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring check was indeterminate for this PR — some files could not be analyzed in time. Not blocking.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: adding runtime-discovered dynamic command catalogs.

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.

Comment thread usage-dynamic/src/lib.rs
Comment thread argv/src/help.rs Outdated
@jdx
jdx force-pushed the feat/dynamic-command-catalogs branch from fbe1ad5 to f9ef667 Compare August 23, 2026 22:48
Comment thread usage-dynamic/src/lib.rs
@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Instruction counts

benchmark trend instructions Δ wall (min) Δ
markdown ▁▁▁▁▃█▇▇ 337,506,238 → 338,127,954 +0.18% 28.38 → 28.42ms +0.14%
startup ▂█▅▅▁▅▅▅ 876,750 → 876,756 +0.00% 0.90 → 0.90ms -0.03%

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 1320432
bpaf 2493280
clap 3101832
framework instructions, cold parse vs usage
usage 8300
clap 6315224 760x
bpaf 21909147 2639x
                                              min       p01       p10    median
usage-rs: argv -> struct                      429       436       441       449  ns
clap: build tree + parse -> struct         518768    520939    523669    529984  ns
bpaf: build parser + parse -> struct      1613958   1613958   1625491   1667446  ns

usage: argv -> struct                             429 ns      0.43 µs
clap: build tree + parse -> struct             536924 ns    536.92 µs
clap: parse -> struct, tree reused              23879 ns     23.88 µs
clap: build tree only                          323951 ns    323.95 µs

fe7f4908be10 vs 46b22cac1a4f · measured on the runner, not pushed to the history.

jdx and others added 8 commits August 23, 2026 23:47
`walk` swallowed `Event::External`, so a position past an `external_subcommand`
catch-all looked like the declaring command's own — and completion answered with
that command's subcommands, flags and working directory. Every one of those is an
answer about a CLI these tables do not describe.

`Position::external` says where the words left, and both implementations stop
answering there: nothing offered, no path fallback. The corpus pins it for both,
which needs a way to say "nothing is the claim" — an empty expectation is
otherwise a mistake, and stays refused.

`CompletionRequest` is the protocol parser made public, and `App::complete_request`
is its answer before rendering, for a host that answers part of a line itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Inserting a command into a built tree leaves three things describing where
it used to be: its `full_cmd`, its usage line, and its parent's memoized
subcommand lookup. The way to fix them was to write the whole spec out as
KDL and parse it back — a quarter of a second for a mise-sized spec, to
correct some strings.

`Spec::restamp` is the pass itself, force-recomputing what parsing only
filled in when blank, and a test pins it against the round trip it replaces.

Rendering a help page also cloned the spec twice, once at the call site and
again inside the docs conversion. Taking a reference makes it once.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The catalog answered whole command lines from its merged tree, which meant
a host adopting runtime commands quietly lost everything the static engine
does for the words that are still its own: registered sync and async
completers, multicall projections, and the `--candidates` half of the
protocol, which answered a different question than the emitted KDL promised.

Now the line has two answerers. Up to the catch-all the host's tables answer,
and the catalogued names are added where a subcommand belongs — closing the
path fallback, since a name to offer is something to say. Past it the plugin's
own spec answers alone, with the rules the static engine follows for what a
declared position closes.

Assembling the merged tree waits for `app()`: dispatch never reads it, and
building it cost a KDL round trip of the whole host spec — 230ms of it for a
mise-sized CLI, on every plugin command. Grafting and restamping replaces the
round trip that followed insertion: 97ms to 97us.

A parent path spelled with a hidden static alias resolves, as `under` always
said it would.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The page opened on an abstract capability list, never said what a `Spec` is
or how an application gets one, and showed three fragments in three unrelated
scopes for a feature whose whole difficulty is wiring. It also hid lines with
rustdoc `#`, which VitePress renders literally.

Rewritten around the problem it solves, with one end-to-end `main` that is
`usage-dynamic/examples/host.rs` — compiled in CI, which is how the two API
shapes the old page would have got wrong came to light: `parse_from` takes
`&[&OsStr]`, and rendering host help through the merged tree needs the
command's path rather than its name.

The page is also in the sidebar now, rather than reachable only from two
links on the crate index.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
It polled a future once and panicked on `Pending`, which is fine for a host
that registered no callbacks and a crash for one that registered an async
completer — a distinction the caller cannot see at the call site. The async
answer is the only answer now; `CompletionRequest::for_split` is how a caller
holding a split line reaches it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The page taught eager catalog construction — load every plugin at the top of
main — which is backwards: most invocations are built-in commands, and the
whole point of anchoring on the catch-all is that a built-in parses and runs
with no plugin discovered, loaded, or parsed. The example now constructs the
catalog only on the three paths that need one (the catch-all, help,
completion), a cost table says which call pays for what, and a test pins the
pattern: a builtin dispatches with no catalog, and a catalog of one spec is a
complete dispatcher for that plugin.

Also handles --version, which the previous example rendered as a failure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jdx
jdx force-pushed the feat/dynamic-command-catalogs branch from ef4a07f to 5626fca Compare August 23, 2026 23:59

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

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 5626fca. Configure here.

Comment thread argv/src/complete.rs
Reasons first, fewer aphorisms. The lazy-loading section now opens with why
("because loading plugins is expensive and most invocations never touch one")
instead of a list of costs, the intro states the build-time/runtime mismatch
directly, and the example's comments match the register since the page shows
them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
argv/src/complete.rs (1)

1328-1356: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Suppress named completion after an external boundary.

complete_named_with calls for_name and overlay_for_name after walk reports position.external. A --candidates request for host plugins myplugin can return host completion values after myplugin was forwarded.

Return empty Completions immediately after Line 1328 when position.external.is_some(). This must match complete_inner.

Proposed fix
     let position = walk(spec.root.cmd, split.argv());
+    if position.external.is_some() {
+        return Completions {
+            candidates: Vec::new(),
+            files: None,
+        };
+    }
     let attached = attached_long_value(&position, &split.prefix);
🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@argv/src/complete.rs` around lines 1328 - 1356, Update complete_named_with to
return empty Completions immediately when position.external.is_some() after
walk, before calling for_name or overlay_for_name, matching complete_inner and
preventing host completions after an external boundary.
🧹 Nitpick comments (1)
usage-dynamic/src/lib.rs (1)

581-600: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Define shared complete-type semantics

files_kind duplicates part of usage_argv::complete::declared_files, but the mappings differ. The dynamic code accepts executable_path; the static code accepts case-insensitive names, config_file, and command_args, and filters extensions differently.

If both paths must support the same types, extract a shared helper with explicit semantics. Do not call declared_files directly because it includes static-only behavior.

🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@usage-dynamic/src/lib.rs` around lines 581 - 600, Unify file-type parsing
between files_kind and usage_argv::complete::declared_files by extracting a
shared helper with explicitly defined common semantics. Preserve support for
case-insensitive type names, config_file, command_args, and the established
extension-filter behavior, while keeping any static-only behavior out of the
shared helper and retaining dynamic-only aliases only where appropriate.
🤖 Prompt for all review comments with AI agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

Inline comments:
In `@docs/rust/dynamic-commands.md`:
- Around line 220-223: Qualify the NonUtf8 match in the dynamic command dispatch
example with usage_dynamic::Error, rather than the imported usage::Error, while
preserving the existing handling alongside None.
- Around line 15-22: Update the dependency block in the dynamic commands
documentation to include the executor required by the async complete_request
example, such as the futures dependency used by futures::executor::block_on, or
explicitly document the runtime dependency the reader must provide.

In `@usage-dynamic/src/lib.rs`:
- Around line 740-742: Update insert_plugin so plugin spec-level complete
entries are preserved throughout the entire grafted command subtree, not only in
the root command.complete map. Ensure nested plugin commands resolve their
completers from the merged app.spec() tree while retaining existing host
completion behavior.

In `@usage-dynamic/tests/catalog.rs`:
- Around line 282-287: Move the environment-dependent test block using
USAGE_DYNAMIC_TEST_COLOR out of the shared catalog tests into a separate
integration test file such as env_fallback.rs, so it runs in its own process.
Preserve the existing parse_external("plugins", [&quot;formatter&quot;])
behavior and cleanup, and leave the other catalog tests unchanged.

---

Outside diff comments:
In `@argv/src/complete.rs`:
- Around line 1328-1356: Update complete_named_with to return empty Completions
immediately when position.external.is_some() after walk, before calling for_name
or overlay_for_name, matching complete_inner and preventing host completions
after an external boundary.

---

Nitpick comments:
In `@usage-dynamic/src/lib.rs`:
- Around line 581-600: Unify file-type parsing between files_kind and
usage_argv::complete::declared_files by extracting a shared helper with
explicitly defined common semantics. Preserve support for case-insensitive type
names, config_file, command_args, and the established extension-filter behavior,
while keeping any static-only behavior out of the shared helper and retaining
dynamic-only aliases only where appropriate.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro Plus

Run ID: ca89f3a3-a65c-420e-b16a-beecdd98dd22

📥 Commits

Reviewing files that changed from the base of the PR and between 46b22ca and 5626fca.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • .github/workflows/test.yml
  • Cargo.toml
  • argv/src/complete.rs
  • argv/src/help.rs
  • cli/src/cli/complete_word.rs
  • conformance/src/complete.rs
  • conformance/tests/complete.rs
  • corpus/complete/03-external-boundary.json
  • corpus/complete/README.md
  • docs/.vitepress/config.mts
  • docs/rust/dynamic-commands.md
  • docs/rust/index.md
  • lib/Cargo.toml
  • lib/src/docs/cli/mod.rs
  • lib/src/docs/mod.rs
  • lib/src/docs/models.rs
  • lib/src/lib.rs
  • lib/src/parse.rs
  • lib/src/spec/choices.rs
  • lib/src/spec/cmd.rs
  • lib/src/spec/mod.rs
  • usage-dynamic/Cargo.toml
  • usage-dynamic/examples/host.rs
  • usage-dynamic/src/lib.rs
  • usage-dynamic/tests/catalog.rs

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

Comment thread docs/rust/dynamic-commands.md
Comment thread docs/rust/dynamic-commands.md Outdated
Comment thread usage-dynamic/src/lib.rs
Comment on lines +740 to +742
for (key, complete) in &plugin.complete {
command.complete.insert(key.clone(), complete.clone());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Spec-level complete blocks are lifted only onto the grafted root command.

insert_plugin copies plugin.complete into command.complete, which is the grafted top-level command alone. Nested plugin subcommands rely on the spec-level fallback that completion_for implements at Line 610. In the merged tree that fallback resolves against the host's merged.complete, not the plugin's, so a nested plugin command loses its spec-level completers.

Runtime completion is unaffected, because complete_plugin answers from the original spec. The loss is visible to any consumer of app.spec(), for example code that renders the merged tree or emits its KDL. Copy the plugin's spec-level complete entries onto the grafted subtree, or document that app.spec() does not preserve them.

🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@usage-dynamic/src/lib.rs` around lines 740 - 742, Update insert_plugin so
plugin spec-level complete entries are preserved throughout the entire grafted
command subtree, not only in the root command.complete map. Ensure nested plugin
commands resolve their completers from the merged app.spec() tree while
retaining existing host completion behavior.

Comment on lines +282 to +287
std::env::set_var("USAGE_DYNAMIC_TEST_COLOR", "never");
let from_env = catalog
.parse_external("plugins", &[OsString::from("formatter")])
.unwrap()
.unwrap();
std::env::remove_var("USAGE_DYNAMIC_TEST_COLOR");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

std::env::set_var mutates process state while other tests run in parallel.

cargo test runs the tests in this file on multiple threads in one process. set_var and remove_var are not thread-safe; concurrent reads from other threads are undefined behavior. Several other tests in this file call parse_external against the same formatter spec, which declares env="USAGE_DYNAMIC_TEST_COLOR", so those reads can overlap with this write.

No assertion depends on the value today, but the data race is real and the crate declares rust-version = "1.95". An edition 2024 migration will also make these calls unsafe.

Move the env-dependent case to its own integration test file, so it gets its own process.

🛡️ Proposed change
-    std::env::set_var("USAGE_DYNAMIC_TEST_COLOR", "never");
-    let from_env = catalog
-        .parse_external("plugins", &[OsString::from("formatter")])
-        .unwrap()
-        .unwrap();
-    std::env::remove_var("USAGE_DYNAMIC_TEST_COLOR");
-    let Outcome::Parsed(from_env) = from_env else {
-        panic!("expected parsed")
-    };
-    assert!(from_env
-        .output
-        .flag_origins
-        .values()
-        .flatten()
-        .any(|origin| format!("{origin:?}").contains("Env")));
-

Then add the removed block as its own test in a new file, for example usage-dynamic/tests/env_fallback.rs.

🤖 Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

In `@usage-dynamic/tests/catalog.rs` around lines 282 - 287, Move the
environment-dependent test block using USAGE_DYNAMIC_TEST_COLOR out of the
shared catalog tests into a separate integration test file such as
env_fallback.rs, so it runs in its own process. Preserve the existing
parse_external("plugins", [&quot;formatter&quot;]) behavior and cleanup, and
leave the other catalog tests unchanged.

jdx and others added 3 commits August 24, 2026 00:09
A plugin manager is a tool for managing plugins; the subject here is any CLI
whose command set is extended by them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
KDL is the contract with out-of-process plugins; it should not be the only
door. Commands the application itself defines at runtime — tasks from a
config file — had to be rendered as KDL text just so the catalog could parse
it back.

`Spec: From<SpecCommand>` wraps a built command tree (name -> name/bin,
help -> about), the catalog restamps every entry at build() so built and
parsed specs are indistinguishable downstream, and usage-dynamic re-exports
the spec builders so this needs no direct usage-lib dependency.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The setup TOML omitted the executor the example calls, and the dispatch
section said `Error::NonUtf8` under an example importing the parser's
`usage::Error` — qualified as the catalog's own type. Also pins that a
hidden alias dispatches like any other spelling.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jdx
jdx merged commit 5bf0391 into main Aug 24, 2026
12 checks passed
@jdx
jdx deleted the feat/dynamic-command-catalogs branch August 24, 2026 00:37
jdx pushed a commit that referenced this pull request Aug 24, 2026
### 🚀 Features

- **(argv)** add embedded parse outcomes by
[@jdx](https://github.com/jdx) in
[#1250](#1250)
- **(cli)** render inline formatting in help text by
[@jdx](https://github.com/jdx) in
[#1245](#1245)
- **(cli)** split grouped help template sections by
[@jdx](https://github.com/jdx) in
[#1251](#1251)
- **(complete)** add presentation labels to candidates by
[@jdx](https://github.com/jdx) in
[#1239](#1239)
- **(complete)** expose structured completion traces by
[@jdx](https://github.com/jdx) in
[#1241](#1241)
- **(complete)** add semantic candidate kinds by
[@jdx](https://github.com/jdx) in
[#1242](#1242)
- **(complete)** add Elvish runtime completions by
[@jdx](https://github.com/jdx) in
[#1243](#1243)
- **(derive)** let argument groups carry values by
[@jdx](https://github.com/jdx) in
[#1253](#1253)
- **(derive)** add typed command finalization by
[@jdx](https://github.com/jdx) in
[#1254](#1254)
- **(derive)** add runtime-computed defaults by
[@jdx](https://github.com/jdx) in
[#1256](#1256)
- **(derive)** dispatch embedded control requests by
[@jdx](https://github.com/jdx) in
[#1270](#1270)
- **(derive)** emit embedded_outcome_into for converted CLIs by
[@jdx](https://github.com/jdx) in
[#1281](#1281)
- **(docs)** allow overriding markdown templates by
[@jdx](https://github.com/jdx) in
[#1267](#1267)
- **(docs)** default to compact markdown references by
[@jdx](https://github.com/jdx) in
[#1272](#1272)
- **(docs)** polish compact markdown references by
[@jdx](https://github.com/jdx) in
[#1280](#1280)
- **(help)** expose addressable help topics by
[@jdx](https://github.com/jdx) in
[#1257](#1257)
- **(help)** list commands by name in one aligned column by
[@jdx](https://github.com/jdx) in
[#1284](#1284)
- **(help)** wrap the short help page by [@jdx](https://github.com/jdx)
in [#1287](#1287)
- **(parse)** add structured diagnostic reports by
[@jdx](https://github.com/jdx) in
[#1255](#1255)
- **(parse)** add opt-in response files by
[@jdx](https://github.com/jdx) in
[#1259](#1259)
- **(parse)** preserve ordered argument groups by
[@jdx](https://github.com/jdx) in
[#1271](#1271)
- **(spec)** declare command outputs and exit codes by
[@jdx](https://github.com/jdx) in
[#1249](#1249)
- **(spec)** add surface availability metadata by
[@jdx](https://github.com/jdx) in
[#1258](#1258)
- **(spec)** add semantic note and warning blocks by
[@jdx](https://github.com/jdx) in
[#1273](#1273)
- **(spec)** add output media types by [@jdx](https://github.com/jdx) in
[#1274](#1274)
- **(spec)** add help prose to heading sections by
[@jdx](https://github.com/jdx) in
[#1282](#1282)
- add dynamic command catalogs by [@jdx](https://github.com/jdx) in
[#1275](#1275)

### 🐛 Bug Fixes

- **(completion)** handle attached values and emit built-ins by
[@jdx](https://github.com/jdx) in
[#1277](#1277)
- **(derive)** preserve flattened command metadata by
[@jdx](https://github.com/jdx) in
[#1268](#1268)
- **(derive)** skip choice checks for typed defaults by
[@jdx](https://github.com/jdx) in
[#1269](#1269)
- **(derive)** suppress generated partial field lint by
[@jdx](https://github.com/jdx) in
[#1278](#1278)
- **(derive)** keep an invalid choice after an override displaces the
flag by [@jdx](https://github.com/jdx) in
[#1286](#1286)
- **(spec)** make the two KDL writers agree on three more nodes by
[@jdx](https://github.com/jdx) in
[#1289](#1289)

### 🚜 Refactor

- **(deps)** replace versions with semver by
[@jdx](https://github.com/jdx) in
[#1285](#1285)

### ⚡ Performance

- **(argv)** reduce sort code size by [@jdx](https://github.com/jdx) in
[#1264](#1264)
- **(markdown)** skip empty admonition context by
[@jdx](https://github.com/jdx) in
[#1279](#1279)
- document usage-rs parser tradeoffs by [@jdx](https://github.com/jdx)
in [#1265](#1265)

### 🛡️ Security

- **(complete)** filter path candidates by extension by
[@jdx](https://github.com/jdx) in
[#1240](#1240)

### 🔍 Other Changes

- update usage of deprecated `str downcase` thingy in nushell by
[@TheBearodactyl](https://github.com/TheBearodactyl) in
[#1262](#1262)

### New Contributors

- @TheBearodactyl made their first contribution in
[#1262](#1262)
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Aug 24, 2026
⚠️ **CAUTION: this is a major update, indicating a breaking change!** ⚠️

This MR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [usage](https://github.com/jdx/usage) | tools | major | `5.1.0` → `6.2.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jdx/usage (usage)</summary>

### [`v6.2.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#620---2026-08-24)

[Compare Source](jdx/usage@v6.1.1...v6.2.0)

##### 🚀 Features

- **(argv)** add embedded parse outcomes by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1250](jdx/usage#1250)
- **(cli)** render inline formatting in help text by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1245](jdx/usage#1245)
- **(cli)** split grouped help template sections by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1251](jdx/usage#1251)
- **(complete)** add presentation labels to candidates by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1239](jdx/usage#1239)
- **(complete)** expose structured completion traces by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1241](jdx/usage#1241)
- **(complete)** add semantic candidate kinds by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1242](jdx/usage#1242)
- **(complete)** add Elvish runtime completions by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1243](jdx/usage#1243)
- **(derive)** let argument groups carry values by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1253](jdx/usage#1253)
- **(derive)** add typed command finalization by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1254](jdx/usage#1254)
- **(derive)** add runtime-computed defaults by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1256](jdx/usage#1256)
- **(derive)** dispatch embedded control requests by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1270](jdx/usage#1270)
- **(derive)** emit embedded\_outcome\_into for converted CLIs by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1281](jdx/usage#1281)
- **(docs)** allow overriding markdown templates by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1267](jdx/usage#1267)
- **(docs)** default to compact markdown references by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1272](jdx/usage#1272)
- **(docs)** polish compact markdown references by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1280](jdx/usage#1280)
- **(help)** expose addressable help topics by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1257](jdx/usage#1257)
- **(help)** list commands by name in one aligned column by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1284](jdx/usage#1284)
- **(help)** wrap the short help page by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1287](jdx/usage#1287)
- **(parse)** add structured diagnostic reports by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1255](jdx/usage#1255)
- **(parse)** add opt-in response files by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1259](jdx/usage#1259)
- **(parse)** preserve ordered argument groups by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1271](jdx/usage#1271)
- **(spec)** declare command outputs and exit codes by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1249](jdx/usage#1249)
- **(spec)** add surface availability metadata by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1258](jdx/usage#1258)
- **(spec)** add semantic note and warning blocks by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1273](jdx/usage#1273)
- **(spec)** add output media types by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1274](jdx/usage#1274)
- **(spec)** add help prose to heading sections by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1282](jdx/usage#1282)
- add dynamic command catalogs by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1275](jdx/usage#1275)

##### 🐛 Bug Fixes

- **(completion)** handle attached values and emit built-ins by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1277](jdx/usage#1277)
- **(derive)** preserve flattened command metadata by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1268](jdx/usage#1268)
- **(derive)** skip choice checks for typed defaults by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1269](jdx/usage#1269)
- **(derive)** suppress generated partial field lint by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1278](jdx/usage#1278)
- **(derive)** keep an invalid choice after an override displaces the flag by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1286](jdx/usage#1286)
- **(spec)** make the two KDL writers agree on three more nodes by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1289](jdx/usage#1289)

##### 🚜 Refactor

- **(deps)** replace versions with semver by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1285](jdx/usage#1285)

##### ⚡ Performance

- **(argv)** reduce sort code size by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1264](jdx/usage#1264)
- **(markdown)** skip empty admonition context by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1279](jdx/usage#1279)
- document usage-rs parser tradeoffs by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1265](jdx/usage#1265)

##### 🛡️ Security

- **(complete)** filter path candidates by extension by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1240](jdx/usage#1240)

##### 🔍 Other Changes

- update usage of deprecated `str downcase` thingy in nushell by [@&#8203;TheBearodactyl](https://github.com/TheBearodactyl) in [#&#8203;1262](jdx/usage#1262)

##### New Contributors

- [@&#8203;TheBearodactyl](https://github.com/TheBearodactyl) made their first contribution in [#&#8203;1262](jdx/usage#1262)

### [`v6.1.1`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#611---2026-08-23)

[Compare Source](jdx/usage@v6.1.0...v6.1.1)

##### 🐛 Bug Fixes

- **(argv)** simplify generated completion headers by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1226](jdx/usage#1226)
- **(argv)** plan for the target platform, not the host by [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562) in [#&#8203;1233](jdx/usage#1233)
- **(complete)** keep the path separator the caller typed by [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562) in [#&#8203;1230](jdx/usage#1230)
- **(config)** report config paths without the verbatim prefix by [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562) in [#&#8203;1232](jdx/usage#1232)
- **(docs)** separate visible flag aliases by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1228](jdx/usage#1228)
- **(test)** compile the platform-conditional fixtures warning-free on windows by [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562) in [#&#8203;1234](jdx/usage#1234)

##### ⚡ Performance

- **(derive)** outline invalid-value error construction from generated builds by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1235](jdx/usage#1235)
- **(derive)** share the repeated-value collection loop across fields by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1236](jdx/usage#1236)

##### 🧪 Testing

- **(windows)** let the suite run where zsh, fish and bash-completion are not by [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562) in [#&#8203;1229](jdx/usage#1229)

### [`v6.1.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#610---2026-08-22)

[Compare Source](jdx/usage@v6.0.0...v6.1.0)

##### 🚀 Features

- **(cli)** read settings under a prefix mise does not strip by [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562) in [#&#8203;1213](jdx/usage#1213)
- **(derive)** dispatch more of the matches CLIs already write by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1221](jdx/usage#1221)
- **(spec)** apply runtime identity and flatten headings in help by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1220](jdx/usage#1220)

##### 🐛 Bug Fixes

- **(derive)** flow long help and emit kdl raw multiline strings by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1215](jdx/usage#1215)

##### 📚 Documentation

- **(rust)** drop the restated one-declaration line from the intro by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1211](jdx/usage#1211)
- **(spec)** complete KDL reference by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1214](jdx/usage#1214)

### [`v6.0.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#600---2026-08-22)

[Compare Source](jdx/usage@v5.1.0...v6.0.0)

##### 🚀 Features

- **(argv)** add a zero-allocation argv parser by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;798](jdx/usage#798)
- **(argv)** emit a usage spec from static metadata by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;801](jdx/usage#801)
- **(argv)** a bound stops a variadic by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;826](jdx/usage#826)
- **(argv)** route a word that names nothing to the default subcommand by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;848](jdx/usage#848)
- **(argv)** join static tables at compile time by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;851](jdx/usage#851)
- **(argv)** render the usage line, byte-identical to usage-lib's by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;854](jdx/usage#854)
- **(argv)** render `-h`, byte-identical to usage-lib's by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;860](jdx/usage#860)
- **(argv)** render `--help` too, byte-identical to usage-lib's by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;866](jdx/usage#866)
- **(argv)** answer `--help` and `-h` by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;870](jdx/usage#870)
- **(argv)** answer the `help` subcommand by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;872](jdx/usage#872)
- **(argv)** split a command line the way the shell that typed it would by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;874](jdx/usage#874)
- **(argv)** read the cursor's position off a real parse by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;876](jdx/usage#876)
- **(argv)** offer what the reference offers, from compiled tables by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;877](jdx/usage#877)
- **(argv)** generate the shell script each shell wants by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;887](jdx/usage#887)
- **(argv)** let a Rust function answer for a value by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;888](jdx/usage#888)
- **(argv)** write the `run=` a declared completer answers by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;890](jdx/usage#890)
- **(argv)** say what went wrong the way clap says it by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;895](jdx/usage#895)
- **(argv)** suggest what was probably meant by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;897](jdx/usage#897)
- **(argv)** answer `--version`, which an adopter loses on the way from clap by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;909](jdx/usage#909)
- **(argv)** a flag whose value may be left off by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;969](jdx/usage#969)
- **(argv)** take flag-like detached values when declared by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1012](jdx/usage#1012)
- **(bench)** count what a parse allocates, and stop allocating for commands nobody ran by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;829](jdx/usage#829)
- **(cli)** hold a spec's declaration order, the way clap-sort holds a clap CLI's by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;915](jdx/usage#915)
- **(cli)** parse usage's own command line with the parser usage ships by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;965](jdx/usage#965)
- **(cli)** support long version text by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1120](jdx/usage#1120)
- **(cli)** check that examples still parse, and let the derive declare them by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1168](jdx/usage#1168)
- **(cli)** add usage explain by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1179](jdx/usage#1179)
- **(cli)** add usage diff for spec compatibility checking by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1171](jdx/usage#1171)
- **(complete)** complete config keys and values from the spec by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;840](jdx/usage#840)
- **(complete)** add async runtime overlays by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1060](jdx/usage#1060)
- **(complete)** support command value hints by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1081](jdx/usage#1081)
- **(complete)** add shell quoting filter by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1114](jdx/usage#1114)
- **(complete)** support full value hint vocabulary by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1119](jdx/usage#1119)
- **(complete)** expand partial path segments by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1128](jdx/usage#1128)
- **(complete)** support shell alias registration by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1158](jdx/usage#1158)
- **(complete)** **breaking** remove the vendored bash-completion copy by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1176](jdx/usage#1176)
- **(complete)** install a completion script where its shell looks for it by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1188](jdx/usage#1188)
- **(config)** read config files as a layer by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;856](jdx/usage#856)
- **(config)** explain why a setting has the value it has by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;857](jdx/usage#857)
- **(config)** read a resolution as the types a struct holds by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;862](jdx/usage#862)
- **(config)** generate the settings registry from the spec by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;864](jdx/usage#864)
- **(config)** generate the settings struct a CLI reads by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;865](jdx/usage#865)
- **(config)** hold a value to the choices its setting declares by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;868](jdx/usage#868)
- **(config)** carry a setting's choices into the generated registry by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;869](jdx/usage#869)
- **(config)** say what sort of thing each warning is by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;873](jdx/usage#873)
- **(config)** carry the flags a setting declares into its registry by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;880](jdx/usage#880)
- **(config)** read the command line as a layer by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;881](jdx/usage#881)
- **(config)** compare the flags a spec declares with the flags a CLI binds by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;884](jdx/usage#884)
- **(config)** support optional props and aliases by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1134](jdx/usage#1134)
- **(config)** read YAML config files by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1192](jdx/usage#1192)
- **(config)** ask for provenance by key, like a value by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1195](jdx/usage#1195)
- **(config)** a read that keeps every setting that reads by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1196](jdx/usage#1196)
- **(config)** close Config derive and spec authoring gaps by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1202](jdx/usage#1202)
- **(config)** gate deprecated settings by explicit CLI version by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1201](jdx/usage#1201)
- **(derive)** compile a struct into parse tables and a spec by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;803](jdx/usage#803)
- **(derive)** compile subcommands from an enum by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;816](jdx/usage#816)
- **(derive)** check what a parse cannot decide on its own by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;817](jdx/usage#817)
- **(derive)** nest commands to any depth by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;818](jdx/usage#818)
- **(derive)** declare which flags conflict and which require each other by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;820](jdx/usage#820)
- **(derive)** let a flag displace another, the last one given winning by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;821](jdx/usage#821)
- **(derive)** let a command answer to more than one name by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;827](jdx/usage#827)
- **(derive)** let a variant hold its command in a `Box` by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;828](jdx/usage#828)
- **(derive)** let a field be the type it means by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;833](jdx/usage#833)
- **(derive)** declare the words a value may be by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;838](jdx/usage#838)
- **(derive)** hold the bytes a word arrived as by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;841](jdx/usage#841)
- **(derive)** declare the properties mise patches in by hand by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;842](jdx/usage#842)
- **(derive)** accept a value the OS accepts and UTF-8 does not by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;844](jdx/usage#844)
- **(derive)** share declarations between commands with flatten by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;852](jdx/usage#852)
- **(derive)** say three things about a CLI the spec could and the derive could not by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;853](jdx/usage#853)
- **(derive)** answer a completion request from the binary itself by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;885](jdx/usage#885)
- **(derive)** bind a flag to a setting, from what the parser saw by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;889](jdx/usage#889)
- **(derive)** a setting can be declared wherever a flag is by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;896](jdx/usage#896)
- **(derive)** let a field name the function that completes it by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;892](jdx/usage#892)
- **(derive)** say how an argument relates to `--`, all four ways by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;900](jdx/usage#900)
- **(derive)** a default a collecting field can hold by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;902](jdx/usage#902)
- **(derive)** say what a command does to the world by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;905](jdx/usage#905)
- **(derive)** name a value the way clap names it, and say which usage can read the spec by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;907](jdx/usage#907)
- **(derive)** let `parse()` answer a failure the way a program does by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;910](jdx/usage#910)
- **(derive)** read the package's version, and be called what the binary is called by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;917](jdx/usage#917)
- **(derive)** a command that takes nothing can be written that way by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;923](jdx/usage#923)
- **(derive)** say that a command cannot be run alone, which it knew and did not write by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;937](jdx/usage#937)
- **(derive)** keep command aliases on their args by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;946](jdx/usage#946)
- **(derive)** preserve verbatim doc comments by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;949](jdx/usage#949)
- **(derive)** support path value hints by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;951](jdx/usage#951)
- **(derive)** declare a group where the flags are declared by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;934](jdx/usage#934)
- **(derive)** add value-conditional requirements by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1002](jdx/usage#1002)
- **(derive)** add skip for fields that are not arguments by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1009](jdx/usage#1009)
- **(derive)** support inline subcommand fields by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1055](jdx/usage#1055)
- **(derive)** accept runtime metadata expressions by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1056](jdx/usage#1056)
- **(derive)** accept clap value attributes by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1057](jdx/usage#1057)
- **(derive)** parse full argv with program name by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1063](jdx/usage#1063)
- **(derive)** support clap no binary name by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1064](jdx/usage#1064)
- **(derive)** support unit command structs by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1071](jdx/usage#1071)
- **(derive)** reuse args across commands by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1076](jdx/usage#1076)
- **(derive)** support runtime program identity by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1078](jdx/usage#1078)
- **(derive)** preserve value enum metadata by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1079](jdx/usage#1079)
- **(derive)** accept clap field spellings by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1086](jdx/usage#1086)
- **(derive)** preserve hidden flag aliases by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1087](jdx/usage#1087)
- **(derive)** resolve relationships through flatten by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1088](jdx/usage#1088)
- **(derive)** support flattened overrides by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1089](jdx/usage#1089)
- **(derive)** preserve flattened help headings by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1090](jdx/usage#1090)
- **(derive)** support clap casing policies by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1094](jdx/usage#1094)
- **(derive)** bind value enums directly by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1110](jdx/usage#1110)
- **(derive)** accept portable clap field spellings by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1135](jdx/usage#1135)
- **(derive)** inherit clap command metadata by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1136](jdx/usage#1136)
- **(derive)** support clap implicit groups by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1137](jdx/usage#1137)
- **(derive)** generate command dispatch by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1182](jdx/usage#1182)
- **(derive)** add usage::Config derive for settings declared in code by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1180](jdx/usage#1180)
- **(derive)** close remaining PLAN gaps for 6.x by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1197](jdx/usage#1197)
- **(docs)** support granular help visibility by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1107](jdx/usage#1107)
- **(docs)** customize subcommand presentation by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1108](jdx/usage#1108)
- **(docs)** color process-facing help by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1111](https://github.com/jdx/usage/pull/1111)
- **(docs)** support help width controls by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1113](https://github.com/jdx/usage/pull/1113)
- **(docs)** support next-line help layout by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1117](https://github.com/jdx/usage/pull/1117)
- **(docs)** support flattened subcommand help by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1118](https://github.com/jdx/usage/pull/1118)
- **(docs)** support explicit display order by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1121](https://github.com/jdx/usage/pull/1121)
- **(docs)** group subcommands under help headings by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1153](https://github.com/jdx/usage/pull/1153)
- **(docs)** add recursive help by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1132](https://github.com/jdx/usage/pull/1132)
- **(generate)** add json-schema for a CLI's config file by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;839](https://github.com/jdx/usage/pull/839)
- **(go)** emit Go parse tables from a spec, which is what Go has instead of a derive by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;931](https://github.com/jdx/usage/pull/931)
- **(go)** emit the cold table too, so generated code can apply the rules by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;959](https://github.com/jdx/usage/pull/959)
- **(go)** render the usage line, from a third table that costs nothing unused by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;964](https://github.com/jdx/usage/pull/964)
- **(go)** render a failure as something a person can act on by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;977](https://github.com/jdx/usage/pull/977)
- **(go)** generate a struct per command, and the Parse that fills them by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;990](https://github.com/jdx/usage/pull/990)
- **(go)** answer the completion request a shell sends by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1005](https://github.com/jdx/usage/pull/1005)
- **(go)** enforce value-conditional requirements by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1003](https://github.com/jdx/usage/pull/1003)
- **(help)** line the flag column up, and give the short page a column at all by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;912](https://github.com/jdx/usage/pull/912)
- **(help)** list the flags a command inherits by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;913](https://github.com/jdx/usage/pull/913)
- **(help)** list `--help` and `--version`, which every page answers by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;914](https://github.com/jdx/usage/pull/914)
- **(lib)** add usage-rs facade by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;963](https://github.com/jdx/usage/pull/963)
- **(lib)** ship usage-rs as the one-crate rust default by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1041](https://github.com/jdx/usage/pull/1041)
- **(parse)** support inferred prefixes by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1080](https://github.com/jdx/usage/pull/1080)
- **(parse)** support arg required else help by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1093](https://github.com/jdx/usage/pull/1093)
- **(parse)** add narrow token boundary controls by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1097](https://github.com/jdx/usage/pull/1097)
- **(parse)** preserve trailing delimiters by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1098](https://github.com/jdx/usage/pull/1098)
- **(parse)** add scalar repeat policy by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1102](https://github.com/jdx/usage/pull/1102)
- **(parse)** add subcommand requirement policy by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1103](https://github.com/jdx/usage/pull/1103)
- **(parse)** add argument subcommand conflicts by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1104](https://github.com/jdx/usage/pull/1104)
- **(parse)** add subcommand value precedence by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1105](https://github.com/jdx/usage/pull/1105)
- **(parse)** support missing optional positionals by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1106](https://github.com/jdx/usage/pull/1106)
- **(parse)** support optional flag values by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1109](https://github.com/jdx/usage/pull/1109)
- **(parse)** support custom help and version actions by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1123](https://github.com/jdx/usage/pull/1123)
- **(parse)** accept explicit boolean values by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1124](https://github.com/jdx/usage/pull/1124)
- **(parse)** support non-strict choices by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1127](https://github.com/jdx/usage/pull/1127)
- **(parse)** support ordered environment fallbacks by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1130](https://github.com/jdx/usage/pull/1130)
- **(parse)** warn at runtime when a deprecated declaration is used by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1186](https://github.com/jdx/usage/pull/1186)
- **(spec)** support flag relationships by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;793](https://github.com/jdx/usage/pull/793)
- **(spec)** add help\_heading, and render it by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;802](https://github.com/jdx/usage/pull/802)
- **(spec)** allow a mount at the top level by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;806](https://github.com/jdx/usage/pull/806)
- **(spec)** make unknown flags configurable, and keep them as values by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;810](https://github.com/jdx/usage/pull/810)
- **(spec)** add `conflicts` to flags by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;819](https://github.com/jdx/usage/pull/819)
- **(spec)** say that one flag needs another, which nothing here could by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;925](https://github.com/jdx/usage/pull/925)
- **(spec)** **breaking** a group, for the rule that no single flag can state by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;927](https://github.com/jdx/usage/pull/927)
- **(spec)** a flag that has to be given on its own by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;941](https://github.com/jdx/usage/pull/941)
- **(spec)** split a value the way clap splits one by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;961](https://github.com/jdx/usage/pull/961)
- **(spec)** add value-conditional requirements by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1001](https://github.com/jdx/usage/pull/1001)
- **(spec)** refuse a detached value when require\_equals is set by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1013](https://github.com/jdx/usage/pull/1013)
- **(spec)** bind a value when a flag is given with none by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1015](https://github.com/jdx/usage/pull/1015)
- **(spec)** forward unmatched words as an external subcommand by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1021](https://github.com/jdx/usage/pull/1021)
- **(spec)** bind a default when another flag is given by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1023](https://github.com/jdx/usage/pull/1023)
- **(spec)** add portable expression validation by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1037](https://github.com/jdx/usage/pull/1037)
- **(spec)** add borrowed metadata overlays by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1059](https://github.com/jdx/usage/pull/1059)
- **(spec)** omit versions from metadata views by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1066](https://github.com/jdx/usage/pull/1066)
- **(spec)** support positional conflicts and groups by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1085](https://github.com/jdx/usage/pull/1085)
- **(spec)** add fixed arity value names by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1099](https://github.com/jdx/usage/pull/1099)
- **(spec)** complete relationship families by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1100](https://github.com/jdx/usage/pull/1100)
- **(spec)** expose package metadata by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1116](https://github.com/jdx/usage/pull/1116)
- **(spec)** add deprecation milestones by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1129](https://github.com/jdx/usage/pull/1129)
- **(spec)** add executable views by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1143](https://github.com/jdx/usage/pull/1143)
- **(spec)** add deprecated config environment aliases by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1159](https://github.com/jdx/usage/pull/1159)
- **(spec)** declare source\_code\_link\_template on the derive by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1184](https://github.com/jdx/usage/pull/1184)
- **(spec)** answer **usage\_spec** from a binary's own tables by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1183](https://github.com/jdx/usage/pull/1183)
- **(spec)** reusable flag declarations with flagset and use by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1170](https://github.com/jdx/usage/pull/1170)
- **(spec)** **breaking** lower the derive's flatten into a flagset by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1172](https://github.com/jdx/usage/pull/1172)
- **(test)** a test harness for an adopter's own suite by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1181](https://github.com/jdx/usage/pull/1181)

##### 🐛 Bug Fixes

- **(argv)** stop a repeatable flag from eating a positional by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;799](https://github.com/jdx/usage/pull/799)
- **(argv)** inherit `unknown_flags`, which reached one command out of a tree by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;939](https://github.com/jdx/usage/pull/939)
- **(argv)** reject duplicate flags by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;945](https://github.com/jdx/usage/pull/945)
- **(argv)** show choices when a subcommand is required by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;947](https://github.com/jdx/usage/pull/947)
- **(argv)** a bare `-` binds where it was typed by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;986](https://github.com/jdx/usage/pull/986)
- **(argv)** put zsh's magic comment first, and print fish's candidates as data by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1033](https://github.com/jdx/usage/pull/1033)
- **(ci)** unblock releases by cutting usage-derive's dev-dependency by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;811](https://github.com/jdx/usage/pull/811)
- **(ci)** check the version the crates promise, and promise one that is true by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;918](https://github.com/jdx/usage/pull/918)
- **(clap)** say what clap would do with an unknown flag by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;899](https://github.com/jdx/usage/pull/899)
- **(cli)** recognize about as root command help by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;794](https://github.com/jdx/usage/pull/794)
- **(complete)** resolve config keys through aliases and renames by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1169](https://github.com/jdx/usage/pull/1169)
- **(config)** accept case-insensitive boolean words by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1207](https://github.com/jdx/usage/pull/1207)
- **(derive)** let a `--`-only argument follow a variadic by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;823](https://github.com/jdx/usage/pull/823)
- **(derive)** three more descriptions a spec keeps and the derive lost by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;861](https://github.com/jdx/usage/pull/861)
- **(derive)** name the mistake when `settings` has nothing to collect by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;904](https://github.com/jdx/usage/pull/904)
- **(derive)** emit the tables beside the user's types, not in a module above them by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;938](https://github.com/jdx/usage/pull/938)
- **(derive)** a global flag may be given once per command, not once per line by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;991](https://github.com/jdx/usage/pull/991)
- **(derive)** separate value metadata from parsing by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1054](https://github.com/jdx/usage/pull/1054)
- **(derive)** make defaulted fields optional in metadata by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1065](https://github.com/jdx/usage/pull/1065)
- **(derive)** isolate process exit from adopters by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1139](https://github.com/jdx/usage/pull/1139)
- **(derive)** propagate redeclared global values by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1140](https://github.com/jdx/usage/pull/1140)
- **(derive)** preserve set-false actions by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1156](https://github.com/jdx/usage/pull/1156)
- **(derive)** name the count type in standing presence checks by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1205](https://github.com/jdx/usage/pull/1205)
- **(docs)** link multi-word commands to their real source files by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;845](https://github.com/jdx/usage/pull/845)
- **(docs)** link every command to the file that implements it by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;846](https://github.com/jdx/usage/pull/846)
- **(docs)** keep hidden entries out of help by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;859](https://github.com/jdx/usage/pull/859)
- **(docs)** list visible flag aliases by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1112](https://github.com/jdx/usage/pull/1112)
- **(help)** a command's page should say what that command does by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;911](https://github.com/jdx/usage/pull/911)
- **(help)** a declared name is not a short form, and blank help is no help by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;916](https://github.com/jdx/usage/pull/916)
- **(help)** render the page for the mount the words reached by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;928](https://github.com/jdx/usage/pull/928)
- **(help)** a description ending in a break adds no blank line by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;970](https://github.com/jdx/usage/pull/970)
- **(lib)** validate every variadic fallback by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1049](https://github.com/jdx/usage/pull/1049)
- **(parse)** keep every `--` after the first by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;809](https://github.com/jdx/usage/pull/809)
- **(parse)** stop losing a flag that is missing its value by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;807](https://github.com/jdx/usage/pull/807)
- **(parse)** answer the five vectors the reference implementation was failing by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;930](https://github.com/jdx/usage/pull/930)
- **(parse)** **breaking** a command that needs a subcommand says so by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;992](https://github.com/jdx/usage/pull/992)
- **(parse)** keep optional validation lint-clean by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1141](https://github.com/jdx/usage/pull/1141)
- **(parse)** honor separator after automatic args by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1164](https://github.com/jdx/usage/pull/1164)
- **(parse)** let a bundle contain a supplied short by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1175](https://github.com/jdx/usage/pull/1175)
- **(spec)** make the config block survive being written out by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;832](https://github.com/jdx/usage/pull/832)
- **(spec)** apply default\_subcommand only at the root by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;850](https://github.com/jdx/usage/pull/850)
- **(spec)** split a clap default by the delimiter clap splits it by by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;901](https://github.com/jdx/usage/pull/901)
- **(spec)** rank a subcommand name above another command's alias by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;967](https://github.com/jdx/usage/pull/967)
- **(spec)** preserve clap value count bounds by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1032](https://github.com/jdx/usage/pull/1032)
- **(spec)** deduplicate derived completers by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1072](https://github.com/jdx/usage/pull/1072)
- **(spec)** canonicalize derived kdl by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1095](https://github.com/jdx/usage/pull/1095)

##### 🚜 Refactor

- **(deps)** **breaking** stop shipping features and crates nobody uses by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1185](https://github.com/jdx/usage/pull/1185)
- **(deps)** drop heck from usage-derive by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1187](https://github.com/jdx/usage/pull/1187)
- **(deps)** take expr-lang without the builtins a spec cannot reach by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1191](https://github.com/jdx/usage/pull/1191)

##### 📚 Documentation

- **(plan)** tick landed clap gaps and stop quoting vector counts by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1027](https://github.com/jdx/usage/pull/1027)
- correct current Rust limitations by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1029](https://github.com/jdx/usage/pull/1029)
- audit 6.x release documentation by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1084](https://github.com/jdx/usage/pull/1084)
- add third-party license notices by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1174](https://github.com/jdx/usage/pull/1174)

##### ⚡ Performance

- **(derive)** fill the partial through \&mut instead of returning it by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;980](https://github.com/jdx/usage/pull/980)
- **(derive)** hold one subcommand's partial, not every subcommand's by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;981](https://github.com/jdx/usage/pull/981)
- **(derive)** drop proc-macro-crate transitive deps by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1042](https://github.com/jdx/usage/pull/1042)

##### 🧪 Testing

- **(clap)** preserve choices in external adopter probes by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1157](https://github.com/jdx/usage/pull/1157)
- **(corpus)** pin what completes where the cursor is by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;998](https://github.com/jdx/usage/pull/998)
- **(derive)** cover verbatim doc compatibility by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1092](https://github.com/jdx/usage/pull/1092)
- **(docs)** preserve fleet footer spacing by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1142](https://github.com/jdx/usage/pull/1142)
- **(fleet)** refresh typed adopter fixtures by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1115](https://github.com/jdx/usage/pull/1115)
- **(parse)** cover mounted command discovery by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1131](https://github.com/jdx/usage/pull/1131)
- **(parse)** add clap micro-conformance by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1133](https://github.com/jdx/usage/pull/1133)
- **(spec)** import the argv questions clap's suite answers and ours did not by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;926](https://github.com/jdx/usage/pull/926)
- **(spec)** verify portable parser settings by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1053](https://github.com/jdx/usage/pull/1053)

##### 🛡️ Security

- **(config)** resolve settings from layers, with provenance by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;849](https://github.com/jdx/usage/pull/849)
- **(config)** read the environment as a layer by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;867](https://github.com/jdx/usage/pull/867)
- **(config)** give a deprecation notice from anywhere along a rename chain by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;893](https://github.com/jdx/usage/pull/893)
- **(derive)** keep parsed fields live for lints by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1138](https://github.com/jdx/usage/pull/1138)
- **(docs)** render the config block by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;837](https://github.com/jdx/usage/pull/837)
- **(go)** render the page `-h` prints, matching usage-lib on all 211 of mise's by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;974](https://github.com/jdx/usage/pull/974)
- **(go)** render `--help` too, matching usage-lib on all 211 of mise's long pages by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;975](https://github.com/jdx/usage/pull/975)
- **(parse)** require exact command and flag names by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1096](https://github.com/jdx/usage/pull/1096)
- **(spec)** the config vocabulary by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;835](https://github.com/jdx/usage/pull/835)

##### 🔍 Other Changes

- **(docs)** remove stale mise spec fixture by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;1200](https://github.com/jdx/usage/pull/1200)
- **(perf)** say when the clap ratio slides, and record why the derive is stricter by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;996](https://github.com/jdx/usage/pull/996)
- agent/complete files by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;883](https://github.com/jdx/usage/pull/883)

##### 📦️ Dependency Updates

- update rust crate syn to v3 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;808](https://github.com/jdx/usage/pull/808)
- update rust crate toml to v1 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;1016](https://github.com/jdx/usage/pull/1016)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODguMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4OC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWFqb3IiXX0=-->
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