Define standard options to create a consistent CLI experience across tools. When developers get used to certain option behavior, having them available across all tools makes things much easier & smoother. Conversely, when the same option name is used but with wildly different meanings, this can be very surprising for developers, and possibly lead them to do something destructive they didn't intend.
Tools should adhere to these conventions whenever possible, and any deviation should be strongly reconsidered.
| Short | Long | Description |
|---|---|---|
| --debug | Show debugging information. | |
| -f | --force | Force an operation. |
| -h | --help | Show tool help/usage output. |
| -j | --jobs | Control parallelization. |
| -n | --dry-run | Show what would be done. |
| -q | --quiet | Quiet(er) output. |
| -v | --verbose | Verbose(r) output. |
| --version | Show tool version information. | |
| -y | --yes | Skip prompts. |
Show internal debugging information that the user would find helpful. This may be very verbose.
--debug may be specified multiple times to make the output even debuggier.
The short option -d may be used depending on the tool, but usually enabling extra debugging is not a common operation.
The user wants to bypass any safety checks. The help text should provide clear guidance on how this will affect behavior since it can potentially be very dangerous and lead to data loss.
For example, when imaging a device, do not prompt the user whether they really meant to erase the non-removable /dev/sda hard drive. Or if there are mismatches in hashes or other integrity checks, attempt to do the operation anyways (installing files, etc...).
Do not confuse this with the --yes option for agreeing to common prompts.
The short option -f may be used or omitted depending on how dangerous the option actually is in practice. If the tool might delete the user's desktop or source, probably safer to make them type out the full --force. If the tool would only delete some temporary files or something that could be recreated (even if it requires a bit of effort), then -f is OK.
Show the tool usage, examples, and other helpful information. Since the user has explicitly requested the help output, this does not need to be terse. Normal output should only go to stdout, and the tool should exit 0.
When processing unknown or invalid options, it's OK to show a short summary of the specific option, or of valid options, but it should not be the full detailed output like --help. The user should be able to focus on what they got wrong, not wade throw pages of output to try and track down the one error line. This output should only go to stderr, and the tool should exit non-zero (either 1 or 64).
Use of the short -h option is recommended out of wide convention. Avoid reusing this for something else like --human, and definitely never use it for something destructive or unrecoverable.
Limit how much parallelism should be used. This typically translates to how many threads or CPUs to utilize.
The special value 0 should be used to indicate “use all available CPU cores”.
The default does not have to always be 1 thus forcing users to manually pick a value, nor does it have to always be 0. Try to balance how expensive a particular job is (network, servers, I/O, RAM, etc...) with a reasonable default. For example, when talking to a network service, high values like 72 will probably cause many connections to be rejected so it won't be overwhelmed, so find a default that balances real world improvements (compared to -j1) with the server costs.
The default should rarely be hardcoded to a value above 1 -- run it through a max function with how many cores are available. For example, the default could be max(4, os.cpu_count()).
To determine how many CPU cores are available:
os.cpu_count()getconf _NPROCESSORS_CONF 2>/dev/null || echo 1Use of the short -j option is recommended out of wide convention.
Show what would be done, but don't actually “do” anything. Users should be able to add this option anywhere and expect that the tool will not make any changes anywhere. Basically this should always be a harmless idempotent operation.
Use of --dry-run is, by itself, not an error, thus it should normally exit 0. This allows the user to quickly detect problems before trying to make changes. For example, if invalid options were specified, the tool can show fatal errors. Or if inputs don't exist, or are corrupt, they may be diagnosed.
The tool may talk to network services, or otherwise make expensive computations, as long as it doesn't make any changes, and may be rerun many times.
The tool should display what it would have done were --dry-run not specified. This will often take the form like Would have run command: git push ....
Bypassing reasonable prompts is permitted as long as no changes are made. In other words, this may behave like --yes or --force in some situations. Use your best judgment as to what constitutes the best user experience.
Use of the short -n option is recommended out of wide convention, and because use of dry-run first is a common user flow.
The --dryrun option should be accepted as an alias to --dry-run, but should be omitted from documentation (i.e. --help output). This helps users who typo things, and because some tools have adopted one that convention instead of --dry-run (although the latter is still more common).
Make the output less verbose. General information should be omitted, and only display warnings or errors.
--quiet may be specified multiple times to make the output even quieter. Some recommended settings:
-q: Only show warnings and worse.-qq: Only show (fatal) errors and worse.-qqq: Don't show any output -- rely on exit status to indicate pass/fail.Use of the short -q option is recommended out of wide convention.
If desired, --silent may be used as an alias to -qqq behavior; i.e. do not emit any output, only exit 0/non-zero.
Make the output more verbose. This may include some helpful info or progress steps. Important information for the user should not be hidden behind --verbose; i.e. users should not be expected to use --verbose all the time.
--verbose may be specified multiple times to make the output even verboser.
Debugging information should not be included here -- use --debug instead. Use your best judgement as to what is verbose output and what is debug output.
Use of the short -v option is recommended out of wide convention, and because it can be common to type -vvv to quickly get more verbose output when trying to track down problems.
Show version information for the current tool. Normal output should only go to stdout, and the tool should exit 0.
The default output should be short & to the point, and cheap to produce. This may include terse authorship information if desired.
If combined with --verbose, related package/tool information may be included.
If combined with --quiet, the output should be just the version number.
For example, common output might look like:
$ tool --version CrOS tool v1.2.3 Written by some decent engineers. $ tool --version --quiet 1.2.3 $ tool --version --verbose CrOS tool v1.2.3 Current git repo is at add119cea9ebfd7ba89f7606ed04cac7cacaa43d. Some important library information: foo lib v2 another lib v3.4 Written by some decent engineers.
No short option should be provided for --version. It's not a common operation, so allocating one of the limited short options is a waste.
The user wants to “agree” to any standard prompts shown by the tool. This should not be used by itself to bypass safety checks -- see --force instead, with which this can be combined.
The prompts that would have been shown should still be emitted so it's clear what the user has agreed to, and include fake input. For example:
$ do-something --yes Do you want to do something? (Y/n) <yes>
Use of the short -y option is recommended out of wide convention, and because skipping the same set of prompts is a common flow to avoid annoying users.