# CLI Development Patterns

## JSON Output

- Use `print(json.dumps(...), flush=True)` not `console.print()` — Rich adds ANSI codes in TTY mode
- Guard human-readable output: `if not json_output:`
- Write warnings/deprecation to stderr: `Console(stderr=True).print(...)`

## NDJSON Streaming

- Always emit `{"type": "done", "status": "complete"|"error"}` as final line
- Handle `KeyboardInterrupt` separately (inherits from `BaseException`, not `Exception`)
- Docstrings must match actual output schema

## Command Patterns

- `--json` / `-j` flag for machine-readable output
- Prefer `tu <resource> get <id>` over `tu <resource> ls <id>` for single-item fetch

## Bug Notes

When you find a bug in the CLI, add a short note here so future agents avoid repeating it.

- **print_json() adds ANSI in TTY**: Rich's `print_json()` detects terminal and adds color codes. Use `print(json.dumps())` for pure JSON.
- **Early return breaks flag combinations**: Check all flag combinations before returning early. Output shared data (like task ID) before checking if more work is needed, not inside the early-return block.
- **BaseException vs Exception**: `KeyboardInterrupt` inherits from `BaseException`, not `Exception`. Catch it separately.
- **Always exit non-zero on error**: After emitting error JSON, raise `typer.Exit(1)` so CI detects failures.
