A bash script that formats Claude Code's statusline JSON into a readable status bar.
Model, git branch, context window %, 5h and 7d rate limits with pace indicators.
On API/enterprise plans (no rate_limits in the JSON), the script shows session cost, burn rate, cache hit rate, cost per 1k tokens, net lines changed, and budget tracking across sessions.
Claude Code pipes a JSON object to a shell command via stdin on every render (the statusLine config). On Pro/Max plans this JSON includes a rate_limits field with 5-hour and 7-day usage percentages and reset times. On API/enterprise plans that field is absent, but cost data (session spend, API duration, lines changed) is available.
This script parses that JSON with jq. Single bash file, no extra dependencies. Visual style inspired by isaacaudet/claude-code-statusline.
cp statusline-command.sh ~/.claude/statusline-command.sh
chmod +x ~/.claude/statusline-command.shAdd to ~/.claude/settings.json:
{
"statusLine": {
"command": "bash ~/.claude/statusline-command.sh"
}
}- Claude Code CLI
jq(brew install jq)bc(usually pre-installed)- Claude Pro, Max, or API/enterprise plan
Three lines: identity (profile, model, effort, branch, context), usage (rate limits or cost, cache, budget, last-interaction time) on its own line, then location (cwd, transcript id).
- Profile — basename of
CLAUDE_CONFIG_DIR(e.g.claude,claude-work), so you can tell which profile/alias the session is using. Color is auto-derived from the name, so each profile stays visually distinct. Shown on both plan types - Model — color-coded by family: amber (Opus), cyan (Haiku), blue (Sonnet)
- Git branch — magenta, with
⎇prefix. Followed by dirty-state indicators:✓(dim green) when clean, otherwise+Nstaged (green),~Nmodified (yellow),?Nuntracked (dim). Then sync state:⇡N(orange) unpushed commits,⇣N(cyan) commits available to pull. Remote state updates via a backgroundgit fetch(debounced to 10 min per branch, repos with alocal/dir only) - Context window % — cyan under 50%, orange 50-80%, red above 80%
- 5h rate limit —
time_until_reset:used%:on_pace%↓format, color-coded by usage - 7d rate limit — same format, cyan
- Cache hit rate —
cache 99%, ratio of cached input tokens to total. Green ≥80%, cyan ≥50%, orange below - PR number —
PR#42(blue), open pull request for the current branch. Read directly from the statusline JSON'spr.numberfield (Claude Code resolves this natively), so it needs noghcalls or caching. Absent until a PR is found, and removed once it merges or closes
When rate_limits is absent, the script shows cost metrics instead. Example: $2.13 71.00/hr │ cache 96% │ $.02/kt +196 │ $34.63/50 12m
- Session cost —
$2.13, total cost of the current conversation - Active burn rate —
71.00/hr, dollars per hour of API time (not wall clock, so idle time doesn't skew it) - Cache hit rate —
cache 96%, percentage of cached input tokens vs newly created ones. Green above 80%, cyan 50-80%, orange below. High cache rates mean you're paying ~10% per token instead of full price for repeated context - Cost per 1k tokens —
$.02/kt, session cost divided by total tokens (input + output). Captures all work, not just lines changed - Net lines —
+196, lines added minus removed. Green if positive, red if negative - Budget —
$34.63/50 12m, accumulated spend across sessions vs budget, with estimated time remaining at current burn rate
Each session's cost is persisted to $CLAUDE_CONFIG_DIR/usage/ (or ~/.claude/usage/). To track spend against a budget, create a config file:
mkdir -p ~/.claude/usage
cat > ~/.claude/usage/.config << EOF
budget=50
initial_usage=32.50
start_ts=$(date +%s)
EOFbudget— total budget in dollarsinitial_usage— spend already consumed before tracking startedstart_ts— epoch timestamp, only sessions after this are counted
Color-coded: cyan under 50%, yellow 50-80%, red above 80%. Time remaining is based on the current session's active burn rate.
The script tracks cost locally using total_cost_usd from the statusline JSON, which can drift from the billed amount on the web console. To re-sync, set initial_usage to the real value and move start_ts to now so existing session files (already counted in the billed amount) aren't double-summed:
bash statusline-command.sh usage 215.09
sed -i '' "s/^start_ts=.*/start_ts=$(date +%s)/" ~/.claude/usage/.configAlternatively, use the sync subcommand which writes negative offsets for existing sessions instead of using timestamp filtering:
bash statusline-command.sh sync 215.09If you're using Claude Code, a /set-budget slash command is available in .claude/commands/set-budget.md — copy it to ~/.claude/commands/ to use it from any project.
All fields are optional — if data isn't available yet, the section is skipped. Rate limit data only appears after a full message exchange (send + response), since Claude Code updates the statusline on each render using the API response headers.
Each rate limit reads time_until_reset:used%:on_pace%↓. The third figure is the reference: it's the used% you'd need to be at right now to land at exactly 100% by reset. Compare it against the second figure to see your margin at a glance.
17m:8%:94%↓— 17m until reset, 8% used, you'd need to be at 94% to be on perfect pace. Tons of headroom.17m:94%:8%↑— flipped: 94% used with only 8% of the window elapsed. You're cooked.
The arrow projects usage at reset time:
↑red — burning fast, will exhaust the limit before reset. Followed by the wall-clock time you'll hit 100% at the current pace (e.g.↑ 16:20= limit reached around 16:20). Color reflects urgency: red if under 33% of the window remains, orange under 66%, green otherwise→yellow — on pace, roughly at 100% by reset. Also shows the projected exhaustion time↓green — under-consuming, won't hit the limit (no time shown)
Projection formula: projected% = used% × window_duration / elapsed. Suppressed during the first 2% of the window to avoid noise.

