Estimating Claude Code's "5-hour window" from local logs — what I learned building an always-on usage gauge
If you use Claude Code all day, you've probably been stopped mid-task by "usage limit reached". /usage tells you the official number, but only when you stop and ask. I wanted the answer to sit in the corner of my screen while I work, so I built a small Windows gauge that estimates what's left from

If you use Claude Code all day, you've probably been stopped mid-task by "usage limit reached". /usage tells you the official number, but only when you stop and ask. I wanted the answer to sit in the corner of my screen while I work, so I built a small Windows gauge that estimates what's left from the logs Claude Code already writes. This post is about how the estimate works.
Claude Code writes one JSONL file per session under ~/.claude/projects/<project>/<session>.jsonl. Assistant lines carry message.usage:
{ "timestamp": "...", "message": { "model": "...", "usage": { "input_tokens": 12, "output_tokens": 840, "cache_creation_input_tokens": 3021, "cache_read_input_tokens": 98000 }}} Enter fullscreen mode Exit fullscreen mode The files are append-only, so I remember the last byte offset per file and read only what's new. Even with gigabytes of logs, each refresh costs almost nothing. It never reads login data or tokens.
cache_read_input_tokens is huge (a long chat easily reads 100k+ per turn). Adding it in wrecks the estimate. I count input + output + cache_creation as usage and use cache_read only to judge how long a chat's context has grown.
A window starts at the first request after the previous window ended, floored to the hour, and lasts 5 hours (an estimate that matches observed behaviour):
BLOCK = timedelta ( hours = 5 ) def usage_blocks ( events ): out = [] for ts, i, o, cc, _cr, _m in events: if not out or ts >= out [ - 1 ][ 1 ]: start = ts. replace ( minute = 0, second = 0, microsecond = 0 ) out. append ([ start, start + BLOCK, 0 ]) out [ - 1 ][ 2 ] += i + o + cc return out Enter fullscreen mode Exit fullscreen mode 4. Where does the limit come from? Plan limits aren't published and change over time, so the gauge learns your limit:
Spend-limit lines are money-based, so they're ignored for learning.
From the last 30 minutes of usage it projects when you'll run out, and shows a yellow badge when you're going faster than your usual peak. It's not a perfect prediction, but knowing "about an hour left" before starting a big refactor has changed how I plan work.
The same approach reads Codex, Gemini CLI and Antigravity logs. Cursor doesn't store usage locally, so its tab only estimates activity from its chat database (opened read-only).
All of this is packaged as AI Usage Gauge (Windows, EN/JA/ZH/KO UI). 7-day free trial, then a one-time purchase.
https://github.com/aivex2024-spec/usagegauge
Unofficial, independent tool — not affiliated with Anthropic. Numbers are estimates. Feedback on the estimation method is very welcome.