Command structure

Structure

$ program action flags options arguments

Program - the subject, single point of entry

Action - the predicate (verb), as simple and succinct as possible

Flags - booleans

Options - key/value pairs

Arguments - the direct object, target of the command

When displaying the command structure, use <> to highlight options, flags, and arguments.
Use [] to display optional ones.

The whole string should only use lower case letters.

E.g. the only required argument in the following command is a single instance.

$ lxc delete [<remote>:]<instance>[/<snapshot>] [[<remote>:]<instance>[/<snapshot>]...] [flags]

Action

Reads as the “predicate” in the command’s sentence (the verb of the sentence).
Specifies the ACTION within the PROGRAM to invoke.
Does one thing, and one thing well; simple and succinct.
Uses simple, common action verbs:
$ git clone
$ apt update
Aim to find the shortest, unique verb possible for the action that the command is performing.
One syllable is always better than two, which is always better than three. Three syllables are in general not acceptable to be used as an action.
Nested subcommands are to be used only in products where the CLI acts upon multiple objects, e.g. in MAAS you could take an action on a machine, a controller, a KVM host, etc. The commands acting on the primary object should not require the object to be mentioned.
$ maas commission <machine-name>
$ maas subnet reserve-range <IP-from> <IP-to>
If the program doesn’t require subcommands, consider adding another top level action, of verb-objectclass form:
$ juju add-unit
$ juju add-relation

Flags and Options

Handled by the PROGRAM as booleans, either present or not, on the command line.

Must start with a single dash (-) or a double dash (–).
May have a single character representation.

  • Single character flags must start with a single dash (-)
  • Single character FLAGS can be stacked or combined
    $ apt upgrade -yadf
    $ apt upgrade -a -d -f -y
  • Should have a descriptive representation for self-documenting scripts that must start with a double dash (–)
    $ apt dist-upgrade -y
    $ apt dist-upgrade --yes
  • Must not be dependent on ordering
    $ apt upgrade -a -d -f -y
    $ apt upgrade -y -a -d -f
  • Must at a minimum include these flags:
    • -h|-help|–help
    • -v|-version|–version

KEY/VALUE pairs

  • KEY may have a single character representation
  • KEY should have a double-dash descriptive representation
    $ rsync -e “ssh -p 2222”
    $ rsync --rsh=”ssh -p 2222”
  • KEY and VALUE must support separation by whitespace
  • KEY and VALUE may support separation by an equal sign

Handling Multiple values in a KEY (Tuple)

  • When there are more than one values in a key
    i.e. --resource <name>:<revision>
  • a ":" will be used to separate between the tuple values.
    $ charmcraft release mycharm --revision=5 --channel=stable --resource foo:7 --resource bar:1

Optional enhancement "," comma separation can be used to parse multiple values in a flag.
$ maas <profile> vmhose <id> compose pinned_cores= 1, 2, 3
$ juju deploy haproxy -n 2 --constraints spaces=dmz,^cms,^database
$ charmcraft release mycharm --revision=5 --channel=stable --resource foo:7, bar:1

Arguments

The “direct object” of the command’s sentence.

Must be the target of the PROGRAM and the ACTION.
Are any other terms which are neither FLAGS nor OPTIONS:
$ start apache2
$ docker pull ubuntu
$ git remote show
$ snapcraft list-revisions <snap-name>

Plurals

The plural of a noun that’s a common object within the tool should always display the listing page (where a listing page is available).

Commands usually reserve -v as a shortopt for --verbose, considering that --verbose is going to be used more than --version, can this guideline be adapted to that?

Thanks for pointing that out, definitely sounds like something we can amend CC @amylily

Definitely! I think some CLIs that I played with use -V (capital V) for version because of this reason as well. For certain CLIs like NodeJS where the version is crucial, it might be relevant to use -v, but most CLIs that debugging is more important, -v, should represent verbose. @sergiusens, I think this guideline should adapt to that.

1 Like

We have two ways (both used as examples here) to represent an action that will display the listing page — list-<plural> and <plural>. Some standardisation around that would probably be a good idea.

First, it’s probably a good idea to recommend providing both as aliases for each other where possible, since at this point both forms are widely used. (Juju already does this, preferring the <plural> form but keeping the list-<plural> form as aliases, mostly hidden.)

Second, choosing one as the preferred option is probably a good idea. Some programs prefer one format, some prefer the other, and in a few cases we have programs that have one form for some actions and the other form for others. That’s not too bad if the user can use either (though it’s not ideal for the documentation), but when those aliases don’t exist it can be quite counter-intuitive.