Rules for creating great developer CLIs


Heroku’s Nahid Samsami and Jeff Dickey are behind the Heroku developer CLI and the Open CLI framework. Here, in their talk from DevRelCon London 2018, they share their usability principles from great developer CLIs.


[Nahid] Hi, I’m Nahid. And we’re here to talk about rules for creating great developer CLIs. We’re really passionate about building great command line interfaces.

I am a director of product at Heroku, where I’m responsible for overseeing our product interfaces. Which includes our dashboards, our command line interface, and public facing API. And I’m joined by Jeff Dickey, who is Principal CLI Engineer at Heroku. Jeff, has been working on CLIs for about four and a half years. And I’ve been working on the Heroku CLI, for just over two years

The open CLI framework and our users

And in addition, to working in the Heroku CLI, we extracted the Heroku CLI into an open source project, called the open CLI framework. Which is a framework for anyone to build a CLI, a simple CLI or a complex CLI that can be the CLI for you know, a company. So we started out with having the Heroku CLI and the Salesforce CLI running on oclif, the open CLI framework. And I’m happy to say that there are now other companies and organizations building their CLIs on oclif

So just recently ButterCMS wrote a blog post about how they built their own CLI using our framework. Netlify is building… I think rebuilding their CLI using our framework. It’s in beta right now. And I have a little quote from them up there.

And then Apollo also built their CLI on our framework. I’ve been even talking to someone in the audience about how they saw our last talk and their company is building a framework too. So that’s what we really want to see, because we’ve spent a lot of time on the framework and thinking about what makes a really great CLI. A couple of weeks ago we hit about 130,000 weekly downloads of oclif-based CLIs.

So that’s excluding the Heroku and the Salesforce CLI. And along the way, we’ve developed a lot of user experience principles which is what is going to be the focus of the talk today. And then towards the end, Jeff is going to do a demo of building a very simple CLI’s using the oclif framework.

Why use a command line interface?

So the starting point for CLI users is the terminal, and so here we see the terminal. It’s very simple, it’s basically blank, and very clear usability differences relative to a browser interface. When you’re creating an experience for developers and you have a browser, the Heroku dashboard is shown here, there’s a lot of visual real estate.

It’s easier to guide the user, it’s easier to show them how to do something, to show them the different features, to point them in different directions, give them options. And so you have a lot of options of visual things that you can do to guide the user through the interface, and to teach them. And when you’re working the CLI, I mean the obvious drawback is what you have as a tool is words, and you’re able to create inputs and outputs. But it can be more difficult to guide the user.

So, why use a CLI? Why create a CLI? Well, CLIs have their own special superpowers. They’re really great for repeatable, composable, tasks. If you need to do something again and again as a developer, a CLI can be super helpful and able you to do that more quickly.

And you know, at Heroku we care a lot about developer productivity, we know that developers care a lot about productivity too. And so many of our power users love to use the CLI for that reason. It’s great for creating machine readable outputs. Things that you can create scripts for, scripting. And then it’s awesome for interacting with an API. And that’s been a focus you know, in this conference too is the idea of the API economy. And if you think about it, using a CLI can be the simplest way of interacting with an API not having to write calls scripts and things.

Building consistency in CLI: use case example

Okay, next slide. And building for CLI takes a fraction of the time of building for a browser.
So one of the use cases I’m going to point out here is that if you’re building an internal tool, it’s really worth considering could I build this internal tool for my admin users at my company, without a visual interface? And if I was to do that you know, how much time would I save, and would it be useful to them. So that’s one of things that we do at Heroku is many of our admin tools things are things that you run in the CLI. And so we’re able to get those up and running really quickly.

CLI is also great for prototyping functionality, and we also use them for testing a new feature with customers. So we’re able to get sort of the basic concept of a feature fleshed out a little bit with the CLI, which is really easy to trade in.

Okay, so we developed principles to create a delightful CLI for Heroku, and we put them on a style guide which is available online, it’s called our CLI Style Guide. And one of the reasons we did this was that across Heroku, you know, we build the framework, but we had a lot of different teams and different developers working on our CLI. And we wanted to create a consistent experience for all of our users, as one of the ways that we enable users to understand how to do things in the CLI, to create that consistency. To create that structure so that when they’re running a command they know what they’re going to get, and what format that’s going to come in.

And so we have all the principles of our CLI in our style guide, I’m going to run through a few of them today. And I’ve broken it down into four sections. So mission statement, structure and navigation, input and output, and CLI special powers.

CLI mission statement

So starting out with the mission statement, we think it’s very important that every CLI has a goal or mission. So that when you’re making decisions as you’re building your CLI, you’re able to have a framework to guide you around making those decisions. So for us, one of our key goals is usability, and the user experience. We say you know, in our mission statement that Heroku CLI is for humans before machines.

And that means that while we do value machinery usability, when we’re making a decision in terms of CLI design, we’ll always lean towards making the decision that will enable the best human or developer experience over the machine experience.

Next, structure navigation. So in the CLI, you know, you don’t have the visual real estate that you have in the browser, so the tool that you have are words. And you know, how you structure those words, and what words you use, become incredibly important. In the CLI particularly if you think about it once you’ve created a command as a developer for your users to use, there’s a huge amount of muscle memory that goes into that.

So your developers will learn that command and will memorize it and get used to running it. And that means that if you want to later change that command, it’s pretty tricky. I mean yes, you can make it backwards compatible, but ideally, you don’t want to be changing the names of your commands at all after you’ve written them.

Our rules

And that’s a different experience to if you have a website and you change that user experience, you change the layout, or where the buttons are, your user is going to arrive at the website and be able to probably work it out. And in the CLI, it can be very frustrating if a user is running a command that no longer works. And so one of the things we developed to help us make sure that we don’t have to rename commands later, is that we have some rules.

So we have commands organized as topics. We have we have the topics and then commands underneath them. And the topics are nouns and the commands are verbs. And here you can see an example, in the right hand side where apps is the name of the topic, and you have a whole list of commands on the right hand side, like create or destroy which tend to be verbs.

And as a developer, when you’re developing in oclif and you’re creating your CLI, we’ve arranged all the folders which you can see on the left hand side, so that the structure you’re developing in and the folders matches what your user will be seeing in terms of the commands being nested within the topics.

Okay, one of the things we launched pretty recently I think it might have been after our last talk is a command, auto completion for oclif. This is the ability for users to tab to complete a command. So if they can’t remember the whole command they can tab and you know, type in Heroku apps, and they can see the different options. And then they can you know, select the app that they’d like.

So we’re also able to autocomplete values as well as command names. And this is just one of the things that comes out of the box. So if you’re developing a CLI using our framework, you don’t have to write your own autocomplete logic, we sort of give you that out of the box.

And next, I’m going to talk a little about documentation. So documenting consistently is obviously really important. And traditionally, for a long time the main way we documented our CLI, was that we had a help command. So you’d type in the command that you were interested in, and then you’d add “Help” at the end. And there was a standard structure in which you would get an example, and you’d get a description of what that command did. And we ran some user studies, and what I found in the users studies even amongst some of our power users, was that not all of them were using that format of help.

Go where the users are

They were actually going and Googling the thing that they were trying to learn about. And the thing was that not all of our CLI documentation was online at that time. I mean we had just had it sort of buried in the CLI itself. So you know, we thought about should we better teach our users to use this CLI… you know, the CLI help, or should we go to where the users are?

And we decided to go to where the users are and give them that documentation in the format that they wanted it in. And we also noticed that when they were developing, they would often have the CLI open, and they would also have a browser open. And so this enabled them to more easily kind of like pass through the documentation and then go back to the CLI. So we replicated all of our CLI help into the browser.

And if you are developing an oclif CLI, this is something that we also offer out of the box so that you can easily publish all of your documentation to the browser. And I’ll also add that as you’re developing your CLI, we’ve actually made it so that as you’re writing the code for the CLI, that the text for the help is right there.

Because we want that to be sort of like, sort of, top of mind for developers as they’re developing is what is your user going to see when they’re trying to figure out what this command does.

Input and output

Okay, next we’re going to get the meat of the CLI which is and input and output. CLIs are really great for bulk actions, so here we show how we do this picker in the CLI where we have somebody choose from potentially thousands of apps or subset of apps that they want to transfer somewhere else.

I’m going to talk a little bit about safeguards. So in the browser, you know, if you’re going to do something which we call a risky action like delete the database, or delete your app, or close down your whole account for some service, you’ll get a pop-up modal that will say, “Are you sure you want to do this thing?”

And tell you all about it and then you’ll confirm that you want to do it. And in the CLI there wasn’t a natural way of doing that. And so we developed this idea of a repeated pattern for confirming risky actions where you have to re-type in the command but this time put in a confirmation at the end – confirm or retype the name of the app. And this was really helpful for preventing people from taking a really destructive action with just typing a few words.

Now I’m going to talk a little about spinners. So when you’re using a browser, you’ll often see loading screens. And we didn’t actually used to have these spinners in our CLI, so if something was taking a few seconds you wouldn’t necessarily see any… well, you wouldn’t see anything.

You would type in your command and you would just be waiting. And we added these little spinners and got just amazing feedback on them. And it really helped bring the CLI alive for our customers. And one of our customers said something like, “It’s like a promise from the CLI that it will return with something.”

And then some things take a little bit longer, so for example if you’re spinning up a database it could take maybe you know, five minutes, and that’s the case where you don’t really want to be sitting there and have the spinner going. And so for that we use notifications, where you know, once the database has spun up, you would get this notification and this alert.

CLI superpowers

And when we launched this we found this got quite mixed feedback. Some people loved it, and some people didn’t like it. And people tend to like to have a lot of control over their command line, it feels like their space. And one of the things we did was give people the ability to turn this off, so they wouldn’t have to have it if they didn’t like it.

And last, I’ll talk very briefly about CLI’s special powers, because I think we’re running a little bit low on time.

So yes, we often use table outputs in the CLI, you can graph across tables. So we prefer that output to the output that I show sort of on the top left. And we’re currently developing what we call CLI super tables, which will enable you to customize your table outputs, and then choose to extract that output as JSON or CSV.

And again, that’s something that if you think about, that would be really hard to do in the browser. So yeah, that’s a summary of some of the rules for creating a delightful CLI. And if you’d like to learn more, Jeff recently wrote this post called the “12 Factor CLI Apps,” you can find it on Medium if you Google it. And there that’s a lot more detail, and I’m going to hand it over to Jeff, now to do a run-through of an oclif demo.

A quick demonstration of oclif

[Jeff] So I want to show a quick demo of how to build a CLI with oclif. A new pattern that we’re starting to see in JavaScript especially is the idea of generators, and CLIs that sort of start go along with frameworks. So examples of that are you know, Create React App or Vue CLI, or Angular CLI, I think it’s called.

And in that spirit, I thought that, you know, we can’t have a framework without our own CLI, so I built a CLI for a CLI. So here we’re going to build a CLI to show the Stargazers of a GitHub app. So run the generator with NPX, just going to set the default options here.

We’re going to have Mocha and Typescript. You have the option to create your CLI with Typescript or with standard JavaScript. And now I’m going to run the CLI and just kind of list off the help. I might get the help for a specific command. I can run a command, and I can run a command with my name.

So that’s just what you get out of the box. Now I’m going to add Axios, which is a HTTP client for node. And I’ll create a new command called “Stars” so we can run my CLI Stars. And very quickly here I’m just going to go in and import that, get rid of the sample code, add an argument for the repository, set help description here, and make the HTTP request.

If you haven’t used JavaScript in a while it’s great now. They work great with async/await.
Log out to stand out each user. Show the help for the command I just created. You can see it has the description and the argument.

This is sort of what we talked about when we said that you kind of see the help as you develop. And there we just run the command and there we go. All right, thank you so much.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.