Skip to content

The toolkit for command-line interfaces

--usage

Define your CLI once.

Commands, flags, arguments, and settings in one definition. Build a typed Rust CLI, or bring a KDL spec to generate completions, help, documentation, and client libraries.

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"
    }
}

Built around the CLI you want to ship.

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 →

Spend less time keeping things in sync.

Use the same commands, descriptions, choices, and defaults across the tools your users see. Regenerate the artifacts as your interface evolves.

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