CLI tool
jdx/usage avatar
jdx/usage

Usage defines a CLI once in KDL and generates the tools around it

A specification for CLIs

1,061 stars61 forksRustMIT

At a glance

What is it?
The jdx/usage project is three things at once: a portable KDL specification for command line interfaces, a standalone CLI that turns a spec into completions, docs and man pages, and a Rust framework that derives a typed parser and an exportable spec from the same struct. Its 7.0 release moved away from reading Cargo.toml in derive macros and dropped the Fig generation command.
Who is it for?
Adopt usage if you maintain a CLI whose help text, shell completions, man pages and generated documentation have drifted apart, since the whole premise is that one definition drives all of them and the standalone CLI can adopt a spec exported from an existing parser. Do not adopt it as a replacement for clap on a mature Rust project without reading the migration guide, because the derive vocabulary is its own and the project states it is deliberately different.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One definition, four generated artefacts

The pitch is a single sentence: define your CLI once and generate the tools around it. Usage is a portable KDL specification, a command line utility and a Rust framework. You describe commands, flags, arguments and settings in one place, and that definition is then used for parsing, for help output, for shell completions, for Markdown documentation, for man pages, and for typed clients. The KDL choice is worth pausing on, because it is the piece that makes the spec portable. A spec written in the same language as the tool that generated it is tied to that tool, and a spec in a small document language with a versioned syntax can be checked in, linted and diffed on its own terms. The repository ships a conformance directory and a corpus of example spec files, which is the shape you would expect from something that treats the spec as an interchange format.

The Rust framework derives the parser and the spec together

For a new Rust CLI, the framework derives a typed parser and an exportable spec from the same declaration, so the two cannot drift. The dependency is added like any other, and the declaration uses its own derive vocabulary:

rust
use usage_rs::Cli;

#[derive(Cli)]
#[usage(bin = "example", version)]
struct App {
    /// Print more detail.
    #[usage(short = 'v', long, count)]
    verbose: u8,

    /// Files to process.
    files: Vec<String>,
}

fn main() {
    let app = App::parse();
    // app.verbose and app.files are ready to use
}

The `#[usage(...)]` attribute is applied to commands, fields and value variants, and the doc comment on a field becomes its help text, so the help output comes from the same place as the documentation. The framework can also provide completions directly from your binary, which removes the need to have the `usage` executable present when the shell asks for completions. The `usage-rs` crate is the one to depend on, currently at version 6 in the documented snippet.

Four starting points, one answer

The README includes a table of who the project is for, and it is a good summary of the design. For a new Rust CLI, you derive a typed parser and exportable spec from structs and enums. For an existing CLI, you export a spec from your framework, or write the KDL by hand. For a script, you declare the arguments in comments and let Usage parse them, which is a neat trick for a shell script that has no build system. For code that calls a CLI, you generate a TypeScript or Python SDK. The script case is the most unusual: a script with no package manifest, no type annotations and no build step can still have a machine-readable interface, which is the piece that lets an editor or an agent call it. The `argv/` and `clap_usage/` directories in the repository are where the argument parsing and the clap interoperability live.

The standalone CLI lints and generates

The tool is installed one of three ways, and the package is `usage-cli` while the executable is `usage`:

sh
# mise
mise use -g usage

# Homebrew
brew install usage

# Cargo
cargo install usage-cli --locked

With a spec saved as a `.usage.kdl` file, the commands do the work. `usage lint` checks the spec, `usage generate completion` writes a shell script for a given shell, `usage generate markdown` produces reference documentation, and `usage generate manpage` writes a roff man page:

sh
usage lint mycli.usage.kdl
usage generate completion zsh mycli --file mycli.usage.kdl --install
usage generate markdown --file mycli.usage.kdl --out-file reference.md
usage generate manpage --file mycli.usage.kdl --out-file mycli.1

The `--install` flag on the completion command installs the script into the shell's completion directory rather than printing it, which is the behaviour you want in a build script. The one caveat is that the generated shell scripts need the `usage` executable at completion time, since the script calls back into the tool to produce candidates.

7.0 removed the Cargo.toml coupling and the Fig generator

The two most recent releases are breaking changes in substance rather than in version number, and the release titles say so. v7.0.0 is titled that derive macros no longer read Cargo.toml, and that `usage generate fig` was removed. The Cargo.toml dependency is the significant one. If the derive macro read the manifest to find the package name and version, then the spec's binary name and version came from a build artifact, and the specification was therefore not self-contained. Removing that makes the spec portable in the strict sense, which is the point of the project, at the cost of a small amount of duplication that the developer maintains. The follow-up release v7.0.1 is titled as smaller usage-argv help, completion and error rendering code, which is a size reduction rather than a behaviour change. The v6.12.1 release before them is worth noting for a different reason: its title says the test suite passes with each optional feature enabled on its own, which is the kind of guarantee a library with many optional features rarely advertises.

clap is the model, and the differences are deliberate

The acknowledgements section is unusually direct about the project's lineage. Usage's design owes a great deal to clap, and clap's help output and diagnostic conventions make clap migrations familiar, while Usage's native derive attributes reflect its portable spec model. clap's licence is reproduced in NOTICE.md, and the project ships a clap migration guide listing the supported mappings and the intentional differences. That distinction between familiar and identical is the one to hold onto. Anyone moving from clap will find the output shape familiar, but the attribute vocabulary is Usage's own, and the reason it is not clap's is that the spec model requires the definition to be self-describing rather than tied to one library's types. The `clap_usage/` crate in the workspace is the bridge that makes this work in practice.

A wide workspace, and a Go framework that is not ready

The workspace lists a lot of members, and the names describe the parts: `argv`, `config`, `derive`, `usage-rs`, `usage-rs-tests`, `usage-dynamic`, `validation`, `clap_usage`, `cli`, `conformance`, `lib` and `xtask`, plus a large set of benchmark shadows under `benches/shadows/`. Those shadow crates are generated by a mise task and checked in, and they are workspace members like any other, which the manifest explains is so that the command enums in them are boxed in the same way the real mise boxes its own, so that nothing in them needs a lint silenced. The Go framework has its own directory and its own documentation page, and the README is explicit that it is a development preview and is not ready for adoption or testing. The project is MIT licensed with third party notices in NOTICE.md, and the author is Jeff Dickey.

Editorial conclusion

Adopt usage if you maintain a CLI whose help text, shell completions, man pages and generated documentation have drifted apart, since the whole premise is that one definition drives all of them and the standalone CLI can adopt a spec exported from an existing parser. Do not adopt it as a replacement for clap on a mature Rust project without reading the migration guide, because the derive vocabulary is its own and the project states it is deliberately different. Verify first which version you take, since 7.0 changed the derive macros and removed the Fig generation command, and note that the Go framework is a development preview that is not ready for adoption or testing.

Frequently asked questions

What is the jdx/usage project?

It is three things: a portable KDL specification for command line interfaces, a standalone command line utility that turns a spec into completions, documentation and man pages, and a Rust framework that derives a typed parser and an exportable spec from the same declaration.

How do I install the usage CLI?

With `mise use -g usage`, with `brew install usage`, or with `cargo install usage-cli --locked`. The package is `usage-cli` and the executable is `usage`.

What changed in usage 7.0.0?

The release title states that derive macros no longer read Cargo.toml, and that the `usage generate fig` command was removed. The follow-up v7.0.1 is titled as smaller usage-argv help, completion and error rendering code.

Can I use usage with a script that has no build system?

Yes. For a script you declare the arguments in comments and let Usage parse them, so a shell script with no package manifest can still have a machine-readable interface.

Is the usage Go framework ready to use?

No. The README states that the Go framework is a development preview and is not ready for adoption or testing.

Official sources

  1. jdx/usage on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jdx-usage.svg)](https://hysenlabs.com/projects/jdx-usage)

Was this useful?