Friendly Python CLI UX with Progress Bars and JSON Output Prompt
Add polished UX to a Python CLI — progress bars, colored output that degrades gracefully, a --json machine-readable mode, and clean handling of non-TTY and quiet modes.
- Target user
- Developers improving the usability of Python command-line tools
- Difficulty
- Beginner
- Tools
- Claude, ChatGPT
The prompt
You are a senior Python engineer who builds CLIs that are pleasant for humans and parseable by machines — at the same time.
I will provide:
- The CLI and its commands/output today
- Where it runs (interactive terminal, CI logs, piped into other tools)
- Any long-running operations that need progress feedback
Improve the UX with these requirements:
1. **Colored, structured human output** — use `rich` (preferred) or `colorama` for cross-platform color. Use color/emoji for status (success green, warn yellow, error red), tables for tabular data, and clear section headers. Keep it tasteful, not a circus.
2. **Degrade gracefully** — detect TTY (`sys.stdout.isatty()`); auto-disable color and progress bars when not a TTY or when `NO_COLOR` is set or `--no-color` is passed. CI logs must stay clean and readable.
3. **Progress feedback** — show a progress bar or spinner for long operations (with ETA/throughput when known). The spinner must not corrupt output when stderr/stdout are redirected; render progress to stderr so stdout stays clean for data.
4. **`--json` / machine mode** — a flag that emits a single well-formed JSON document (or JSON Lines) to stdout, with NO color, NO progress bar, NO log chatter mixed in. Logs/progress go to stderr. This makes the tool composable with `jq` and other tools.
5. **Verbosity controls** — `-v/-vv` and `-q/--quiet` to scale logging; quiet suppresses everything but errors and the final result.
6. **Correct streams + exit codes** — data on stdout, diagnostics on stderr, non-zero exit on failure so scripts can branch on it.
7. **Helpful errors** — human-friendly error messages (with a hint) in normal mode; structured `{"error": ...}` in `--json` mode.
Output: (a) a small `ui` helper module wrapping color/progress/print, (b) the TTY/NO_COLOR/json detection logic, (c) an example command refactored to use it in both human and `--json` modes, (d) a note on keeping stdout pure for piping.
Bias toward: stdout for data only, stderr for everything else, graceful degradation, and a JSON mode that is genuinely scriptable.