I promised another team at work I would rewrite their shell script as a command line dev tool in Golang.
The old UX of the script was suboptimal. It ran a slow interactive shell script that made you go through an interactive menu tree every time, even when you already knew what you wanted to do. It had to be run inside Docker to handle a python dependency, making the initial startup even more tedious.
It got me thinking: What makes a good command line tool?
To be sure, we already have CLI tool frameworks (like Cobra) that tell us some common best practices in this area:
- Standard Linux-style argument parsing
- Short and long option support
- Subcommand support (like
git blame
,kubectl exec
).
(I’ll use Cobra for extensibility, even though the Go standard lib already has a basic flag package.)
A few more things I thought of:
- Multiple usage modes: It can let you specify the exact command you want, or it can show your options if you don’t know. You can type
cook rice --color=brown
or if you just typecook
, it will ask if you want to make rice, barley, orzo, or couscous. Explain
and/ordry run
mode: It should be able to tell you what it will do without doing it. It should be able to explain its own activity in case of doubts.Verbose
output: It should give you the choice between seeing the implementation details or just seeing the TDLR of what happened.- Pretty output, using colors and/or emojis nicely to convey meaning. (It’s 2024 - our terminals support Unicode too.)
- Diagnostics. It should be able to check its own configuration and self-describe.
- Solid help pages.
tool --help
should be comprehensive.tool subcommand --help
should work too. - Credential integrations. If you have to enter creds for any operations, it should make this as easy as possible. (For instance, using password manager integrations when possible.)
- Progress bars. When we are doing slow operations, display progress nicely.
- Plays well with other tools. It should provide either colorized or noncolorized output; it should provide human and machine readable output; it should fit organically into the shell environment.
- Minimal dependencies.
A few things I don’t like in command line tools:
- Inadequate
--help
output. - Non-GNU option parsing style (see: JVM tools like
keytool
; see also:openssl
). - Pedantic, when that adds no special value.
- Inflexible or difficult to configure.
- Poorly organized codebase (for tools where you can consult the codebase).
- Difficult to install.
- Difficult to upgrade.
I can’t promise anyone that I can accomplish 100% of this, but I think it’s a good start at a wishlist.