>_ DevTrendsnl

Taal

Home

Talen

Secties

Frontend Backend Mobiel DevOps AI / ML GameDev Blockchain Embedded Beveiliging
Rust

Why Console Utilities Need Their Own OpenAPI Alternative and How the Usage Project Works

Every time I write a small console utility, the same story repeats. First you sketch out arguments and flags in code. Then you decide to add autocompletion for bash and zsh, dig into remembering shell script syntax or searching for generators. Next you need to format documentation in Markdown, update man pages, and remember to support environment variables. If the project gets rewritten in another language or gains Python or Bash wrappers, you have to manually duplicate the entire argument structure.

Developer jdx, known for the popular version manager mise, approached this routine systematically and created the Usage project.

A Contract Instead of Scattered Workarounds

The core idea behind Usage is simple: console software needs its own OpenAPI or Swagger equivalent. Instead of tying argument descriptions to a specific library in a specific language, Usage offers a single portable specification in KDL format.

KDL wasn't chosen randomly. This document language is cleaner and more readable than JSON or YAML, making it convenient for describing nested commands, flags, short aliases, and data types.

Describing your utility's interface in this format once solves several problems at once:

  • Generating autocompletion scripts for all popular command shells.
  • Automatic assembly of documentation in Markdown and man pages.
  • Parsing arguments from scripts in other languages.
  • Code scaffolding for different CLI libraries.

What It Looks Like in Rust

If you're writing in Rust, you don't have to write the KDL manifest by hand at all. The project includes a crate usage-rs that generates the spec directly from your data structure using derive macros.

Here's a basic example:

[dependencies]
usage = { package = "usage-rs", version = "6" }
use usage::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 и app.files готовы к работе
}

The runtime parser doesn't drag along heavy dependencies. At the same time, you can export a ready-made KDL specification from the same structure and use it in external build infrastructure or CI/CD pipelines.

Differences from the Familiar clap

Most Rust developers are accustomed to using clap. The author of Usage openly acknowledges this library's influence and preserved a similar output format for help messages and error reports to make the transition as painless as possible.

The difference lies in philosophy. clap is strictly oriented toward the Rust ecosystem. usage moves the interface schema to a higher level, turning it into a universal contract. You can take the spec and parse arguments in a Bash script via the CLI utility usage without rewriting your flag validation logic.

Companies like 37signals are already among the project's sponsors. This demonstrates the industry's interest in standardizing terminal interfaces.

Who the Project Is Useful for Right Now

Usage is unlikely to be needed for a one-off twenty-line script. However, the tool fits perfectly into developing complex internal company utilities, API CLI clients, and platform tools used by different teams.

If you're tired of manually synchronizing documentation with flags and writing autocompletion scripts for each shell, the project is definitely worth looking into. Documentation and migration guides are available on the official website usage.jdx.dev.

Gerelateerde projecten