Skip to content

--usage

Build command-line interfaces and generate their documentation

Define commands, flags, arguments, and settings using the Rust framework or a portable KDL specification. Generate shell completions, reference documentation, and client libraries from that definition.

Already have a CLI? Connect your framework →

Bash · Zsh · Fish · PowerShell · Nushell

mycli.usage.kdl
bin "mycli"
cmd "deploy" help="Deploy a service" {
    arg "<service>"
    flag "--env <env>" {
        choices "staging" "production"
    }
}

Choose how to define your CLI

A new Rust CLI

Declare commands with structs and enums. Get typed parsing, help, completion, validation, and configuration support, plus a portable spec you can export.

Start the Rust quickstart →

An existing command-line tool

Export a spec from clap, Cobra, or another framework, or write KDL directly. Generate reference docs and completions while keeping your application code.

Find an integration →

A script that needs an interface

Declare arguments and flags in comments. Usage validates the input, handles --help, and passes the parsed values to your script as environment variables.

Add parsing to a script →

Generate docs, completions, and clients

The specification supplies the commands, descriptions, choices, and defaults for each generator. When your interface changes, regenerate the outputs from the updated specification.

Install the Usage CLI →

Benchmarks

Parser overhead

What parsing mise use -g node@20 costs each framework, against a shadow of mise's CLI: 211 commands, 711 flags. Every program on both cards is generated from that one checked-in spec.

usage-rs vs clap, bpaf

wall time, in-process parse throughput How this is measured Each parser runs repeatedly inside one process; process startup is excluded, so these bars are not full CLI invocation times. The chart reports the fastest per-parse time from many short rounds. Minima and their ratios drift a few percent between runs and machines, hence the ~. Instructions for one cold parse, which do not drift: 4,155 · 5.89M · 21.9M, agreeing across two machines to 0.15%.

usage-rs0.19 µs
clap480 µs· ~2,500× more
bpaf1,600 µs· ~8,200× more

usage-rs starts from compiler-emitted static tables and scans only the current command's flags plus inherited globals. clap and bpaf build a parser before they can use one Where their time goes Most of clap's is constructing and validating its command tree. bpaf's is larger because it assembles a combinator tree per run as well, which reusing the parser across parses only halves. . Heap allocations for a bare parse: zero, against clap's 6,560.

usage-go vs cobra, urfave/cli, kong

wall time, in-process parse throughput How this is measured The same way as the Rust card, by a harness written to match it: each parser runs repeatedly inside one process and the fastest per-parse time from many short rounds is reported, with the collector run between rounds rather than inside them. Process startup is excluded — a Go process is about a millisecond old before main, which no parser can touch. Whole-process cost, and instructions for one parse: go/README.md.

usage-go5.9 µs
cobra110 µs· ~18× more
urfave/cli v3200 µs· ~34× more
kong3.0 ms· ~500× more

usage-go binds against package-level tables the linker laid out before main. cobra and urfave build a command tree per process and kong reflects over a struct, none of which a spec-driven parser has to do. Instructions for the same parse: 123k vs cobra's 2.8M, urfave/cli's 5.8M, kong's 66.7M — and 1,955 for the binder under usage-go's typed front door.

Methodology and raw numbers: go/README.md · tasks/perf-shadow.sh · time-sweep.rs

MIT LicenseCopyright © 2026jdx.dev