tokenchit
Supports signing in via GitHub device flow to verify a handle, publishing usage stats to a public leaderboard, and providing a GitHub Action to re-fetch and commit the generated stat card.
Turn your local AI coding agent logs into a stat card you commit to your README.
That card is this repository's own, generated by the command below and committed as a file. It is not a screenshot and not a hosted image — which is the whole point.
npx -y @tokenchit/cli@latest generateOne command: it finds your agents, shows your stats, writes the card, and puts you on the
board. Running it often? npm i -g @tokenchit/cli, then tokenchit generate.
┃ [1/3] DETECT AGENTS
┃ ● claude-code ~/.claude*/projects/**/*.jsonl
┃ ✓ 3 agents, written to .tokenchit.json
────────────────────────────────────────────────────────────
┃ [2/3] YOUR STATS
┃ ~16.7B $7,392 27d 51
┃ TOKENS EQUIV. COST STREAK ACTIVE DAYS
┃
┃ 30d ▁··▄▆▆▆▅▁▃▅█▃▂▄▂▁▅█▆▂█▇█▅▄█▇▆▃ 3.07B in 7d
┃ ✓ wrote tokenchit.svg
────────────────────────────────────────────────────────────
┃ [3/3] THE BOARD
┃ ✓ published as @iyashjayesh — tier: verifiedWhy this one
The card is a file, not a URL. Comparable tools serve cards from a hosted endpoint, so your README depends on someone else's uptime and rate limits. A committed SVG has none of that — GitHub serves it directly, and it keeps working if this site goes away.
Nothing leaves your machine unless you ask.
syncandrecapmake no network request.publishis the only command that uploads, and--dry-runprints the exact bytes.Honest about what it cannot see. Logs get rotated, prices change, and some models have no public price. Where a number is incomplete, the tool says so.
npx -y @tokenchit/cli@latest recap # the year in review, a second committable SVGRelated MCP server: claude-spend
What it reads
agent | source |
Claude Code |
|
Codex |
|
OpenCode |
|
Copilot CLI and Gemini CLI are detected and reported as unsupported: Copilot records only a live context gauge, and Gemini's transcripts carry no token counts.
Your numbers will not match Claude Code's Stats panel. It counts an API call once per
streaming rewrite, so it reads roughly twice as high. sync prints both figures and the gap.
Equivalent cost is not what you paid — it is what these tokens would cost at list API
rates. Most agent usage runs under a subscription. See docs/internals.md.
Commands
tokenchit generate detect agents, write the card, join the board
--no-publish stop after the card
tokenchit init detect agents, write .tokenchit.json
tokenchit sync read your logs, show your stats, write the card
tokenchit publish put your row on the public board
tokenchit recap year in review, as a second committable SVG
tokenchit ledger show the local history bank, or rebuild it
tokenchit schedule print a cron or launchd entry; installs nothing
tokenchit login prove your GitHub handle (device flow, no password)
tokenchit logout forget this machine
tokenchit whoami who this machine is signed in astokenchit help <command> explains one command. NO_COLOR=1 drops colour and animation.
Common flags: --out, --theme auto|light|dark, --layout default|compact, --json,
--dry-run.
Keeping the card fresh
The card is a file, which is the point — and a file does not update itself. Re-running
generate is the honest answer, but nobody remembers to.
There is an action in this repository for the half a runner can actually do:
# .github/workflows/card.yml
name: card
on:
schedule: [{ cron: "0 6 * * *" }]
workflow_dispatch:
jobs:
refresh:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v7
- uses: iyashjayesh/tokenchit@v1
with:
handle: your-handleIt does not read your logs, and it cannot. An Actions runner has no access to
~/.claude or ~/.codex, so nothing on a runner can regenerate a card from source — you
still run publish from the machine that has the logs. What the action does is re-fetch the
card you already published and commit it, so the SVG in your README stops drifting away from
your real numbers while readers keep loading a committed file rather than an endpoint.
It refuses to overwrite a good card with a bad response: a non-SVG body, a non-200, or the
placeholder card the endpoint returns for a handle with nothing on the board. That last one
matters — without it a typo in handle commits an empty card on a schedule, silently,
forever.
Inputs are handle (required), output, layout, theme, agents, hide, commit and
commit-message; layout, theme, agents and hide are the same options the embed
endpoint takes. It outputs changed so you can gate later steps on a real update.
One thing to know: GitHub disables scheduled workflows in a repository after 60 days with no
activity, and a run that finds an unchanged card makes no commit. On a quiet repository the
schedule can switch itself off. workflow_dispatch is there so you can start it again, and
the run summary says which happened.
From an agent, not a terminal
There is an MCP server in packages/mcp, so a model can answer questions about your usage
instead of you reading a table:
{
"mcpServers": {
"tokenchit": { "command": "npx", "args": ["-y", "@tokenchit/mcp@latest"] }
}
}Four tools — get_usage, get_daily_usage, get_recap and detect_agents. All of them
read the same logs the CLI reads, and none of them can make a network request: the
net.isolated test covers packages/mcp/src alongside the CLI, and unlike the CLI this
package has no allowlisted module, so every file under it must be clean. Adding a fetch
anywhere in it fails the suite.
Two things it does that a plain data dump would not. Every figure ships with its caveat as a
sibling field, because a model handed equivCostUsd on its own will report it to you as
money you spent — and it is not. And a tool that fails answers with isError rather than a
transport error, so "no logs on this machine" reaches the model as something it can relay
instead of something it has to guess at.
It reads the ledger and never writes it. sync banks what it saw because you asked it to; a
tool call is a question, and a question that mutates state on disk is a surprise you cannot
see or undo.
Privacy
sync and recap make no network request at all.
publish is the only command that uploads anything. It sends daily token totals per agent,
model names, and your handle — never prompts, replies, file paths, branch names, or repository
names. --dry-run prints the exact bytes so you can check rather than take our word.
Five tests in packages/cli/test/privacy.test.js enforce this on every push, including one
that fails if any file outside net.ts can open a socket — across the CLI, the core engine
and the MCP server.
The board
Opt-in, and only publish puts you there. Verified rows rank above unverified ones: signing
in is the only thing that ties a row to a GitHub account. An unverified row still appears.
Submissions are self-reported, so two bands guard them — rejected for the arithmetically
impossible, and held for review for the possible but far outside anything seen. A held row
is stored and returned to you, and kept off the board until a person looks. Both thresholds
have been raised after real users were refused; the reasoning is in
docs/internals.md.
Development
npm install
npm run build # core, then cli, then site
npm test # core, cli and site suites
npm run dev # the site at http://localhost:3000Node 22 or newer — OpenCode support uses the built-in node:sqlite. The site and the CLI
render through the same buildCardSvg(), so they cannot drift.
Licence
MIT.
Available Tools
4 toolsdetect_agentsA
Which coding agents are installed on this machine, where each one's logs live, and whether they hold readable usage. Call this first when a usage read comes back empty.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose the diagnostic nature of the operation plus the three facts returned. It does not state that this is a read-only/local scan, whether it is slow, or what permissions it needs, so some behavioral context is still missing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler, and the primary function is front-loaded ahead of the fallback-trigger guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no parameters, the description must describe the return payload, and it enumerates all three returned facts. An agent has enough to decide to call it and to interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; there is nothing for the description to clarify beyond what the empty schema already conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States precisely what the tool reports: installed coding agents, their log locations, and whether readable usage exists. This is specific enough to distinguish it from get_usage/get_daily_usage, which read usage rather than enumerate agent installations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger: 'Call this first when a usage read comes back empty.' That is a clear when-to-use condition tied to the sibling read tools. It stops short of naming the siblings outright or stating when not to bother calling it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_daily_usageA
Tokens per local calendar day, most recent last. Use this for questions about a specific stretch of time rather than a lifetime total.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | How many calendar days back to return, ending today. Idle days are included as zero. | |
| agents | No | Restrict the read to these agents. Omit for all of them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does disclose the return ordering (most recent last) and implies a read-only, non-destructive operation via 'get', but says nothing about pagination, response shape, or whether idle days are zeroed (that detail lives only in the schema). Adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with zero filler; the output semantics are front-loaded before the usage rule. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple, two-optional-parameter read tool with no output schema, the description covers what is returned and when to pick it. It is nearly complete; only the read-only/cost profile is left implicit, which is a minor gap given the 'get' naming.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters (days, agents) are already fully documented, including the zero-fill for idle days. The description adds no parameter syntax or behavioral detail beyond implying a bounded lookback window, so it earns the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the resource precisely ('tokens per local calendar day') and the ordering ('most recent last'), and implicitly separates itself from the sibling get_usage by contrasting a stretch of time with a lifetime total. It could be sharper by naming get_usage outright, but an agent can place it correctly without the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit selection rule: use this for a specific stretch of time rather than a lifetime total. That is genuinely actionable routing guidance, though it stops short of naming the alternative tool (get_usage) or giving any exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recapA
Year in review for one calendar year: headline tiles, per-agent and per-model breakdown, the busiest hour range, and activity aggregated by weekday and hour (not by date). The same figures tokenchit recap renders.
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | Calendar year. Omit for the current one. | |
| agents | No | Restrict the read to these agents. Omit for all of them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It does disclose the aggregation shape (by weekday and hour, not by date) and the returned content, but says nothing about read-only safety, required permissions, or error behavior for a 2-param tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core scope ('Year in review for one calendar year'), then a compact enumeration of outputs. The list of contents is long but each item conveys distinct return-value information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, describing the returned tiles, breakdowns, busiest hour, and weekday/hour aggregation is genuinely valuable and makes the return shape predictable. Minor gaps: no statement of read-only nature or expected failure modes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both 'year' (omit for current) and 'agents' (omit for all) are already fully documented in the schema. The description only reinforces 'one calendar year' and 'per-agent', adding no syntax or format detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (year-in-review recap for one calendar year) and enumerates the contents, which clearly separates it from get_daily_usage and get_usage. It never names a sibling for contrast, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the scope ('one calendar year', 'not by date'), which points away from the daily/usage siblings. There is no explicit when-to-use or when-not-to-use statement and no alternative is named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_usageA
Total local AI coding agent usage: tokens, equivalent cost, streak, active days, per-agent mix and per-model breakdown. Windows are all time, the current calendar year so far, the last 30 days and the last 7 days. Reads logs on this machine; makes no network request.
| Name | Required | Description | Default |
|---|---|---|---|
| agents | No | Restrict the read to these agents. Omit for all of them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden and does deliver a meaningful trait: 'Reads logs on this machine; makes no network request', which tells the agent this is a local-only read with privacy implications. It stops short of noting read-only safety, expected scan cost on large logs, or empty-state behavior, so it is good but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the returned metrics and followed by the windows and the local-read note. Every sentence contributes; the only minor density is the metric list, which is justified by the breadth of the return.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description compensates well by listing the returned dimensions, the four time windows, and the local/no-network behavior. The remaining gap is sibling orientation relative to get_daily_usage and get_recap, which matters for correct tool selection.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the single 'agents' parameter is already documented in-schema ('Restrict the read to these agents. Omit for all of them.'). The description adds no syntax or filtering detail beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('total ... usage') and resource, then enumerates the exact metrics returned (tokens, equivalent cost, streak, active days, per-agent mix, per-model breakdown). Very clear about what it does, but it never differentiates itself from siblings like get_daily_usage or get_recap, so an agent must infer the granularity distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The enumerated time windows (all time, current year, last 30 days, last 7 days) implicitly signal when this aggregate view is appropriate. However, there is no explicit when-to-use guidance and no direction to or away from get_daily_usage / get_recap, leaving the alternative-selection question unanswered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
- First observed
detect_agents - First observed
get_daily_usage - First observed
get_recap - First observed
get_usage
This server cannot be deployed
TDQS
Scored across 4 tools
get_usage (windowed totals), get_daily_usage (per-day series), and get_recap (year-in-review aggregates) have partially overlapping subject matter, but each description clearly states its scope and output shape. detect_agents is cleanly distinct. Minor risk that an agent asks for a time range and picks get_usage over get_daily_usage.
Three tools follow a clean get_<noun> snake_case pattern (get_usage, get_daily_usage, get_recap). detect_agents breaks the prefix convention slightly but is still snake_case and readable, so the set is nearly uniform.
Four focused tools cover the analytics surface without redundancy. It is on the lean side but each tool earns its place; nothing feels padded or missing at the count level.
Covers lifetime/window totals, daily series, yearly recap, and agent discovery/diagnostics, which addresses the core questions of a usage-tracking server. Possible gaps like per-project rollups or cross-agent comparison views are not indicated as supported, but no obvious dead end for the stated purpose.
Maintenance
Related MCP Connectors
Exact Claude API cost calc with real cache economics, plus a tiktoken-misuse scanner.
Anthropic organization usage and cost reporting through an admin API key connected by the user.
Cookieless dashboard aggregates for Claude and Cursor. No visitor hashes. Starter and Growth.
OpenAI organization usage and cost reporting through an admin API key connected by the user.
Related MCP Servers
- AlicenseAqualityAmaintenanceLocal-first dashboard + MCP server that parses Claude Code and Codex JSONL files into a SQLite cost / token tracker. Per-MCP and per-tool breakdown, session drill-down, dedup by request_id; never talks to vendor APIs51001MIT
- AlicenseNot gradedqualityDmaintenanceProvides tools for Claude to query local Claude Code token usage and cost data, enabling spend analysis and insights through natural language.171MIT
- AlicenseNot gradedqualityBmaintenanceAnalyzes Claude Code session token usage and cost locally — where spend actually lands across cache-read, cache-write and output, and what is consuming the context window. Read-only and offline: it parses your own session files and exposes analyze_claude_cost, get_cost_benchmark and tokenscope_share_summary.274MIT
- AlicenseNot gradedqualityAmaintenanceEnables local-first tracking of AI token usage and costs from Claude Code and OpenCode, answering queries about tokens, models, sessions, and cost through MCP tools and a CLI, with no network calls.1611MIT