PREFACE
Command line clients are everywhere. Almost everyone, at least in tech, is using them.
There are a lot of successful command line clients out there: the Linux project has git and the Node.js project has npm. We use some of them multiple times per day. Apache CouchDB recently got nmo (speak: nemo), a tool to manage the database cluster. We can learn a lot from successful command line interfaces in order to write better command line clients.
When I started to get interested in command line clients I realised that there are a lot of discussions and informations on the web about writing APIs. The web is full of tutorials to teach you how to build APIs, especially REST-APIs, but almost nothing can be found about writing good CLIs. This book tries to explain what makes a good CLI. In the second part of the book we will build a small command line client to learn how to use Node.js to create great command line clients that people love.
The goal of the book is to show the principles to build a successful command line client. The provided code should give you a good understanding what is important to build successful command line clients and how you could implement them.
Every section has its own code examples. Before you run the code, you have to run npm install
in the folder that belongs to the section.
You can download the code samples at http://theclibook.com/material/sourcecode.zip.
I trust you and published this book without DRM. Please buy a copy at http://theclibook.comin case you did not buy the book.
I am very happy about feedback. Please send and feedback or corrections to
I hope you enjoy the book please recommend it in case you like it.
WHATMAKESAGOODCLI?
In this chapter we will take a look at successful command line clients and what they are doing pretty well, which will help us to understand the problems users face using the Terminal. Understanding the problems of our users will help us to build better command line clients with Node later in the book.
Lets take a look at how people usually use a CLI: most of the time a human sits in front of a keyboard and interacts with a terminal. We want to use simple and recognisable commands for our CLI. Sadly just easy recognisable commands dont get us very far right now.
Maybe the problem is easier to understand if we take a look at something what I would call a bad CLI:
$ mycli -A -a r foo.html error: undefined is not a function
In my example I have to enter cryptic commands which is answered by a very cryptic error message. What does -A -a 16 and r mean? Why I am getting an error back, am I using it wrong? What does the error mean and how can I get my task done?
So what makes a good CLI? Lets try it with the following three principles:
- you never get stuck
- it is simple and supports powerusers
- you can use it for all the things!
In short: A successful CLI is successful because its users are successful and happy.
You never get stuck
Nobody likes to be in a traffic jam, stuck, just making a few meters per minute.We want to reach our target destination, thats all we want!The same applies for our users. Both developers and users are extremely unhappy whenthe tools they use are standing in their way. They just want to get their task done.
So what does, You never get stuck mean, exactly? It means that we should always offer our users a way to solve their task, a command should never be a dead end. Additionally the developers of the CLI should avoid every source of friction in their tool.
Lets take a look at me, trying to use git:
$ git poll git: 'poll' is not a git command. See 'git --help'. Did you mean this? pull
In this example I entered a wrong command. git answers friendly: Hey Robert, it looks like you entered a wrong command, but if you type in git --help
, you can list all the existing commands. And hey, it just looks like you mistyped git pull, did you mean git pull?
git offers us a way to continue our work and finish the task.
And if we take a look at npm, another successful CLI client, well see the same concept:
$ npm ragrragr Usage: npm where is one of: access, add-user, adduser, apihelp, author, bin, bugs, c, cache, completion, config, ddp, dedupe, deprecate, dist-tag, dist-tags, docs, edit, explore, faq, find, find-dupes, get, help, help-search, home, i, info, init, install, issues, la, link, list, ll, ln, login, logout, ls, outdated, owner, pack, prefix, prune, publish, r, rb, rebuild, remove, repo, restart, rm, root, run-script, s, se, search, set, show, shrinkwrap, star, stars, start, stop, t, tag, test, tst, un, uninstall, unlink, unpublish, unstar, up, update, upgrade, v, verison, version, view, whoami npm -h quick help on npm -l display full usage info npm faq commonly asked questions npm help search for help on npm help npm involved overview Specify configs in the ini-formatted file: /Users/robert/.npmrc or on the command line via: npm key value Config info can be viewed via: npm help config npm@2.7.4 /Users/robert/.nvm/versions/node/v0.12.2/lib/node_modules/npm
In this example I try to put garbage into npm, so npm answers friendly: Hey Robert, I dont know that command, but here are all the commands that would be possible. You can use them like this and get help about them by typing in npm help .
Like git, npm immediately offers help to enable me to finish my task, even if I have no idea how to use npm at all.
Still lost?
What if I still need help? Maybe I want to get some help before I just try out commands. Turns out there is a quite reliable way to ship documentation on Unix or Linux, man-pages!
Figure 1. The man-page for git pull
Man-pages are quite nice, as you dont need the internet to open them. You can also stay in the same terminal window to read them and dont have to switch to another window, e.g. a browser.
But some users dont know about man-pages or they dont like to use them. Additionally many of them will be on Windows which cant handle man-pages natively, so git and npm offer their documentation as webpages, too:
Figure 2. The documentation website of the git project
Both git and npm are making use of a trick: they write their documentation once (e.g. in Markdown or Asciidoc) and use the initital source as the base for the different formats of their docs. Later they convert them to different formats, e.g. to html.
If you take a look at the man-pages of git and npm, you will notice that their websites are basically framing the content from the man-page with a header and a sidebar.
Figure 3. The manpage for npm publish
Figure 4. The documentation website of npm
Error handling
Sometimes things go still horribly wrong Lets take a look at my example for a bad CLI again:
$ mycli -A -a r foo.py events.js:85 throw er; // Unhandled 'error' event ^ Error: ENOENT, open 'cli.js' at Error (native)
In this case we are getting back a stacktrace without much context. For most people these stacktraces look quite cryptic, especially for people that dont write Node.js on a daily basis.