Writing accessible CLIs π
Because of their simple, text-based interface, CLIs seem to be ideally suited for accessibility. However, there are a number of things you can include in your CLI design that will make it easier to use by people facing one or more sets of visual, auditory, or cognitive disabilities.
Because a CLI's interface with users is text-based, you should keep in mind how your CLI's interface is described and used by users who rely on screen-readers to interact with their computer. You have a choice whether to provide a relevatory or frustrating experience for such users.
Accessible input π
Keep your interface clean and consistent π
A great advantage to organizing your CLI's command, subcommand, and options (flags/switches) is that it improves the ability of the CLI to offer help output when needed, without that help being overly complex and confusing.
If your interface is full of conditional options (that is, options that are used only when other options are used), you should consider making the option its own subcommand, so you only need to document and consider those conditional options.
Use lowercase for command and flag names π
Only use lower-case and words-separated-by-hyphens for command names and flags. CamelCase names have accessibility issues and force the user to remember where you chose to add capital letters in the command-name, which isn't a great experience.
- Best
--user-id username--userid usernameIn this case, both flags use all-lowercase, and are clear to the user whether or not the flag is displayed onscreen as text or read by a screen-reader (see accessibility). The hyphen in the first example is equally easy to discern in both cases.
- Not great
--UserID username--UserId username--userID usernameIn this case, each of these flags use the same letters, differing only in capitalization. Without prior knowledge of the rest of your CLI's interface and the patterns used, it would be indiscernable to any users relying upon a screen reader or with poor vision where to capitalize the flag name.
- Acceptable (but dubious) alternative
To avoid user confusion, you might elect to make your switches case-insensitive, in which case, these all function exactly alike:
--userid username--UserID username--UserId username--userID username--USERID usernameThe ostensible benefit of this is that it doesn't matter what capitalization your users input, making it easier to type. Furthermore, converting input to lowercase and then comparing that to a known flag name is done easily in languages such as Python by applying the
lower()method to the user input.However, this alternative offers dubious value above the all-lowercase version! Typing lowercase characters with dashes is simpler as only one key must be pressed for each character in the command-name, and as previously noted, dashes are spoken as individual words separated by "dash", and therefore are discernable to users relying upon a screen-reader.
It can also potentially confuse your users if you use anything but the all-lowercase version in your
--helpoutput or in CLI documentation, as an assumption can easily be made that if any capitalization is shown in the documentation, it is also required when typing the command, as well.
Accessible output π
Provide alternative output for complex text π
For any text output that doesn't make much sense when read aloud, consider providing a switch to output that information in an alternative, structured, format which is easier for screen-readers to understand, such as HTML. Examples of when you should do this include:
Output includes... |
Make it more accessible! |
|---|---|
Tables |
Render as HTML to an external file that can be viewed in a browser window. |
ASCII art |
Provide an option or setting to eliminate such graphics from the output. |
While many CLIs provide their primary output in the form of text (such as ls, mentioned earlier), there are equally many CLIs which produce output files (such as audio, graphics, PDF documents, and so on) as output.
In the first case, where the CLI provides output directly to the terminal, the accessibility of your output is similar to the accessibility of the terminal itself.
In the case where CLI output is a generated (or modified) file or any other form of output that isn't sent directly to the terminal, it can be helpful to provide some output that explains what the program generated, and where (especially in the case of generated files). Reporting nothing at all in the CLI output can be confusing to people with disabilities. What did the program do? Where is the output? For example, if you have a program that takes in the name of a text file and then converts it and saves it to a PDF file, announcing the results of the action can be the difference between the user understanding that the program succeeded and output was produced, or if the program failed along the way. If there are any important details about either the success or failure of the CLI, then report them to the user.
For example:
Complete! PDF file was generated at `output/chapter-1.pdf`.
or:
Error: Input file, `source/chapter-1.md`, could not be found!
In both these cases, success or failure, the user is alerted about what was produced, or what problem in the input or functioning of the program occurred. Each gives the user some information that can be used to find the CLI's output file, or to understand why it did not succeed.
Programs that silently succeed or fail, which rely solely on the error-code returned to the environment, give no readable indication to the terminal user about whether or not the command succeeded.
On the other hand, if your program produces output designed for input to another program (creates a
file or is a pipe), then consider adding a flag to provide that output instead of sending it to
stdout. Remember that the terminal is the user interface, and assume that your users are humans.
The GNU recommendations for CLIs also reflect this:
If you think one behavior is most useful when the output is to a terminal, and another is most useful when the output is a file or a pipe, then it is usually best to make the default behavior the one that is useful with output to a terminal, and have an option for the other behavior.
