Catch the 5-Hour Cap Before You Hit It: token-budget-advisor and Status-Line Integration A developer created token-budget-advisor.sh, a tool that warns users before hitting Claude MAX's 5-hour output token cap by detecting dangerous thresholds around 800k tokens and critical levels past 1.2M tokens. The script integrates into a dashboard and status line, reading from Claude's stdin and ccusage blocks to provide absolute token counts rather than percentages, preventing abrupt session halts during unattended background jobs. My last piece, " Auto-resuming a session that stalled on a rate limit https://zenn.dev/bokuwalily/articles/ratelimit-resume ," was about what to do after a 5-hour block stops you. This one is about the machinery that lets you notice before it stops you . Claude MAX's 5-hour block halts your session the instant output tokens hit the ceiling. Even with ๐Ÿ• 5h 82% visible in the status line, you have no idea how many tokens that remaining 18% actually represents. token-budget-advisor.sh detects the boundary in absolute terms โ€” "getting dangerous around 800k, already cooked past 1.2M" โ€” and this article covers its design, its integration into dashboard.sh , and how it gets wired into the status line. The Claude Code status line shows ๐Ÿ• 5h N% . ~/.claude/scripts/statusline.sh reads this straight from Claude's stdin. H5=$ j '.rate limits.five hour.used percentage // empty' H5R=$ j '.rate limits.five hour.resets at // empty' The pcolor function turns the value yellow at 50%+ and red at 80%+, but that's the percentage Claude computed , not an absolute token count. What 80% translates to in tokens shifts depending on your Max plan's contract state, and if you keep going with long completions you hit the cap and get abruptly stopped from the next turn onward. To check, you have to run ccusage blocks every single time, and if you forget and then kick off a heavy task, you'll cleanly burn through your 5-hour window. When an unattended job is running in the background, everything can slip into an all-SKIP state before a human even notices. The policy in the header of ~/.claude/scripts/token-budget-advisor.sh doubles as its design. ใ—ใใ„ๅ€ค: 5h block: output 800k โ†’ warn 1.2M ใง critical weekly: cost $3000 โ†’ warn sessions: 5/day โ†’ warn ้›†ไธญไฝœๆฅญใฎ็–‘ใ„ ๅคฑๆ•—ๆ™‚ใฏ exit 0 ใง fail-open dashboard ็ตฑๅˆใฎใŸใ‚ bash 3.2 ไบ’ๆ› It first tries ccusage blocks --json . if command -v ccusage /dev/null 2 &1; then CC JSON=$ ccusage blocks --json 2 /dev/null || true if -n "$CC JSON" ; then EXTRACTED=$ printf '%s' "$CC JSON" | python3 -c " import sys, json try: d = json.load sys.stdin active = b for b in d.get 'blocks', if b.get 'isActive' if active: b = active 0 tc = b.get 'tokenCounts', {} or {} out = int tc.get 'outputTokens', 0 cost = float b.get 'costUSD', 0 print f'{out}|{cost}' ..." In environments where ccusage isn't present, it runs on cost-log.jsonl alone. When both are available, it prefers ccusage's values and records the discrepancy as source diff pct . ccusage ใฎๅ€คใŒๆœ‰ๅŠนใชใ‚‰ใใกใ‚‰ใ‚’ๅ„ชๅ…ˆ transcript ่จˆ็ฎ—ใ‚ˆใ‚Šไฟก้ ผใงใใ‚‹ own out 5h = out 5h if cc out is not None and cc out 0: out 5h = cc out ๆฏ”่ผƒ ๆคœ่จผ็”จ diff pct = None if cc out is not None and own out 5h 0: diff pct = round abs cc out - own out 5h / max cc out, own out 5h 100, 1 When the gap is large, there may be a problem with the cost-log side's aggregation logic, and source diff pct serves as a signal for that. cost-log.jsonl gets written across multiple lines under the same session id, transcript key by design, the cumulative value mid-session is appended . Summing all lines double-counts the tokens. cost-log ใฏ session id ร— transcript ใ”ใจใซ็ดฏ็ฉๅ€คใงๆ›ธใ‹ใ‚Œใ‚‹ไป•ๆง˜ใ€‚ ๆœ€ๆ–ฐ่กŒใฎใฟๆŽก็”จใ™ใ‚‹ใŸใ‚ใ€ session id, transcript ใงๆœ€็ต‚่กŒใ‚’ๅ–ใ‚Š็›ดใ™ใ€‚ latest = {} with open log path as f: for line in f: r = json.loads line key = r.get "session id", "" , r.get "transcript", "" prev = latest.get key if prev is None or t prev 0 : latest key = t, r You adopt only the final line, then filter by the 5h/7d windows. Sum every line without knowing this and you'll get numbers 2โ€“3x the real value. THRESH 5H WARN = 800 000 output tokens THRESH 5H CRIT = 1 200 000 THRESH WEEK WARN = 3000 USD THRESH SESS PER DAY = 5 if out 5h = THRESH 5H CRIT: s5 = "critical" elif out 5h = THRESH 5H WARN: s5 = "warn" else: s5 = "ok" The intensive-work check is made from "average over the last 3 days 5 sess/day." recent days = sorted by day.keys -3: avg sess = sum by day d for d in recent days / max 1, len recent days burst = avg sess THRESH SESS PER DAY --short mode The short field is generated on the Python side. " short": f"{icon} {label} 5h:{out 5h/1000:.0f}k tok ${cost 5h:.1f} / 7d:${cost 7d:.0f} ", Example outputs per state actual token counts will vary . ๐ŸŸข OK 5h:234k tok $0.3 / 7d:$2 ๐ŸŸก burst 5h:841k tok $1.2 / 7d:$8 ๐Ÿ”ด cap-near 5h:1243k tok $2.1 / 7d:$12 Since you can match just the icon with grep -qE '๐Ÿ”ด|cap-near' , you can drop it directly into a shell-script gate. On error it prints โšซ n/a and returns with exit 0 fail-open design , so the caller doesn't get halted. The ๐Ÿ’ฐ Cost 7d section of ~/.claude/scripts/dashboard.sh looks like this. echo " ๐Ÿ’ฐ Cost 7d " ~/.claude/scripts/cost-summary.sh --short echo " budget: $ ~/.claude/scripts/token-budget-advisor.sh --short " It gets written out to ~/.claude/dashboard.md , so at the start of a project you just open the file to see the budget situation. Here's the config for ~/Library/LaunchAgents/com.shun.dashboard.plist .