See where your Claude Code tokens, time, and money actually go.
ccpulse-demo.mp4
Live, local-first analytics for Claude Code — tokens, cost, tool latency, and session timelines, sliced by project and session. A daemon watches your local session logs, indexes them into SQLite, and serves a dashboard. Nothing leaves your machine.
npx @omartoma/ccpulse@latest # starts the daemon and opens the dashboardOr install globally:
npm i -g @omartoma/ccpulse
ccpulse # same thingThe daemon watches ~/.claude/projects/, indexes events into SQLite, and serves
the dashboard at http://localhost:7878. To scope the dashboard to one project,
run npx @omartoma/ccpulse@latest open from that project's directory while the
daemon is running.
npx @omartoma/ccpulse@latest daemon --no-open # daemon without auto-opening the browser
npx @omartoma/ccpulse@latest status # check daemon health
npx @omartoma/ccpulse@latest reindex # drop the SQLite index, rebuild on next start- Per-project rollups — cost, tokens, sessions, and tool calls, with projects sorted by recency.
- Per-session timeline — sortable by time, in / out / cache↓ / cache↑, total
tokens, or cost. Filter by kind (
tool/claude/user/system/attachment). Click any row for the full event — message text, tool input JSON, hook payloads, the raw JSONL line. - Tool latency — count, average, and p95, per project and per session.
- Global time range — scope every view to the last 24h / 7d / 30d, a custom window, or all time. The range lives in the URL, so it survives reloads and makes views shareable.
Live updates stream over SSE — click the status pill in the header to pause or resume the subscription; resuming refreshes everything that changed while paused.
Environment variables:
| Variable | Default | Purpose |
|---|---|---|
CCPULSE_PORT |
7878 |
Dashboard / API port |
CCPULSE_DB |
~/.ccpulse/ccpulse.db |
SQLite index location |
CCPULSE_CLAUDE_DIR |
~/.claude/projects |
JSONL session-log root |
Cost is estimated from a per-model rate table mirrored from
LiteLLM.
Each daemon start fires a non-blocking fetch and writes the latest table to
~/.ccpulse/litellm-pricing.json; if the network is unreachable the bundled
snapshot stays in effect. The merge order, highest priority first:
~/.ccpulse/models.json— your override, always wins~/.ccpulse/litellm-pricing.json— runtime LiteLLM refresh- bundled snapshot — last successful build-time refresh
- hand-maintained defaults — final fallback for unknown models
Maintainers can rebuild the bundled snapshot with pnpm pricing:refresh.
- Reads
~/.claude/projects/*.jsonldirectly — if Anthropic changes that log format, parsing may need an update. - Cost is an estimate from bundled rates; correct it via
~/.ccpulse/models.jsonif the published rates drift. - Built in an hour to scratch a personal itch. No roadmap — but issues and PRs are welcome.
Requires Node ≥ 22.5 (uses the built-in node:sqlite). The daemon is local and
your data stays on your disk.
MIT — @omar-toma
