Renders a GitHub profile dashboard card — headline token/cost usage, a trend
graph, an activity streak, and a usage breakdown — from your local AI coding
agent session data, and publishes it into your username/username README.
It merges usage across all the machines you run it on using git itself as
the sync layer: no server, no account, no hosted service. The card renders
inside a collapsible <details> section, headline visible at a glance, so
it doesn't dominate your profile README(See my profile as live example).
By default, the injected card is one full-color SVG image — title, headline
stats, trend chart, streak, and breakdown together — switched between GitHub's
light and dark themes via <picture>, with the attribution line kept outside
the image as real markdown text (links are inert inside an <img>). Here's a
real card this tool rendered, embedded live below (switch your GitHub theme to
see the dark variant):
In your own profile repo, token-profile run writes the two SVGs under
.token-profile/ and injects the equivalent markup between the markers (the
docs/assets/ paths above are just this README's committed sample):
<picture>
<source media="(prefers-color-scheme: dark)" srcset=".token-profile/card-dark.svg">
<img src=".token-profile/card-light.svg" alt="Token Profile — last 3 days. Tokens: 2,700 (+50%) Cost: $4.05 (-10%). Streak: 3 days." width="100%">
</picture>Setting "renderMode": "ascii" in your config (see
Configuration below) renders the original plain-text card
instead — the same stats, no image, no color:
Token Profile — Tokens: 2,700 (+50%) Cost: $4.05 (-10%) Streak: 3 days
┌────────────────────────────────────────────────────┐
│ Token Profile — last 3 days │
│ │
│ Tokens: 2,700 (+50%) Cost: $4.05 (-10%) │
│ │
│ Trend: │
│ 1,200 ┼────────╮ │
│ 1,083 ┤ ╰──────────╮ │
│ 966 ┤ ╰────╮ │
│ 850 ┤ ╰───╮ │
│ 733 ┤ ╰────╮ │
│ 616 ┤ ╰────╮ │
│ 500 ┤ ╰ │
│ └┬───────────────────┬──────────────────┬ │
│ 06-30 07-01 07-02 │
│ tokens/day │
│ │
│ Streak: 3 days │
│ │
│ Breakdown (per model): │
│ claude-sonnet-5 — 2,200 tokens ($3.30) │
│ gpt-5.4 — 500 tokens ($0.75) │
│ │
│ Last updated: 2026-07-03 10:19 UTC │
└────────────────────────────────────────────────────┘
Generated by token-profile
- agentsview, installed and on
your
PATH. token-profile shells out to it to read local AI coding session data — see agentsview's own installation instructions. git, on yourPATH, with push access to the repo hosting your rendered profile (usuallygithub.com/<you>/<you>) from every machine you run token-profile on.
Pre-built binaries (linux/darwin, amd64/arm64) with checksums are published via GoReleaser on each tagged release — download one from this repo's Releases page, or build/install from source with Go 1.26+:
go install github.com/Christophe1997/token-profile/cmd/token-profile@latesttoken-profile initThe first time you run this with no config file yet, init launches a short
interactive wizard: it asks for your GitHub username, clone protocol
(https/ssh), and local clone path — each pre-filled with a sensible guess —
then:
- Clones your profile repo into place (or adopts an existing clone already sitting at that path, as long as its remote matches what you entered).
- Writes a full config file with the three collected fields plus safe, hand-editable defaults for everything else (see Configuration).
- Scaffolds
<!-- token-profile:start -->/<!-- token-profile:end -->markers into the target repo'sREADME.md, if they aren't there yet. - Performs a first run: resolves your local usage, writes this machine's snapshot, renders the card, and commits + pushes the updated README.
- Asks whether to register the refresh schedule now (default: every 6
hours) — on yes,
initinstalls it itself vialaunchctl bootstrap(macOS) orcrontab(Linux/other), no manual copy-paste required. A reviewable snippet is still written to--schedule-desteither way, in case you'd rather install it by hand or on another machine.
Re-running init against an existing config skips the wizard entirely and
just performs another run — it's idempotent and safe to re-run on any
machine.
After that, keep the profile fresh by running token-profile run again —
manually, or on whatever schedule you registered above.
Add --dry-run to either init or run to perform every real write
(clone, config, snapshot, render, README) but stop before the commit/push,
printing a summary of what would have been committed instead:
token-profile init --dry-run
token-profile run --dry-runOn init, a dry run also skips the schedule-registration prompt entirely —
installing a live schedule isn't something a dry run should ever do.
token-profile cleanupReverses token-profile's footprint: deregisters the refresh schedule (it
checks live state first, so it never falsely reports removing something
that was never registered) and strips the README card and
.token-profile/ from the target repo's working tree. It requires a real
terminal — cleanup shows exactly what it's about to touch, including any
uncommitted changes already sitting in the target repo (e.g. from a prior
--dry-run), before asking you to confirm. It never commits or pushes —
review the resulting working-tree diff and commit it yourself — and it
never touches ~/.token-profile/ itself (your config, machine ID, or
cloned repos), only this machine's schedule registration and the target
repo's own footprint.
If you'd rather not use init, or need to see exactly what it automates:
-
Add the markers to your target repo's
README.mdyourself, on their own lines, in the section you want the card to occupy:<!-- token-profile:start --> <!-- token-profile:end -->
token-profile runreplaces only the content between these two lines, leaving everything else in the README untouched. If the markers are missing,runfails with an actionable error rather than guessing where to insert them. -
Write a config file (see Configuration below) with at least
targetReposet to the local working-copy path of the repo that hosts your rendered profile. -
Schedule
token-profile runyourself, via cron, launchd, or a manual habit, on at least one machine where your usage data lives. token-profile doesn't provide its own always-on scheduler. -
Run it once to produce the first commit:
token-profile run --config /path/to/config.json
token-profile reads a JSON config file, by default at
~/.token-profile/config.json (override with --config on either
subcommand). A missing file is not an error — every field falls back to its
default.
| Field | Type | Default | Description |
|---|---|---|---|
targetRepo |
string | (required) | Local working-copy path of the repo hosting your rendered profile. run/init fail fast if this is unset. |
breakdown |
"per-model" | "per-tool" | "combined" |
"per-model" |
How the rendered breakdown groups usage: by model, by coding agent/tool, or one combined total. |
renderMode |
"svg" | "ascii" |
"svg" |
Which dashboard card gets rendered: the default full-color SVG image, or "ascii" to opt into the original plain-text card instead. |
trailingWindow |
duration string (e.g. "720h") |
(unset) | How far back the rendered card reaches, and the length of the window compared against for the window-over-window rate. Also bounds how far back usage is queried on each run. Unset defers to a 30-day default, matching agentsview's own. |
breakdownLimit |
integer | 3 |
How many entries the breakdown section shows individually, highest-token first; the rest are folded into one "N more" summary line rather than dropped silently. 0 (unset) defers to the default of 3; a negative value shows every entry with no cap in ascii mode. The default svg card's fixed-height canvas always caps at 4 rows regardless of this setting — use renderMode: ascii if you need every entry visible. |
machineIdPath |
string | ~/.token-profile/machine-id |
Where this machine's cached random identity is stored. Identity is random, not derived from hostname, so two machines that happen to share a hostname never collide. |
scheduleInterval |
duration string, one of 1h/2h/3h/4h/6h/8h/12h/24h |
6h |
How often the schedule init registers (or the --schedule-dest snippet describes) fires. Must be an hourly divisor of a day so a run always lands on the same wall-clock hours day over day — any other value is rejected with an error naming the accepted set. |
Example:
{
"targetRepo": "/Users/you/code/you",
"breakdown": "per-tool",
"trailingWindow": "720h",
"breakdownLimit": 5
}Note on token counts: "tokens" throughout the card counts input, output,
prompt-cache creation, and prompt-cache read tokens together — every token
dimension agentsview reports, matching what the shown cost is actually
billed against. Totals of a million or more are shortened with a unit
suffix (e.g. 12.3M, 1.4B) everywhere a token count is shown, including
the trend graph's y-axis.
Note on the window-over-window rate: the (+50%)/(-10%) next to
Tokens/Cost compares the current window against the immediately preceding,
equal-length window (e.g. this week vs. last week). It's omitted once
you've been running token-profile for less than two windows, since there's
nothing yet to compare against.
Each machine writes its own usage history under
<targetRepo>/.token-profile/snapshots/<machine-id>/, one file per calendar
month (<start-date>-<end-date>.json) so an actively-used machine's history
doesn't pile up into a single ever-growing file. Within a month's file, a
new run's data is merged in by (date, agent, model), so history a day has
already rolled out of the trailing window still stays on disk rather than
being dropped. Every run reads every snapshot present in the repo —
including ones from machines that haven't run in a while — and merges them
into the totals, trend, and streak shown on the card, which is itself
scoped to just the current window (see trailingWindow above). Git is the
only sync layer: there's no server, queue, or shared database, and pushes
retry through a bounded fetch-rebase loop if another one of your machines
pushed first.
token-profile intentionally stays a README-snippet generator, not a general analytics dashboard:
- Deferred, not planned for now: GitHub Action-based auto-refresh (there's no hosted API for an Action runner to poll — agentsview only reads local session data); additional profile content blocks beyond the four shipped today (e.g. an activity heatmap, badges).
- Out of scope entirely: a general usage-analytics or team-leaderboard dashboard, and team/org-wide reporting or centralized sync backends. For that, see agentsview itself.
MIT — see LICENSE.