Self-hosted Claude Code usage & analytics dashboard (SvelteKit + SQLite). Agent parses JSONL transcripts; Docker one-command deploy.
Find a file
megaproxy 71a60ab054 toknmtr — self-hostable Claude Code usage & analytics dashboard
Server (SvelteKit + SQLite Docker container) + per-machine agent that parses
Claude Code JSONL transcripts. docker-compose one-command deploy; raw transcript
view + search gated behind SHOW_TRANSCRIPTS (hidden by default).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 19:33:55 +01:00
agent toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
ops toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
src toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
static toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
.dockerignore toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
.env.example toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
.gitignore toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
.npmrc toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
.prettierignore toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
.prettierrc toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
DEPLOY.md toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
docker-compose.yml toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
Dockerfile toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
eslint.config.js toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
package-lock.json toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
package.json toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
README.md toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
tsconfig.json toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00
vite.config.ts toknmtr — self-hostable Claude Code usage & analytics dashboard 2026-07-08 19:33:55 +01:00

toknmtr

Self-hosted Claude Code usage & analytics dashboard. An agent on each of your machines parses Claude Code's JSONL transcripts into a full event log and pushes it to a server (one SvelteKit + SQLite container). The server stores everything — usage, tool calls, commands, raw prompts/responses — and serves a dashboard plus a full-text-searchable session archive.

It's two halves:

  • Server (src/, shipped as a Docker image) — the dashboard, the ingest API, the DB.
  • Agent (agent/ + ops/, runs on each machine) — parses ~/.claude/projects/**/*.jsonl and POSTs to the server. Not part of the image; you run it wherever you use Claude Code.

The server image contains no data — the SQLite DB is created empty in a mounted volume on first run. All conversation content only ever comes from your agent pushing your transcripts to your server.

New here? Follow DEPLOY.md — a full step-by-step walkthrough (prerequisites, server, agent, security, updating). The sections below are the quick reference.


1. Run the server (Docker)

Requires Docker with the Compose plugin. From the repo root:

cp .env.example .env
# edit .env: set API_TOKEN to a long random secret
#   openssl rand -hex 32
docker compose up -d --build

The dashboard is now at http://localhost:3001. The DB lives in the toknmtr-data Docker volume; the container restarts unless stopped.

Privacy note — the dashboard has no auth. By default the two surfaces that expose verbatim prompt/response text (the per-session transcript view and full-text search) are hidden; charts, KPIs, and session metadata stay visible. Only set SHOW_TRANSCRIPTS=true in .env once you've put the dashboard behind auth (reverse proxy, VPN, etc.). Don't expose it to the public internet as-is.

Config (.env)

Var Purpose
API_TOKEN Required. Bearer token the agent must send to /api/ingest.
SHOW_TRANSCRIPTS true reveals transcript view + search. Unset = hidden (safe).
PORT Host port is set in docker-compose.yml (3001:3000).

2. Feeding it data (the agent)

The server starts empty. To populate it, run the agent on each machine where you use Claude Code (needs Node 24+ for --experimental-strip-types). One-time setup per machine:

mkdir -p ~/.toknmtr
cat > ~/.toknmtr/env <<'EOF'
TOKNMTR_URL=http://<server-host>:3001
TOKNMTR_TOKEN=<the same API_TOKEN you set on the server>
EOF
chmod 600 ~/.toknmtr/env

Then, from a clone of this repo on that machine:

# one-time: ingest all transcripts already on disk
node --experimental-strip-types agent/run.ts --backfill

# ongoing capture — register the Stop hook so every turn pushes incrementally
ops/install-hook.sh

ops/install-hook.sh adds a near-zero-cost Claude Code Stop hook (additive + reversible with --remove). An optional ops/install-cron.sh adds a reconcile sweep as a safety net. Full agent/capture docs — the ~/.toknmtr/env format, the hook-vs-cron tradeoff, backfill, and troubleshooting — are in ops/README.md.

Ingest is an idempotent upsert (keyed on host + session_id + uuid), so re-running the backfill or overlapping hook/cron sweeps never duplicates data.


3. Development

Node 24, SvelteKit 2 (Svelte 5), TypeScript, better-sqlite3.

npm install
npm run dev        # dev server
npm run check      # typecheck
npm run build      # production build → build/ (run with `node build`)
npm run lint       # prettier + eslint

Pricing lives server-side in src/lib/server/pricing.ts — adding a model is a one-line update. Because the subscription is flat-rate, all $ figures are notional (API-equivalent).