BlogUsage and limits
How do I show Claude Code usage in the menu bar or status line?
Claude Code passes a rate_limits object to your status line script: the percentage used and the reset time of your session window and your weekly window. Print those fields and they appear at the bottom of every Claude Code session. For the macOS menu bar, have the same script save the values to a file, then display that file with a menu bar tool such as SwiftBar.
Everything below uses features documented by Anthropic as of October 2026. No third-party usage service, no extra login.
What Claude Code gives your script
The status line is a bar at the bottom of Claude Code that runs a command you configure. Claude Code sends the command a JSON object on stdin and shows whatever it prints. For claude.ai subscribers, the JSON includes:
"rate_limits": {
"five_hour": { "used_percentage": 23.5, "resets_at": 1738425600 },
"seven_day": { "used_percentage": 41.2, "resets_at": 1738857600 }
}
(The values above are Anthropic's sample data, not real limits.)
used_percentagegoes from 0 to 100.resets_atis a Unix timestamp in seconds.- The object is only present for Pro and Max subscribers, or behind a Claude apps gateway with spend limits, and only after the first API response of the session. Your script must handle it being absent.
The same JSON carries other fields worth showing next to it: model.display_name, context_window.used_percentage, cost.total_duration_ms.
Option 1: let Claude Code write it
/statusline show model, session and weekly rate limit usage, and when the week resets
Claude Code generates a script in ~/.claude/ and updates your settings. Approve the file edits when asked.
Option 2: write the script yourself
Point statusLine at your script in ~/.claude/settings.json:
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}
Then create ~/.claude/statusline.sh and make it executable (chmod +x). It needs jq:
#!/bin/bash
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
S=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
W=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
WR=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty')
OUT="[$MODEL]"
[ -n "$S" ] && OUT="$OUT session $(printf '%.0f' "$S")%"
[ -n "$W" ] && OUT="$OUT · week $(printf '%.0f' "$W")%"
[ -n "$WR" ] && OUT="$OUT (resets $(date -r "$WR" '+%a %H:%M'))"
echo "$OUT"
# Save the latest limits for the menu bar (see below)
RL=$(echo "$input" | jq -c '.rate_limits // empty')
[ -n "$RL" ] && echo "$RL" > "$HOME/.claude/rate-limits.json"
date -r <seconds> is the macOS (BSD) syntax for formatting a Unix timestamp. Claude Code reloads settings automatically and runs the script as soon as you save.
When it refreshes
The script runs when a session starts, then again when a new assistant message arrives, when /compact finishes, when the permission mode changes, and in a few other cases. It also re-runs when a rate-limit window it last received reaches its resets_at time. Updates are debounced at 300 ms.
An idle session can go quiet. To re-run the script on a timer as well, add refreshInterval (in seconds, minimum 1) to the statusLine block.
Option 3: put it in the macOS menu bar
The script above already writes ~/.claude/rate-limits.json each time it receives limits. Any menu bar tool that runs a script can show that file. SwiftBar is an open-source (MIT) one:
brew install swiftbar
On first launch, SwiftBar asks you to choose a plugin folder and treats every script in it as a plugin. Everything a script prints before the first --- line is shown in the menu bar. The refresh interval is in the file name, as {name}.{time}.{ext}. Create claude-usage.1m.sh in that folder:
#!/bin/bash
F="$HOME/.claude/rate-limits.json"
[ -f "$F" ] || { echo "Claude –"; exit 0; }
S=$(jq -r '.five_hour.used_percentage // 0' "$F")
W=$(jq -r '.seven_day.used_percentage // 0' "$F")
WR=$(jq -r '.seven_day.resets_at // empty' "$F")
printf 'S %.0f%% · W %.0f%%\n' "$S" "$W"
echo "---"
[ -n "$WR" ] && echo "Week resets $(date -r "$WR" '+%a %d %b %H:%M')"
SwiftBar makes new plugin files executable if needed. Lines after --- appear in the dropdown. If the plugin can't find jq, use the full path printed by which jq.
Limits of this method
- The file is only as fresh as your last active session. It updates when some session receives a response. If all sessions are idle, the menu bar shows the last known value.
- It shows the rate limits, not what used them. For the breakdown by subagent, skill or MCP server, you still need
/usage. - It doesn't work with an API key.
rate_limitsis a subscriber field. - The status line hides during some interactions, including the help menu and permission prompts.
- Third-party monitors. If you install a ready-made usage monitor instead, read what it accesses before you give it your Claude credentials.
For what each number means and what to do when it gets high, see how to check your Claude Code usage limits and why the weekly limit runs out fast.
With Kanbell
Kanbell is a macOS app with one window per project and real terminals in panes and tabs. It shows your Claude Code subscription usage, session and week, in the app, with no status line script to maintain. Codex CLI usage is read locally. For Gemini CLI, quota shows as "not available" because Gemini does not publish it.
In the menu bar, Kanbell shows an orange dot when an agent is waiting for you, and ⌘⇧J jumps to the next waiting agent.
FAQ
Does the status line cost tokens?
No. Anthropic's docs say the status line runs locally and does not consume API tokens.
Why is rate_limits missing from the JSON?
It is only sent to claude.ai Pro and Max subscribers (or behind a Claude apps gateway with spend limits), and only after the first API response of the session.
How often does the status line update?
On events such as a new assistant message, /compact finishing or a permission mode change, and when a rate-limit window reaches its reset time. Set refreshInterval to also re-run it on a timer.
Can I show usage for several sessions at once?
The limits are account-wide, so every session reports the same windows. Saving the latest values to one file gives the menu bar a single readout.