Skip to content

Christophe1997/token-profile

Repository files navigation

token-profile

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):

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%). Streak: 3 days.

Generated by token-profile

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>

ASCII mode

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

Prerequisites

  • 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 your PATH, with push access to the repo hosting your rendered profile (usually github.com/<you>/<you>) from every machine you run token-profile on.

Install

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@latest

Quick start

token-profile init

The 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:

  1. 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).
  2. Writes a full config file with the three collected fields plus safe, hand-editable defaults for everything else (see Configuration).
  3. Scaffolds <!-- token-profile:start --> / <!-- token-profile:end --> markers into the target repo's README.md, if they aren't there yet.
  4. Performs a first run: resolves your local usage, writes this machine's snapshot, renders the card, and commits + pushes the updated README.
  5. Asks whether to register the refresh schedule now (default: every 6 hours) — on yes, init installs it itself via launchctl bootstrap (macOS) or crontab (Linux/other), no manual copy-paste required. A reviewable snippet is still written to --schedule-dest either 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.

Dry run

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-run

On init, a dry run also skips the schedule-registration prompt entirely — installing a live schedule isn't something a dry run should ever do.

Cleanup

token-profile cleanup

Reverses 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.

Manual setup

If you'd rather not use init, or need to see exactly what it automates:

  1. Add the markers to your target repo's README.md yourself, on their own lines, in the section you want the card to occupy:

    <!-- token-profile:start -->
    <!-- token-profile:end -->

    token-profile run replaces only the content between these two lines, leaving everything else in the README untouched. If the markers are missing, run fails with an actionable error rather than guessing where to insert them.

  2. Write a config file (see Configuration below) with at least targetRepo set to the local working-copy path of the repo that hosts your rendered profile.

  3. Schedule token-profile run yourself, 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.

  4. Run it once to produce the first commit:

    token-profile run --config /path/to/config.json

Configuration

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.

How multi-machine sync works

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.

Scope

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.

License

MIT — see LICENSE.

About

Turn local AI coding session token usage into a git-native GitHub profile README card

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages