tokenarchive
Enables agents to query your archived AI coding usage through read-only tools for usage summaries, project breakdowns, daily trends, and archive health.
README
tokenarchive
Daily snapshots of your AI coding usage, kept forever.

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:

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:

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
/mcpfor machines that do not hold the archive. Mint anmcptoken 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
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。