USAGE(1)
πΈ USAGE(1) πΈ
okay so this is usage(1) straight out of the General Commands Manual, and bestie, she does a LOT. π
β¨ NAME β¨
usage β generates completions, docs, manpages, and SDKs from a usage spec, and runs scripts that carry one. that's the whole vibe. π¦
β¨ SYNOPSIS β¨
usage <COMMAND>
usage --completions <COMPLETIONS>
usage --usage-spec
β¨ DESCRIPTION β¨
so what does usage actually do? it generates completions, docs, manpages, and SDKs from a usage spec, and it runs scripts that carry one. iconic, we know. π
a usage spec describes a CLI's commands, flags, and arguments once, in KDL. like, write it down one time and never again, periodt. most commands here read one, and it can come from:
- a
.usage.kdlfile, handed over with-f - a script whose
#USAGEcomments declare it -for stdin
and here's the slay part β¨ β a binary built with the Rust framework prints its own spec, so a pipeline like mycli __usage_spec__ | usage generate markdown -f - needs no file at all. no cap.
π guides + a reference for every command live at https://usage.jdx.dev/cli/ β go read them, iykyk.
β¨ OPTIONS β¨
--completions <COMPLETIONS>β prints a completion script for theusageCLI itself, for the named shell. yes,usagecompletesusage. main character energy. π--usage-specβ prints the usage spec for theusageCLI itself-h,--helpβ print help-V,--versionβ print version
β¨ COMMANDS β¨
bashβ run a script whose usage spec is written in its own comments πcomplete-wordβ generate shell completion candidates for a partial command line. aliases:cwdiffβ compare two usage specs and report what changed about the interfaceexecβ run a script through any interpreter, with its parsed arguments as environment variables. aliases:xexplainβ explain what a command line binds tofishβ run a script whose usage spec is written in its own comments πgenerateβ generate completions, docs, manpages, SDKs, and parse tables from a usage spec. aliases:ggenerate completionβ generate a shell completion script forbash,fish,nu,powershell, orzsh. aliases:cgenerate completion-initβ generate a shell init script that completes every usage-shebang script onPATH. aliases:cigenerate goβ generate Go parse tables from a usage specgenerate jsonβ print a usage spec as JSONgenerate json-schemaβ generate a JSON Schema for a CLI's config file from its usage specgenerate manpageβ generate a manpage from a usage spec. aliases:mangenerate markdownβ generate Markdown documentation from a usage spec. aliases:mdgenerate sdkβ generate a type-safe SDK from a usage speclintβ lint a usage spec for mistakes that still parse πmcpβ serve a usage spec over the Model Context Protocol. aliases:mcp-serverpowershellβ run a script whose usage spec is written in its own commentssponsorsβ show the companies sponsoringusageand the jdx.dev open source tools π«Άzshβ run a script whose usage spec is written in its own comments
π USAGE BASH π
run a script whose usage spec is written in its own comments.
usually you get here through the script's shebang: the kernel hands the script and its arguments to usage, which parses them against the #USAGE lines at the top of the file, then runs the script with this shell. π
every flag and every argument reaches the script as an environment variable named usage_<name> β so --force becomes usage_force, and <file> becomes usage_file. a value declared var=#true arrives as one string, joined with shell_words::join() so that an element containing a space stays quoted. literally so considerate. π
-h and --help print the script's help page rather than this one. (rude? no, correct. π)
this command's shebang is #!/usr/bin/env -S usage bash, and the program it runs is bash from PATH. USAGECLI_SHELL_BASH names a different one β which is exactly how it gets pointed at Git Bash on a Windows machine where bash is the WSL launcher. fix it with an env var, slay. β¨
Usage:
usage bash [OPTIONS] <SCRIPT> [<ARGS>] ...
Options:
-hβ print the script's help page instead of running it--helpβ print the script's help page instead of running it
Arguments:
<SCRIPT>β the script to run; its spec is read from the#USAGEcomments at the top of the file<ARGS>β arguments to pass to the script
anything usage does not recognise is a value rather than a mistake, which is what lets a shebang script take flags of its own. that's the whole trick, bestie. π«Ά
β¨οΈ USAGE COMPLETE-WORD β¨οΈ
generate shell completion candidates for a partial command line.
this is what the scripts from usage generate completion run on every Tab: they pass the words typed so far and read back one candidate per line. also genuinely useful by hand, for checking what a spec offers at a given point without installing anything. lowkey a debugging icon. π₯
Usage:
usage complete-word [OPTIONS] [<WORDS>] ...
Options:
-f,--file <FILE>β a usage spec file, or a script with a usage shebang;-reads stdin-s,--spec <SPEC>β the spec itself, as a string, instead of a file--cword <CWORD>β index of the word being completed; defaults to the last word--shell <SHELL>β the shell the candidates are for, which decides how they are quoted. default:bash-h,--helpβ print help
Arguments:
<WORDS>β the words typed so far, starting with the program name
π¦ USAGE DIFF π¦
compare two usage specs and report what changed about the interface.
findings get grouped into three lil buckets:
- breaking changes π β a command line that used to work now fails, binds differently, or resolves to a different value
- compatible changes π β the interface gained something or relaxed a rule
- metadata changes π β help text, effect, deprecation. nothing about parsing, so breathe
exits 1 when there is a breaking change, so a release job can gate on it. and either spec may be -:
mycli --usage-spec | usage diff released.usage.kdl -
version is ignored on purpose: a release bumps it, and a check that fires every release does not get left switched on. not a bug, it's β¨designβ¨.
Usage:
usage diff [OPTIONS] <OLD> <NEW>
Options:
-f,--format <FORMAT>β output format. default:text-b,--breakingβ report only breaking changes--exit-zeroβ exit0even when there are breaking changes-h,--helpβ print help
Arguments:
<OLD>β the spec as it was, typically the released one; use-to read from stdin<NEW>β the spec as it is now; use-to read from stdin
π§ USAGE EXEC π§
run a script through any interpreter, with its parsed arguments as environment variables.
this one's for scripts in a language usage has no dedicated command for. a shebang of #!/usr/bin/env -S usage exec node parses the arguments against the USAGE comments at the top of the file, then runs node <script> <args> with each flag and argument exported as usage_<name>. π«
and when a file named .<script>.usage.kdl sits beside the script, the spec is read from that instead of from the comments. sneaky, but make it fashion. π
a command with whitespace in it is split like a shell would, so interpreter arguments can come before the script:
#!/usr/bin/env -S usage exec "deno run --allow-env=usage_*"
runs deno run --allow-env=usage_* <script> <args>. but a name that is an existing file, or is found on PATH, is never split. important. π
-h and --help belong to the script once one is named, so they print its help page rather than this one. asked with no script to describe, they print this page instead.
Usage:
usage exec [OPTIONS] <COMMAND> <BIN> [<ARGS>] ...
Options:
-hβ print the script's help page instead of running it--helpβ print the script's help page instead of running it
Arguments:
<COMMAND>β the interpreter to run the script with, such asnodeorpython3, or a quoted command with its own arguments, such as"deno run --allow-env"<BIN>β the script to run<ARGS>β arguments to pass to the script
π USAGE EXPLAIN π
explain what a command line binds to.
it prints a row per argv token saying what it became, then the values that came from somewhere other than argv, then anything that went wrong. and it exits 0 even when the explained command line does not parse β because the report succeeded, and that is exactly the case worth a report. π«Ά
Usage:
usage explain [OPTIONS] [<ARGV>] ...
Options:
-f,--file <FILE>β a usage spec file, or a script with a usage shebang;-reads stdin-s,--spec <SPEC>β the spec itself, as a string, instead of a file--format <FORMAT>β output format. default:text--view <VIEW>β a spec-declared executable view to explain-e,--env <ENV>β environment to explain against, asKEY=VALUE, repeatable
π given at all, these are the whole environment: an explanation pasted into a bug report has to mean the same thing on the machine that reads it. omitted, the process environment is used, which is what an execution would see. no vibes-based ambiguity here.
-h,--helpβ print help
Arguments:
<ARGV>β the command line to explain, starting with the program name
usage's own flags come before it, and flag parsing ends at the program name, so both of these work:
explain -f f.kdl mycli --env=prod
explain -f f.kdl -- mycli --env=prod
separate with -- when the explained line carries its own: the first -- is still usage's separator, so explain -f f.kdl mycli a -- b loses one. yeah. π tricky but true.
π USAGE FISH π
run a script whose usage spec is written in its own comments.
usually you get here through the script's shebang: the kernel hands the script and its arguments to usage, which parses them against the #USAGE lines at the top of the file, then runs the script with this shell. πΈ
each flag and argument reaches the script as an environment variable named usage_<name>, so --force becomes usage_force and <file> becomes usage_file. a value declared var=#true arrives as one string, joined with shell_words::join() so that an element containing a space stays quoted. same deal as bash, fish just has better vibes. π
-h and --help print the script's help page rather than this one.
this command's shebang is #!/usr/bin/env -S usage fish, and the program it runs is fish from PATH. USAGECLI_SHELL_FISH names a different one.
Usage:
usage fish [OPTIONS] <SCRIPT> [<ARGS>] ...
Options:
-hβ print the script's help page instead of running it--helpβ print the script's help page instead of running it
Arguments:
<SCRIPT>β the script to run; its spec is read from the#USAGEcomments at the top of the file<ARGS>β arguments to pass to the script
anything usage does not recognise is a value rather than a mistake, which is what lets a shebang script take flags of its own. π
β¨ USAGE GENERATE β¨
Okay so this is the β¨everythingβ¨ subcommand β it takes your usage spec and spins it into completions, docs, manpages, SDKs, and parse tables. One spec, so many fits. π
Usage: usage generate [OPTIONS] <COMMAND>
Options:
-h,--helpβ prints the help, bestie. That's it, that's the option.
π USAGE GENERATE COMPLETION π
Generates a shell completion script for bash, fish, nu, powershell, or zsh. Slay.
Lowkey the important thing to know: the script is a shim. Every time you hit Tab, it hands the words you've typed so far over to usage complete-word β which means usage has to actually be installed wherever that script lives. No usage, no completions, no vibes. π
Where does the spec come from? Either --file, or it runs --usage-cmd right at completion time β and that second one is iconic because it means a CLI that prints its own spec can, like, never go stale. Fr fr.
Usage: usage generate completion [OPTIONS] <SHELL> <BIN>
Options:
--installβ installs the script wherever this shell goes looking for it, instead of just printing it out.
Heads up: it writes the script file and nothing else. No shell rc file gets edited, no PowerShell profile gets touched. Where a shell needs its own one-time line β zsh's fpath+=, PowerShell's dot-source β it prints that line for you to go add yourself. π
--forceβ replaces a file at the target path thatusagedidn't write. (i.e. it'll clobber something it doesn't own. Rude, but you asked.)-f,--file <FILE>β a usage spec file, or a script with a usage shebang;"-"reads stdin.--cache-key <CACHE_KEY>β caches whatever--usage-cmdprints under this key, so it runs once per key instead of on every single Tab. The CLI's version is a great key for this, just saying. π--usage-bin <USAGE_BIN>β theusageexecutable the script calls back to, for when it's not justusageonPATH. Default:usageEnvironment:JDX_USAGE_BIN--usage-cmd <USAGE_CMD>β a command that prints the CLI's spec, run instead of reading--file. Made for a CLI that answers with its own spec, likemycli __usage_spec__, so the script always completes the version that's actually installed. Required unless--fileis given.-h,--helpβ print help.
Arguments:
<SHELL>β the shell to generate the script for.<BIN>β the name of the CLI being completed, exactly as it's typed at the prompt.
π§ USAGE GENERATE COMPLETION-INIT π§
Generates a shell init script that completes every usage-shebang script on PATH. Not one, not a few β all of them. π
The whole point: you source this once from your shell's rc file and then Tab just works on any executable whose first line is a usage shebang. No per-script usage generate completion step, no fifteen-step setup, none of that. β¨
How each shell pulls it off is honestly a little different:
bashandzshregister a fallback completer that asksusage complete-wordwhenever the command has such a shebang.fishhas no fallback (sad), so instead it scansPATHonce at startup and registers each script it finds. Different strategy, same energy.
Usage: usage generate completion-init [OPTIONS] <SHELL>
Options:
--usage-bin <USAGE_BIN>β theusageexecutable the script calls back to, for when it's notusageonPATH. Default:usageEnvironment:JDX_USAGE_BIN-h,--helpβ print help.
Arguments:
<SHELL>β the shell to generate the script for.
π¦ USAGE GENERATE GO π¦
Generates Go parse tables from a usage spec, which are read by github.com/jdx/usage/go/argv. π«Ά
Here's the tea: Go has no macros. So the thing a Rust CLI gets from a derive at compile time, a Go CLI has to get from this at build time. Same destination, different road. Typically you wire it up from a go:generate line like this:
//go:generate usage generate go -f mycli.usage.kdl -o tables.go
Usage: usage generate go [OPTIONS]
Options:
-f,--file <FILE>β a usage spec file, or a script with a usage shebang;"-"reads stdin.-o,--out-file <OUT_FILE>β where to write the Go source, or"-"for stdout (default).-p,--package <PACKAGE>β the Go package clause for the generated file (defaults to the spec's bin name).--field-type <FIELD_TYPE>β converts a generated field by its key, e.g.FlagTimeout=duration. Repeatable, so go wild. π₯--spec <SPEC>β the spec itself, as a string, instead of a file.-h,--helpβ print help.
π USAGE GENERATE JSON π
Prints a usage spec as JSON. That's it. That's the whole thing. β¨
It's the same document the KDL describes β just with included files merged in and defaults filled out β for a tool that would honestly rather not parse KDL itself. Understandable, honestly. π
Usage: usage generate json [OPTIONS]
Options:
-f,--file <FILE>β a usage spec file, or a script with a usage shebang;"-"reads stdin.--spec <SPEC>β the spec itself, as a string, instead of a file.--view <VIEW>β render one spec-declared executable view.-h,--helpβ print help.
π USAGE GENERATE JSON-SCHEMA π
Generates a JSON Schema for a CLI's config file, straight from its usage spec. Iconic behaviour, no cap.
The whole thing is built from the spec's config block: each prop becomes a property with its type, default, and help β so your editor can complete and validate the exact file the CLI reads. Editor autocomplete for config files is such a flex. π
Real talk though: a spec whose settings can't live in a file is an error, not an empty schema. It won't just hand you a sad little empty {} and pretend everything's fine.
Usage: usage generate json-schema [OPTIONS]
Options:
-f,--file <FILE>β a usage spec file, or a script with a usage shebang;"-"reads stdin.--out-file <OUT_FILE>β write the schema here instead of to stdout.--spec <SPEC>β the spec itself, as a string, instead of a file.--title <TITLE>β the schema's title, which is what editors show.--url <URL>β where the schema is published, used for its$id.-h,--helpβ print help.
π USAGE GENERATE MANPAGE π
Generates a manpage from a usage spec. Yes, the very genre of document you're reading right now. We contain multitudes. π
Usage: usage generate manpage [OPTIONS]
Options:
-f,--file <FILE>β a usage spec file, or a script with a usage shebang;"-"reads stdin.--view <VIEW>β render one spec-declared executable view.-o,--out-file <OUT_FILE>β output file path, or"-"for stdout (default).-s,--section <SECTION>β manual section number (default:1). The common sections, for the uninitiated:1: User commands5: File formats7: Miscellaneous8: System administration commands Default:1
-h,--helpβ print help.
πΈ USAGE GENERATE MARKDOWN πΈ
Generates Markdown documentation from a usage spec. One page by default, or a whole page per command if you pass --multi. Choose your fighter. βοΈ
Nerdiest-but-coolest detail: every part of the output comes from a Tera template, and --template lets you swap any of them out. So if you hate how it looks, that's genuinely on you now. π«Ά
Usage: usage generate markdown [OPTIONS]
Options:
-f,--file <FILE>β a usage spec file, or a script with a usage shebang;"-"reads stdin.--view <VIEW>β render one spec-declared executable view.-m,--multiβ render each subcommand as a separate markdown file.--html-encodeβ escape HTML in markdown.--out-dir <OUT_DIR>β directory for the per-command pages (required with--multi).--out-file <OUT_FILE>β output file path for single-file markdown generation, or"-"for stdout (default).--indented-blocks-to-code-fencesβ turns four-space indented blocks in help text into markdown code fences. Fun fact:--replace-pre-with-code-fencesis the former name and still works. It was always kind of a misnomer tbh β this has never looked at<pre>tags. Like, not once. π--url-prefix <URL_PREFIX>β prefix for the links between pages, such as/cli/reference.--link-extension <LINK_EXTENSION>β extension for page links (including the dot); empty means extensionless URLs. Default:.md--template <TEMPLATE>β replace a built-in Tera template, asNAME=PATH; the names arespec,index,command,argument,flag, andconfig.-h,--helpβ print help.
π USAGE GENERATE SDK π
Generates a type-safe SDK from a usage spec, and bestie, it's giving "I don't write argument lists by hand anymore." π
The SDK is a subprocess wrapper: typed arguments, flags, and choices for every command, plus a client that builds the argument list and runs the binary for you. No string-stitching chaos. β¨
Usage: usage generate sdk [OPTIONS]
Options:
-f,--file <FILE>β a usage spec file, or a script with a usage shebang;"-"reads stdin.-l,--language <LANGUAGE>β target language for the SDK.-o,--output <OUTPUT>β directory to write the SDK into.-p,--package-name <PACKAGE_NAME>β override the package/module name (defaults to spec bin name).--spec <SPEC>β the spec itself, as a string, instead of a file.-h,--helpβ print help.
π USAGE LINT π
Lints a usage spec for mistakes that still parse β which, real talk, is the sneakiest kind. π
Because a spec can be perfectly valid KDL and still be straight-up wrong:
- a flag or subcommand declared twice
- a required argument after an optional one
- a variadic argument that isn't last
- a command or flag with no help
- an example that its own spec can't even parse (the audacity)
Every finding carries a code, such as duplicate-flag, and --format json prints the findings as a list so a script can act on them. Automate your shame. π€
Exit status tea: it exits1when there's an error, or when there's a warning and you passed--warnings-as-errors.
Usage: usage lint [OPTIONS] <FILE>
Options:
-f,--format <FORMAT>β output format. Default:text-W,--warnings-as-errorsβ treat warnings as errors.--sortedβ also checks that subcommands and flags are declared in sorted order. It's off by default, and here's why: declaration order is a house convention, not a correctness question β a spec keeping a different order isn't wrong. Pair it with--warnings-as-errorsif you want to hold that order down in CI. π―-h,--helpβ print help.
Arguments:
<FILE>β a usage spec file, or a script with a usage shebang;"-"reads stdin.
π§ USAGE MCP π§
Serves a usage spec over the Model Context Protocol. Fancy. π
It reads JSON-RPC over stdin and writes responses to stdout β which is exactly how MCP clients launch a local server. So you just point one at usage mcp -f mycli.usage.kdl and you're off. β
Two tools get served:
list_commandsβ every command, with its effect.describe_commandβ one command's help, flags, and arguments.
Together? An agent can learn what a CLI does and what running it would touch β all without ever running it. Chef's kiss. π
Usage: usage mcp [OPTIONS]
Options:
-f,--file <FILE>β a usage spec file, or a script with a usage shebang (not"-": stdin is the MCP transport, so it's already booked, sorry π«Ά).-s,--spec <SPEC>β the spec itself, as a string, instead of a file.-h,--helpβ print help.
πͺ USAGE POWERSHELL
Run a script whose usage spec is written in its own comments π«Ά
Lowkey you'll almost never type this yourself β it's reached through the script's shebang, bestie. The kernel hands the script and its arguments straight to usage, which parses them against the #USAGE lines at the top of the file, and then runs the script with this shell. Glow-up pipeline, honestly β¨
Every flag and argument reaches the script as an environment variable named usage_<name> β so --force becomes usage_force and <file> becomes usage_file. And a value declared var=#true? It arrives as one string, joined with shell_words::join() so that an element containing a space stays quoted. No cap, it's that careful π
Heads up bb:-hand--helpprint the script's help page rather than this one. Yes, really β the script takes over, main character energy π
This command's shebang is #!/usr/bin/env -S usage powershell, and the program it runs is pwsh from PATH. USAGECLI_SHELL_PWSH names a different one β which is also how it gets pointed at powershell.exe on a machine that has only Windows PowerShell. iykyk π
usage powershell [OPTIONS] <SCRIPT> [<ARGS>] ...
β¨ Options β¨
-hβ Print the script's help page instead of running it--helpβ Print the script's help page instead of running it
πΈ Arguments πΈ
<SCRIPT>β The script to run; its spec is read from the#USAGEcomments at the top of the file<ARGS>β Arguments to pass to the script
Okay so about <ARGS>: anything usage does not recognise is a value rather than a mistake, which is literally what lets a shebang script take flags of its own. Not a bug, it's a feature, periodt π¦
π USAGE SPONSORS
Show the companies sponsoring usage and the jdx.dev open source tools π
usage sponsors [OPTIONS]
β¨ Options β¨
-h,--helpβ Print help
Short and sweet, no notes, we stan π
π USAGE ZSH
Run a script whose usage spec is written in its own comments πΈ
Same iconic setup as before, bestie: usually reached through the script's shebang, where the kernel hands the script and its arguments to usage, which parses them against the #USAGE lines at the top of the file, then runs the script with this shell π«Ά
Every flag and argument reaches the script as an environment variable named usage_<name> β so --force becomes usage_force and <file> becomes usage_file. A value declared var=#true arrives as one string, joined with shell_words::join() so that an element containing a space stays quoted. Chef's kiss πβ¨
Reminder bestie:-hand--helpprint the script's help page rather than this one π
This command's shebang is #!/usr/bin/env -S usage zsh, and the program it runs is zsh from PATH. USAGECLI_SHELL_ZSH names a different one π₯
usage zsh [OPTIONS] <SCRIPT> [<ARGS>] ...
β¨ Options β¨
-hβ Print the script's help page instead of running it--helpβ Print the script's help page instead of running it
πΈ Arguments πΈ
<SCRIPT>β The script to run; its spec is read from the#USAGEcomments at the top of the file<ARGS>β Arguments to pass to the script
And again, for the people in the back π£οΈ anything usage does not recognise is a value rather than a mistake, which is what lets a shebang script take flags of its own. We love a flexible icon π¦
π SOURCE
https://github.com/jdx/usage
That's the whole page, bestie β you made it to the end ππ This was USAGE(1), complete with its source/version info and build date down there in the footer, and the source lives at the repo right above if you wanna snoop. Go forth and slay your shell scripts β¨ππΈ
π¦ where this page comes from
- nixpkgs unstable: usage 7.1.3
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms