# Clawdmeter v3 — multi-provider (alpha) Extend the watch beyond Claude Code to show usage for several AI coding providers, let you pick which one the display tracks, and recolor the whole UI to the active provider's brand. Branch: **`v3-dev`** (off v2 `d55dc4a`). v2 stays on `v2-dev`. ## Providers (initial set) | id | provider | used via | brand accent | | ----------- | --------------------- | -------------------------------- | ------------ | | `anthropic` | Claude Code | Anthropic OAuth (today's daemon) | `#d97757` clay | | `openai` | OpenAI Codex | Codex CLI subscription (`~/.codex`) | `#10a37f` green | | `zai` | z.ai GLM Coding Plan | Anthropic-compatible endpoint | blue (TBD) | ## Locked decisions (2026-07-10) - **Metric = rate-limit %** — the same two-bar 5h / weekly model as Claude, read from each provider's CLI subscription. Fall back to spend / token counts for a provider only if it genuinely doesn't expose limits. - **Switch on both PC and watch** — pick the active provider in the desktop panel *and* on the watch (cycle / selector); the theme recolors live. - **Brand palette** (starting point, tuned on-device): Anthropic clay `#d97757`, OpenAI `#10a37f`, z.ai blue (exact hex TBD). ## Architecture ### Daemon — provider abstraction - New `daemon/providers/` package: - `base.py` — `Provider` ABC: `id`, `label`, `accent`, `async poll() -> ProviderStatus`. - `anthropic.py` — today's logic moved here (`poll_api`, `compute_today_usage`, OAuth refresh), behaviour-identical. - `openai_codex.py`, `zai.py` — added in M2 / M3. - `ProviderStatus` = normalized `{s, sr, w, wr, st, ok, tokens_today?, cost_cents_today?}`. - **Config v2** (`config.py`): add `providers` (per-provider enable + creds), `active_provider`, `display_order`. Migrate v1→v2 by wrapping the existing setup as `anthropic`. - Poll loop drives the **active** provider; for on-watch cycling it may poll all enabled providers and cache, so switching is instant. ### Payload - Add **`pv`** (provider id) so the watch knows which theme to wear; usage fields stay normalized (`s/sr/w/wr/st/tk/tc/...`). - On-watch switch: watch → PC command **`{"cmd":"prov","id":"..."}`** sets `active_provider` (same channel as the dimmer / button commands, no new GATT). ### Firmware — runtime theming (the meaty part) - Convert `theme.h` compile-time `#define`s into a runtime **`Palette`** (`lv_color_t accent/green/amber/panel/bar_bg/...`) plus shared `lv_style_t` objects for the accent / panel / text roles. - `ui_set_theme(pv)` swaps the palette + updates the shared styles + invalidates — **no widget recreation** (LVGL styles propagate to attached widgets). - Per-provider **logo** on the usage screen (swap the image source). - On-watch provider switch: a small selector (button on the usage screen, or a Providers entry in the launcher) → sends `{"cmd":"prov",...}`. ### Panel (desktop) - Provider selector (which one displays) + per-provider credential / enable fields. Reuses the existing FastAPI + WebView2 settings panel. ## Milestones - **M1 — framework + Anthropic refactor + runtime theming.** Provider ABC + `AnthropicProvider` (identical behaviour) + config v2 + `pv` in the payload. Firmware runtime palette + shared styles + `ui_set_theme` + per-provider logo slot + on-watch switch plumbing. Panel provider selector (only Anthropic active yet). *Deliverable: behaviour unchanged, but themeable and switch-ready.* This is the big refactor and de-risks M2/M3. - **M2 — OpenAI (Codex) provider.** Read Codex rate-limit / usage. Source TBD — Codex is installed at `~/.codex` (`auth.json`, `config.toml`, `state_*.sqlite`, `logs_*.sqlite`, `sessions/`); investigate whether limits come from the state DB or ChatGPT backend headers. Green theme + OpenAI logo. Fall back to spend/tokens if the % model isn't available. - **M3 — z.ai (GLM Coding Plan) provider.** `ANTHROPIC_BASE_URL` is already set on the dev machine → z.ai is likely used through its Anthropic-compatible endpoint, so reuse the Anthropic poll pointed at z.ai's base URL + z.ai key, reading the same `anthropic-ratelimit-*` headers. Blue theme + z.ai logo. - **M4 — polish.** On-watch switch UX, per-provider splash decision, panel niceties. ## Open items / assets - Exact brand hexes (OpenAI `#10a37f` proposed; z.ai blue TBD — finalize on device). - **Logos** — need official OpenAI + z.ai marks as RGB565 (user provides / points to source, per the "don't hand-author brand art" preference). Claude logo already in `logo.h`. - Splash — currently Claude pixel-art (claudepix); per-provider splash is an open choice (keep Claude, go neutral, or per-provider). - Naming — keep **Clawdmeter**; multi-provider under the same identity.