Skip to main content
Glama
ddyy

tokenarchive

by ddyy

tokenarchive

Daily snapshots of your AI coding usage, kept forever.

The dashboard: per-device health, totals, and daily cost over time

ccusage can tell you what Claude Code, Codex, Gemini and friends cost you — but only as far back as the logs on your machine go, and those logs rotate. tokenarchive snapshots the ccusage report once a day, keeps every snapshot as an append-only JSON archive, and renders a dashboard from it. Optionally, a Cloudflare Worker keeps a copy of the archive off your machine, behind a passkey.

Two principles shape everything here:

  • Nothing is ever erased. Snapshots are the archive; every database is a derived copy that can be rebuilt from them.

  • Absence is never reported as zero. A day with no snapshot says so. $0.00 would claim we looked and you spent nothing.

Quickstart (macOS)

npx tokenarchive

The installer prompts for a device name and an optional Worker URL, puts the runtime under ~/.local/share/tokenarchive/app, schedules the daily job (23:50 plus every login — the script is idempotent), lets security prompt for the ingest token so it never crosses the installer's hands, and proves the whole thing with one real run. Re-run it any time to reconfigure; --uninstall removes everything except your archive.

Snapshots land in ~/.local/share/tokenarchive/{device}/{date}.json. To try it once without installing anything:

git clone https://github.com/ddyy/tokenarchive && cd tokenarchive && ./snapshot.sh

Other platforms: everything except the scheduling glue is portable. sync.js, the importer and the dashboard are plain Node; port snapshot.sh to a systemd timer or cron job and the rest follows.

Related MCP server: Semantic Code Search MCP Server

The dashboard

generate-dashboard.js builds a single self-contained HTML file — no framework, no server, no external requests. It imports new snapshots into a local SQLite read model first (import-snapshots.js), so regeneration is incremental.

Every panel is a filter: click or drag across models, devices, agents, days, or billing windows and the rest of the page follows (⌘ adds to a selection, ⇧ extends it). Filters compose across dimensions with AND, and live in the URL fragment, so a view can be bookmarked.

A Display as switch — above the totals, and again in the sticky bar once they scroll away — measures the whole page in dollars or in tokens: the chart and its axis, the coverage shading, the billing windows, and every list, which reorders to match. Hovering a row gives the full name it had to truncate, its cost, tokens, the implied rate per million, its share of what is on screen, and — for projects — the session count and the span they cover:

Row hover detail

The coverage strip shows one cell per calendar day, so a gap is visible as a gap — days with no snapshot are never drawn as zero-usage days:

Coverage strip

Multiple devices

The archive is partitioned by device from the filesystem up: snapshots live in {data}/{device}/{date}.json, every database row carries the device, and importing is upsert-only. Machines therefore never merge or clobber each other, and anything that lands both machines' files under one data directory gives you a combined archive — a Worker, a synced folder, or a copied directory all work the same way.

Health is judged per device: each gets its own green/amber/red dot, its own last-snapshot date, and its own missing-days list, so one current machine cannot hide another that has gone quiet. A device that stops reporting keeps all of its history — the archive never erases; it just shows the gap.

The Worker below is the way to do this without moving files by hand.

The worker/ directory is a Cloudflare Worker that accepts snapshot pushes and serves the same dashboard from D1, behind WebAuthn passkeys. The raw snapshots are kept verbatim in R2 — that is what makes it a backup rather than a view: /admin/replay can rebuild D1 from the bucket without your laptop. See worker/README.md for the five-command deploy.

Once deployed, register a passkey at /auth/ — the first passkey claims the archive; adding another device's passkey requires being signed in. Then generate a per-device ingest token at /admin (the token reveal includes setup instructions) and the daily snapshot job pushes automatically. A machine that never syncs has lost nothing: the files on disk are the archive, and the next successful sync catches up. Stale pushes cannot clobber newer data — ingest keeps whichever snapshot is newest.

/admin manages the rest: ingest tokens and read-only MCP tokens (shown once, revocable per device), session-key rotation, a snapshot inventory, and /admin/replay, which rebuilds D1 from the R2 originals.

To add a second machine, run the installer there with the same Worker URL and mint it its own ingest token — a token only ingests as the device it was minted for, so one machine cannot write as another and revoking one never touches the others.

MCP

Ask your agent about your own usage. Two servers, same four read-only tools (usage_summary, usage_by_project, usage_by_day, archive_health), one shared implementation:

  • Local, over the SQLite archive on this machine:

    claude mcp add tokenarchive node /path/to/tokenarchive/mcp-server.js
  • Remote, served by the Worker at /mcp for machines that do not hold the archive. Mint an mcp token at /admin, then:

    claude mcp add --transport http tokenarchive https://YOUR-WORKER/mcp \
      --header "Authorization: Bearer YOUR-TOKEN"

Read-only by construction: there is no tool that writes, deletes or rewrites anything.

Configuration

Everything is overridable by environment variable, nothing requires it:

Variable

Default

TOKENARCHIVE_DATA

~/.local/share/tokenarchive

TOKENARCHIVE_DB

{data}/tokenarchive.db

TOKENARCHIVE_DEVICE

short hostname

TOKENARCHIVE_URL

unset — no sync

TOKENARCHIVE_TOKEN

unset — read from the login keychain (tokenarchive-ingest)

Tests

bash test/run.sh

Most suites are hermetic. Three (static, interaction, tooltip) run against the dashboard you last generated at ~/.local/share/tokenarchive/index.html, so they need a real archive on the machine — run the snapshot once first.

License

MIT

A
license - permissive license
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    B
    quality
    Not graded
    maintenance
    Provides comprehensive telemetry and usage analytics for Claude Code sessions, including token usage tracking, cost monitoring, and tool usage patterns. Enables users to monitor their Claude usage with detailed metrics, warnings, and trend analysis.
    12
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI assistants to query and analyze past Claude Code sessions, providing structured insights like file changes, decisions, errors, and git history across projects.
    11
    40
    1
    MIT

View all related MCP servers

Related MCP Connectors

  • One shared brain for your AI coding agents: team memory, agent Q&A, tasks, and file claims.

  • Read-only bank access for your AI agent. Connects Claude, ChatGPT, Cursor, Gemini, Codex.

  • See, price, and control every tool call your AI agents make: policy checks, cost, and audit tools.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ddyy/tokenarchive'

If you have feedback or need assistance with the MCP directory API, please join our Discord server