« Back to Index

CLI: terminology and design guidelines

View original Gist on GitHub

Tags: #cli #terminology #flags #arguments #args #options #design #guidelines #clap

CLI terminology and design guidelines.md

Guidelines

The following information was copied verbatim from https://clig.dev/ (an excellent resource).

This is only a small subset of the overall content, so I highly recommend reading the full document (see link above).

Terminology

NOTE: You might sometimes see in CLI --help output sections such as FLAGS: and OPTIONS: (the latter functions the same as the flags section). The difference is, and there’s no official document or guidelines to support the following, that ‘Flags’ are boolean on/off switches (e.g. --debug) while ‘Options’ are flags that accept a value (e.g. --id=123). This all depends on the library you use to create your CLI. For instance, some libraries will generate REQUIRED FLAGS and OPTIONAL FLAGS sections instead.

Example Structure

<command|program> [<flags|options>] <subcommand> [<flags|options>] [<args> ...]

Note: ‘command’ is the name of the binary executable (i.e. the ‘program’) while ‘options’ was historically used to suggest the input as being ‘optional’ and so it typically maps to flags.

Best Practices

Prefer flags to args. It’s a bit more typing, but it makes it much clearer what is going on. It also makes it easier to make changes to how you accept input in the future. Sometimes when using args, it’s impossible to add new input without breaking existing behavior or creating ambiguity.

Have full-length versions of all flags. For example, have both -h and --help. Having the full version is useful in scripts where you want to be verbose and descriptive, and you don’t have to look up the meaning of flags everywhere.

Only use one-letter flags for commonly used flags, particularly at the top-level when using subcommands. That way you don’t “pollute” your namespace of short flags, forcing you to use convoluted letters and cases for flags you add in the future.

Multiple arguments are fine for simple actions against multiple files. For example, rm file1.txt file2.txt file3.txt. This also makes it work with globbing: rm *.txt.

If you’ve got two or more arguments for different things, you’re probably doing something wrong. The exception is a common, primary action, where the brevity is worth memorizing. For example, cp <source> <destination>.

If a complex piece of software has lots of objects and operations that can be performed on those objects, it is a common pattern to use two levels of subcommand for this, where one is a noun and one is a verb. For example, docker container create (container is the noun; create is the verb). Be consistent with the verbs you use across different types of objects.

Common Flags

Here’s a list of commonly used options: