Subject: PSARC FastTrack [02/09/2006]: CLIP Companion - command line interface guidelines This is the result of work done by UIRB and various interested ARC members. Hopefully all the major arguments and debates have happened as part of the authoring of this best practice document and this fasttrack will be truely non-controversial. -John Template Version: @(#)sac_nextcase 1.56 10/26/05 SMI 1. Introduction 1.1. Project/Component Working Name: CLIP Companion - command line interface guidelines 1.2. Name of Document Author/Supplier: Author: David Burrows 1.3 Date of This Document: 02 February, 2006 4. Technical Description 1: Introduction This is a companion document to the CLIP Guidelines(PDF). This clarifies some of the details in the CLIP document and describes how to solve common design problems within that family of utilities. If your utility does not belong to the CLIP family, these guidelines may not apply to it. There is a terminology section at the end of this document, which defines what this means by words like "utility" and "operand". Some sections of this document contain "tentative" design suggestions. These describe design patterns that have recently been thought of or identified but that we are not yet certain are "right". These might be thought of as "cautiously recommended". 2: Big Questions Consider these questions when you start to design a utility: 1. Are there other utilities which your users will think of as closely "related" to this one? (That is, will your users use other utilities to manipulate the same things that your utility does?) For example, if you are creating an X Windows System utility, its users will be using other X Windows System utilities. * If so, see the guidance about "Families of Utilities", below. 2. Has this utility shipped before? (That is, is this an update, or might users have used this in a script?) * If so, see the guidance about "Backward Compatibility" 3. Can you write or draw a diagram of the objects that the utility operates on? For example, an Array has a set of Disks, each of which has a set of Partitions * If not, see the section about Object Models. 4. Does your utility have multiple actions, or do you have options that are specifying actions? For example: can your utility both create and un-create something, or do you have an option like "-a" to mean "add"? * If so, see the guidance about subcommands. 5. Does your utility operate on multiple kinds of objects? For example, does it manipulate disks, disk arrays and mirrors? * If so, see the guidance about subcommands of the form "verb-objectClass" 6. Does your utility allow the user to specify values which are attributes of an object (as opposed to values that affect an action the utility can perform)? For example, do you specify the port number for a server (as opposed to getting a detailed listing of servers). * If so, see the guidance about Properties 3: General Design Guidance 3.1: Utility Families When you plan to design a utility, you must first decide what "family" it must belong to. You may also need to pick a sub-family. The word "family", in this document, refers to a distinct interface style. Often, the syntax of one family is incompatible with the syntax of another family (e.g. in the CLIP family, "ls -lar" is the same as "ls -l -a -r", while in the Sun Compiler family, "cc -fast" is not equivalent to "cc -f -a -s t). Often, a family is defined by a a set of guidelines, though in some cases (e.g. the Java family) there are none. One family of utilities may have multiple sub-families, where each sub-family adheres to the rules of the family, and then has particular conventions used only among that sub-family (e.g. a sub-family of disk management utilities might specify volumes with -d while NFS utilities might use -v). It is strongly in Sun's interest to minimize the number of families that we ship, and that the differences between sub-families be minimal. Here is the guidance for choosing among families: * Your utility should adhere to the CLIP Standard unless: * it is a compiler in Sun Studio product line (See the Compiler Flags standard). * Your utility ships as part of Java SE or Java EE (there are no written guidelines for this family) * it is an X Window System utility (there are no written guidelines for this family) * it is a GNOME utility (GNU Guidelines and geopt_long() and popt) * it is a service processor utility (See the DMTF/SMASH standard). * it might be submitted to a SUS-related standards body (see the SUS Utility Conventions). There is currently no information about different CLIP sub-families. Note that in some cases your utility may actually belong to a family that is defined outside of Sun. For example, if you were to ship a utility on AIX, you might need to conform to the family rules on that platform. Related to the previous point, if your utility is part of an open source project, you may have little or no control over what family it belongs to. If you have questions about what to do, talk to your product team or talk with some of the open source experts here at Sun. [IMG]FAQ Q: I don't like the CLIP interface style. It is wrong, or inefficient, or family Z does it better A: The most important question to ask is what your users will want, and not what you or your team want (you are, after all, seeking to make your users happy and productive). Repeated findings in usability studies have told us that users prefer consistency/commonality over completely optimal interfaces. They use many utilities and don't like memorizing special rules for each one. At the moment, we have no data saying any of the common interface styles are inherently better or worse than any of the others. Q: How do I define a new family? A: creating a new family should be done very rarely (preferably never), and should be presented to the ARC and UIRB for approval. 3.2: Backward Compatibility Utilities are used in two ways: * In an interactive environment where commands are issued and results are returned. * In scripts, which amounts to a kind of programming environment. When used in a script, a utility is effectively a programming API, so changing its interface (if it has been specified as a stable interface) can cause programs (scripts) to stop working, and that can bring a multi-million dollar facility to stop functioning. As a result of this, you should be very cautious any time you change the interface to your utility. [IMG]FAQ Q: My utility has shipped, but is in family Foo. I'd like to make it follow the CLIP guidelines. A: This is a delicate situation that should be thought about carefully. In some cases, details from these guidelines can be added to an existing utility without breaking any existing use. It is up to your product team to decide whether this evolution of the interface brings enough value to be worth the change. Additionally, if your utility is part of a distinct sub-family, any effort to move your utility towards CLIP should also involve moving the whole sub-family in the same direction. In any case, this is not something you should do lightly. Q: I can't adhere to this standard without making incompatible changes. But, they're small. Isn't that OK? A: In the majority of the cases, this isn't OK. Causing scripts to break is very undesirable. 3.3: Overall Design One of the most effective tools for designing a command line interface is to first figure out what the "object model" is that the utility will operate on. This usually means identifying the kinds of objects that it works with and their relationships (e.g. some objects are contained in other objects). Note: this doesn't mean the objects in the implementation of your utility. It means the objects that the end user must think in terms of. For example a hypothetical disk management utility might have these objects: * Disk Array * Disk * Mirror * Tape Drive An object model can be enhanced by noting the properties and operations that can be performed on each kind of object. This might make a full object model look like this: +----------------------------------------------------------------------------+ | Object | Properties |Creation|Addition |Change |Display| Other | | Kind | |Actions | Actions |Actions|Actions| Actions | |----------+--------------------+--------+---------+-------+-------+---------| | | | |add(disk,| | |power on,| |Disk Array|Name, Location | |mirror | | |power off| | | | |tape) | | | | |----------+--------------------+--------+---------+-------+-------+---------| | Disk |Model, Serial | | |format |list, | | | |Number, Size | | | |show | | |----------+--------------------+--------+---------+-------+-------+---------| | | |create | | | | | | Mirror |Mirrored Disk, |mirror, | | |list, | | | |Model, Serial Number|delete | | |show | | | | |mirror | | | | | |----------+--------------------+--------+---------+-------+-------+---------| | Tape |Contains Tape, | | |erase |list, |rewind, | |Drive |Capacity | | | |show |wind | +----------------------------------------------------------------------------+ Once you have an object model like this, much of the rest of your command line interface design can follow very automatically. It is worth noting here that some utilities operate on an object model where there is a single topmost object which is always a singleton on a system. In these cases, all the subcommands operate on the objects contained by the singleton object, and that singleton object does not need to be specified in a command (these utilities generally take no operands). If the object model begins to be fairly complex, it may be reasonable to ask: "Should I create one utility or many?" There are no firm rules for this. In general, fewer utilities are better, but if the end result is a utility with 50 subcommands, it may make more sense to have multiple utilities. In general, the best rule of thumb is to look at how your users will think of the set of objects, and then have one utility for each set of objects that have related meanings to your users. When in doubt, it is better to have one utility than many separate utilities. Another important design tool for CLI design is to do a usability study on your command line utility. It is easy to create only the parser for your utility and run a simple usability study of it. In this way, you can try out several variations of your interface and get feedback on them to determine which is best. Often, the results of a usability study are quite different from what your intuition would predict. Another factor to keep in mind when doing design is that most of the time your users will not use your utility exclusively. Instead, they will often use it with a variety of other utilities. This is why staying within the guidelines for your utility family is important, and why it isn't useful to optimize your interface to a high degree. Remember that anything that the user can specify on the command line can show up in places like ps output. Because of this, no potentially sensitive information should be specified on the command line. For example, rather than specifying a password as an option argument, the password should either be asked for interactively or specified in a file which is named on the command line. 4: Design Guidance For Syntactic Parts 4.1: Commands Guidance To help provide some context for the sections below, here are two examples of commands: $ qsformat -q -f ufs -p name="mything" foo $ qsdisk eject --force -n mydisk In the first of these, the utility named qsformat is given three options (-q, -f ufs and -p name="mything", where the third is specifying a property) and is operating on an operand named foo. In the second, the utility named qsdisk is given a subcommand eject which is given two options (--force and -n) and is operating on an operand named mydisk. [IMG]FAQ Q: My utility has multiple usage lines (e.g. qsformat -abc and qsformat -jkl). Someone told me I should use subcommands. Why is that? A: The fact that you have multiple synopsis lines suggests strongly that you actually have multiple different operations, and thus should consider using subcommands. Try to do a design where you use different subcommands and see how that feels. 4.2: Utility names Guidance The name of a utility should uniquely identify the utility and give some reasonable hint as to what it does. As a designer, you should strive to find a balance between clarity (e.g. sun-penta-processor-performance-tuner) ease of typing (e.g. sp), and memorability. Note that utility names and subcommands longer than 9 characters or with hyphens violate the CLIP guidelines. However, these violations are usually acceptable (and encouraged when needed for clarity). Any violation of the guidelines should be specified in the case materials when you submit your utilities to an architectural review committee. One common strategy to try to meet these constraints is to rely on acronyms. This can be a reasonable strategy, but try to avoid using non-obvious acronyms (for an example of what not to do, what does sctpgtadm do?) Sometimes, a set of utilities that work on some logical set of things will share some common prefix to help distinguish them from other utilities. One big example of this is that Sun's clustering software have utilities with a prefix of cl. At the same time, avoid product names in the utility name, since product names change frequently. As one example of what not to do, the Sun Studio IDE is called sunstudio, which will be inappropriate as soon as the product name changes. If your utility has no subcommands, it should have a verb-like name, and should follow the general guidelines in the subcommands section below. If your utility has subcommands, it should have a verb-like name that is evocative of the operation it can perform. It is also particularly good if the kind of object it operates on is named in the utility name (e.g. qsdisk supports multiple operations on disks). [IMG]Guidelines 1. Utility names should be between two and nine characters, inclusive. 2. Utility names should include lower-case letters (the lower character classification) and digits only from the portable character set. [IMG]FAQ Q: My utility name is 20 characters long. Is this OK? A: While some users do use auto completion features in shells, many don't. So, your utility with a long name will need to be fully typed out by those users, and 20 characters is asking for problems. Your utility name doesn't need to be literal or complete. Perhaps you can replace several words of the name with something more generic, or do some careful abbreviation. If your utility name must be longer than the maximum in the guidelines, you should note this exception in the materials you present to any review bodies. Q: What about prefixes like "mk", "ls", "rm" as found in some *nix utilities? A: On the one hand, these are used in a variety of Unix and Unix-like environments. However, there's a strong feeling that utility names and subcommand names must follow the same basic rules, and these names partially conflict with the names that already exist in the CLIP family for the same operations. [IMG]List cfg If your utility has no subcommands, and is used to do initial configuration of some object (usually, this configuration consists of setting values for various properties), then the suffix cfg can be used. For example regioncfg might be a utility to do initial configuration of a "region". Use "cfg" rather than "config" because it is a well-recognized abbreviation and helps keep the utility name short. adm If a utility performs various operations on several kinds of objects, then using a suffix of adm is good. For example sarxadm might allow the user to administer a variety of objects within the "sarx" subsystem. Use "adm" rather than "admin" because it is well recognized and keeps the name short. mgr If a utility performs many operations on a particular kind of object, and the only reasonable name for the utility is that kind of object and that name is too generic, then use the suffix of "mgr". For example, imagine that there is a kind of thing in the system called a "part", and it seems reasonable to have commands like part create etc. That name, "part" is probably too generic. So, use the name partmgr instead. 4.3: Subcommands Guidance A subcommand is used to name the operation that a command should carry out. For example: sharemgr create foo The subcommand here is "create" and it tells sharemgr to create something named "foo". Subcommands are useful because they provide a memorable way for users to remember what kinds of operations a utility can perform. Each subcommand also has its own set of options, and this also makes it easier for users to remember. Like utility names, subcommand names should be picked that provide a balance between clarity, ease of typing, and memorability. Like utility names, it is good to avoid acronyms and other abbreviations that aren't obvious. Unlike utility names, there is no "tab completion" for subcommands, so it is important to take into consideration how often the subcommand will need to be typed when considering its length. Subcommand names should generally be verbs that describe the action to be performed. Single word subcommands are best. For example: qsdisk format adisk qsdisk eject adisk qsdisk verify adisk In some cases, a utility may operate on a type of object and its sub-objects. For the operations on the sub-objects, the pattern for the subcommands is to use a verb followed by a hyphen and the name of the kind of object to operate on. For example: qsarray create anarray qsarray add-drive -q newdrive anarray qsarray remove-drive -q newdrive anarray qsarray delete anarray As mentioned above, some of these forms violate the CLIP guidelines. This is usually acceptable. You should simply mention these violations in your case materials. Operands to a utility should usually remain the same for all subcommands. When there are sub-objects, they should be specified with an option (as shown in the example above). Usability studies have indicated that when subcommands are used, users expect that if two subcommands are ultimately acting on an object, it should be specified in the same way and place in all the subcommands. As an aside, note that one effect of the naming recommendations for utilities, subcommands and so on is that the command becomes vaguely "readable" as an English sentence. [IMG]Guidelines 14. The form "utility-name subcommand [options] [operands]" is appropriate for grouping similar operations. Subcommand names should follow the same conventions as command names as specified in guidelines 1 and 2. 21. The subcommand in the form described in guideline 14 is generally required. In the case where it is omitted, the command shall take no operands and only options which are defined to stop further argument processing when encountered are allowed. Invoking a command of this form without a subcommand and no arguments is an error. [IMG]FAQ Q: Why should I use subcommands, rather than a set of separate utilities without subcommands? A: Both approaches are reasonable. The subcommands approach is beneficial in that a user only needs to remember one name explicitly (the utility name) and can from there quickly and easily locate the subcommands the utility offers. Subcommands also make it easier to discover what functionality a utility can provide in the man page or --help output. Another factor to consider, however, is frequency of use. If your utility will be used very, very frequently, then it may make more sense to represent it as a set of utilities. Q: Why should I use subcommands, rather than options? (e.g. qsdisk create -q mydisk versus qsdisk -c -q mydisk) A: In the CLIP family, subcommands are preferred over using options because we believe they make it easier to remember and discover functionality. Q: My utility has XX subcommands! This seems terrible for our users! A: It probably isn't as bad as you think. If you have XX subcommands, then you really do have a large number. You can reorganize this (e.g. create more utilities, or push that functionality into options or operands), but you can't get rid of it. The subcommand model, even when long, provides more "ease of use" than any other scheme we have found so far. When put into the --help output or the usage of a man page, this makes it very easy to determine what functionality a utility provides. This clumping of actions or actions and object types also seems to represent a very natural way for users to remember this functionality. If you still feel like the number of subcommands is excessive, you can make some other designs by, say, breaking your utility into multiple utilities and see if this works better for your users Q: I'd prefer to see verbNoun, verbnoun, "verb noun", "verb -t noun" or "noun" as my subcommand form, rather than "verb-noun" A: This is one of these cases where all the possible design alternatives provide roughly the same level of usability. So, the question then defaults to what is most consistent? Each of these design possibilities has been closely examined, and the "verb-noun" scheme seems to be the best. "verbNoun" involves mixed capitalization which many dislike. "verbnoun" tends to produce names that are hard to parse as soon as unusual terms appear in them, "verb noun" and "verb -t noun" don't really save any typing and ad other complexities, and "noun" doesn't convey any sense of action. Q: I seem to need to specify more than one level of objects (e.g. verb-noun-subnoun). What do I do? A: Usually, this suggests that your object model is too complex, or your decomposition into utilities isn't as fine grained as it should be. Try a different design. It is true that in programming languages like, say, Java, you can say things like myObject.getFoo().getBar.getBaz().doSomething(), and this kind of nesting is natural for a developer. Our usability data suggests, however, that administrators are less eager to think in terms of deep hierarchies like this. Q: My subcommand allows two very different cases, and each has mutually unrelated options (e.g. myutility add [-gou] entity and myutility add [-ghklr] entity A: You should probably go back and revise your design. This suggests that you actually have a couple different operations, and so should use different names. Q: Can I allow my subcommands to be truncated? (e.g. type qsdisk cr for qsdisk create) A: You may not. Doing so limits your future compatibility and may break scripts. See the options section, below, for more thoughts on this topic. Q: Is my subcommand limited to 9 characters like a utility name is? A: Like the utility name, you should strive to meet the requirements, but if you can't it will probably be OK Q: I have a subcommand called "print". Some people tell me that isn't good. Is this true? A: If your print subcommand will direct information to a printer, then it is probably a good name (though, it does demand that you explain why people shouldn't use the standard printing utilities instead). If your goal is to display information on the screen, a name like "show" or "list" or some other would be better and avoid the possible confusion of people thinking you mean to direct information to a printer. Q: I'd like to have a "help" subcommand. A: We'd rather not see this, since the "--help" is already available and you must support that. Our concern is that we want users to become familiar with using --help since it can be used on all utilities (whether or not they have subcommands). Other ways to learn about a utility simply provide other ways for users to feel we have inconsistent ways of getting help. Q: My utility mostly uses subcommands, but I'd like to allow one case where specifying no subcommand means to do something special. Is this OK? A: In general, this is not a good thing. If that subcommand takes any operands, those operands may conflict with some future (or present) subcommand and that can cause scripts to break. [IMG]List create Creates a new object. delete Un-creates a new object. add Adds an existing object to some set. remove Removes an existing object from some set. list Gets a list of objects show Displays details about an object set Creates or modifies properties on an object. get Displays properties of an object. unset Deletes properties of an object. reset Sets properties of an object back to their default values. 4.4: Options Guidance An option is used to change how an operation is carried out. The classic example is that ls displays a listing of the current directory, while ls -l displays a detailed (long) listing of the current directory. The same basic operation is done in both cases, but the option (-l) changes how that is done. Options are somewhat complex, syntactically. Here are the general forms that are allowed with some notes: * -l : Short (single letter) option that takes no option-argument. * -l -a : Two short options that take no option-arguments. * -la : An alternate way of specifying the previous example, with the short options clustered * -f myfile : A short option with an option-argument (these may not be clustered) * --long-listing : Long option with no option-argument * --input-file=myfile : An alternate way of specifying the previous CLIP requires that whenever there is a long option, there must also be a short option. Options always appear after the utility name (if there are no subcommands) or the subcommand and before the operands. The set of options may always be ended by a -- argument, and everything after that will be considered an operand. [IMG]Guidelines 3. Each option name should be a single alphanumeric character (the alnum character classification) from the portable character set. The -W (capital-W) option shall be reserved for vendor options. Multi-digit options should not be allowed. 4. All options should be preceded by the '-' delimiter character. 5. Options without option-arguments should be accepted when grouped behind one '-' delimiter. 6. Each option and option-argument should be a separate argument. 7. Option-arguments should not be optional. 8. When multiple option-arguments are specified to follow a single option, they should be presented as a single argument, using commas within that argument or blanks within that argument to separate them. 9. All options should precede operands on the command line. 10. The argument -- should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the '-' character. The -- argument should not be used as an option or as an operand. 11. The order of different options relative to one another should not matter, unless the options are documented as mutually exclusive and such an option is documented to override any incompatible options preceding it. If an option that has option-arguments is repeated, the option and option-argument combinations should be interpreted in the order specified on the command line. 15. Long-options should be preceded by -- and should include only alphanumeric characters and hyphens from the portable character set. Option names are typically one to three words long, with hyphens to separate words. 13. "--name=argument" should be used to specify an option-argument for a long-option. The form "--name argument" should also be accepted 14. All utilities should support two standard long-options: "--version" (with the short-option synonym "-V") and "--help" (with the short-option synonym "-?"). 15. Every short-option should have exactly one corresponding long-option and every long-option should have exactly one corresponding short-option. 16. The short-option name should get its name from the long-option name according to these rules: 1. Use the first letter of the long-option name for the short-option name. 2. If the first letter conflicts with other short-option names, choose a prominent consonant. 3. If the first letter and the prominent consonant conflict with other short-option names, choose a prominent vowel. 4. If none of the letters of the long-option name are usable, select an arbitrary character. 17. If a long-option name consists of a single character, it must use the same character as the short-option name. [IMG]FAQ Q: I'd like to have options before my subcommands. This makes sense because some options apply to all operations. A: This often makes sense from an engineering perspective, but our usability data suggests most users don't understand the system model well enough to be able to predict whether the option should go before or after the subcommand. Q: I don't like the double dash on long option names, but I want to have long names anyway. Can't I use a single dash? A: You may not, because this will conflict with the goal of allowing single letters to be clustered. Even if you can support both simultaneously at the moment, your utility may eventually require some of those letters for short option names. Q: I am running out of short option names. What do I do? A: First, check several details of your design. If you are using subcommands, note that you do not need to keep your option names unique across subcommands. That is, if you use -f in one subcommand to mean "force", you can use -f in another subcommand to mean "file". Users are not bothered by this level of "inconsistency" (however, if you use -f to mean force in one subcommand, and -r to mean "force" in another, your users are likely to be unhappy). If this doesn't account for your problem, review the section on "properties" below. Perhaps you are trying to do something with options that would be better with properties. If you still have a problem, you may need to redesign your utility. You should discuss this with your UI designers or your review bodies to determine if this is reasonable for your utility. Q: I am finding it difficult to choose reasonable option names. For example, I have to say something like -t (or, worse, -q) for "hostname". What do I do? A: Users appreciate mnemonic option letters, but this isn't an absolute requirement. Try to use the guidance in guideline 19 to pick a better letter. If that doesn't work, consider using non-mnemonic letters (e.g. -q for "hostname"). Alternately consider redesigning your utility. Q: Can I allow truncation of option names (e.g. allow a user to specify --input-file with --inp? A: This is not permitted. The reason is that a system administrator may use that abbreviation in a script, and the next release of your utility might contain an option like --input-port. In that case, the abbreviation would now be ambiguous and the script would have to fail. This might be reasonable to do if one could force people to not use truncation in scripts, but this isn't something that can be done. Rather than have a multi-million dollar server go down because of something like this, it is best to not allow the abbreviations. Q: Can I do something like -f file1 file2 file3? (pass many values to a single option) A: Not in this way. That would be interpreted by your utility as identical to -f file1 -- file2 file3. To specify multiple values for an option, you should separate them with commas (e.g. -f file1,file2,file3) or spaces,or allow the option to be repeated (e.g. -f file1 -f file2 -f file3) Q: Guideline 8 says use commas or spaces. Which is better? A: In general, commas are better. There is a function, getsubopt(3C), which can help parse these, and spaces can sometimes be a nuisance for users because of quoting requirements. However, there are times where it is necessary to use spaces (for instance,if your option accepts numeric values that may have decimal points, then you can't use commas because in some locales a comma is used as a decimal point separator). If it can be done unambiguously, it is reasonable to accept both commas and spaces. If all of this gives you a headache, consider simply allowing your option to be repeated and accumulating values with each repetition rather than replacing the earlier uses. Q: Can I have a -h option to get help? A: See the discussion of "help" as a subcommand in the subcommands section. 4.5: Properties Guidance Sometimes a command is used to change attributes of an object, or to retrieve those values. This is different than changing how an operation is to be carried out. For example, you might specify how a format operation should be done (quickly or thoroughly) as opposed to specifying that the label on a disk should be set to "fred" or "mydisk". The former changes an action, the latter changes an object. It is possible to use options for both cases. But, some utilities use properties to specify changing values on an object, and options for changing how an operation is performed. Properties are specified with a name=value format. For example: $ qsdisk format --quick-format newdisk $ qsdisk set -p label="mydisk" newdisk Note that properties are always treated as option-arguments to a -p or --properties option. There are several variations of how properties are dealt with in different utilities: * An object may have a specific set of properties that are "pre-defined" and a user can only change which values are stored in those properties. * An object may have arbitrary properties added to and removed from it * An object may allow specific properties to be added to and removed from it. See the section about idioms, below, for details about the set, get etc. subcommands. Note that there is one problem with using properties. Some shells can be started (e.g. with the -k option to sh) so that any command that has strings of the form name=value will be consumed by the shell so the utility will never see them. That is, in the rare case when a shell is started in this mode, any utility that uses properties (including things like mkfs) will not work correctly. [IMG]FAQ Q: How should I specify property names? Should they be "propertyname" or "property-name" or "propertyName"? A: The form "property-name" (all lower case, with hyphens separating words). seems to be the best. But please talk to us if you have a good reason they should be different. Q: I think I need to use hierarchical property names. Is that OK? A: We've seen at least one case where this is reasonable. Please talk to us and explain your need. Q: I can't tell if I have a property or an option. I can think of doing it either way. A: If you can retrieve the value later from the object affected by the operation, then it is a property. Q: My implementation doesn't have the notion of properties. The interface to the utility shouldn't have these. A: It isn't necessary that the interface reflect the implementation. If your users are likely to naturally think of these values as properties, then that is how they should appear in the interface, regardless of the implementation 4.6: Operands Guidance Operands usually name the objects or things that your utility will operate on. These are listed after the options. There is little that can be said about how operands should be specified, in general, because these tend to be the most utility-specific part of the interface. [IMG]Guidelines 10. The argument -- should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the '-' character. The -- argument should not be used as an option or as an operand. 12. The order of operands may matter and position-related interpretations should be determined on a utility-specific basis. 3. For utilities that use operands to represent files to be opened for either reading or writing, the '-' operand should be used only to mean standard input (or standard output when it is clear from context that an output file is being specified). [IMG]FAQ Q: My subcommand can take multiple operands. Should I allow that, or just accept one? A: If your users can specify multiple operands as easily as they can specify one, then it is good to allow multiple. However, two design considerations should be made here. First, if you must add some kind of special syntax to disambiguate between one and multiple, then you should allow only one. If your common use case is to allow multiple, then you should allow multiple. (sometimes those two criteria will conflict, and so you must make a difficult design decision). Second, If most of your subcommands can only operate on one operand, but you have one subcommand that can operate on many, you may want to still restrict the latter to operate on one, so that your utility seems more consistent to your users. Q: What happens if the user specified three operands, and the utility fails when processing the third? A: The general Unix convention is to continue with processing the third, and report an error (both a message and a status code) when all are done. Q: I'd like to specify things with operands in a particular order. Rather than using required options, I'd like to say that operand #1 is one thing, operand #2 is another thing, and so on. A: These are called "positional parameters". In general, these seem to be a bad idea. More than two positional parameters is hard for people to remember. In the general case, even two is difficult because it is often hard to remember whether A goes before or after B. One common utility which uses positional parameters reasonably easily is cp, where the last operand is the destination while the preceding are all the things to be moved. Yet, you have probably on occasion not specified the destination item and so moved all the files into some other location than you intended. This demonstrates that this good case can still cause problems. In general, we strongly recommend the use of options (even required options) rather than positionally-significant operands because this reduces the usability problems that positional ones involve. 4.7: Idioms There are several ways of doing common things which appear in command line utilities again and again. This section discusses some of these. Set/Get/Unset/Reset/Create It is common to want to specify properties that are applied to objects that a utility manipulates. This is a common idiom for supporting this in a command line interface: myutility create -p propname=value newobject myutility set -p propname=value newobject myutility get -p propname newobject myutility unset -p propname newobject myutility reset -p propname newobject In this idiom: * set is used to assign an initial or new value to a property (and possibly create the property in the object). * get retrieves the value from the object. If one property is specified, then only the value is returned. If multiple properties are specified, then "name=value" pairs is returned. If no properties are specified, then all properties are returned in "name=value" pairs. * create can be used both to create an object and as an implicit set operation. * unset removes the property and its value from the object (only relevant if you can add a property to an object) * reset sets the value of a property to its default value (only relevant if properties are pre-defined in the object In some cases, the -p is redundant. Nonetheless, it should always be used in utilities. Even in those cases users do not particularly mind typing these letters, and prefer them to be there so they can behave in predictable ways across utilities. In these cases, however, it may be made optional if there is no chance that it will ever become ambiguous. If the object model has subobjects that have properties, then the subcommand names should be of the form setprops-objecttype. List, Show and Get list and show have distinctly different meanings, and usability studies reflect that most users guess the purposes accurately. list is used to get a list of objects. This may be a plain list of their names, or their names with a minimal amount of additional information. show, on the other hand, displays detailed information about one or more objects. In some cases, get and show both are used in the same utility. In this situation, get shows just the properties of an object, while show may show the same properties and may show additional information. 5: Design Guidance For Other Parts Of The Interface 5.1: Help Usability studies have repeatedly shown us that man pages and --help output are a crucial part of the user's experience when using a utility. Small terminology problems, inconsistent formatting, and similar issues can seriously hinder a user's ability to use a utility easily. Use the standard formats for man pages and --help output as listed in the CLIP spec. In particular, note that each subcommand should be listed on a separate line in the synopsis section of the man page. For utilities that operate on many different kinds of objects, it may be reasonable to group the subcommands, in the help output, according to the different objects. For example: $ myutility --help Usage: myutility Use this utility to do something wonderful ROOT-OBJECT SUBCOMMANDS create Create a root-object delete Delete a root-object list List root-objects SUBOBJECT SUBCOMMANDS create-subobject Create a subobject delete-subobject Delete a subobject 5.2: Output When your utility writes information to standard out, you should always keep in mind whether it may be used only by people or only by other utilities or both. In the most trivial of cases it may be possible to address both needs in one format, but that's rarer than you might think. Human-oriented output formats need to be localized and should optimize for readability over formal consistency. As the format evolves, it should evolve for readability even if that involves a significant structural overhaul. On the other hand, program-oriented output formats need to be optimized for precision and extensibility, usually at the expense of readability. Example: ls -l output This format was developed before this dichotomy was understood, and it has feet in both camps. In many ways it fails both. If you think that ls -l output is parsable, have you considered the effect of localization on date formats, or the effect of special characters in file names? A file with " -> " in its name is lots of fun, as is a file with a newline in its name. Where would new information be added into "ls -l" output that wouldn't break existing consumers? On the other hand, because there *are* consumers of ls -l output, it can't be cleaned up for human consumption either. In particular, it's hard to add any information to the output. Output intended for humans should have a stability level below "Unstable". On the other hand, output intended for programs requires precision - absolutely every possible special character and pathological case must be handled unambiguously - and extensibility, so that next year's output can contain more information but be usable with today's consumers. Output intended for programs should have an appropriate stability level, anywhere from Unstable to Stable. When it comes to tabular data, here are some thoughts: If your subsystem uses and produces relatively simple data that can be expressed effectively in tabular form, then you should provide a way for users to get or provide that data in a stable space- or colon-delimited form for use within scripts. If your subsystem uses or produces complex data that cannot be expressed effectively in tabular form, consider providing a way to get or provide this data in XML with appropriate stability for the tags and schema. If there are compatibility issues with third-party products or controlling standards, then those should be weighed as well. XML and tabular forms do not necessarily comprise all of the interchange media of choice across all possible products. 5.3: Other Important Topics There are many other things relevant to the command line experience that are not covered here currently. This is a list of things that may be addressed in the future * Where a utility (and its support materials) should be placed in the filesystem (for the moment, refer to man -s 5 filesystem * Non-batch-oriented interfaces * Subshell interfaces (libtecla) * Error Messges * How to manage lists of objects in the object model * perhaps add-foo, remove-foo, set-foo-list * Error codes * More guidance about help and man page issues * Conventions for using standard in and standard out * Abbreviations of subcommands * When should/may subcommands and option names be plural versus when not? * possible: when a subcommand always or primarily operates on a set, use a plural. otherwise use a singular 6: Terminology This document uses a particular set of terms to refer to parts of the command line experience: Utility A program, excluding special built-in utilities provided as part of the Shell Command Language, that can be called by name from a shell to perform a specific task, or related set of tasks. Sometimes called a "command" Subcommand An argument to a command used to specify which operation the utility should perform. Option An argument to a command that is generally used to specify changes in the utility's default behavior. Sometimes called a "flag" or a "switch". Option Argument A parameter that follows certain options. Operand An argument to a command that is generally used as an object supplying information to a utility necessary to complete its processing. Operands generally follow the options in a command line. Command A directive to the shell to perform a particular task. 6. Resources and Schedule 6.4. Steering Committee requested information 6.4.1. Consolidation C-team Name: Policy Document 6.5. ARC review type: FastTrack