Skip to content

Repository files navigation

usage-recover

Recover deleted Claude Code and Codex usage history from a public leaderboard profile, back into the cc.json shape ccusage emits.

npx @intframe/usage-recover <username> -o cc.json

Why

Claude Code deletes session transcripts after cleanupPeriodDays, which defaults to 30. Once they are gone the usage they represent is gone with them: ccusage reads raw session files, so it cannot report a month it can no longer see, and neither can anything built on top of it.

We lost four months this way across six accounts, on a machine that was decommissioned before anyone thought about it. What made the history recoverable was that aggregates had been submitted to viberank months earlier. This tool is that recovery, packaged.

What it recovers, and how exactly

per-day cost exact
per-model cost exact
token totals, all four buckets exact
per-day token split derived from cost

A profile publishes cost per day but only aggregate token counts, so the daily token split does not exist in the source and cannot be recovered. It is apportioned by cost, which keeps every total truthful and every day's relative weight intact. The output states this in a fidelity field rather than leaving a consumer to assume the whole file is measured.

Flow: a public profile is fetched, its flight payload splits into an exact daily cost series and token buckets published twice, an integer search over the label and bar width recovers exact token totals, cost apportions the daily split, and the result is verified before it is written

Getting the token totals exactly

The interesting part is that the totals come out exact rather than rounded.

A profile prints each token bucket twice. Once as a label, 36.2B, which at that scale covers a 50-million-wide interval and is useless on its own. Once as a bar width, 95.05060355502121%, which carries full float precision but is a ratio with no absolute anchor.

Together they pin the integers. Every percentage is bucket / total computed from whole numbers, so scanning candidates for the smallest bucket and testing whether the other three land on integers isolates one consistent solution. On the profile above it converges with zero residual:

label     36.2B        1.0B          202.6M       657.2M
bar       95.0506035%  2.6933182%    0.5315882%   1.7244898%
solved    36,223,082,857   1,026,403,707   202,584,370   657,190,346
                                                    total 38,109,261,280

Output

Standard cc.json, so anything that reads ccusage daily --json reads this: leaderboard submissions, importers, your own scripts.

Every conversion is checked before it is written. Token buckets must sum to their totals at both day and profile level, model costs must sum to the day, dates must be ISO, and cost per token must land inside the band leaderboards accept. A file that fails any of these is not emitted, because the errors it would produce downstream point at the payload rather than at the conversion that made it.

Library

import { fetchProfile, buildCcJson, verify } from "@intframe/usage-recover";

const profile = await fetchProfile("aron-intframe");
const cc = buildCcJson(profile, new Date().toISOString());

const problems = verify(cc);
if (problems.length) throw new Error(problems.join("\n"));

recoverTotals is exported separately if you only want the integer-recovery step.

Limits

Only public viberank profiles are supported. It reads the rendered page, so a markup change upstream can break parsing; the verification step is there so that surfaces as a clear failure rather than as plausible wrong numbers.

Recovered aggregates are not a substitute for measured sessions. If your transcripts still exist, run ccusage against them.

License

MIT

About

Recover deleted Claude Code and Codex usage history from public leaderboard aggregates, back into ccusage cc.json format

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages