Skip to content

Releases: jdx/usage

v6.10.0: Default-subcommand help pages, typed Go CLI fields, and Go help/version rendering

Choose a tag to compare

@github-actions github-actions released this 19 Sep 13:42
Immutable release. Only release title and notes can be modified.
d5f56ec

Help output can now mark and append the default subcommand's page, usage generate go can emit typed struct fields, and the Go runtime gains argv.RenderRequest plus fixes so generated parsers actually surface --help and --version. Embedders that parse spec text also get proper diagnostics, a path for relative includes, and environment-variable expansion in include paths.

Added

  • (help) Mark the default subcommand and optionally append its help page (#1424, @lu-zero). A visible default_subcommand is now listed with (default) in the command list. The new default_subcommand_help #true setting (Rust: #[usage(default_subcommand_help)]) appends the default child's own page after the parent's, so ex --help shows the default command's flags and args without hoisting them into the root grammar. Hidden defaults are neither marked nor appended, flatten_help skips the append since it already inlines every child, and usage lint reports default_subcommand_help without a default_subcommand. Supported in the Rust and Go help renderers. Fixes #1423.

    default_subcommand "install"
    default_subcommand_help #true
    cmd "install" help="Put a package on the system" {
        flag "-u --update"
        arg "[package]"
    }
  • (go) Explicitly typed fields from usage generate go (#1441, @zeitlinger). The repeatable --field-type KEY=TYPE flag binds a generated flag or argument key constant (for example FlagTimeout or FlagRunTimeout) to int, int64, uint64, float64, bool, or duration (time.Duration); variadic entries become typed slices. Conversion happens once on the final resolved value after argv/env/default precedence and validation, and invalid values return argv.CodeInvalidValue. Unknown keys, duplicate bindings, unsupported types, and valueless or count flags are rejected at generation time. Library callers get usage::go::generate_with_types and ValueType; unconfigured output is unchanged. Typed output requires the runtime from this release (argv.NativeInt).

    usage generate go -f mycli.usage.kdl -o tables.go \
      --field-type FlagTimeout=duration --field-type FlagJobs=int
  • (go) argv.RenderRequest renders help and version requests (#1439, @zeitlinger). Go applications no longer need to rebuild the command chain and pick a renderer themselves: pass the parser's CodeHelp/CodeVersion error, the help metadata, root command, and the same words given to the parser, and get back the rendered text. It handles short, long, and recursive help plus short/long version (falling back to Version when LongVersion is empty), preserves invoked aliases and shared-command ancestry, and includes inherited globals from the correct route. Output, write errors, and exit status stay with the caller; ordinary errors return ("", false).

    meta := HelpMeta
    meta.Version = buildVersion
    if text, handled := argv.RenderRequest(request, meta, Root, args, HelpText); handled {
        io.WriteString(os.Stdout, text)
    }
  • (spec) Environment variables in include paths (#1446, @jdx). Spec::parse_str_with_path_and_env accepts an environment map so include file="$CONFIG_ROOT/shared.usage.kdl" expands $NAME and ${NAME} (with $$ for a literal dollar sign) without mutating the process environment. Undefined variables return a diagnostic, nested includes inherit the same map, and relative paths still resolve from the declaring file. Expansion applies only to include paths.

  • (spec) Spec::parse_str_with_path (#1443, @jdx). Callers that extract spec text from a larger file (script comments, a rendered template) can now say which file it came from, so relative include paths resolve against it. FromStr still rejects relative includes since it has no path to resolve them against.

Fixed

  • (go) Generated Go parsers return help and version requests (#1437, @zeitlinger). Generated Parse previously ignored the built-in -h/--help and -V/--version flags, so a CLI with required arguments reported a missing argument and one without could continue into normal execution. They now become CodeHelp/CodeVersion errors that preserve the selected command and short/long spelling; declared flags that shadow the built-ins still bind normally, and disabled built-ins stay disabled. Regenerate your Go code to pick this up.
  • (go) argv.Walk keeps the full help-topic command chain (#1440, @zeitlinger). Walk(root, []string{"help", "config", "ls"}) resolved Cmd to ls but left Chain containing only the root, so the help renderers selected the wrong page and dropped the topic's ancestors. The chain now follows the actual parsed route, including through commands shared by more than one parent.
  • (help) No repeated global flags on the appended default-subcommand page (#1436, @lu-zero). With default_subcommand_help, a root flag declared global (such as --color) appeared once under the root's Flags: and again under the appended child's Global flags:. The appended page now omits its Global flags: section, in both the Rust and Go renderers.
  • (parse) Suggest -- when a refused flag could have been a value (#1430, @jdx). mise exec node --version only offered tip: a similar argument exists: '--verbose', even though exec can only take that value after --. Following clap's rule, the error now also prints tip: to pass '--version' as a value, use '-- --version' when the command takes positionals and no -- precedes the token, and either there is no close spelling match or a positional is double_dash = "required"/"automatic". Ordinary typos still get only the spelling suggestion, and nothing is offered once a -- has already been typed or when the command takes no positionals. Related to jdx/mise#13202.
  • (spec) String-parsed specs get proper diagnostics (#1443, @jdx). A spec parsed via str::parse::<Spec>() had no source text attached, so errors like unsupported flag key bogus_key rendered a caret under a blank line at 1:1. The diagnostic now points at the offending line and column, which is what embedders such as mise show for a task's usage field.
  • (spec) Include resolution is logged at debug instead of info (#1444, @jdx). It was the library's only info! call, so embedders whose loggers show info by default (mise, for every task run using a shared .usage.kdl) printed an include: /path/... line on every invocation.

New Contributors

Full Changelog: v6.9.1...v6.10.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.

v6.9.1: Default-only flags commit to the default subcommand, and large KDL specs parse about 4x faster

Choose a tag to compare

@github-actions github-actions released this 14 Sep 11:26
Immutable release. Only release title and notes can be modified.
3a68495

A default-only flag now commits the rest of the line to the default subcommand even when a later word spells a sibling command, and the KDL parser scans strings in chunks so large generated specs load several times faster. The Go modules now require Go 1.26.

Fixed

  • (parse) Keep the implicit default after a default-only flag (#1418, @lu-zero). With default_subcommand_flags, the lookahead cancelled default routing whenever any later word matched a sibling command or alias, so em -u pkg failed with UnknownFlag -u just because pkg is also a command. Once a default-only flag has been seen, later words are now the default command's arguments: em -u query parses as em install -u query, as do em -X foo query, em -pu query, and --output query search. A sibling name before any default-only flag still selects it (em query, em -p query), and parent-only flags, --help, and bare invocations stay on the parent. Applied consistently to the Rust library, usage-argv, and the Go runtime; fixes #1417.

Changed

  • (parse) Faster KDL parsing for large specs (#1426, @jdx). Identifier, quoted-string, and raw-string runs are scanned as contiguous slices instead of one Unicode scalar at a time, with escapes, delimiters, newlines, and dedent handling preserved at the boundaries. Parsing the checked-in mise spec drops from 66.9 ms to 16.2 ms in an optimized build, and from roughly 800 ms to 250 ms in a debug build of mise's 321 KB generated spec. Parsed output is unchanged; a regression test covers embedded quotes in multiline raw strings.
  • (go) The github.com/jdx/usage/go and integrations/cobra modules now declare go 1.26.0 (#1421, @sahidvelji). Projects importing the Go runtime or the Cobra integration need Go 1.26 or newer; expr-lang/expr is now listed as a direct dependency of the runtime module. No behavior changes.
  • (go) usage generate go emits type X struct{} for a command with no flags, arguments, or subcommands instead of an empty two-line struct body, matching gofumpt output (#1425, @sahidvelji). Regenerating existing code will show this whitespace-only diff.

New Contributors

Full Changelog: v6.9.0...v6.9.1

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

v6.9.0: Default-subcommand flag routing, standalone Args parsing, and smaller help builds

Choose a tag to compare

@github-actions github-actions released this 12 Sep 15:11
Immutable release. Only release title and notes can be modified.
9e65ac0

Flags belonging to a default subcommand can now select it without typing its name, a derived Args type can be parsed on its own, help colours can be remapped, and a series of help-rendering changes trims binary size for usage-rs adopters. Bash completion also stops mangling colon-separated candidates.

Added

  • (parse) Opt-in default-subcommand flag routing (#1413, @jdx). With default_subcommand_flags, leading flags that belong only to the configured default subcommand route to it, so em -ua @world parses as em install -ua @world. Explicit command names and aliases still win, parent-only flags and bare invocations stay on the parent, a mixed short bundle such as -pua keeps the parent's -p, and -- or an unknown flag stops the lookahead. Completion also offers the default command's flags at the root. Supported in KDL specs, the Rust derive, and the Go runtime; existing routing is unchanged without the opt-in. usage lint reports default_subcommand_flags declared without a default_subcommand.

    default_subcommand "install"
    default_subcommand_flags #true
    #[usage(default_subcommand = "install", default_subcommand_flags)]
  • (parse) Parse a derived Args type without an enclosing CLI (#1419, @jdx). usage::parse_args_from::<T> treats the slice as that command's words; usage::parse_args_from_argv::<T> strips argv0 first. Both reuse the command's compiled flags, positionals, defaults, validation, and nested subcommands, and return the ordinary parse errors, including help and version requests. Available behind the spec feature.

    let install = usage::parse_args_from::<Install>(&args)?;
  • (help) Remap semantic help colours with a Palette (#1414, @lu-zero). The heading, option, metavar, and command roles were previously fixed SGR colours. help::Palette remaps any of them using the existing {$…} tag vocabulary (for example "cyan+bold"), and Style::palette applies it; role names expand once, so mapping metavar to "heading" uses the built-in heading colour. Hosts that own the exit path get embedded_outcome_paletted / embedded_outcome_into_paletted (and embedded::outcome_paletted); parse() and plain rendering are unchanged.

    let palette = usage::help::Palette::DEFAULT.metavar("cyan+bold");
    match Ex::embedded_outcome_paletted(&argv, palette) { /* … */ }

Changed

  • (cli) Smaller binaries and faster help rendering (#1396, #1399, #1400, #1401, @jdx). Help sorting and rendering do less work and share more code, plain (uncoloured) help skips colour-span analysis, and the flag diagnostics share one formatter. Help output is byte-identical; on the oxc binaries used for measurement this removed roughly 360 KiB combined, and plain --help rendered about 18% faster locally. Two new opt-ins let CLIs trim further:

    • Flattened subcommand pages, HelpAll, and recursive render_all now live behind a help-advanced feature (enabled by default in usage-rs and usage-argv). A CLI that uses none of them can disable defaults and omit it:

      usage = { package = "usage-rs", version = "6", default-features = false, features = ["help", "diagnostics", "completions"] }
    • #[usage(spec_endpoint_file = "cli.usage.kdl")] answers __usage_spec__ from a KDL file included at compile time, keeping the endpoint without linking the runtime serializer. to_kdl() still generates from live metadata, so regenerate the file after CLI changes and test the two for drift.

    Compatibility note: dependents that already set default-features = false and declare flatten_help or a HelpAll flag must add help-advanced; the derive now rejects those declarations at compile time, and hand-written metadata requesting advanced help panics when rendered instead of being silently ignored.

Fixed

  • (bash) Preserve colon-prefixed completion words (#1405, @jdx). When : is in COMP_WORDBREAKS, Readline replaces only the fragment after the last colon, so candidates such as update:deps:no-cooldown were inserted with a duplicated update:deps: prefix. The generated Bash script now forwards the current Readline word and COMP_WORDBREAKS to the __complete_word__ request, and the binary reports the prefix Readline keeps so the script can trim it; escaped colons, consecutive colons, and a cursor on a colon are handled. Path candidates are unaffected. Regenerate Bash completion scripts to pick up the fix (reported in jdx/mise#12970).

New Contributors

Full Changelog: v6.8.0...v6.9.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.

v6.8.0: Native completions and sharper docs output

Choose a tag to compare

@github-actions github-actions released this 06 Sep 17:46
Immutable release. Only release title and notes can be modified.
592aef0

This release gives the usage CLI native shell completions (including PowerShell), adds a configurable link extension for Markdown docs, and fixes a batch of synopsis and Markdown rendering issues across docs and man pages.

Added

  • (cli) Native shell completions (#1388, @jdx). usage --completions <shell> now emits native scripts that call the installed binary's compiled completion handler instead of caching a spec and relying on the bash-completion helpers. Bash, Zsh, Fish, and a new PowerShell script are all supported, and scripts use command usage so a shell function or alias can no longer shadow the executable. All four scripts are published alongside the CLI spec as signed Packslip resources. General usage generate completion behavior is unchanged.

  • (docs) Configurable Markdown link extension (#1394, @jdx). Generated Markdown links previously always ended in .md, forcing consumers who serve HTML or extensionless pages to rewrite links after generation. A new --link-extension flag (and MarkdownRenderer::with_link_extension, default .md) controls the suffix on command and configuration links without changing output filenames:

    usage generate markdown --file mycli.usage.kdl --link-extension .html
    

    Custom templates now also receive link_extension and config_link in their context.

Fixed

  • (docs) Render optional subcommands and mount synopses (#1393, @jdx). Generated synopses showed <SUBCOMMAND> even when a command could run without one; the shared usage string now honors subcommand_required (using [SUBCOMMAND] when optional) and custom placeholder names, keeping terminal help, Markdown, man pages, JSON, and SDK docs consistent. Unresolved mounts can also declare a display-only synopsis (for example mount run="mycli tasks --usage" synopsis="[TASK] [ARGS]…") to document dynamic arguments without running discovery; parsing and completion are unchanged.
  • (docs) Preserve Markdown code blocks and headings (#1392, @jdx). Indented help text was converted to code fences by stripping four spaces from every matching line, which could corrupt nested lists and existing fenced examples. Markdown code-block boundaries are now parsed so only real indented code blocks are converted, fences are chosen longer than any embedded backtick runs, and HTML escaping recognizes longer fences. Hidden subcommands are now filtered out before the Subcommands heading, and the duplicate synopsis line was removed from the multipage index.
  • (manpage) Render mount synopses and custom command names (#1395, @jdx). Completes the man-page side of the synopsis fixes above. The man-page renderer now carries declarative mount synopses and custom subcommand names into its own synopsis (instead of hard-coded <COMMAND>/[COMMAND]), includes mount fragments in root and subcommand synopses without running discovery, and emits a detail section for a command whose only documentation is a mount synopsis.

Changed

  • (docs) Refreshed guides, navigation, and landing page (#1391, @jdx). A new getting-started guide walks from install through KDL, lint/explain, docs/man, completions, and diff. Navigation is reorganized into guides, framework docs, and references with route-specific sidebars; the landing page is simplified with clearer starting points for Rust apps, existing CLIs, and scripts. Installation commands, Rust and SDK examples, and completion setup were corrected, Go is now labeled a development preview, and broken links across all 171 Markdown files were fixed.

Full Changelog: v6.7.1...v6.8.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.

v6.7.1: macOS Release Build Fix

Choose a tag to compare

@github-actions github-actions released this 05 Sep 20:37
Immutable release. Only release title and notes can be modified.
cb49eec

This is a small maintenance release with no user-facing changes. It fixes the release automation and macOS build pipeline so that v6.7.1 could be published; there are no library, CLI behavior, or output changes for end users.

Changed

  • (release) Bypass mbx for universal macOS release builds (#1385, @jdx). The universal macOS build failed because mbx 1.8.1 rejects Cargo invocations that pass both Apple architecture targets at once. MBX_DISABLE is now set for the universal target so Cargo runs directly; other release targets are unaffected.
  • (release) Allow empty commits to trigger release PRs (#1386, @jdx). Release automation no longer restricts git-cliff to crate paths, so version bumps and changelog entries now account for all qualifying commits in the release range, including workflow-only fixes.

Full Changelog: v6.7.0...v6.7.1

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

v6.7.0: Semantic command styling and sharper CLI docs

Choose a tag to compare

@github-actions github-actions released this 05 Sep 20:37
Immutable release. Only release title and notes can be modified.
edabe42

This release adds a new semantic style for subcommand names in help output, fixes several help and parsing edge cases, and notarizes the macOS binary so browser downloads pass Gatekeeper.

Added

  • (help) Semantic command styling (#1375, @jdx). Colored help now highlights subcommand names and the built-in help row with a new command semantic style (bold green by default), matching the palette family used for options. Plain output is unchanged, so stripping ANSI still yields byte-identical pages. The {$command}…{/$} tag is now recognized across the derive, KDL, Go, and shared help-template vocabularies alongside heading, option, and metavar.

Fixed

  • (cli) Show help for a bare exec command (#1361, @jdx). usage exec --help (and the x alias, with -h or --help) now prints the exec command page instead of failing with a missing <COMMAND> error. Fully specified invocations like usage exec <COMMAND> <BIN> --help still route help to the wrapped script as before.
  • (parse) Report the next implicit clause argument (#1372, @3w36zj6). When a partial parse of a bare command with an implicit clause stopped, the parser incorrectly returned no next argument, so completion could not offer that argument's choices or invoke its custom completer. The stopping position is now resolved through the active argument set, restoring completions for clause commands.
  • (docs) Make --indented-blocks-to-code-fences work on single-file markdown (#1367, @jdx). The flag that converts four-space indented blocks into code fences was a no-op for single-file usage generate markdown output because the model was rendered before the option was applied; it now takes effect. The flag was also renamed from the misleading --replace-pre-with-code-fences (kept as a hidden alias for compatibility).

Changed

  • (docs) Rewrote CLI help text and guide pages (#1364, @jdx). Since help text is the source for reference pages, man pages, and completions, this corrects and expands it: --usage-cmd no longer documents a nonexistent default, <SCRIPT> and --shell now have help, per-shell commands explain that -h/--help print the wrapped script's page, and commands like lint, mcp, generate completion, and the root command gained long help. The CLI guide pages were rewritten around task-to-command tables. Adopters with snapshot tests over usage's help output will see diffs.
  • (release) Notarize the macOS binary (#1378, @jdx). Release macOS binaries are now signed with the hardened runtime and submitted to Apple's notary service, so archives downloaded through a browser no longer hit the "cannot be verified" Gatekeeper dialog.

New Contributors

Full Changelog: v6.6.1...v6.7.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.

v6.6.1: Cleaner plain help and smarter flag completion

Choose a tag to compare

@github-actions github-actions released this 01 Sep 17:05
Immutable release. Only release title and notes can be modified.
4dc3ffb

A small bugfix release focused on help rendering and shell completion. Plain help output no longer leaks embedded ANSI escapes, root-only help metadata stays on the root page, and completion now handles attached --flag=value syntax.

Fixed

  • (complete) Complete attached long flag values (#1349, @nfvelten). Completions now work for inline long-option syntax like --flag=value: the fragment after = is used to narrow suggested values, the full --flag= prefix is reattached to each candidate (since shells replace the whole word), and file-path fallback still applies when a flag has no explicit choices. Fixes #999.
  • (docs) Strip authored ANSI from plain help (#1357, @jdx). Style::PLAIN now removes ANSI CSI/SGR sequences that were already baked into command metadata (common when migrating from clap's color_print::cstr! help), keeping plain terminal help and generated Markdown escape-free while colored output is unchanged.
  • (help) Keep root help on the root page (#1358, @jdx). Before/after help, examples, author, and license are now command-local instead of falling back to the root spec. Root-specific material no longer appears on unrelated leaf commands (e.g. mise self-update --help), aligning with clap's command-local help behavior. Applied consistently across the Rust renderer, documentation templates, and the Go renderer.

New Contributors

Full Changelog: v6.6.0...v6.6.1

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

v6.6.0: Scoped flags and implicit clauses

Choose a tag to compare

@github-actions github-actions released this 30 Aug 21:38
Immutable release. Only release title and notes can be modified.
9732c63

This small release extends the repeatable clause groups introduced in v6.5.0 with per-instance scoped flags and separator-free (implicit) clauses, and completes their integration across the compiled parser, portable KDL, help, completions, and generated documentation.

Added

  • Scoped flags and implicit clauses. Clauses can now carry flag nodes that are scoped to a single repeatable instance and reset at each boundary. The separator is now optional: when omitted, a clause with exactly one required, non-variadic positional ends each instance implicitly as soon as that terminal positional is consumed. Scoped flags precede and apply to the next terminal positional, and the parser rejects ambiguous implicit layouts, conflicting flag spellings, duplicate scalar flags within an instance, and trailing scoped flags that never complete an instance. Threaded through the interpreted parser, the compiled argv parser, Rust derive, portable KDL emission, help/completion, usage diff, and the generated Go bindings (#1343, @jdx). Requires min_usage_version "6.6".

    clause "tools" {
      flag "--postinstall <COMMAND>"
      arg "<tool>"
    }

    use --postinstall A a --postinstall B b produces two tools instances: postinstall="A", tool="a" and postinstall="B", tool="b". In Rust derive, omit separator and place the scoped fields on the nested Args type.

Fixed

  • Complete implicit clause integration (#1345, @jdx):
    • Command-level relationships (requires, conflicts, etc.) can now target arguments inside typed clauses in the compiled parser, so e.g. --force can require a clause's terminal positional.
    • Portable KDL now emits spec-facing argument names (e.g. TOOL, --postinstall) for clause relationship fields instead of Rust field selectors, keeping reference-parser round-trips valid.
    • Repeated clauses are now rendered as optional groups (wrapped in […]) in compiled help, manpage synopsis, and Markdown, and clause-scoped flags and arguments now appear in generated documentation. Empty clauses no longer fail to render.

Full Changelog: v6.5.0...v6.6.0

💚 Sponsor usage

usage is maintained by @jdx, an open source developer for entire.io, the title sponsor of the jdx.dev open source tools including mise, aube, hk, and more. Work on usage is funded by sponsorships.

If usage powers CLI specs, docs, or completions for a tool you maintain or use, please consider sponsoring at jdx.dev. Every sponsorship helps the project stay independent and moving.

v6.5.0: Sigils, clauses, and Cobra examples

Choose a tag to compare

@github-actions github-actions released this 28 Aug 15:10
Immutable release. Only release title and notes can be modified.
853d8db

This release introduces two new positional-argument primitives — sigil-classified arguments and repeatable clause groups — plus support for Cobra's Example field when generating specs, and a zsh completion fix for aliases.

Added

  • Sigil-classified positional arguments. Positionals can now be declared with a leading sigil prefix so they are matched by that prefix rather than by slot order. The prefix is treated as syntax and stripped before the value is stored, validated, or completed, and a sigil argument never advances the ordinary positional cursor — so classified values can interleave with flags and normal positionals. Completion, canonical KDL, argv tables, derive metadata, the Python/TypeScript SDKs, and the conformance corpus all carry sigils through the same contract, and tab completion strips/restores the prefix on every candidate (#1322, #1319, @jdx). Requires min_usage_version "6.5".

    arg "[tool]..." sigil="+" {
      choices "node@22" "node@24" "python@3.14"
    }
    arg "<command>"
    arg "[args]..."

    With that spec, ex +node@24 node -v binds tool=["node@24"], command="node", and args=["-v"]. In Rust derive, annotate the field with #[usage(sigil = "+")].

  • Repeatable clause groups. A command can declare one separator-delimited group of positionals that repeats: each separator ends the current instance and starts a new one instead of overwriting it, and every instance is stored independently in parse output. Flag and positional state reset at each boundary, an explicit -- protects a literal separator, and completion treats the separator like a restart. Clauses are wired through the interpreted parser, the zero-allocation compiled argv parser, Rust derive (#[usage(clause, separator = "…")] on Vec<T>), the Go parser, and usage diff (which reports clause add/remove/separator changes as breaking) (#1321, #1320, @jdx). Requires min_usage_version "6.6".

    clause "tasks" separator=":::" {
      arg "<task>"
      arg "[args]..." var=#true double_dash="automatic"
    }

    run lint --fix ::: test --all produces two tasks instances: task="lint", args=["--fix"] and task="test", args=["--all"].

  • Cobra Example field support. Specs generated with --usage-spec now include Cobra's Example text as example nodes — a root command's example becomes a top-level node, and a subcommand's becomes a child of its cmd block. The conventional two-space indent is stripped while multiline formatting and comment lines are preserved (#1333, @thecodesmith).

Fixed

  • (zsh) Command-position aliases are now expanded before the line is sent to the completion binary, so completions work for aliases that add arguments (e.g. gfin="mise run git:finish-branch"). Recursive and cyclic aliases are handled safely (#1330, @halms).

Changed

  • The Rust framework (usage-rs) documentation and site no longer carry the experimental label; usage-cli itself is built with it. The separate usage-dynamic crate remains marked experimental, and Go remains a work in progress (#1334, @jdx).

New Contributors

Full Changelog: v6.4.1...v6.5.0

💚 Sponsor usage

usage is maintained by @jdx, an open source developer for entire.io, the title sponsor of the jdx.dev open source tools including mise, aube, hk, and more. Work on usage is funded by sponsorships.

If usage powers CLI specs, docs, or completions for a tool you maintain or use, please consider sponsoring at jdx.dev. Every sponsorship helps the project stay independent and moving.

v6.4.1: Colorful Help and Sharper Negative-Value Parsing

Choose a tag to compare

@github-actions github-actions released this 26 Aug 03:12
Immutable release. Only release title and notes can be modified.
59b5da7

A focused patch release that adds terminal-aware color to interpreted help output, tightens how negative numbers are parsed as flag values, and lowers the published crates' minimum supported Rust version.

Added

  • Colorized help output. The usage CLI, usage bash, and usage exec now render interpreted help with terminal-aware semantic styling (headings, options, metavars, inline markdown, and help_template {$…} tags). Coloring is auto-detected from the terminal and honors NO_COLOR and CLICOLOR_FORCE; plain rendering remains available for snapshots and generated artifacts (#1309, @jdx).

Fixed

  • More predictable negative-value parsing. Tokens like -1 are only consumed as a detached flag value when allow_negative_numbers is set or when the flag's value is truly required (no default_missing, not optional). This keeps optional and default_missing flags from swallowing negative numbers during subcommand and external_subcommand discovery, while required flags and explicit opt-ins still bind them correctly. Missing-value errors are also now reported for the awaiting flag even when another recognized option follows (#1317, #1318, @jdx).
  • Hidden commands excluded from Markdown docs. Single-file Markdown reference generation no longer emits sections for commands marked hide=#true, matching the existing index and flag/arg filtering (#1315, @jdx).
  • Simplified the required_unless predicate logic for arguments and flags with no change in behavior (#1326, @jdx).

Changed

  • Lowered MSRV to Rust 1.91. The published usage-lib, usage-dynamic, clap_usage, and usage-cli crates now build on Rust 1.91 (down from 1.95), letting usage-cli install on runner images that ship Rust 1.94 (#1314, @jdx).

Dependency Updates

Full Changelog: v6.4.0...v6.4.1

💚 Sponsor usage

usage is maintained by @jdx, an open source developer for entire.io, the title sponsor of the jdx.dev open source tools including mise, aube, hk, and more. Work on usage is funded by sponsorships.

If usage powers CLI specs, docs, or completions for a tool you maintain or use, please consider sponsoring at jdx.dev. Every sponsorship helps the project stay independent and moving.