# Architecture

## Goal

Keep the CLI architecture shallow and legible so command-level changes stay local and easy to validate.

## Package Boundaries

- `cmd/clinic`: tiny binary entrypoint that delegates to `internal/cmd.Run`.
- `internal/cmd`: command graph, parsing, validation, per-command request shaping, and response rendering.
- `internal/timeexpr`: shared parsing for relative `now` expressions (`now`, `now-<duration>`, with `d` as a 24-hour day).
- `internal/legendlabels`: shared extraction of distinct legend labels across series metrics.
- `internal/config`: config storage, defaults, and environment resolution.
- `internal/clinic`: HTTP client, request transport, timeout handling, and API error normalization.

Dependency direction:

- `cmd/clinic` -> `internal/cmd`
- `internal/cmd` -> `internal/config`, `internal/clinic`
- `internal/cmd` -> `internal/timeexpr`
- `internal/cmd` -> `internal/legendlabels`
- `internal/timeexpr`, `internal/legendlabels`, `internal/config`, and `internal/clinic` are leaf packages.

## Request Lifecycle

1. `main.go` passes args into `cmd.Run`.
2. Cobra parses persistent global flags (`--env`, `--profile`, `--verbose`) before command dispatch.
3. runtime context resolves the selected environment, then resolves an optional profile inside that environment and builds a `clinic.Client` for that environment.
4. family handler in `internal/cmd/*` validates arguments and builds a `clinic.Request`.
5. `internal/clinic.Client.Do` executes the request and decodes output or returns `HTTPError`.
6. command handler writes formatted output.

## Key Invariants

- Runtime selection precedence:
  1. global `--env`
  2. persisted `active_env`
- Global diagnostics:
  - `--verbose` (or `-v`) prints runtime context diagnostics to stderr:
    - selected env/profile and their source,
    - current `CLINIC_CLUSTER_ID` / `CLINIC_RANGE_START` / `CLINIC_RANGE_END`,
    - selected profile defaults for `cluster_id` / `range_start` / `range_end`,
    - source used for resolved cluster/range parameters (`flag` vs `env` vs `profile`),
    - every outbound Clinic request method/path/query (+ headers/body when present).
- Profile selection precedence inside the selected environment:
  1. global `--profile`
  2. env-local `active_profile`
  3. no profile is valid
- Required parameter default precedence for cluster/range flags:
  1. explicit command flag
  2. environment variable fallback (`CLINIC_*`)
  3. selected profile defaults, when a profile is active in the selected environment
- If no profile is active in the selected environment, the profile layer is skipped entirely and command handlers rely on explicit flags or `CLINIC_*` variables.
- `cluster search-id` can auto-create an env-local profile on first exact cluster-ID match in the selected environment, but it does not switch `active_profile`.
- Config location and security:
  - path: `$XDG_CONFIG_HOME/clinic/config.json` or `~/.config/clinic/config.json`
  - directory mode: `0700`
  - file mode: `0600`
- Generated help and behavior must stay aligned; Cobra command metadata plus the shared help template in `internal/cmd/cobra_helpers.go` are part of the contract.

## Extending Safely

When adding behavior:

- keep parsing/validation in `internal/cmd`,
- keep transport concerns in `internal/clinic`,
- add tests beside changed package,
- update command and agent docs in `docs/`.
