Python CLI Tool with Click Prompt
Design a well-structured Python command-line tool using Click (or argparse) with subcommands, config precedence, good help text, and clean exit codes — packaged so it installs as a console script.
- Target user
- Engineers turning ad-hoc Python scripts into shareable CLIs
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a Python tooling expert who has shipped CLIs used by hundreds of engineers and knows that the interface is the product.
I will provide:
- What the tool does and its primary commands
- Inputs: flags, env vars, config file, stdin
- Distribution target (pip, pipx, internal index, single-file zipapp)
Design the tool and deliver working code:
1. **Library choice** — recommend Click vs argparse vs Typer for my case and justify it in two sentences. Default to Click for multi-command tools, argparse for zero-dependency single scripts.
2. **Command structure** — a top-level group with subcommands; shared options (`--verbose`, `--config`, `--output {text,json}`) defined once via a group callback or decorator and passed through `ctx.obj`.
3. **Config precedence** — explicit, documented order: CLI flag > environment variable > config file > built-in default. Show the resolution code and how `--config` loads YAML/TOML.
4. **Help + UX** — concise docstrings that become help text, sensible defaults shown in help, examples in the epilog, and `--version`.
5. **Exit codes + errors** — never let a raw traceback hit the user; catch expected errors, print a clean message to stderr, and exit with documented codes (0 ok, 1 generic, 2 usage). Use `click.ClickException`/`sys.exit` deliberately. Keep `--verbose` to surface the traceback for debugging.
6. **Output discipline** — machine-readable JSON when `--output json`, human text otherwise; data to stdout, logs/progress to stderr so the tool composes in pipelines.
7. **Testing** — a `CliRunner` (Click) or `subprocess`/`capsys` (argparse) test that asserts exit codes and output for the happy path and one error path.
8. **Packaging** — a `pyproject.toml` with a `[project.scripts]` console-script entry point so `pipx install` exposes the command. Note the minimal dependency pin.
Output: (a) the CLI module, (b) `pyproject.toml`, (c) two pytest tests, (d) example invocations showing text and JSON output.
Bias toward: predictable flags, no global mutable state, friendly errors over stack traces.