Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active March 24, 2022 13:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Integralist/5e0bd295c7db33c7900876fa934949e2 to your computer and use it in GitHub Desktop.
Save Integralist/5e0bd295c7db33c7900876fa934949e2 to your computer and use it in GitHub Desktop.
[CLI terminology and design guidelines] #cli #terminology #flags #arguments #args #options #design #guidelines #clap

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

  • Arguments, or args, are positional parameters to a command. For example, the file paths you provide to cp are args. The order of args is often important: cp foo bar means something different from cp bar foo.
  • Flags are named parameters, denoted with either a hyphen and a single-letter name (-r) or a double hyphen and a multiple-letter name (--recursive). They may or may not also include a user-specified value (--file foo.txt, or --file=foo.txt). The order of flags, generally speaking, does not affect program semantics.

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:

  • -a, --all: All. For example, ps, fetchmail.
  • -c, --color: Configure Always/Auto/Never enum variants as colour output might not work for every TTY.
  • -d, --debug: Show debugging output.
  • -f, --force: Force. For example, rm -f will force the removal of files, even if it thinks it does not have permission to do it. This is also useful for commands which are doing something destructive that usually require user confirmation, but you want to force it to do that destructive action in a script.
  • --json: Display JSON output. See the output section.
  • -h, --help: Help. This should only mean help. See the help section.
  • --no-input: See the interactivity section.
  • -o, --output: Output file. For example, sort, gcc.
  • -p, --port: Port. For example, psql, ssh.
  • -q, --quiet: Quiet. Display less output. This is particularly useful when displaying output for humans that you might want to hide when running in a script.
  • -u, --user: User. For example, ps, ssh.
  • --version: Version.
  • -v: This can often mean either verbose or version. You might want to use -d for verbose and this for version, or for nothing to avoid confusion.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment