Git commit attribution
How Centrail maps tokens to the commits they produced — on your machine.
Centrail maps the tokens an agent spent to the commits they helped produce — entirely on your machine.
The idea
Every usage event has a timestamp. Every commit has one too. Centrail attributes each event to the earliest commit at or after it — the change that work landed in. Events newer than your latest commit are treated as work-in-progress and left unattributed.
How it runs
- The CLI reads
git log --numstatfor each repo. - Events are matched to commits by timestamp.
- Only the attribution rows are sent — never diffs or messages.
git log --numstat --pretty=format:%H%x1f%cI
Re-syncing the same history changes nothing — attribution is idempotent. Your git history never leaves your machine.
Ship status
Every attributed commit also gets a fate, so your dashboard can show spend by what actually shipped:
- Shipped — the commit reached your repo's default branch. Squash merges count: a commit whose patch is squash-equivalent to one on the default branch is shipped too.
- In flight — not shipped yet, but some branch containing it has a tip commit newer than 14 days.
- Unshipped — not shipped, and no containing branch has been active in the last 14 days (dormant or deleted). It's a bucket, not a judgment.
Fates are recomputed on every sync, so an in-flight commit that later merges self-heals to shipped. Commits synced by an older CLI show as a fourth honest bucket, "unchecked".
The CLI computes fates locally with plain git commands:
git log --all --since="90 days" # recent shas + dates
git merge-base --is-ancestor <sha> <default>
git cherry <default> <branch-tip> # squash-merge detection
git branch -a --contains <sha> # which branches carry it
What leaves your machine for this: shas and branch names only — never diffs, messages, or paths.