Weekly usage limits
July 8, 2026 · View on GitHub
cctop can show your Claude subscription's rate-limit usage in the summary line:
Limits: 8% 7d (2d9h left) 60% 5h (2h32m left)
7d— the rolling 7-day ("weekly") window, across all models.5h— the rolling 5-hour window.(… left)— time until each window resets, or(due)once a window's reset time has passed but the snapshot hasn't refreshed yet.
The percentages heat toward red as they climb, like the CPU and context columns.
Setup
You configure a status-line command in ~/.claude/settings.json. The tap is a
small block added to that command's script. It reads the JSON Claude Code sends
on stdin and persists the rate_limits object.
If you don't have a status-line script yet, create one (e.g.
~/.claude/statusline.sh) and point settings.json at it:
{
"statusLine": { "type": "command", "command": "bash \"$HOME/.claude/statusline.sh\"" }
}
Then add the tap near the top of the script, right after you read stdin:
input=$(cat)
# persist the account-wide 5h/7d rate limits
printf '%s' "$input" | cctop --capture-usage || true
# ... the rest of your status-line rendering, using "$input" ...
A complete example script
If you don't have a status-line script at all, here's a self-contained
~/.claude/statusline.sh to start from. It runs the tap, then renders a compact
model · dir · git:branch line; trim or replace the rendering to taste — the
only line cctop needs is the cctop --capture-usage tap.
Requires
jq. Only the rendering below uses it (to read fields out of the stdin payload); cctop itself stays dependency-free and the tap never needsjq. Install it withbrew install jq(macOS) orapt install jq(Debian/Ubuntu), or drop thejqlines and print your own status text instead.
#!/usr/bin/env bash
# Claude Code status line, with the cctop usage-limits tap.
# Claude Code pipes a JSON payload to this command on stdin once per turn;
# whatever we print to stdout becomes the rendered status line.
input=$(cat)
# persist the account-wide 5h/7d rate limits for cctop (best-effort; the
# `|| true` keeps a missing/failed cctop from tripping a status line under `set -e`)
printf '%s' "$input" | cctop --capture-usage || true
# --- render the status line (stdout is the rendered text) ---
model=$(printf '%s' "$input" | jq -r '.model.display_name // empty')
dir=$(printf '%s' "$input" | jq -r '.workspace.current_dir // .cwd // empty')
dir_name=""
[ -n "$dir" ] && dir_name=$(basename "$dir")
branch=""
if [ -n "$dir" ] && git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
branch=$(git -C "$dir" branch --show-current 2>/dev/null)
fi
line="$model"
[ -n "$dir_name" ] && line="$line · $dir_name"
[ -n "$branch" ] && line="$line · git:$branch"
printf '%s' "$line"
Make it executable (chmod +x ~/.claude/statusline.sh) and point
settings.json at it as shown above.
Thecctop --capture-usage reads the payload on stdin and
writes the snapshot; the || true keeps a missing or failed cctop from
tripping a status line that runs under set -e.
What it does and why it's safe
cctop --capture-usage reads the same stdin Claude Code already gives your
status line and writes the rate_limits object to ~/.claude/cctop/usage.json.
It is best-effort and cannot disrupt your status line:
- Silent and non-failing — it prints nothing (your status line's stdout is
its rendered text) and always exits 0, even on a malformed payload, so it is
safe even under
set -euo pipefail(the|| trueonly guardscctopitself being absent fromPATH). - Throttled to ~once per 30s across all sessions (via the file's mtime), so a burst of turns or dozens of running instances doesn't spam writes.
- Race-free — each write goes to a temp file and is renamed into place atomically, so concurrent taps never corrupt the file (last writer wins; the data is identical account-wide anyway).
- Non-destructive — only a non-empty
rate_limitsobject is written, so a missing /null/{}payload (before the first turn, or on API-key accounts) never clobbers a good snapshot.
Why this needs a status-line hook
cctop's monitor is read-only: it reads ~/.claude and the process table, and
makes no network calls (its only network access is the explicit cctop upgrade
command). Claude Code surfaces the limits in exactly two places:
the interactive /usage panel, and therate_limits object it passes
to your configured status-line command on stdin, once per turn.
So the data already flows past your status line for free. The setup taps
that stream and writes the latest snapshot to ~/.claude/cctop/usage.json, which
cctop then reads like any other file — no API key, no network, no stored
secrets. (The only alternative source, the Anthropic OAuth usage endpoint, would
require reading your subscription token and making network calls, which cctop
deliberately does not do.)
This is opt-in: without the hook, cctop simply omits the Limits: line.
The file cctop reads
~/.claude/cctop/usage.json:
{
"rate_limits": {
"five_hour": { "used_percentage": 0, "resets_at": 1781544600 },
"seven_day": { "used_percentage": 8, "resets_at": 1781568000 }
},
"captured_at": 1781527457
}
resets_at and captured_at are unix epoch seconds.
Notes
- Subscription accounts only. The
rate_limitsfield is present for Pro/Max subscribers, after the first turn of a session. API-key accounts don't get it, so theLimits:line stays hidden. - Freshness follows activity. The snapshot updates only while a session
renders its status line. Once it's over an hour old, cctop appends its age,
e.g.
Limits: 8% 7d (2d left) · 2h ago, so a stale reading isn't mistaken for a live one. The(… left)countdowns come from the absolute reset time, so they stay accurate regardless. - Aggregate only. The status-line payload carries just the combined 5h/7d
windows — not the per-model breakdown the
/usagepanel shows.7dis the all-models weekly figure.