~/sumit/portfolio — notes-on-writing-a-cli-people-will-actually-use.md
writing.md/Notes on writing a CLI people will actually use
---
title: "Notes on writing a CLI people will actually use"
date: 2025-01-09
tags: [craft]
reading_time: 8 min
slug: notes-on-writing-a-cli-people-will-actually-use
---

Notes on writing a CLI people will actually use

8 min read craft by sumit

Most CLIs fail at being CLIs the moment they start acting like applications. A good CLI is a function you can call from a terminal; a bad one is an app you have to learn.

Two years of building internal tools, a pile of feedback from people who'd rather not be using my stuff, here's what actually moves the needle.

Defaults are the product

The default command is 80% of the user experience. If typing mytool without arguments doesn't do something useful — print help, run the common case, explain itself — the rest of the polish doesn't matter.

Whatever the most common subcommand is, make it the default. Don't hide behind subcommands for their own sake.

Flags should be rare

Every flag is a decision I'm asking the user to make. Users don't want to make decisions; they want their thing to work.

"The best flag is the one that doesn't need to exist."

If two flags are almost always set together, collapse them. If a flag has a sensible default 95% of the time, set that default and let the rare case override.

Errors are documentation

When something fails, the error message is the only documentation most users will read. Write it like a human:

✗ Cannot deploy — your git working tree has uncommitted changes.
  Run `git status` to see them, commit, then retry.

Not:

Error: WORKING_TREE_DIRTY

The three commands most CLIs forget

  • mytool --version
  • mytool --help (and mytool subcommand --help)
  • mytool doctor — or whatever you call "is my environment OK?"

The first two are table stakes. The third is the one that separates polite CLIs from great ones.

One last thing

Ship with one good example in the README. Not three. Not a reference. One, annotated line-by-line. That's the example people will copy, modify, and base their mental model on.