Six things to consider when designing for the command line
The nature of my work the last several months has immersed me on the command-line. We’re working on a secure, shared workplace for secrets. You can check out what we’re up to here, but let’s keep going.
I’ve learned over the last few months that maintaining UX across an entire suite of commands is extremely difficult.
How are subcommands delimited? What happens when a required flag is missing — are they prompted for it? Lists or tables? Added whitespace or not? Is the language consistent? Let’s not forget success and error states.
Once you make a checklist, you realize you’re herding cats.
Most people wouldn’t associate user experience with the command line, but in many respects you need proper UX on the command line even more than web because you can’t rely on visuals to aid the user.
Just like you have a brand/style guide for your website, you have to establish similar constraints and norms for a command line tool.
Sidebar: At Manifold while hiring a designer we often joked that we needed to list the position as ASCII Designer. I’d say the position didn’t fall too far from that tree.
So here are six things to keep in mind when you start building a CLI tool:
1. What is the barrier to entry with installation?
We learned early on with Torus that installation flow is a huge part of UX. We wrote our initial prototype in Node.js, which required users to have that runtime installed (a relatively large barrier to entry). That is what pushed us to make the switch to Go, which enables us to be portable to any platform with a precompiled binary.
Your command has to be easily accessible at the point of need. If your target user is deploying Linux, you want to be available in the package manager that is applicable to that distribution. If it’s not available in their conventional source, then they’re going to look for alternatives to your tool.
2. Are your commands intuitive?
Every detail matters on the command line: Things aren’t just a click away, the user has to define what they are looking to do with their keyboard.
On one hand you have the benefit of a typical command-line user being familiar with reading help text, or man pages. If they can’t recite the commands as long as you’ve added documentation they’re likely to figure it out.
That’s no good, though. You want the experience to be intuitive.
You want a user to be able to understand how to navigate what you’ve built by learning the structure of a few base commands, and then extrapolate that everywhere else naturally.
3. How annoying is it to type each command?
Our initial prototype used colons to delimit subcommands (e.g torus projects:create name). We wrote the entire prototype this way, but we came to the realization that it was really awkward to keep reaching for shift just to enter a colon: we got rid of every colon and use spaces now.
Avoid inputs which are non-standard or cumbersome to enact.
4. Are your error messages helpful?
Your application is performing a million operations behind the scenes. That’s why the user is employing your tool in the first place: to reduce the complexity for them.
But what happens when a step fails? Your tool ideally does a good job at recovering from a situation, but in the event that it doesn’t you need to surface relevant content that will aid the user in solving the problem themselves. We were actually guilty of this and were actually hiding context from the user which made the experience confusing.
You want to surface clear and concise errors, which tell the user what action (if any) must be taken, so that the user doesn’t have to ask for help.
5. Do you maintain consistent output?
You’ve gone on a vision quest and reconciled differing opinions of spaces vs tabs, new lines or not, and how many emoji you’re comfortable scattering throughout. That sets you up to be consistent.
Command line tools need to be consistent, as they are often used in scripts.
Exit codes, table formatting, newlines and whitespace. All of these must remain consistent with the type of action you’re performing so that it makes it easy to understand and parse the output in a script.
6. What is your automation strategy?
We’re human, we’re error-prone.
We want to be able to move fast, continuously deploy and deliver new features to our customers. We can’t afford regressions.
At my last job (GoInstant/Salesforce, working on shared web, and mobile screen sharing) we focused a lot of resources on QA automation in multi-user/interactive applications. I learned a lot along the way about what it takes to test complex edge cases, and it’s something I’ve drawn on to apply to the command line.
You need to have an automation strategy so you can remove humans from the process of maintaining consistency, as we’re simply not wired for it.
With Torus we perform mostly manual QA, but are working towards fully automating that process. I’ll be writing another post specifically about our approach to automation soon.
Hopefully these lessons we have learned along the way will help you achieve success in building your own robust command line utility.