Wrapper CLIs can now pass completion of their trailing words to the wrapped tool's own shell completion. Argument values can come from a command's output with choices run=, and scripts get the chosen subcommand as $usage_cmd. The release also fixes several completion bugs in bash, zsh and fish, and two crashes in #[derive(Cli)] binaries.
Added
-
(complete)
complete … delegate="<command>"completes a wrapped command's arguments with that command's own shell completion (#1498, @jdx). With the spec below,wrapper layer1 plan -o<Tab>offers whateverterraform plan -o<Tab>would.delegatecan carry fixed arguments (delegate="kubectl --context prod"), and it can't be combined withrunortype. It works in fish, bash (requires bash-completion) and zsh. PowerShell and Nushell get no delegated candidates. Typed words are passed to the shell as arguments, not spliced into a script, so they are never run. If the shell can't answer within 3 seconds, completion falls back to files. Fig output leaves delegated args bare.arg "<layer>" arg "<command>" var=#true complete "command" delegate="terraform"
-
(spec)
choices run="…"builds an argument's or flag's allowed values from a command that prints one value per line (#1497, @jdx). These values are used to check input (strictandignore_casestill apply), for Tab completion, and in--helphandled by the parser,usage bashandusage exec. Any values written on the node are kept alongside them. Static outputs never run the command.render_help, Markdown and man pages describe it asoutput of `…`, Fig emits a generator, and Go tables and TypeScript/Python SDK types treat the value as an open string. During a parse, the command runs at most once and only when a declared value doesn't match.Parser::with_envvalues are passed to it. New library API includesSpecChoices::run,resolved_values(env),SpecArgBuilder::choices_run,usage::docs::cli::render_runtime_helpandusage::sh::sh_with_env. Fig generator commands, from bothchoices run=andcomplete run=, now escape backslashes, backticks and${.arg "<service>" { choices run="docker compose config --services" }
-
(spec) A
completenode can now sit inside theargit completes, including a flag'sarg, or directly inside a flag as shorthand for its value (#1496, @jdx). The inline form takesrun,typeanddescriptionsbut no name. It takes precedence over a namedcomplete "<name>"for the same arg. The newSpec::completer(cmd, arg)applies this order, andcomplete-word, Fig, usage-dynamic and the Go generator all follow it.flag "--out <path>" { complete type="dir" }
-
(lib) Scripts run by
usage bash,zsh,fish,powershellandexecget the chosen subcommand's canonical name inusage_cmd, with nested names joined by spaces, such as"db migrate"(#1505, @jdx). It is unset at the top level, and ausage_cmdinherited from a parent process is cleared. If the spec declares its own flag or arg namedcmd, that one keeps the variable. The value comes fromParseOutput::as_env, so other embedders such as mise tasks get it too. -
(lib)
FlagMeta,CommandMetaandArgMetainusage-rs/usage-argvhave aconst fngetter for every field, including the fields that 6.11.1 moved intoextra(#1491, @jdx). For example,flag.env_fallback()works however the struct is laid out. The fields stay public for now, but v7 plans to hide them, so switch to the getters. -
(lib)
Parser::without_running_commands()parses without starting anychoices run=command (#1503, @jdx). A value outside the declared choices is accepted unchecked.usage explainnow uses this mode, so explaining a command line against an untrusted spec never runs that spec's commands. -
(cli) Releases now ship a version-matched
usageagent skill for writing specs, parsing script arguments, usingusage explain, and generating completions and docs (#1509, @jdx). mise users can install it withmise use usageand thenmise skills sync --dir .agents/skills.
Fixed
- (derive) A generated
Cli::parse()no longer panics when output goes to a closed pipe, for example withmycli --help | head -1or a cancelled completion (#1484, @jdx). Before,panic = "abort"builds aborted with SIGABRT. Exit statuses are unchanged. - (derive) Async dispatch generated by
#[usage(run_async)]andrun_async_withnow boxes the selected command's future (#1488, @jdx). Before, debug builds reserved stack for every command's future at each dispatch level, which could overflow the stack in large CLIs (for example,STATUS_STACK_OVERFLOWon Windows). This costs one heap allocation per dispatch level. The API is unchanged. - (derive) A renamed
usage-rsdependency inherited from[workspace.dependencies]now resolves even when an earlier entry uses a multi-line inline table (#1507, @jdx). The derive now reads manifests with a real TOML parser. - (complete) Typed completers (
#[usage(complete = my_fn)]) now receive the command line when called through a spec'srun=(#1487, @jdx).CompletionRequest::parseused to ignore--line=…and now accepts--option=valuefor every option that takes a value. - (complete) A command line that doesn't parse no longer prints an error over the prompt when you press Tab (#1495, @jdx). zsh shows the message below the prompt with
_message. bash, fish and Nushell discard it. - (bash) Values for
--flag=valuenow complete when the cursor is after the=, in both per-binary scripts and thecompletion-inithandler (#1499, @jdx). - (fish) Words you've started quoting or escaping now complete:
'prod<Tab>finds'prod env'(#1500, @jdx). Text after the cursor is no longer sent. Multi-line help no longer shows up as extra fake candidates in fish, zsh, Nushell or PowerShell. - (zsh) With
completion-init zshsourced, file completion for commands that aren't usage scripts works normally again, including in cases likeemacs --<Tab>that used to insert a literal*(#1493, @jdx). The fix applies from the next shell start. - (cli)
usage bash <(…),/dev/stdinand other pipe or FIFO script paths used to run an empty script and exit 0. usage now copies the script to a private temp directory first, for bash, zsh, fish and PowerShell (#1494, @jdx). - (lib) The published
usage-rscrate's tests now pass on their own, so downstream packagers such as Debian can test the released source (#1510, @jdx).
Changed
- All crates now use the Rust 2024 edition, and the minimum supported Rust version stays at 1.91 (#1511, @jdx). Public macros accept 2024 expression syntax such as
var_min = const { 1 }. Generated shadow crates rename reserved field names such as--gentogen_.
Upgrading
Regenerate completion scripts made with usage generate completion <shell> <bin> to get the fixes from #1495 (all shells), #1499 (bash) and #1500 (fish). If you use completion-init, just start a new shell.
Full Changelog: v6.11.1...v6.12.0
💚 Sponsor usage
usage is built and maintained by @jdx, an open source developer at entire.io, the title sponsor of his open source work.
If usage powers CLI specs, docs, or completions for a tool you maintain or use, please consider becoming an individual or company sponsor. Your support funds ongoing development and helps keep usage fast, free, and independent.