Define your CLI once.
Usage is a toolkit for building command-line tools. Define your CLI's commands, flags, and args once in a KDL spec — get argument parsing, shell completions, --help, docs, and manpages from that one definition. Experimental reference frameworks for Rust and Go build your CLI from the spec, with Python and JavaScript planned.
Frameworks
Derive your CLI from Rust types — parsing, help, and completions generated from the usage spec. Experimental: APIs may change between releases.
Build Go CLIs on the usage spec, with parsing behavior verified against the same conformance corpus as the Rust implementation. Work in progress: APIs may change between releases.
Spec & tooling
Tab completions for bash, zsh, fish, PowerShell, and nushell, generated from the spec.
--help output, markdown docs, and manpages, all generated from the same spec.
Declare a script's interface in a USAGE comment and get arg parsing, validation, and completions.
Define your CLI once in KDL. Completions, docs, and parsers are all generated from it.
The standalone tool for generating completions, docs, and parsing from any spec file.
name "mycli"
flag "-v --verbose" help="Enable verbose output"
arg "<file>" help="File to process"
cmd "deploy" { flag "--env <env>" }Benchmarks
What parsing mise use -g node@20 costs each framework, against a shadow of mise's CLI: 211 commands, 711 flags. The usage, clap, bpaf, and cobra programs are generated from the same checked-in spec; urfave/cli and kong are still hand-measured.
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-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.
wall time, startup-adjusted process cost How this is measured Whole-process wall time with the ~950 µs startup cost of a do-nothing Go process subtracted. usage-go and cobra have generated mise-scale shadows; urfave/cli and kong are hand-measured and should be read as orders of magnitude. The subtraction makes every bar approximate.
The measured event parser walks package-level tables already laid out before main: no runtime tree construction, reflection, or heap allocation. Instructions for the same parse: ~1.6k vs cobra's 3.25M, urfave/cli's 5.6M, kong's 57.9M.
Methodology and raw numbers: go/README.md · tasks/perf-shadow.sh · time-sweep.rs