CLI tools are wonderfully focused: no layout, no responsive design, no browser quirks. Input, work, output. And they compose with everything else on your machine.

1. Follow the conventions

Users of command line tools have strong, correct expectations. Meet them and your tool feels professional; break them and it feels broken.

Read from stdin when no file is given. Write results to stdout, messages and errors to stderr. Exit 0 on success, non-zero on failure. Support --help and --version. Never use colour when output isn't a terminal.

cli-build.txt
Build a CLI tool that <what it does>. Language: <language>.

Conventions to follow exactly:
- Reads from a file argument, or stdin if none given.
- Results to stdout; all messages and errors to stderr.
- Exit 0 on success, 1 on error, 2 on bad usage.
- --help with usage, examples and every flag. --version.
- --json for machine-readable output.
- Colour and progress only when stdout is a TTY.
- Handle a broken pipe silently — piping to `head` must not error.

Make it work as part of a pipeline. That's the point.

That broken-pipe detail is small and it's what separates tools that feel right from tools that spew errors when you pipe them into head.

2. Errors on stderr, always

The rule that makes a tool composable. If your progress messages go to stdout, they end up in the file the user redirected to, and their data is corrupted with your chatter.

3. Make it safe by default

Anything destructive gets a --dry-run that prints what would happen, and ideally requires a confirmation or an explicit flag to actually do it. Tools that modify files in place without a preview get used once, cause a bad afternoon, and get deleted.

4. Distribution

For your own use, a script on your PATH is plenty. For sharing, a single self-contained binary or an install via the language's standard package manager. Don't ask people to clone a repo and install dependencies for a small utility.

Write the --help text before the code. It forces you to name the flags and describe the behaviour, and it usually simplifies both.