Designing Command Line Experiences
The best software products are those that give their customers great
experiences. The opportunity to delight customers or users of your products can
happen during any interaction. For example, Slack’s awesome onboarding
is great for setting expectations within the app. While web and mobile apps tend
to get all of the limelight relative to experience design, creating exceptional
command line experiences can be just as unique and challenging. Command line
tools can be large pieces of software, like the gcc compiler, to the smallest of
tools like the
ls command that lists the contents of the current working
directory on Unix systems. The famously titled, “Art of Unix
distills a philosophy from the way programs and interfaces were built for Unix
systems. One of my favorite Unix philosophy tenants is building programs that do
one thing and doing it well. While the Unix
philosophy is a good base for
defining a good command line experience, I’ve found that I’ve needed a few more
Building trust means doing what you say you’re going to do and if you can’t, you need to be forthcoming and explicit. Being consistent with this behavior across all of the possible interactions of your tool helps your customers easily identify when the tool is not working as expected.
As an example of what not to do, let me use a fake command called
that will give a user temporary authorization against an API which requires one
parameter, the duration I want the authorization to be valid in hours.
$ credential 1 Credential successfully created!
Great based on the above command, I’d assume that my credential was created successfully and I have 1 hours before the system will revoke my access. Now what if I wanted to increase my duration?
$ credential 100 Credential successfully created!
Based upon this message, I’d assume that I got a credential that’s good for 100 hours. Little did I know that the maximum value for duration is 30 hours. Once I go over 30 hours, I’ll get error messages interacting with my service saying that I don’t have access any more. That’s a mismatch between what I expected and what I actually got. Don’t make your users guess!
I’m a huge fan of the concept of progressive enhancement. I’m borrowing this term from the web design sphere and applying it to command line tools. Essentially, progressive design is a way of providing the most basic functionality to all users but if the user has a deeper understanding of the underlying systems at play, more power and flexibility should be available.
For example, let’s use something as mundane as the
ls command on unix systems.
This command tips its hat to the concept of progressive enhancement. At the
command’s most basic level you can just get the contents of your current working
$ ls Applications pgadmin.log
Knowing what you know about filesystems, you understand that hidden files can
have their names prefaced with a dot and that some of the items that you’ve
listed in this current directory might have sub-directories. Diving a little
deeper, I could issue the
ls command with a few extra options to get that
$ ls -ap .vimrc Applications/ pgadmin.log
Be very careful about this concept. Understand the range of abilities of the users that you expect to use your tool and make sure you target those levels and nothing more. You may not need everything under the sun from super beginner to ultra-mega-professional.
Documentation can take many forms, from the help text that gets outputted when a command is run incorrectly, to the source code comments and even the website that houses the extended information on how to operate the command, just to name a few. Unfortunately, in practice, building good documentation tends to be one of the areas that really gets neglected. Now there’s something to be said for a user not having to read the full set of docs to figure out your command line tool. If they have to go to the docs to figure it out, then the experience is largely a failure. In that sense, I view documentation as addressing a few other areas for the user. The first of which is discoverability around what your command line tool can do and the second is building you or your company’s brand.
Web site and mobile apps have it way easier when it comes to discoverability.
They have all sorts of navigation menus, notifications and graphical elements
like font sizes to work with. However, documentation can provide a level of
discoverability that you might not get when a user interacts with your tool on a
daily basis. Let’s use the ngrok tool as an example. Ngrok is a tool that allows
you to create secure introspected tunnels to your local machine. What I love
about it is how easy it is to get started and how it tells you what you need to
do via documentation. For example, you can go to the ngrok site, download the
binary, unzip and issue the command
ngrok. What’s happens next is fantastic, a
full set of information on what ngrok is, examples of how to use it, version
numbers and commands get published in the terminal:
$ ngrok NAME: ngrok - tunnel local ports to public URLs and inspect traffic DESCRIPTION: ngrok exposes local networked services behinds NATs and firewalls to the public internet over a secure tunnel. Share local websites, build/test webhook consumers and self-host personal services. Detailed help for each command is available with 'ngrok help <command>'. Open http://localhost:4040 for ngrok's web interface to inspect traffic. EXAMPLES: ngrok http 80 # secure public URL for port 80 web server ngrok http foo.dev:80 # tunnel to host:port instead of localhost ngrok tcp 22 # tunnel arbitrary TCP traffic to port 22 ....
From a discoverability perspective, I know now what ngrok can do and how to get extra help.
The second front where documentation can help is on the branding side. How thorough are you in your docs? Do you provide examples? Do you tell users where to go if they have more questions? Going back to our ngrok example, the documentation on their website does a good job of answering all of the questions above and more. To me, the docs convey a sense of quality and that contributes to how I may perceive the quality of the command line tool itself and how the company conducts itself. When it comes to branding, every touch point a customer has with anything the company produces results in the customer building a profile of what that company stands for. Docs are a great way of implicitly communicating that value.
My Tenets of Great Command Line Experiences
The Unix philosophy is a great starting point for understanding what it takes to build good command line experiences. I highly recommend reading through the “Art of Unix Programming”. On top of that, I’ve found that build command line tools takes a little bit more:
- Trust - trust for a command line tool means that a developer can reason about the behavior of your tool.
- Progressive enhancement - understand who’s going to use your tool and give them some options to get more out of it.
- Documentation - use it to teach and delight your users on what your tool can do.
While these are the tenets that I follow, I’m sure there’s more out there. If you have principles that you swear by when you create command line tools, drop me a line, @neovintage, or comment over on Hacker News.