Control Tower
A personal Claude Code usage dashboard built into mariansan.io. Tracks token consumption across all projects — input, output, cache reads/writes, estimated cost, sessions, and turns. Supabase-backed ingest API, HMAC-SHA256 cookie auth, Recharts daily breakdown with range picker, and two sync scripts: one for org accounts via the Anthropic Admin API, one reading local SQLite directly.
What it does
- Password-protected dashboard at `/control-tower` showing Claude Code token consumption across all projects
- Per-project breakdown: input tokens, output tokens, cache reads, cache writes, estimated cost, sessions, and turn count
- Recharts stacked area chart with daily token breakdown by type and a range picker — 7 days, 30 days, 90 days, or all time
- Auto-refreshes every 30 seconds without a full page reload
- Ingest API at `/api/control-tower/ingest` accepts usage payloads secured by a Bearer token
- Two sync scripts: one pulls from the Anthropic Admin API (for org accounts), one reads from Claude Code's local SQLite database (`~/.claude/usage.db`) — no org account required
Why it matters
- ~20 minutes/week saved vs. estimating Claude Code costs manually from billing dashboards and API receipts
- Per-project, per-model attribution replaced ballpark monthly estimates — exact cost visibility that the Anthropic dashboard doesn't expose at the project level
- Owned data: token counts live in Supabase under my control, not in a third-party dashboard that holds API key access
Architecture
- Next.js App Router page with HMAC-SHA256 signed cookie authentication — Edge-safe, no JWT dependency
- Supabase PostgreSQL stores all ingested usage records; rows keyed by project, date, and model
- `/api/control-tower/ingest` endpoint validates Bearer token, upserts the usage record, and returns the stored row
- Recharts `AreaChart` with a controlled range state; data is fetched server-side on the page and passed as props
- `scripts/sync-claude-usage.py` reads `~/.claude/usage.db` (SQLite) and POSTs to the ingest API — works on any machine without an Anthropic org account
- Org script hits the Anthropic Admin API and maps the response to the same ingest shape
- Design follows the mariansan.io token system: ink/ivory/gold palette, ember gradient backgrounds, gold mono wordmark
Philosophy
- The feedback loop for AI usage should be as tight as the usage itself
- Two sync paths because most developers don't have org-level API access — the SQLite script makes it available to everyone
- Owned data: token counts live in a database I control, not a third-party dashboard with access to my API keys
- Next.js
- Supabase
- Recharts
- Anthropic API
- SQLite