|
| 1 | +# Five-minute consumer quickstart |
| 2 | + |
| 3 | +This is the smallest useful `base-cli` application: one public `App`, one |
| 4 | +command, one option, and the `run_app()` process boundary. It is suitable for |
| 5 | +a temporary consumer project and does not require Typer, Rich, YAML, or any |
| 6 | +private repository layout. |
| 7 | + |
| 8 | +## Install and create the command |
| 9 | + |
| 10 | +Use an isolated virtual environment when trying the recipe. Activate it using |
| 11 | +the command appropriate for your shell, then install the core package: |
| 12 | + |
| 13 | +```bash |
| 14 | +python -m venv .venv |
| 15 | +python -m pip install base-cli |
| 16 | +``` |
| 17 | + |
| 18 | +Create `hello.py`: |
| 19 | + |
| 20 | +```python |
| 21 | +from __future__ import annotations |
| 22 | + |
| 23 | +import base_cli |
| 24 | + |
| 25 | + |
| 26 | +app = base_cli.App( |
| 27 | + name="hello", |
| 28 | + lifecycle_options=base_cli.LifecycleOptions( |
| 29 | + json=base_cli.LifecycleOption("--json"), |
| 30 | + ), |
| 31 | +) |
| 32 | + |
| 33 | + |
| 34 | +@app.command() |
| 35 | +@base_cli.option("--name", default="world", show_default=True) |
| 36 | +def hello(ctx: base_cli.Context, name: str) -> int: |
| 37 | + ctx.log.info("greeting %s", name) |
| 38 | + print(f"Hello, {name}!") |
| 39 | + return base_cli.ExitCode.SUCCESS |
| 40 | + |
| 41 | + |
| 42 | +if __name__ == "__main__": |
| 43 | + raise SystemExit(base_cli.run_app(app)) |
| 44 | +``` |
| 45 | + |
| 46 | +The recipe uses only the public `base_cli` facade. Click remains the parser, |
| 47 | +while the consumer owns the command and its application behavior. |
| 48 | + |
| 49 | +## Run it in human mode |
| 50 | + |
| 51 | +```bash |
| 52 | +python hello.py --name Ada |
| 53 | +``` |
| 54 | + |
| 55 | +The command prints `Hello, Ada!` on stdout. The greeting log is on stderr, so a |
| 56 | +consumer can redirect or suppress logs without corrupting command output. |
| 57 | + |
| 58 | +## Run the same command as JSON |
| 59 | + |
| 60 | +The recipe explicitly enables the optional lifecycle `--json` flag. Capture and |
| 61 | +parse the one JSON envelope like this: |
| 62 | + |
| 63 | +```bash |
| 64 | +python hello.py --json --name Ada > result.json |
| 65 | +python -m json.tool result.json |
| 66 | +``` |
| 67 | + |
| 68 | +The success payload has `schema: "base-cli.output"`, `code: "ok"`, and a |
| 69 | +`details.stdout` string containing the command's human output. The `run_id` is |
| 70 | +runtime data and should not be hard-coded. Logs and diagnostics remain on |
| 71 | +stderr. See [JSON contracts](json-contracts.md) for the complete success, |
| 72 | +usage-error, and unexpected-error boundary. |
| 73 | + |
| 74 | +## What to validate |
| 75 | + |
| 76 | +The focused consumer checks are the two invocations above: confirm the human |
| 77 | +stdout and the JSON parse independently, and confirm that the process exit |
| 78 | +status is zero. For a repository change, run the focused documentation test |
| 79 | +with `python -m pytest tests/test_consumer_quickstart_docs.py` and run |
| 80 | +`git diff --check`. |
| 81 | + |
| 82 | +The core package requires Click and Python 3.10 or newer. Install |
| 83 | +`base-cli[yaml]` only when the consumer selects YAML configuration or output; |
| 84 | +Typer and other integrations are separate optional boundaries. See |
| 85 | +[dependency support](dependency-support.md) and [output contracts](output-contracts.md) |
| 86 | +before adding those integrations. |
0 commit comments