Long sessions
3.1M3 sessions ended several times larger than the 128K this machine usually reaches. Every turn after that re-reads the whole window.
acme-web · 214 turns · 62.4K → 604.1Kbilling-api · 168 turns · 58.1K → 511.7K
Local · open source · zero dependencies
Four terminals, and you lose time to all of them: one session sat blocked on a question while you watched another think. Claude Code already writes every session to ~/.claude — this reads it and puts them all on one page, with their status and their token spend.
Across the top: how much of your five-hour window and your week is gone, and where each lands at this rate. A second page says where the last month of tokens actually went.
npx claude-code-session-trackerThen open the printed http://127.0.0.1:3099.
Node 20 or newer · macOS, Linux, and Windows
Preview
Both limits across the top, what the week went on under them, running sessions below, and a panel for whichever row you open. Invented data.
Claude Code
Sessions
SessionsHistorySettingsResets 19:30 · 2h 41m left
Against your heaviest five-hour window in 7 days — 4.1M.
Resets Mon 25 Aug, 03:00 · 2d 10h left
Every model, against your heaviest week in 28 days — 52.9M.
Last 7 days
3 sessions ended several times larger than the 128K this machine usually reaches. Every turn after that re-reads the whole window.
acme-web · 214 turns · 62.4K → 604.1Kbilling-api · 168 turns · 58.1K → 511.7K
Sessions open holding 74.3K — the system prompt, tools, skills and memory files, paid before anything is asked.
38 sessions
Ranked by what each accounts for, in the tokens a limit counts. A finding appears only where the range runs heavier than this machine's own middle.
| Project | Session | Status | Model | Tokens (in/out/total) | Uptime |
|---|---|---|---|---|---|
| acme-web~/code/acme-web | Rework the checkout flow279ed6ae | busy | opus-5 | 182.4K / 12.9K / 195.3K | 1h 24m |
| billing-api~/code/billing-api | Paginate the invoices endpointb41c7d02 | waitinginput needed | sonnet-5 | 96.2K / 7.4K / 103.6K | 18m 42s |
| design-system~/code/design-system | Tidy the button variants5f2a91c4 | idle | sonnet-5 | 41.8K / 3.1K / 44.9K | 3h 06m |
| Project | Session | Model | Last active | Tokens (in/out/total) |
|---|---|---|---|---|
| acme-web~/code/acme-web | Fix the flaky checkout testit only fails on CI, never on my machine | opus-5 | 12m ago | 214.7K / 15.3K / 230.0K |
| mobile-app~/code/mobile-app | Retry the offline write queueflush the queued writes once the connection is back | sonnet-5 | 2h ago | 158.9K / 11.2K / 170.1K |
| docs-site~/code/docs-site | Add dark mode to the docsauto, light and dark, and no flash on first paint | sonnet-5 | 5h ago | 88.4K / 6.1K / 94.5K |
| billing-api~/code/billing-api | Rotate the webhook secretmove it to the secret store and re-sign the callbacks | haiku-4-5 | yesterday | 23.1K / 1.9K / 25.0K |
| acme-web~/code/acme-web | Windows CI: separators in the path testthe path assertions only hold on posix | opus-5 | 3d ago | 61.2K / 4.4K / 65.6K |
50 of 794 on disk
Read-only. Bound to loopback. Nothing leaves this machine.
The panel is the rest of the session: what it spent, how much of the model’s window is still free, when it started, and how much of the elapsed time was actually worked. It carries the first and last prompt, a resume command you can copy, and a button that reveals the transcript in your file manager.
Under that, the two readings a total cannot give. Static context itemises what the window was already holding before you asked anything — which CLAUDE.md, the skill listing, the deferred tools, the agents, the MCP instructions — because that block is paid again on every turn, and it is the one part of the window you can actually go and shorten. What this session cost is that multiplication done out loud: the window an average turn held, times however many turns there were.
Every figure comes from the transcript Claude Code already wrote. Nothing is estimated, and a number the transcript does not carry is left out rather than guessed at — bar the static rows, which are priced from the text each block put in the window and say so.
acme-web
Rework the checkout flow
19% of 1M tokens · opus-5
41,207 tokens before the first turn ran, estimated from the text each block put in the window.
Its 38 turns read 4.2M back out of cache between them. Those reads bill at a fraction of the rest, so they sit outside the totals above.
Limits
Claude Code bills against two windows: five hours, and seven days. Neither is written to your disk, so both are measured off the transcripts.
Neither quota is written to disk. The five-hour window is chained off turn timestamps and floored to the half hour; the week is pinned to the reset Claude Code cached. If Claude has refused a turn, its own reset time wins.
Input, output and newly-cached tokens, across every project and every subagent. Cache reads are shown apart — they cost a fraction as much and would swamp the rest fifty to one.
Where the window lands by its reset at the rate it has kept. It stays hidden until a fifth of the window has gone, since an early rate is noise.
The bar is a share of your heaviest closed window — 7 days back for the five-hour card, 28 for the weekly one. Past it the bar reads full and the percentage keeps counting.
Transcripts are append-only, so files untouched since the cutoff are skipped on mtime and the rest are cached per version. On the development machine, 901 files and 1 GB come to ~1.3s cold and ~7ms warm. The page reads every 15 seconds and ticks the countdown itself in between.
Alerts
A desktop notification when a window is headed past your heaviest one. One switch per limit, both off until you turn them on.
Claude Code
Settings
SessionsHistorySettingsA desktop notification when a window is headed past your heaviest one — then quiet for as long as you say.
Session limit
At this pace, it won't last the five-hour window — it resets at 19:30.
Hear about a limit before you reach it
A desktop notification when a window is on course to run past your heaviest one — even with this tab behind your editor.
The same fact the card already shows in colour, addressed to whoever is not looking at the card. It carries the reset time, because that is the half you can act on.
Settings is the third tab, with one switch per limit. Turning one on is what asks the browser for permission — nothing asks on load. If the browser is blocking the page, the switches come back off and say so.
It speaks once, then holds its tongue: an hour for the five-hour window, four for the week. Crossing the line again inside that interval is the same interruption twice, so it is not sent.
A sheet offers these the first time there is a limit to show. Not now means not now — it returns once, a fortnight later, and that is the last of it. Settings live in this browser, like the theme.
Nothing runs in the background: the page notices on the same 15-second read the cards already make, so a tab has to be open. And a week with no reset from Claude has nothing to project into, so it never speaks.
History
A page at /history for the weeks behind the cards: by day, by hour, by project and by model. Same sweep as the limit cards, so it costs almost nothing.
Claude Code
History
SessionsHistorySettings25 Jul – 23 Aug · 30 days
Billed tokens per local day. A mark under a bar is a turn Claude refused.
Every half hour of the range, over one week. Darker is heavier.
Ranked by billed tokens. Pick one to narrow everything above.
| Project | Turns | Billed | Cache reads | Share |
|---|---|---|---|---|
| acme-web~/code/acme-web | 4,182 | 18.4M | 902.6M | 44% |
| billing-api~/code/billing-api | 2,140 | 9.1M | 431.7M | 22% |
| mobile-app~/code/mobile-app | 1,884 | 6.7M | 318.2M | 16% |
| design-system~/code/design-system | 1,102 | 4.3M | 205.9M | 10% |
| docs-site~/code/docs-site | 903 | 3.3M | 154.1M | 8% |
Every model that answered in this range.
| Model | Turns | Billed | Cache reads | Share |
|---|---|---|---|---|
| opus-5 | 6,204 | 27.6M | 1.3B | 66% |
| sonnet-5 | 3,411 | 12.1M | 620.4M | 29% |
| haiku-4-5 | 596 | 2.1M | 92.1M | 5% |
Read at 21:14
A bar for every local day in the range, quiet days included. Heights are linear, so one heavy day flattens the rest. A mark under a bar is a day Claude refused a turn.
Every half hour of the range laid over one week, darker where it is heavier. Tells you what the daily bars cannot: whether the window opens at nine in the morning or eleven at night.
Cache reads held apart, as on the limit cards. Pick a project and the summary, both charts and the model list narrow to it; pick it again to let go.
`?range=7d&project=…`, so reload, bookmark and Back all work. Ranges are whole local days, capped at 90.
No read of its own: the page reuses the sweep the limit cards already make. A 7-day page is ~450ms cold and ~15ms warm, and the cache is shared, so whichever you open second is the cheap one. Nothing here polls — Refresh is how you ask for another read.
A project whose directory has moved or been deleted cannot be resolved from the folder name Claude Code stores, so the page shows the plainest reading of it — and says so rather than passing a guess off as fact.
What you get
Both limits, live status, token usage, a month of history, and enough per-session detail to pick the one worth going back to.
Quickstart
Four runners need no install at all. Homebrew is there if you would rather have it on your PATH.
npx claude-code-session-trackerNo install step. The command downloads, starts a local server, and opens your browser.
Served at http://127.0.0.1:3099. If the port is taken it steps forward and prints what it bound.
The list refreshes every 2 seconds. Click any row for the full read.
Command line
Every flag the CLI takes, and every key the page answers to.
| Flag | Description | Default |
|---|---|---|
| -p, --port <number> | Port to listen on, stepping forward up to 20 times if taken | 3099 |
| --host <address> | Address to bind. Anything but loopback drops the guard, and the CLI says so | 127.0.0.1 |
| --no-open | Do not open a browser | — |
| --json | Print the session list as JSON and exit | — |
| -n, --limit <number> | How many sessions to list. Running sessions always show | 50 |
| --claude-dir <path> | Override the Claude data directory | ~/.claude |
| -h, --help | Show usage | — |
| -v, --version | Show the version | — |
Click any row for the full read. Everything has a key.
Scripting
The same server the page talks to, so anything it does you can do with curl.
| Method | Route |
|---|---|
| GET | /api/sessions?limit=NThe session list. `limit` matches --limit, and running sessions are always included. |
| GET | /api/sessions?since=&until=The same list, narrowed by last-written time. Epoch ms; `since` inclusive, `until` exclusive. |
| GET | /api/sessions?sort=`recent` (default), `tokens-desc`, or `tokens-asc`. Ranks across the whole window, not just the page. |
| GET | /api/sessions/:idOne session with counts, tokens, models, activeMs, awaySummary, and notes. |
| GET | /api/limitsBoth limits, as `session` (five hours) and `weekly` (seven days). Each carries the window in progress, the heaviest closed one, and `lastLimited`. |
| GET | /api/usage/history?since=&until=&project=A sparse half-hour series, plus every project and model in the range ranked by billed tokens. Defaults to 30 days; spans over 90 are narrowed, and `range` in the reply is what was read. |
| GET | /api/usage/adviceThe findings behind the `Where it goes` panel as measurements, not sentences. Same params as the history route; defaults to 7 days. |
| GET | /api/healthStatus, version, the Node it runs on, the resolved Claude directory, and per-source status. |
| POST | /api/sessions/:id/revealShows that transcript in your file manager. Requires a loopback Origin. |
--json prints the same payload the page uses, then exits.
npx claude-code-session-tracker --json | jq '.sessions[] | .project.name'{
"sessions": [
{
"id": "279ed6ae-49fd-4234-a74e-145f5535341c",
"source": "claude-code",
"status": "busy", // busy · waiting · idle · ended
"project": { "name": "…", "path": "…", "gitBranch": "main" },
"title": "Disable dependabot", // Claude's own title, when it wrote one
"firstPrompt": "…",
"lastPrompt": "…",
"model": "claude-sonnet-5",
"version": "2.1.235",
"startedAt": 1787142489923,
"lastActiveAt": 1787142700231,
"transcriptPath": "…/279ed6ae….jsonl",
"sizeBytes": 136133,
"live": { "pid": 4129, "kind": "interactive", "entrypoint": "cli" }
}
],
"total": 794,
"generatedAt": 1787142701002
}Privacy
Transcripts hold your prompts, your paths, and sometimes your secrets. That is why the defaults are what they are.
It reads what Claude Code already put on disk, opens nothing for writing, and creates nothing.
Binds to 127.0.0.1 and refuses any request whose Host is not loopback, so no website can point your browser at it.
No telemetry, no update check, no analytics. Nothing leaves the machine.
Nothing third-party runs on your machine, at install time or after.
Everything comes from what Claude Code already writes to disk.
| Path | Used for |
|---|---|
| ~/.claude/sessions/<pid>.json | Running sessions and their live status |
| <session cwd>/.git/HEAD | The branch a running session is on |
| ~/.claude/projects/**/*.jsonl | Session history — titles, prompts, models, branch |
| ~/.claude/projects/*/*/subagents/agent-*.jsonl | Subagent turns, for the limit windows they bill to |
| ~/.claude.json | The weekly reset, from Claude Code's cached usage readout — the only place that clock is written down |
FAQ
Node 20 or newer · macOS, Linux, and Windows. MIT licensed.
npx claude-code-session-tracker