Claude
Skills
Sign in
Back

cli

Included with Lifetime
$97 forever

CLI application design: argument conventions, output streams, exit codes, configuration hierarchy, interactive modes, and terminal UX. Invoke whenever task involves any interaction with command-line tools or terminal applications — building, reviewing, debugging, or designing CLI interfaces.

Design

What this skill does


# CLI Design

**Programs are composable by default.** stdout carries data, stderr carries diagnostics, exit codes carry status, and
signals carry intent. Get the boundaries right and everything else follows.

## References

- **Arguments** [`${CLAUDE_SKILL_DIR}/references/arguments.md`] — Full POSIX guidelines, GNU long option table,
  subcommand patterns, flag design
- **Output** [`${CLAUDE_SKILL_DIR}/references/output.md`] — Stream separation details, color codes, ANSI escapes,
  NO_COLOR spec, pager setup
- **Exit codes** [`${CLAUDE_SKILL_DIR}/references/exit-codes.md`] — Standard/extended code tables, signal exit codes,
  partial success patterns
- **Interaction** [`${CLAUDE_SKILL_DIR}/references/interaction.md`] — TTY detection, prompting patterns, confirmation
  levels, progress display, error format
- **Configuration** [`${CLAUDE_SKILL_DIR}/references/configuration.md`] — Full hierarchy, XDG spec, env var catalog,
  config file formats, secret handling
- **Signals** [`${CLAUDE_SKILL_DIR}/references/signals.md`] — Full signal table, SIGPIPE handling, crash-only design,
  child process signals

## Output Streams

This is the single most important convention. Mixing data and diagnostics in stdout is the #1 way to break
composability.

- **stdout is data.** Primary output goes to stdout -- query results, computed values, formatted data. This is what gets
  piped to the next command or redirected to a file.
- **stderr is diagnostics.** Progress indicators, status messages, warnings, errors, and debug output go to stderr.
  Users see stderr in the terminal even when stdout is redirected.
- **Check each stream independently.** stdout may be piped while stderr is still a TTY. Adapt output format per-stream:
  human-readable when TTY, machine-parseable when piped.
- **No animations when not a TTY.** Disable spinners, progress bars, and color when the target stream is not an
  interactive terminal. This prevents CI logs from becoming escape-code garbage.
- **Print something within 100ms.** Before any network request or long operation, print a status line to stderr. Silence
  looks like a hang.
- **Tell the user what changed.** When a command modifies state, describe what happened and suggest what to do next.

## Arguments

- **POSIX short flags, GNU long flags.** Single-letter options use `-x`, multi-letter use `--long-name`. Every short
  flag must have a long equivalent. Reserve one-letter flags for frequently-used options.
- **`--` terminates options.** Everything after `--` is an operand, even if it starts with `-`. This is POSIX Guideline
  10 and is non-negotiable.
- **Prefer flags over positional arguments.** Flags are self-documenting. Exception: primary action on a single target
  (`rm file.txt`, `cat file.txt`). Two or more positional args for different things is a design smell.
- **`-` means stdin/stdout.** When a command accepts file arguments, `-` means read from stdin (or write to stdout when
  context is clear).
- **Use standard flag names.** `-h`/`--help`, `--version`, `-v`/`--verbose`, `-q`/`--quiet`, `-f`/`--force`,
  `-n`/`--dry-run`, `-o`/`--output`, `--json`, `--no-color`, `--no-input`. Don't reinvent these.
- **Make flags order-independent.** Users add flags by pressing up-arrow and appending. `mycmd --flag subcmd` and
  `mycmd subcmd --flag` should both work where possible.

## Subcommands

- **`noun verb` or `verb noun`, pick one and be consistent.** Don't mix ordering styles. `docker container create` and
  `docker image pull` follow `noun verb`.
- **Support help at every level.** `mycmd --help`, `mycmd subcmd --help`, and `mycmd help subcmd` should all work.
- **No catch-all subcommand.** Don't interpret unknown first arguments as an implicit default subcommand. This prevents
  you from ever adding new subcommands.
- **No arbitrary abbreviations.** If `mycmd i` aliases `mycmd install`, you can never add `mycmd init`. Aliases must be
  explicit and stable.

## Exit Codes

- **0 = success, 1 = error, 2 = usage error.** This covers most programs. Only define additional codes when callers need
  to distinguish specific failure modes.
- **Signal exit codes use 128+N.** SIGINT (Ctrl-C) exits 130, SIGTERM exits 143. Preserve this convention so calling
  scripts can distinguish "user cancelled" from "error."
- **Never return 0 on failure.** Scripts depend on exit codes via `$?` and `set -e`. A false success silently breaks
  pipelines.

## Configuration

- **Flags > env vars > project config > user config > system config > defaults.** This is the universal precedence
  hierarchy. A flag always wins over an env var, which always wins over a config file.
- **Follow XDG for user-level files.** Use `$XDG_CONFIG_HOME/myapp/` (default `~/.config/myapp/`), not `~/.myapp`.
  Respect `XDG_DATA_HOME`, `XDG_STATE_HOME`, `XDG_CACHE_HOME`.
- **Respect well-known environment variables.** `NO_COLOR`, `FORCE_COLOR`, `DEBUG`, `EDITOR`, `PAGER`,
  `HTTP_PROXY`/`HTTPS_PROXY`, `TMPDIR`, `HOME`, `TERM`, `LINES`, `COLUMNS`. Check these before inventing app-specific
  alternatives.
- **Never read secrets from environment variables.** They leak through `ps`, Docker inspect, systemd, and process
  listings. Accept secrets via `--password-file`, stdin, or a credential helper.
- **Never read secrets from flags.** `--password=secret` leaks into `ps` output and shell history. Use `--password-file`
  or stdin.

## Color and Terminal Output

- **Disable color when:** stdout/stderr is not a TTY (check each independently), `NO_COLOR` is set and non-empty,
  `TERM=dumb`, or `--no-color` is passed.
- **Support `FORCE_COLOR` or `--color`** to override detection and force color output when the user explicitly wants it.
- **Use color intentionally.** Red for errors, green for success, yellow for warnings. Don't paint everything -- if
  everything is colored, nothing stands out.
- **Use a color library.** Don't hand-code ANSI escape sequences. Libraries handle NO_COLOR, TERM detection, and
  cross-platform differences.

## Interactive Behavior

- **Only prompt when stdin is a TTY.** If stdin is not interactive, fail with an error telling the user which flag to
  pass. Never hang waiting for input that will never come.
- **Provide `--no-input`.** An explicit flag to disable all prompts. Required for CI/CD, cron, and automation.
- **Confirm before destructive actions.** Prompt for `y/N` interactively, require `--force` non-interactively. For
  severe operations (deleting infrastructure), require typing the resource name.
- **Provide `--dry-run`.** For any state-modifying command, let users preview what would happen without executing it.
- **Don't echo passwords.** Disable terminal echo when accepting secret input. Provide `--password-file` as a
  non-interactive alternative.

## Signal Handling

- **Respond to SIGINT immediately.** Print "Shutting down..." before starting cleanup. Add a timeout so cleanup can't
  hang forever.
- **Second Ctrl-C skips cleanup.** Tell the user: "press Ctrl+C again to force." Then exit immediately.
- **Handle SIGTERM like SIGINT.** Process managers (systemd, Docker, K8s) send SIGTERM before SIGKILL. Complete cleanup
  within the grace period.
- **Handle SIGPIPE silently.** When the user pipes your output to `head`, don't print an error when the pipe closes.
  Exit quietly with code 141 or 0.
- **Design for crash recovery.** Use atomic file operations (write to temp, rename). Check for incomplete state on
  startup. Don't require cleanup to complete for correctness.

## Help Text

- **Support `-h` and `--help`.** Both must show help. Don't overload `-h` for anything else.
- **Show concise help with no arguments.** When a command requires arguments and gets none, show a brief description,
  one or two examples, and a pointer to `--help` for the full listing.
- **Lead with examples.** Users read examples first. Show common invocations before the flag catalog.
- **Suggest corrections.** When the user types a close misspelling, suggest the correct
Files: 8
Size: 37.6 KB
Complexity: 51/100
Category: Design

Related in Design