Comment by bfirsh
6 years ago
Hello HN!
We’re Ben, Aanand, Carl, Eva, and Mark, and we made the Command Line Interface Guidelines.
Earlier this year, I was working on the Replicate CLI [0]. I had previously worked on Docker so I had a bunch of accumulated knowledge about what makes a good CLI, but I wanted to make Replicate really good, so I looked for some design guides or best practices. Turns out, nothing substantial had been published since the 1980s.
On this search I found a superb blog post by Carl about CLI naming [1]. He must be the only person in the world who cares about CLI design and is actually a good writer, so we teamed up. We also were joined by Aanand, who did loads of work on the Docker CLIs; Eva, who is a technical writer, to turn our scrappy ideas into a real piece of writing; and Mark, who typeset it and made a super design.
We love the CLI, but so much of it is a mess and hard to use. This is our attempt to make the CLI a better place. If you’re making a tool, we hope this is useful for you, and would love to hear your feedback.
Some of it is a bit opinionated, so feel free to challenge our ideas here or on GitHub! [2] We’ve also got a Discord server if you want to talk CLI design. [3]
[1] https://smallstep.com/blog/the-poetics-of-cli-command-names/
I did not see a personal pet-peeve of mine:
If a user of your CLI tool has explicitly requested the built-in help text via --help (or an equivalent switch that requests help) then that help text shall be output on stdout.
It always peeves me to do:
only to find that the explicit request for help (the --help switch) has output the help text on stderr, and I then have to redo the invocation:
to cause the help text to actually be piped into less.
I've learned since to use |& instead (on bash):
Less characters to type.
What I do is with the -man switch:
it opens the browser on the manual page for the command, such as for dmd it's https://dlang.org/dmd-windows.html
The result so convenient I added -man to the other command line tools. I thought about adding clickable urls to the error messages, but it just made the output too cluttery.
THANK YOU. Showing the usage documentation when the user has explicitly asked for it /is not an error/.
Yes, but many apps show help text when incorrect arguments are provided so, it’s an error in those cases. The dev probably doesn’t want to bother with using different output channels for the same help text.
2 replies →
Your CLI should also have a man page, installed in the standard way. IMO, -? or --help should be fairly terse, ideally one screenful or less. More complete documentation should go in the man page.
Edit: wrote this before I read "Don’t bother with man pages." Strongly disagree. Relying on web docs leaves your users in the lurch if they are working on a system with no external network.
> "Don’t bother with man pages." Strongly disagree.
Me too. I don’t want to jump to a different program, plus man pages are greppable. And you want the man pages that apply to the machine you’re using (versions, etc) — especially important when you’re using a remote machine (think how common then idiom is to do `ssh foo man blah|less` )
> "Don’t bother with man pages." Strongly disagree.
Me as well. Though I am not against well linked documentation on the web. But man pages provide several unique advantages.
- Because man pages are installed with the same package the software comes in, their version matches exactly to the version of the installed software.
- Man pages don't require an internet connection or a running server. The internet connection can be a problem in certain kinds of enterprise networks, embedded system or during my commute in the train. The running server costs money who might not be willing to spend it as long as I would like to use the software.
- Linking from the executable to the web is tricky. Does the terminal support clickable links? Which browser should I start? Does it help the user in any way to start a browser on a far away machine that he connected to through ssh, mosh, telnet or morse code over avian carrier?
- It is very easy and safe to open a man page to an unknown command. You can be sure the command is not executed by accident. If I have to type `some-command --help` I am never sure if this is one of those commands that doesn't accept --help and does something stupid instead.
Despite all these advantages of man pages or offline available documentation I also like good online documentation. https://www.postgresql.org/docs/current/ comes to my mind when thinking about excellent software documentation. Granted it is not a one-minute tutorial for the latest newbie. But for someone using that piece of software for years, its value cannot be overstated imho.
While I regularly rely on `man` (and would agree with you for systems that have it), I'd also like to add that you should consider people on other systems, as well.
I'm still stuck on Windows for work, and e.g. the way Git (at least the Windows version from git-scm.org) handles this is problematic.
Something like `git --help` will open the URL to a help page (that also takes ages to load) in the browser. Manpages don't exist and there is no useful substitute. And this in a Git distribution that ships with its own GNU environment (MSYS2). And then, there's Git LFS, for which I haven't even found a working help command yet.
While the original idea might have been that the terminal way of looking things up is too confusing for Windows users (which I find ironic, given that said users installed a terminal program), I find it still makes Git even more arcane on this platform.
Edit: Coming back to `man`: Git is in the useful position of shipping their own GNU environment. That means, they could still introduce manpages. Other, small CLI utilities usually don't have that luxury. In those cases, some kind of access to the information in the manpage would still be very handy, even if it is just in `tool --help`.
4 replies →
I think (correct me if im wrong) tools shells like fish and zsh use the man pages to extract the param suggestions. That saves me so much time
1 reply →
I’ve been learning Perl lately, and was surprised and pleased to learn that the built-in pod2usage() functionality for converting POD documentation in your program into --help output also automatically supports manpage output. So the Perl programs I’ve been writing all include this as part of their arg-parsing loop:
That second line is all it takes to produce a manpage too. Then it’s just a matter of writing the POD documentation for it.
It is admittedly a little unusual to consume a manpage by typing `someprog --man` instead of typing `man someprog`, but it’s very convenient for self-contained scripts.
I write docs as a plain text file (in /usr/share/doc), works everywhere, view with anything in any way you want, locally or in the web, no converters needed.
Turns out, nothing substantial had been published since the 1980s.
The best reference I've found on this is The Art of Unix Programming, which was published in 2003:
https://www.amazon.com/UNIX-Programming-Addison-Wesley-Profe...
The book is also online for free:
Command Line Options: http://www.catb.org/~esr/writings/taoup/html/ch10s05.html
User Interface Design Patterns: http://www.catb.org/~esr/writings/taoup/html/ch11s06.html
Still it's nice to see this knowledge circulating!
Joel Spolsky's 2003 review of this book: https://www.joelonsoftware.com/2003/12/14/biculturalism/
An excellent book! It was one of the first software development books I read and still shapes my programming style. I probably ought to read it again though, I suspect I would understand a lot of it a lot better now...
Since you bring up Docker, this little behavior has always baffled me:
But:
What's up with that? I'm guessing cobra nonsense, because everyone ends up wrapping cobra's weird API differently...
I know you're talking about how it's repeated three times, but something else here really bothers me.
I understand if they're deprecating it because they plan to replace it with something else, but if they don't then I'll be pretty disappointed. From their docs, it looks like some of their other subcommands have shorthands which conflict with `-h'? Fine, I guess, but that just means when `-h' does work it'll shoot people in the foot with that other behavior.
Software that clearly knows what I want, but refuses to, annoys me so much. For example,
because they added `quit' as a top level variable with a `__str__' defined which returns that string. Do anything else! Make the `__str__' definition quit the program or something, test if it's being run at the top level in the CLI and quit, special case the CLI input so if only `quit' is entered, it quits. Heck, maybe just prefill the `quit()' on the next line so I just have to hit return. Do anything but instruct me to do what you should have done in the first place.
I don't agree. Fail fast fail hard or you deliberately lie and confuse your users.
If I make a mistake - tell me. If you allow me to do it slightly wrong then suddenly in my universe there is no consistency between commands and that is way worse than being told what I did wrong.
I mean if you did that how would you access 'quit' if it is defined? It's a bit more complicated than it seems.
Though I get your general point.
3 replies →
He doesn't claim that docker cli is well designed, only that he worked on it. Docker cli is pretty bad indeed, tar tier. Its web docs are also an example of butchered web 2.0.
Looks like it wants you to type --help, not -h.
Still weird though, since -h is indeed a very very common shorthand used in many commands.
This is great, thank you! Under pagers, maybe add a note to respect PAGER if set? I prefer relying on terminal scrollback in some situations, and e.g. in psql often set PAGER=cat. Git respects this, too.
Most of what you say is useful common sense, but the bit about not bothering with manpages is plain evil. If anything, the man page must be written before the program interface!
Is there a usage statistic for how often man pages are read? I violently agreed with the article here. There are zero times I wouldn’t rather switch to a browser. Even if I had to dig up my phone from my pocket and search for help there, I’d much rather do that.
Also, more and more tools are cross platform and man pages aren’t a thing on windows (are they?).
I don't have any statistic, but I use them all the time.
Under vim's default configuration, manpages are a single keypress away. If you press "K", vim opens a window with the manpage of the word under the cursor. It happens instantaneously, and it uses the same font and color scheme than your code. I would really hate it if it opened a browser!
Really? So if I make a man page for my CLI tool you would assault me physically?
You should take your own description of your beliefs as a red flag to reassess them.
I use a few tools that don’t have man pages and I always find it jarring that I have to leave the CLI to get some basic usage info.
There is already tooling to generate manages and online/html docs from a single source. Reasonable thing seems to be “do both”. I’m not persuaded by “Windows is leaking.”
4 replies →
you're not the only ones who care! I've been collecting CLI design thoughts and nodejs utilities for a couple years: https://github.com/sw-yx/cli-cheatsheet/blob/master/README.m... just added yours!
It always seems to fall through the cracks in these discussions, maybe because there's not a lot of folks who run the distro, but Gentoo has very nice command line tools.
Do you mean emerge et al? I've been running Gentoo on my main machine for >1 year now, and I'm still having to check the manpage for flags constantly... I guess I wish that it was more explicitly "subcommandy."
Thanks for these resources! Definitely relate. CLI is the original chatbot
Thanks for writing! I haven't had a chance to read it yet, but I'm always looking for new opinions here. Looking forward to going through it :)
Hey, I can't zoom in or out on the website... The font always stays at the same huge size. Using Firefox on Windows
Hit us up on Twitter.
Eh, I think not.
The "commands" I create are, most often, small tools for my own use, so I don't worry about making the names short. I always try to make the name a verb, or include a verb, e.g. "fetchbookmarks", "deleteduplicates"; one exception would be in the case of converters, in which case "convert" is implicit, e.g. "csv2xml" or whatever; and there may be other cases where the verb is implied. The Huffman Coding is important, though, and I have made some tools I use a lot, so I gave them short names. I use gvim a lot, and the wrapper I wrote for it (which does smart finding - it will load foo.cpp wherever it is under your cwd, as long as there's only one) I named g. I don't expect to distribute this tool, so I don't care. :-)