tokenarchive

tokenarchive

Enables agents to query your archived AI coding usage through read-only tools for usage summaries, project breakdowns, daily trends, and archive health.

Category
Visit Server

README

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.

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.

<table> <tr> <td width="50%"><img src="docs/models.png" alt="Cost by model"></td> <td width="50%"><img src="docs/projects.png" alt="Cost by project"></td> </tr> <tr> <td><img src="docs/devices.png" alt="Cost by device"></td> <td><img src="docs/blocks.png" alt="Recent billing windows"></td> </tr> </table>

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 (optional, recommended)

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

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured