iTranslated by AI
Monitoring Claude Usage in the Menu Bar: A Single-File Implementation with SwiftBar and OAuth API
When using Claude Pro/Max, keeping track of the 5-hour session and weekly usage limits can be a hassle. Since opening claude.ai every time to check these is tedious, I decided to display them constantly in the macOS menu bar.
Recently, a weekly quota for Claude Design was added, so I decided to combine the 5-hour, weekly, and Design quotas into a single line:
5h:21% (4h14m) 7d:74% (9h24m) De:7% (Mon)
About Claude Design
Released as a research preview in April 2026, this is Anthropic's visual creation tool. It allows you to create slides, UI prototypes, one-pagers, and more through conversations with Claude. It is based on Claude Opus 4.7 and is available for Pro, Max, Team, and Enterprise plans.
Structure of Limits
Usage limits on claude.ai are managed through three independent buckets:
| Bucket | Reset | Scope |
|---|---|---|
| 5-hour session | 5 hours after the first message (rolling) | Regular conversations |
| Weekly (all models) | Every 7 days | Combined total of claude.ai and Claude Code |
| Weekly (Claude Design) | Every 7 days | Design usage only |
The weekly bucket for all models is aggregated across claude.ai conversations, IDE plugins, and Claude Code. Since the Design bucket is independent, using Design does not affect your regular weekly quota.
*Note: Definitions and names of these buckets may be changed by Anthropic without notice.
Mechanics
Claude Code saves an OAuth token to the macOS Keychain upon login. By using this token to query Anthropic's internal endpoint api.anthropic.com/api/oauth/usage, you can retrieve the same usage data displayed in the claude.ai UI. This endpoint was discovered by the community while inspecting Claude Code's network traffic.
The response takes the following form. The Design quota is returned under the key seven_day_omelette.
{
"five_hour": { "utilization": 21.0, "resets_at": "..." },
"seven_day": { "utilization": 74.0, "resets_at": "..." },
"seven_day_omelette": { "utilization": 7.0, "resets_at": "..." }
}
*Note: seven_day_omelette is the internal key name for Claude Design and is not documented in official manuals.
Prerequisites
- Claude Code installed and logged in
- SwiftBar installed
Script
Save the following as claude-usage.5m.sh in your designated SwiftBar plugin directory and run chmod +x on it.
#!/bin/bash
# <bitbar.title>Claude Usage</bitbar.title>
# <bitbar.version>v1.2</bitbar.version>
# <bitbar.refreshInterval>300</bitbar.refreshInterval>
CACHE_FILE="$HOME/.cache/claude-usage.json"
mkdir -p "$(dirname "$CACHE_FILE")"
CREDS=$(security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null)
if [ -z "$CREDS" ]; then
echo "Claude: N/A"
exit 0
fi
TOKEN=$(echo "$CREDS" | python3 -c "
import sys, json
d = json.load(sys.stdin)
print(d.get('claudeAiOauth', {}).get('accessToken', ''))
" 2>/dev/null)
if [ -z "$TOKEN" ]; then
echo "Claude: auth error"
exit 0
fi
RESPONSE=$(curl -s "https://api.anthropic.com/api/oauth/usage" \
-H "Authorization: Bearer $TOKEN" \
-H "anthropic-beta: oauth-2025-04-20" \
-H "Accept: application/json")
IS_OK=$(echo "$RESPONSE" | python3 -c "
import sys, json
try:
d = json.load(sys.stdin)
sys.exit(0 if 'error' not in d else 1)
except Exception:
sys.exit(1)
" 2>/dev/null; echo $?)
if [ "$IS_OK" -eq 0 ]; then
echo "$RESPONSE" > "$CACHE_FILE"
elif [ -f "$CACHE_FILE" ]; then
RESPONSE=$(cat "$CACHE_FILE")
else
echo "Claude: rate limited"
exit 0
fi
echo "$RESPONSE" | python3 -c "
import sys, json, datetime
try:
d = json.load(sys.stdin)
except Exception:
print('Claude: error')
sys.exit(0)
def pct(key):
v = d.get(key)
if v and v.get('utilization') is not None:
return int(round(v['utilization']))
return None
def remaining(key):
v = d.get(key)
if not v or not v.get('resets_at'):
return None
t = datetime.datetime.fromisoformat(v['resets_at'])
now = datetime.datetime.now(datetime.timezone.utc)
secs = int((t - now).total_seconds())
if secs <= 0:
return 'reset'
h, rem = divmod(secs, 3600)
m = rem // 60
days, h2 = h // 24, h % 24
if days:
return f'{days}d{h2}h'
elif h:
return f'{h}h{m:02d}m'
else:
return f'{m}m'
def reset_day(key):
v = d.get(key)
if not v or not v.get('resets_at'):
return None
t = datetime.datetime.fromisoformat(v['resets_at'])
return t.astimezone().strftime('%a')
fh_pct = pct('five_hour')
sd_pct = pct('seven_day')
de_pct = pct('seven_day_omelette') # Claude Design weekly quota. Remove de_ variables and output lines if not needed
fh_rem = remaining('five_hour')
sd_rem = remaining('seven_day')
de_day = reset_day('seven_day_omelette')
fh_str = f'{fh_pct}%' if fh_pct is not None else 'N/A'
sd_str = f'{sd_pct}%' if sd_pct is not None else 'N/A'
de_str = f'{de_pct}%' if de_pct is not None else 'N/A'
fh_rem_str = f' ({fh_rem})' if fh_rem else ''
sd_rem_str = f' ({sd_rem})' if sd_rem else ''
de_day_str = f' ({de_day})' if de_day else ''
print(f'5h:{fh_str}{fh_rem_str} 7d:{sd_str}{sd_rem_str} De:{de_str}{de_day_str}')
print('---')
print(f'5h session: {fh_str}{fh_rem_str}')
print(f'Weekly: {sd_str}{sd_rem_str}')
print(f'Design: {de_str}{de_day_str}') # Remove if not needed
"
The .5m. in the filename sets the update interval to 5 minutes. If the API hits a rate limit, the script displays the last cached data.

About Rate Limits
In practice, the rate limits for /api/oauth/usage (HTTP 429) are quite aggressive, and once triggered, they may last for over 30 minutes. This is a known issue reported by multiple users on GitHub.
The script above handles this by falling back to the cached ~/.cache/claude-usage.json file if the API request fails.
Cautions
Anthropic OAuth Policy
In February 2026, Anthropic clarified in their Terms of Service that using OAuth tokens for Free/Pro/Max plans with tools other than Claude Code or claude.ai is a violation of their policy. As of April, technical blocks have been implemented against third-party tools (such as OpenClaw).
This script only retrieves usage statistics and performs no inference requests to Claude models. While the purpose differs from the subscription abuse (token arbitrage) that these restrictions target, it remains in a gray area according to the Terms of Service. Use it at your own risk.
Others
/api/oauth/usage is an internal endpoint not mentioned in official documentation. Changes by Anthropic could break this script at any time. A GitHub issue requesting an official usage API exists here, so a formal method might eventually be provided.
When running the script for the first time, macOS may display a dialog requesting permission to access the Keychain. Once you select "Allow," you will not be prompted again.
The script uses the python3 command. It runs with the default macOS Python 3, but if you manage multiple versions using Homebrew or similar, you can explicitly use /usr/bin/python3 if preferred.
Discussion