[HN Gopher] CLI Guidelines - A guide to help you write better co... ___________________________________________________________________ CLI Guidelines - A guide to help you write better command-line programs Author : bfirsh Score : 145 points Date : 2020-12-04 16:33 UTC (6 hours ago) (HTM) web link (clig.dev) (TXT) w3m dump (clig.dev) | macintux wrote: | Thanks, this is sorely needed. Looking forward to taking time to | dig more deeply into it. | postgrescompare wrote: | Thank you! I'm working on the cli for | https://www.postgrescompare.com and I really want to make it | great! | klodolph wrote: | I think we should abolish different prefixes for short/long flags | except for core POSIX programs (like ls, cp, rm, mkdir, etc.) In | other words, "-flag" should be interchangeable with "-flag". The | ONLY reason I can think of why you would not recognize "-flag" as | equal to "--flag" is because you want to recognize it as "-f -l | -a -g", which makes sense for programs like ls, but for 99% of | newer programs, don't do it. Just make "-flag" and "--flag" | equivalent. | attractivechaos wrote: | > _for 99% of newer programs, don't do it_ | | The majority of recent tools in my circle follow this Unix | convention. That is a natural result when you use | getopt_long(). | mdoms wrote: | There's some excellent content here. Unfortunately it is hidden | behind an excessively wordy document. You should consider | bringing in a ruthless editor to cut this down to about a quarter | of it's current length. | dllthomas wrote: | Loving this! | | As a nit: | | > Let the user escape. Make it clear how to get out. (Don't do | what vim does.) If your program hangs on network I/O etc, always | make Ctrl-C still work. If it's a wrapper around program | execution where Ctrl-C can't quit (SSH, tmux, telnet, etc), make | it clear how to do that. For example, SSH allows escape sequences | with the ~ escape character. | | I find it confusing that vim is considered less discoverable here | than SSH. In either case, you can find the information in the | manual (not ideal, but a baseline). In the case of vim, when you | hit ctrl-c it tells you how to leave for real. So far as I'm | aware, there's no real way to discover the magic ~ invocations in | SSH except resorting to the manual or exhaustively trying every | key combo with no evidence that you're on the right track or that | there's even a track to be on. | | Also, vim _is_ (in part) a wrapper around program execution. | kevincox wrote: | I agree, if you press Ctrl-C vim (with default settings) | literally tells you how to quit. `\n~` in SSH is completely | unrecoverable. | kitotik wrote: | This is a great resource, thanks for the effort. | | I strongly disagree with the " Don't bother with man pages" | advice. It's extremely annoying when tools don't provide a | manpage. The overhead of opening up a browser to reference | command is cumbersome and highly annoying. | | There are tools such as pandoc that make generating manpages from | various source formats very easy. | | Perhaps it is just my grouchy old man syndrome... | jen20 wrote: | Absolutely - I can't buy into the "don't write man pages" idea. | | For many years I've had this function in my RC files for macOS: | pman() { man -t "$@" | open -f -a Preview; } | | It opens the given man page in Preview, typeset beautifully. No | such thing is available for random text printed to the console, | nor is a console pager (as recommended by this article) an | acceptable substitute for this. | mmalone wrote: | They're not saying you shouldn't provide command-line help. | Just that you should deliver them through a `help` subcommand | and/or through a `--help` flag (like `git` does) because people | don't find man pages and because man pages don't work on every | platform. | reaperducer wrote: | Why not both? | | Write the help for the more verbose of the two, then trim it | back for the other. | | Everyone gets what they want. | kitotik wrote: | Right. I still prefer terse help text from the command line, | and more in-depth in the man pages. | | I find commands with copious -h output and having to pipe | that into a pager or using scroll back a far worse UX than | just opening up a man page that's easily searchable / | scrollable. | mmalone wrote: | Yea that's reasonable, but there are pros and cons and it's | also definitely an opinion :). | | I don't see the problem with piping help text through a | pager (that's literally all `man` is doing). Alternatively, | a tool can use a pager automatically (as `git help ...` | does). So `man` isn't required to have a pager. Whether you | should use a pager by default is a different argument. | | That said, I find pagers annoying because it's hard to | switch back and forth between typing a command and the | docs. That's way easier to do with scrollback. Although | someone in this comment thread also mentioned the `PAGER` | env var, and that you can set `PAGER=cat`, which is a good | pro-tip. So, TIL. | | Still, if you're concerned with command-line ergonomics for | a broad audience I think there are more people that either | 1) know how to `| less` or 2) prefer or don't care about a | pager than people who are gonna automatically just know | they can do `PAGER=cat man <some-subcommand-of-my-cli- | tool>`. | | Plus, there's still the cross-platform argument. | | Oh, and OP doesn't mention this, but man pages also | complicate install, uninstall, versioning, and having | multiple versions of a tool installed simultaneously. | Built-in help is obviously just works and is distributed | with the standalone binary. To use man pages you have to | place additional artifacts on the system and make sure | they're managed correctly (e.g., versioned). It's | additional complexity with basically zero benefit. | | So yea. Seems like, as a rule, their guidance is | reasonable. I don't see a lot of benefit to using man pages | other than "because that's how it's always been done". | scbrg wrote: | > I don't see a lot of benefit to using man pages other | than "because that's how it's always been done". | | Man pages are organized, categorized, indexed and | searchable. It's a common format that can be read by | multiple pagers (including dedicated GUI browsers for | those so inclined). They're also available when the | command might not be. There are definitely benefits over | _command --help_ other than the syntax of the invocation. | | > I find pagers annoying because it's hard to switch back | and forth between typing a command and the docs. | | less -X | | If people don't know about _man_ , why not teach them? A | simple line in the summary -h gives that says: _For more | information, read the man page: man foo_. | | > Plus, there's still the cross-platform argument. | | This just makes me sad. I don't know exactly where we'd | be if every computer system didn't feel it needed to be | garbage just because Windows is. But I don't think it'd | be quite as bad as where we are. | colordrops wrote: | Perhaps prioritize a --help flag over a man page, but add | both if time permits. In any case, a man page is static text | and much easier to implement than --help, especially if you | have multiple help modes (e.g. verbose or different sets of | commands). | dllthomas wrote: | Man pages improve discoverability. You only find --help | contents if you already know which command you want. Man | pages are searchable (with `man -k` or `apropos`). | | This is most relevant when it's a tool that isn't going to be | immediately obvious anyway (if I'm trying to figure out how | to do XYZ on heroku, it's not unreasonable to expect me to | look at the heroku program I installed), and especially when | it's a tool that might be installed by default or installed | and forgotten about. | jcynix wrote: | Agreed. And man page content is searchable too, even with | regular expressions while in a pager like less. | dllthomas wrote: | Sure, but they advise pulling up a pager anyway if the | content is long. | _underfl0w_ wrote: | Maybe I'm suffering from similar syndrome, but I'm under 30 in | human Earth years. However, I very much agree with you and | would take it a step further to say that programmatically | opening the browser with the help flag is also very unwelcome | (I'm looking at you, git >.> ) | rhencke wrote: | It is your choice, in Git: git config | --global help.format man | kitotik wrote: | TIL! Thanks for that. | dllthomas wrote: | > Which means O_O and OwO are the only emoticons that are also | valid environment variable names. | | O_o | jdporter wrote: | XD | fwip wrote: | uwu what's this? | EE84M3i wrote: | It's kind of crazy that we still don't have a standard computer | readable way for a program to describe it's argument structure in | a computer readable way that could be used for command line | autocomplete. E.g. something like an extra section in the binary | that describes how arguments are processed. | d0mine wrote: | http://docopt.org/ | mmalone wrote: | Yea, like, imagine if posix pipes and command-line flags could | be typed. | vageli wrote: | Powershell offers this I believe. | jmmv wrote: | That's right. I recently wrote on this topic: | https://jmmv.dev/2020/10/powershell-cmdlet-params.html | mmalone wrote: | Yep. Not perfect... type systems have come a long way since | PowerShell did it. But it's a good start. | | Look at stuff like PowerShell secure strings for an example | of the sort of neat stuff you can do. | ChrisSD wrote: | NuShell is also attempting this. Both are cross platform. | | https://github.com/nushell/nushell | _underfl0w_ wrote: | Thanks for mentioning this! It looks super interesting, | but I hadn't heard of it before. | delusional wrote: | The general problem is that typing for these sorts of systems | suck. If it works it's a nice little safety feature, but when | the types don't line up it's infuriating. Treating everything | as a lowest common denominator makes compatibility trivial. | jmmv wrote: | Hah. This is a topic that's dear to my heart and have blogged | occasionally about it... but never in such a comprehensive form. | Great job! Now... I gotta read through everything. | | But... here is a series of blog posts in which I covered similar | themes years ago: https://jmmv.dev/series.html#CLI%20design | | And here is another single post that touches upon a single | guideline I came across while skimming through the text: | https://jmmv.dev/2020/08/config-files-vs-directories.html . It | might be helpful in providing more details about the _whys_ | behind each guideline. | | Lastly, I'll also mention the "Producing open source software" | book by Karl Fogel, which provides a lot of useful advice too, | especially on how to ship the tools: https://producingoss.com/ | bfirsh wrote: | 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] | | [0] https://replicate.ai/ | | [1] https://smallstep.com/blog/the-poetics-of-cli-command-names/ | | [2] https://github.com/cli-guidelines/cli-guidelines | | [3] https://discord.gg/EbAW5rUCkE | jdporter wrote: | _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. :-) | abathur wrote: | 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 :) | ucarion wrote: | Since you bring up Docker, this little behavior has always | baffled me: $ docker image ls -h Flag | shorthand -h has been deprecated, please use --help | | But: $ docker image -h ls Flag | shorthand -h has been deprecated, please use --help | Flag shorthand -h has been deprecated, please use --help | Flag shorthand -h has been deprecated, please use --help | | What's up with that? I'm guessing cobra nonsense, because | everyone ends up wrapping cobra's weird API differently... | codetrotter wrote: | 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. | whelming_wave wrote: | 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, $ python3 | Python 3.9.0 (default, Dec 2 2020, 10:34:08) [Clang | 12.0.0 (clang-1200.0.32.27)] on darwin Type "help", | "copyright", "credits" or "license" for more information. | >>> quit Use quit() or Ctrl-D (i.e. EOF) to exit | | 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. | resonantjacket5 wrote: | 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. | cle wrote: | You just access it, it's just a normal variable. | $ python3 Python 3.8.6 (default, Nov 18 2020, | 23:56:33) [GCC 9.3.0] on linux Type | "help", "copyright", "credits" or "license" for more | information. >>> quit Use quit() or | Ctrl-D (i.e. EOF) to exit >>> q = quit | >>> quit = "foo" >>> quit 'foo' | >>> quit() Traceback (most recent call last): | File "<stdin>", line 1, in <module> TypeError: | 'str' object is not callable >>> q() $ | uhoh-itsmaciek wrote: | 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. | raywu wrote: | Thanks for these resources! Definitely relate. CLI is the | original chatbot | swyx wrote: | 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! | alcover wrote: | Nice initiative! | | A few remarks : | | - the intro text is way too long | | - you contradict yourselves about stdout : `Log | messages, errors, and so on should all be sent to stderr.` | `Don't treat stderr like a log file, at least not by default.` | zokier wrote: | > The command line of the past was machine-first | | > Traditionally, UNIX commands were written under the assumption | they were going to be used primarily by other programs | | Is there any real factual basis for these claims? I find them | hard to believe, considering the origins of UNIX and the fact | that shell was the primary (or even only) user interface for the | system, and it was pretty much from day 1 designed as an | interactive system (contrasted to the more batch/system oriented | mainframes of IBM etc) | nrclark wrote: | I'd say say there's some truth to it, but maybe in an | accidental way. | | Shell scripts have been part of UNIX since day 1. A lot of | early UNIX commands were implemented as scripts, and shell was | always intended to be one of the main extension mechanisms for | users. Scripting is fundamentally based on the assumption that | a script will run various commands, glued together in a user- | specified way. | | So it's true to say that most early UNIX commands were designed | to be useful in a script, which implies that they were designed | for use by programs. Maybe not designed _exclusively_ for use | by programs, but definitely an important design consideration. | reaperducer wrote: | My recollection is that non-programmers followed the | instructions in the binder, which told them how to log in, and | then how to start the program they needed. Very basic stuff. | Actual commands were the province of programmers. | gruez wrote: | Why are the font sizes so huge? The computed font size is 30px, | compared to 12px for hn. ___________________________________________________________________ (page generated 2020-12-04 23:00 UTC)