# Clinic CLI Implementation Plan (Micro-Task + Context-Window Friendly)

> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Build a local `clinic` CLI binary in `clinic-cli` that wraps the Clinic API spec from `skills/platform/clinic-api/SKILL.md`, with separate API keys for `prod`, `staging`, and `dev`, plus easy environment switching.

**Architecture:** Implement a standalone Go module under `clinic-cli` with a single executable entrypoint and small internal packages for config, HTTP client, and command handlers. Persist env/key/url state in `~/.config/clinic/config.json` (or `$XDG_CONFIG_HOME/clinic/config.json`) with strict file permissions. Expose core API workflows as first-class subcommands and retain a generic `raw request` escape hatch.

**Tech Stack:** Go 1.23+, standard library (`flag`, `os`, `net/http`, `encoding/json`, `path/filepath`, `time`, `testing`, `net/http/httptest`).

**Tracking Artifacts:**
- Plan: `clinic-cli/docs/2026-04-03-clinic-cli-implementation-plan.md`
- Progress log: `clinic-cli/docs/2026-04-03-clinic-cli-progress-log.md`

## Execution Protocol (Mandatory)

Execute chunks/subtasks one at a time; do not run multiple plan subtasks concurrently.

For each subtask/chunk, use a fresh non-inherited subagent session and provide only the current subtask instructions plus minimal required repository context.

After each subtask/chunk, the parent agent must review/integrate the result, commit that subtask boundary, and update plan/progress tracking before moving to the next subtask.

If the runtime requires explicit delegation authorization, use this operator prompt template:

`Implement docs/2026-04-03-clinic-cli-implementation-plan.md using fresh non-inherited subagents per subtask, sequentially, with parent review/integration, one commit per subtask, and Progress updates after each subtask commit.`

---

## 1. How To Use This Plan

1. Work chunk-by-chunk (`C0` -> `C12`).
2. Complete steps in order inside each chunk.
3. After each completed step:
   - check the box,
   - add one line in the progress log,
   - note evidence command/output summary.
4. At context-window boundary (or end of session), fill the handoff template in the progress log.
5. Keep commits scoped to one chunk whenever possible.

## 2. Status Board

Update this table continuously.

| Chunk | Scope | Status (`todo/in_progress/done/blocked`) | Last Step | Evidence |
|---|---|---|---|---|
| C0 | Tracking scaffold and execution conventions | done | C0.3 | Progress log created and populated |
| C1 | Module bootstrap and CLI skeleton | done | C1.7 | `go build -o clinic ./cmd/clinic` and `./clinic --help` succeeded |
| C2 | Config model and secure persistence | done | C2.9 | `go test ./internal/config -v` passed (4 tests) |
| C3 | Root parser and global env resolution | done | C3.6 | `go test ./internal/cmd -run Root -v` passed (3 tests) |
| C4 | `auth` + `env` command family | done | C4.11 | `go test ./internal/cmd -run 'Auth|Env' -v` passed |
| C5 | Shared HTTP client and error contract | done | C5.9 | `go test ./internal/clinic -v` passed (6 tests) |
| C6 | Cluster commands (`search`, `search-id`, `get`) | done | C6.7 | `go test ./internal/cmd -run Cluster -count=1 -v` passed (3 tests) |
| C7 | Cluster commands (`get-by-id`, `topology`) | done | C7.7 | `go test ./internal/cmd -run Cluster -v` passed (7 tests) |
| C8 | Data proxy commands (`query`, `schema`) | done | C8.6 | `go test ./internal/cmd -run Data -v` passed (3 tests) |
| C9 | Metrics commands (`query`, `range`, `series`) | done | C9.7 | `go test ./internal/cmd -run Metrics -v` passed |
| C10 | Loki commands (`query-range`, `labels`, `label-values`) | done | C10.8 | `go test ./internal/cmd -run Loki -v` passed |
| C11 | Events + raw request command | done | C11.8 | `go test ./internal/cmd -run 'Events|Raw' -v` passed |
| C12 | Docs, full verification, and build artifact | done | C12.7 | `go test ./... -v` passed; `go build -o clinic ./cmd/clinic` succeeded; `./clinic --help`, `./clinic env current`, and unauthenticated `raw request` smoke check ran against prod (expected `401 Unauthorized: Invalid User`) |

## 3. Command Surface (Locked)

### Global
- `clinic --env <prod|staging|dev> ...`

### Auth and Env
- `clinic auth set-key --env <env> --api-key <key>`
- `clinic auth unset-key --env <env>`
- `clinic auth set-url --env <env> --url <https://...>`
- `clinic auth show [--env <env>]`
- `clinic env use <env>`
- `clinic env current`
- `clinic env list`

### Cluster
- `clinic cluster search --query <text> [--show-deleted --limit --page --cluster-status --deploy-type]`
- `clinic cluster search-id --cluster-id <id> [--show-deleted --limit --page]`
- `clinic cluster get --org-id <internal-org-id> --cluster-id <id>`
- `clinic cluster get-by-id --cluster-id <id>`
- `clinic cluster topology --cluster-id <id>`

### Data Proxy
- `clinic data query --cluster-id <id> --sql <sql> [--timeout <seconds>]`
- `clinic data schema --cluster-id <id> --tables <comma-list>`

### Metrics
- `clinic metrics query --cluster-id <id> --query <promql> [--time <ts> --timeout <duration>]`
- `clinic metrics range --cluster-id <id> --query <promql> --start <ts> --end <ts> [--step <interval> --timeout <duration>]`
- `clinic metrics series --cluster-id <id> --match <selector> [--match <selector> ...] [--start <ts> --end <ts>]`

### Loki
- `clinic loki query-range --cluster-id <id> --query <logql> --start <time> --end <time> [--limit <n> --direction <forward|backward> --step <interval> -o <format> --output <format>]`
- `clinic loki labels --cluster-id <id> [--start <time> --end <time>]`
- `clinic loki label-values --cluster-id <id> --label <name> [--start <time> --end <time>]`

Loki output and time handling notes:
- `loki query-range` defaults to log-line output; use `-o json` (or `--output json`) for raw API JSON.
- `loki query-range` `--limit` defaults to `30`, and accepted range is `1..1000`.
- `<time>` accepts:
  - datetime (`YYYY-MM-DD HH:MM:SS`, timezone optional; defaults to local timezone)
  - epoch in seconds/milliseconds/nanoseconds (auto-detected)
  - explicit suffix units: `s`, `ms`, `ns`

### Events
- `clinic events list --cluster-id <id> --begin-ts <sec> --end-ts <sec> [--name <event> --severity <n> --limit <n> --cursor <cursor>]`

### Raw
- `clinic raw request --method <HTTP_METHOD> --path </clinic/api/...|/data-proxy/...> [--query k=v]... [--header K:V]... [--body <json>|@file]`

## 4. File Layout (Target)

- `clinic-cli/go.mod`
- `clinic-cli/cmd/clinic/main.go`
- `clinic-cli/internal/cmd/root.go`
- `clinic-cli/internal/cmd/auth.go`
- `clinic-cli/internal/cmd/env.go`
- `clinic-cli/internal/cmd/cluster.go`
- `clinic-cli/internal/cmd/data.go`
- `clinic-cli/internal/cmd/metrics.go`
- `clinic-cli/internal/cmd/loki.go`
- `clinic-cli/internal/cmd/events.go`
- `clinic-cli/internal/cmd/raw.go`
- `clinic-cli/internal/config/config.go`
- `clinic-cli/internal/clinic/client.go`
- `clinic-cli/internal/.../*_test.go`
- `clinic-cli/README.md`

## 5. Chunked Implementation Tasks

### Chunk C0: Tracking Scaffold

**Objective:** Put progress/context tracking in place before code.

**Files:**
- Create: `clinic-cli/docs/2026-04-03-clinic-cli-progress-log.md`
- Modify: `clinic-cli/docs/2026-04-03-clinic-cli-implementation-plan.md` (status board updates during execution)

- [x] **C0.1** Create progress log template (session log + handoff block).
- [x] **C0.2** Add first session row with current branch and target chunk.
- [x] **C0.3** Define commit naming convention for chunks (`cX: ...`).

**Exit Criteria:** progress log exists and first row is filled.

### Chunk C1: Module Bootstrap

**Objective:** Produce a buildable `clinic` binary skeleton.

**Files:**
- Create: `clinic-cli/go.mod`
- Create: `clinic-cli/cmd/clinic/main.go`
- Create: `clinic-cli/internal/cmd/root.go`

- [x] **C1.1** Run `go mod init clinic-cli`.
- [x] **C1.2** Create `main.go` with `main()` calling root runner.
- [x] **C1.3** Add root runner with static help output.
- [x] **C1.4** Handle unknown command with non-zero exit.
- [x] **C1.5** Build `clinic` binary.
- [x] **C1.6** Run `./clinic --help` smoke test.
- [x] **C1.7** Record evidence in progress log.

**Verification:**
```bash
cd clinic-cli
go build -o clinic ./cmd/clinic
./clinic --help
```

**Exit Criteria:** binary builds and help renders.

### Chunk C2: Config Model + Secure Persistence

**Objective:** Implement env/key/url persistence with safe defaults.

**Files:**
- Create: `clinic-cli/internal/config/config.go`
- Create: `clinic-cli/internal/config/config_test.go`

- [x] **C2.1** Write failing test for config path resolution.
- [x] **C2.2** Write failing test for first-run defaults (`prod/staging/dev` URLs, `active_env=prod`).
- [x] **C2.3** Write failing test for round-trip save/load.
- [x] **C2.4** Implement config structs (`active_env`, `environments`).
- [x] **C2.5** Implement path resolver (`$XDG_CONFIG_HOME` fallback to `~/.config/clinic`).
- [x] **C2.6** Implement `LoadOrInit` with default URLs:
  - prod: `https://clinic.pingcap.com`
  - staging: `https://staging-clinic.pingcap.com`
  - dev: `https://dev-clinic.pingcap.com`
- [x] **C2.7** Implement `Save` with dir mode `0700` and file mode `0600`.
- [x] **C2.8** Implement `ResolveEnv(override)`.
- [x] **C2.9** Run config test suite and record results.

**Verification:**
```bash
cd clinic-cli
go test ./internal/config -v
```

**Exit Criteria:** config tests all green.

### Chunk C3: Root Parser + Global `--env`

**Objective:** Wire command dispatch with consistent env selection.

**Files:**
- Modify: `clinic-cli/internal/cmd/root.go`
- Create: `clinic-cli/internal/cmd/root_test.go`

- [x] **C3.1** Write failing test for global `--env` parsing before subcommand.
- [x] **C3.2** Write failing test for invalid env rejection.
- [x] **C3.3** Add shared runtime context object (`selected env`, `config`, `client`).
- [x] **C3.4** Route command families (`auth`, `env`, `cluster`, `data`, `metrics`, `loki`, `events`, `raw`).
- [x] **C3.5** Ensure fallback to `active_env` when no override provided.
- [x] **C3.6** Run root parser tests and log evidence.

**Verification:**
```bash
cd clinic-cli
go test ./internal/cmd -run Root -v
```

**Exit Criteria:** root command reliably resolves env and dispatch.

### Chunk C4: `auth` and `env` Commands

**Objective:** Make env/key/url switching usable before API commands.

**Files:**
- Create: `clinic-cli/internal/cmd/auth.go`
- Create: `clinic-cli/internal/cmd/env.go`
- Create: `clinic-cli/internal/cmd/auth_env_test.go`

- [x] **C4.1** Write failing test for `auth set-key`.
- [x] **C4.2** Write failing test for `auth unset-key`.
- [x] **C4.3** Write failing test for `auth set-url` URL validation.
- [x] **C4.4** Write failing test for masked output in `auth show`.
- [x] **C4.5** Write failing test for `env use` persistence.
- [x] **C4.6** Implement `auth set-key`.
- [x] **C4.7** Implement `auth unset-key`.
- [x] **C4.8** Implement `auth set-url`.
- [x] **C4.9** Implement `auth show` (masked key only).
- [x] **C4.10** Implement `env use`, `env current`, `env list`.
- [x] **C4.11** Run tests and record evidence.

**Verification:**
```bash
cd clinic-cli
go test ./internal/cmd -run 'Auth|Env' -v
```

**Exit Criteria:** auth/env commands pass tests and persist config correctly.

### Chunk C5: Shared HTTP Client

**Objective:** Centralize request execution, auth, and error handling.

**Files:**
- Create: `clinic-cli/internal/clinic/client.go`
- Create: `clinic-cli/internal/clinic/client_test.go`

- [x] **C5.1** Write failing test for base URL + path join.
- [x] **C5.2** Write failing test for bearer auth header injection.
- [x] **C5.3** Write failing test for query encoding and repeated params.
- [x] **C5.4** Write failing test for JSON body serialization.
- [x] **C5.5** Write failing test for non-2xx error contract.
- [x] **C5.6** Implement request builder and executor.
- [x] **C5.7** Implement JSON decoding and raw error passthrough.
- [x] **C5.8** Add default timeout and per-call override support.
- [x] **C5.9** Run client tests and record evidence.

**Verification:**
```bash
cd clinic-cli
go test ./internal/clinic -v
```

**Exit Criteria:** shared client behavior is deterministic and test-covered.

### Chunk C6: Cluster Commands Part A

**Objective:** Implement `search`, `search-id`, and `get`.

**Files:**
- Create: `clinic-cli/internal/cmd/cluster.go`
- Create: `clinic-cli/internal/cmd/cluster_test.go`

- [x] **C6.1** Write failing test for `cluster search` query params.
- [x] **C6.2** Write failing test for `cluster search-id` using `cluster_id`.
- [x] **C6.3** Write failing test for `cluster get` path format.
- [x] **C6.4** Implement `cluster search`.
- [x] **C6.5** Implement `cluster search-id`.
- [x] **C6.6** Implement `cluster get`.
- [x] **C6.7** Run tests and record evidence.

**Verification:**
```bash
cd clinic-cli
go test ./internal/cmd -run Cluster -v
```

**Exit Criteria:** cluster part A commands behave as expected.

### Chunk C7: Cluster Commands Part B

**Objective:** Implement `get-by-id` and `topology` with correct org/cluster logic.

**Files:**
- Modify: `clinic-cli/internal/cmd/cluster.go`
- Modify: `clinic-cli/internal/cmd/cluster_test.go`

- [x] **C7.1** Write failing test for exact `clusterID` match in org resolution.
- [x] **C7.2** Write failing test for `get-by-id` not-found behavior.
- [x] **C7.3** Write failing test for `topology` dedicated flow.
- [x] **C7.4** Write failing test for `topology` premium/byoc parent flow.
- [x] **C7.5** Implement `get-by-id`.
- [x] **C7.6** Implement `topology` branching by deploy type.
- [x] **C7.7** Run tests and record evidence.

**Verification:**
```bash
cd clinic-cli
go test ./internal/cmd -run Cluster -v
```

**Exit Criteria:** ID-based cluster workflows are reliable and tested.

### Chunk C8: Data Proxy Commands

**Objective:** Implement `data query` and `data schema`.

**Files:**
- Create: `clinic-cli/internal/cmd/data.go`
- Create: `clinic-cli/internal/cmd/data_test.go`

- [x] **C8.1** Write failing test for `data query` required args.
- [x] **C8.2** Write failing test for `data query` payload shape.
- [x] **C8.3** Write failing test for `data schema` query params.
- [x] **C8.4** Implement `data query`.
- [x] **C8.5** Implement `data schema`.
- [x] **C8.6** Run tests and record evidence.

**Verification:**
```bash
cd clinic-cli
go test ./internal/cmd -run Data -v
```

**Exit Criteria:** data commands map 1:1 to documented endpoints.

### Chunk C9: Metrics Commands

**Objective:** Implement instant/range/series PromQL commands.

**Files:**
- Create: `clinic-cli/internal/cmd/metrics.go`
- Create: `clinic-cli/internal/cmd/metrics_test.go`

- [x] **C9.1** Write failing test for `metrics query` params (`query`, `time`).
- [x] **C9.2** Write failing test for `metrics range` params (`query`, `start`, `end`, `step`).
- [x] **C9.3** Write failing test for repeatable `match[]` in `metrics series`.
- [x] **C9.4** Implement `metrics query`.
- [x] **C9.5** Implement `metrics range`.
- [x] **C9.6** Implement `metrics series`.
- [x] **C9.7** Run tests and record evidence.

**Verification:**
```bash
cd clinic-cli
go test ./internal/cmd -run Metrics -v
```

**Exit Criteria:** metrics commands fully covered by tests.

### Chunk C10: Loki Commands

**Objective:** Implement log query and label discovery commands.

**Files:**
- Create: `clinic-cli/internal/cmd/loki.go`
- Create: `clinic-cli/internal/cmd/loki_test.go`

- [x] **C10.1** Write failing test for `loki query-range` required args.
- [x] **C10.2** Write failing test for `loki query-range` optional args (`limit`, `direction`, `step`).
- [x] **C10.3** Write failing test for `loki labels` optional `start/end`.
- [x] **C10.4** Write failing test for `loki label-values` path and label arg.
- [x] **C10.5** Implement `loki query-range`.
- [x] **C10.6** Implement `loki labels`.
- [x] **C10.7** Implement `loki label-values`.
- [x] **C10.8** Run tests and record evidence.

**Verification:**
```bash
cd clinic-cli
go test ./internal/cmd -run Loki -v
```

**Exit Criteria:** Loki command family is complete and tested.

### Chunk C11: Events + Raw Request

**Objective:** Implement events listing and generic escape hatch.

**Files:**
- Create: `clinic-cli/internal/cmd/events.go`
- Create: `clinic-cli/internal/cmd/events_test.go`
- Create: `clinic-cli/internal/cmd/raw.go`
- Create: `clinic-cli/internal/cmd/raw_test.go`

- [x] **C11.1** Write failing test for events org resolution from cluster ID.
- [x] **C11.2** Write failing test for events query params and `cursor` header.
- [x] **C11.3** Implement `events list` endpoint call.
- [x] **C11.4** Write failing test for raw method/path validation.
- [x] **C11.5** Write failing test for repeated `--query` and `--header`.
- [x] **C11.6** Write failing test for `--body` and `@file` body handling.
- [x] **C11.7** Implement `raw request`.
- [x] **C11.8** Run tests and record evidence.

**Verification:**
```bash
cd clinic-cli
go test ./internal/cmd -run 'Events|Raw' -v
```

**Exit Criteria:** events and raw commands are available and validated.

### Chunk C12: End-to-End Verification and Documentation

**Objective:** Finalize docs, run all tests, and produce the `clinic` binary.

**Files:**
- Modify: `clinic-cli/README.md`
- Modify: `clinic-cli/docs/2026-04-03-clinic-cli-implementation-plan.md` (status board only)
- Modify: `clinic-cli/docs/2026-04-03-clinic-cli-progress-log.md`

- [x] **C12.1** Document build and setup in README.
- [x] **C12.2** Document env/key/url commands with examples.
- [x] **C12.3** Document one example per API command family.
- [x] **C12.4** Run full unit test suite.
- [x] **C12.5** Build binary `clinic`.
- [x] **C12.6** Run smoke command checks (`help`, `env`, one API call with mocked/real key as available).
- [x] **C12.7** Update status board and progress log with final evidence.

**Verification:**
```bash
cd clinic-cli
go test ./... -v
go build -o clinic ./cmd/clinic
./clinic --help
```

**Exit Criteria:** all tests pass, binary builds, docs match behavior.

## 6. Acceptance Criteria

- Multi-env config works for `prod/staging/dev` with independent API keys.
- Active env switching works via `clinic env use`.
- One-off override works via global `--env`.
- Default URLs are seeded exactly as agreed.
- Core command families map to Clinic endpoints and return API responses.
- Non-2xx responses include status and body for diagnosis.
- Existing skill helper scripts remain unchanged.

## 7. Context-Window Handoff Checklist

Use this at session end (also mirrored in progress log):

- Current chunk and step ID:
- Last completed checkbox:
- Files changed in this session:
- Commands run and outcomes:
- Open failures/blockers:
- Immediate next step (single action):
- Any assumption/decision made:

## 8. Assumptions

- This is additive work; no migration or deprecation of existing shell workflow.
- API keys stored in plaintext config with strict local file permissions (`0600`).
- JSON-first CLI output in v1.
- No CI integration required in this phase.
