How To Make Your CLI More Intuitive

Posted in

CLIs are the unsung heroes of modern software development. While web GUIs and programmatic interfaces may be expected, CLIs can be a powerful interface into an API, providing extensive and complex modes of consumption, interaction, and transformation.

Today, we’re going to discuss why it’s worth the effort to make your CLI intuitive. We’ll discuss some user-friendly choices that can drastically improve the consumption experience and some usability improvements that result in greater understanding and efficiency.

This piece was inspired by the excellent talk given by Noah Dietz at the Austin API Summit on CLIs for APIs. However, our advice below will be platform and language agnostic, applying broadly to all CLIs.

Watch Noah Dietz present:

Why Care About CLI Consumption?

“Today, the web interface is really the only consumption channel that people really focus on for a human use case. When you’re trying to consume an API from the command line, I feel like you have to kind of start assimilating with the Borg […] The command line consumption channel can become something way more human oriented, and we can take some steps to get there.”

One big first step in making any CLI more intuitive is to revisit the assumption concerning who actually uses them. CLIs are often thought of as just another machine-centric interface. In reality, CLIs are somewhere between machine and human-oriented, and as such, could be vastly improved by thinking of the human interacting with them.

Additionally, CLIs are a common gateway for new developers. Web interfaces and GUIs might be the most visible and often used by the everyday user, but power users and developers often require a CLI to work at a different level. There are just some things that a GUI can’t do as efficiently as a CLI – imagine trying to pass a call with fifteen flags and variables using your favorite web GUI, and you’ll immediately understand why passing it all as a simple string may be more attractive for a developer.

With this in mind, how do we improve the CLI experience?

Improving the CLI Experience

Defaults

Defaults are often not thought of as a core user experience function. Instead, they’re usually considered a nice extra bit of functionality. In reality, a default can inform users, provide a better user experience through contextualization, and ease the learning curve for new users.

A default option presented to a user can serve to suggest the core function of the function itself. For instance, if the default setting is to output data in a specific format and a specified output endpoint, a user could quickly infer context. That kind of knowledge is typically something that can only be derived from documentation or individual instruction, yet a single default could speak volumes.

Additionally, the default can serve to reduce the time needed to perform common functions. If something is a default, this means that the process is routinely used and is thus repetitively used. In such a case, requiring the user to enter that function over and over is senseless. A default could increase the CLI’s intuitiveness while easing the effort required to carry out core functions.

Adopt Structured Definitions

“We can use structured to intuitively represent the interface on the command line. When I say structured definitions, I mean an API description, an API schema […] Use that specification to actually model the experience.”

One practice that can help make any CLI more intuitive is the adoption of structured definitions. When creating a CLI, properly structuring it by form and function, and then allowing this to be expressed to the end-user can significantly increase the user’s ability to reason, understand, and extend their interactions.

You can accomplish this in various ways – the easiest being to simply adopt this practice by developing with a CLI in mind. While some refer to this as “CLI-first,” this is, in reality, another branch of development consideration and should be considered core to the overall business logic of the API in question.

Another method of doing this is by adopting schema and specifications which explain what these functions do, organize them by form and function, and then map these functions visibly within the CLI. By adopting this methodology, the software can benefit from better organization, and as such, the user can infer basic functions.

For instance, if your API schema groups all functions related to media transformation under a morphing function group, then the user can necessarily infer that, if a function exists under that group, it is designed for that use case. In conjunction with defaults, a user can look at a function in a single glance and understand an incredible amount of context.

On a related point, names should be succinct, and where possible, aliases should be accessible. If your API schema is properly formed, something like “status” should be reflected as such — forming this function under “-statusOfOrder” may make sense from a theoretical point of view, but to the end-user, it’s opaque. If possible, it could be better to use something like “–s” or “-status”; this is not only easier to use repeatedly, it’s also easier to understand in context.

Adopt Common CLI Patterns and Practices

Adopting common CLI patterns can go a long way to improving the intuitiveness of a CLI. CLIs are not just an API facet — they exist as a pervasive way of interacting with machines, and accordingly, there are some common methods and practices that, when missing, serve to make an interaction worse.

The major point is to standardize output. In most CLI systems, stdout serves as a standard output location, and stderr serves for standard errors. If CLIs don’t adopt this, users could suffer issues in locating the output files for their content and for interacting with the API. In essence, making your users chase outputs and errors reduces user experience and results in more complexity.

Additionally, adopting common CLI patterns in terms of flags can result in significant gains in understanding. Something as simple as using the default -r for recursive, instead of something like -recu, can result in a CLI function that is easily discernible, understandable, and usable. Non-standard choices in this space can only serve to make for a less-easily understood engagement paradigm.

Provide In-CLI Documentation and Help

“Embrace the idea of a unified experience across the consumption mediums. […] Help documentation, the use of documentation and flags and commands, is generated for the entire command line […] so you actually get the documentation that would render somewhere else as usage information.”

No matter how intuitive you think your CLI is, the reality is that the user will always find something difficult at some point. This is just the nature of an interface – if they did not develop the CLI, they will inevitably need some form of clarification. How your CLI provides this help and documentation can help clarify a large part of this inequity.

Don’t make people chase down information. Instead, provide that information immediately to the user upon request through the CLI itself. Utilizing -help, -h, etc., to deliver in-line documentation on demand can result in immediate knowledge development, reducing complexity and easing the learning curve. Additionally, this can help reduce the frequency of errors arising from mistyped commands.

To take it one step further, the CLI can provide error correction when typos are accidentally submitted. By having a CLI automatically suggest alternatives and corrected commands in-line, and allowing the user to easily invoke these corrected commands, the user can navigate the CLI and its functionality without placing so much emphasis on eliminating spelling mistakes.

Conclusion

The reality is that while CLIs are perhaps one of the best interfaces to an API, the primary reason they are often not preferred over GUIs and other frontends comes down almost entirely to a lack of understanding, education, documentation, and ease of use.

Anything that can be done to clarify these points, then, can only lead to increased adoption, and therefore greater power to the user. How one goes about improving their CLI is quite important — as such, adopting common standards, practices, and methods will result in greater results.

What do you think is the chief reason CLIs are not more commonly used? Is it a concern over usability? Is it perhaps a concern over user-friendliness? What more can be done to ease these issues? Let us know in the comments below.