A local, always-on activity monitor and cost/token telemetry for Claude Code and Codex. It reads the JSONL session files these tools already write to disk and turns them into two views:
- Live monitor — an
htopfor Claude + Codex. Every active chat, its workflow / sub-agents (Claude and Codex), what each is doing this second, tokens ticking up, and an estimated cost. Web (:8181) + aclaude-topterminal command. - Cost / output history — a per-chat ledger across all sessions with a daily chart, a by-project breakdown, and an output ⇄ cost ranking toggle.
Plus an optional Grafana + Prometheus historical dashboard fed by Claude Code's OpenTelemetry export.
No cloud, no accounts, zero npm dependencies — the live monitor is standard Node.js.
Windows? The live monitor runs as-is (it uses
os.homedir(), no hardcoded paths). See WINDOWS.md — it has a paste-ready prompt for Claude Code on Windows.
The live monitor replicates Claude Code's built-in workflow progress panel — for all your live work at once:
- Per chat: project, git branch, model, current tool (
Read server.js,Bash …), tokens (gen / in / cache), estimated cost, running-agent count. - Workflows → phases → agents: each workflow expands into its phases (Map / Design / Synthesize …) with completion dots and a per-agent table of Tokens · Tools · Time · Cost. The Tokens column matches Claude's own panel exactly (the agent's final-turn input context). Completed workflows collapse to one line; running ones stay expanded.
- Codex agents nested under the chat that launched them (linked via
sessionId), with live token usage read from the Codex rollout file in real time. - By-engine sidebar: a sticky panel rolling up all work — ✦ Claude (chats + running sub-agents) and ⟠ Codex (all recent jobs, tagged with their project).
The history page (/history) adds an all-time / today / 7-day summary, a daily bar chart, a
cost/output-by-project breakdown, and the full per-chat ledger grouped by day.
- Node.js 18+ (for the live monitor — the only hard requirement).
- Claude Code and/or Codex actually running on the machine (so the session files exist).
- Optional, historical stack: Prometheus 3.x + Grafana (macOS:
brew install prometheus grafana).
git clone https://github.com/NeoRagnar777/claude-codex-telemetry.git
cd claude-codex-telemetry
node live-monitor/server.mjs # then open http://127.0.0.1:8181
# terminal view:
node live-monitor/claude-top.mjs # --all to expand completed workflowsThat's it — no install step. It reads your local session files and updates live.
The bin/ scripts install everything (live monitor + Prometheus + Grafana + a Codex token
exporter) as launchd user agents that start on login:
brew install prometheus grafana
bin/start.sh # install + start all four services
bin/status.sh # health check
bin/stop.sh # stop + uninstall- Live monitor: http://127.0.0.1:8181
- Grafana dashboard: http://127.0.0.1:3000/d/claude-code-telemetry (anonymous, localhost only)
The
launchd/*.plistandbin/*.shfiles use absolute paths for the author's machine — adjust the/Users/...paths (and thenode/ Homebrew paths) if you clone to a different location. The live monitor itself needs no such changes.
See WINDOWS.md — the live monitor works out of the box; there's a copy-paste brief for Claude Code to set it up (including a Scheduled Task for auto-start).
Everything is derived from files Claude Code and Codex already write:
| Source | Path (macOS ~ / Windows %USERPROFILE%) |
Gives |
|---|---|---|
| Chat transcripts | .claude/projects/<proj>/<uuid>.jsonl |
model, tokens, current tool, branch, status |
| Workflow agents | <uuid>/subagents/workflows/wf_*/ + <uuid>/workflows/wf_*.json |
phases, labels (map:backend), per-agent state |
| Codex jobs | .claude/plugins/data/codex-inline/state/*/jobs/task-*.json |
model, effort, status — linked to the chat via sessionId |
| Codex live tokens | .codex/sessions/**/rollout-*-<threadId>.jsonl |
real-time tokens — a job's threadId == the rollout's session id (in the filename); we tail-read the last token_count event (last 64 KB only, so running jobs stay cheap) |
The backend (live-monitor/server.mjs) serves the web UI, pushes state over SSE
(/events), and exposes JSON at /api/state and /api/history. claude-top reads
/api/state. Files are re-parsed only when their mtime changes, so it stays light.
Cost = cumulative input·output·cache_creation·cache_read tokens × model pricing
(opus-4-8 $5/$25/$6.25/$0.50, sonnet-5 $3/$15/…, haiku-4-5 $1/$5/… per M). It's an
estimate (and cache-read-heavy on long sessions), useful for relative spend, not an
invoice. Codex is subscription-billed, so its rows show tokens, not dollars — the primary
Codex number is "new work" = non-cached input + output.
Claude Code can export OpenTelemetry metrics. Enabling it (via a env block in
~/.claude/settings.json) pushes token/cost metrics to a local Prometheus, visualized in
Grafana — token usage and estimated cost broken down by model, subagent (agent.name),
and session, over time.
// ~/.claude/settings.json → "env": { ... }
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://127.0.0.1:9090/api/v1/otlp",
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": "cumulative",
"OTEL_METRIC_EXPORT_INTERVAL": "10000"Prometheus runs with --web.enable-otlp-receiver; Grafana auto-provisions the datasource and
the "Claude Code + Codex Telemetry" dashboard from grafana/provisioning/. The codex-exporter
scrapes ~/.codex/sessions for Codex token/rate-limit metrics (Codex has no OTel export).
| Service | Port | What |
|---|---|---|
| live-monitor | 8181 | real-time web UI + SSE + /api/state + /api/history (drives claude-top) |
| prometheus | 9090 | OTLP receiver + TSDB (historical) |
| grafana | 3000 | historical dashboards |
| codex-exporter | 9464 | Codex token/rate-limit metrics for Prometheus |
live-monitor/ server.mjs, collector.mjs, claude-top.mjs, public/{index,history}.html
codex-exporter/ exporter.mjs
grafana/ provisioning/ (datasource + dashboard) , dashboards/claude-code.json
prometheus.yml Prometheus config (OTLP receiver + scrape)
launchd/ macOS user-agent plists
bin/ start.sh / stop.sh / status.sh / claude-top (macOS)
Everything binds to 127.0.0.1 only. Cost/token figures are estimates. Not affiliated with
Anthropic or OpenAI.