Monitoring Claude Pro Usage with a Bash Script
If you run Claude Code heavily, you've probably stared at the usage bar wondering how much of your 5-hour block is gone — and whether your extra credits are quietly draining. I built a small bash script to stop guessing and start logging.
The problem
Claude Pro has three usage dimensions worth tracking:
- 5-hour block utilisation — the rolling window that gates your active sessions
- 7-day utilisation — the broader weekly cap
- Extra credits — the paid overflow, billed in euros
None of this is exposed in a machine-readable way by default. It turns out there is an undocumented OAuth endpoint that exposes exactly that data.
The endpoint
Claude Code stores an OAuth access token in ~/.claude/.credentials.json. The same token works against the usage API:
GET https://api.anthropic.com/api/oauth/usage
Authorization: Bearer <token>
anthropic-beta: oauth-2025-04-20
The response looks like this:
{
"five_hour": { "utilization": 7.0, "resets_at": "..." },
"seven_day": { "utilization": 19.0, "resets_at": "..." },
"extra_usage": {
"is_enabled": true,
"monthly_limit": 1700,
"used_credits": 190.0,
"utilization": 11.18,
"currency": "EUR"
}
}
Note: monthly_limit and used_credits are in eurocents. Divide by 100 for the actual euro amounts.
The script
The script reads the token, hits the endpoint, optionally queries ccusage blocks for remaining block time, and appends a single JSON line to a log file — ready for Loki to scrape and Grafana to visualise.
#!/usr/bin/env bash
# Dependencies: jq, curl, ccusage (npm install -g ccusage)
LOGFILE="/var/log/ccusage.log"
CREDENTIALS_FILE="${HOME}/.claude/.credentials.json"
ANTHROPIC_USAGE_URL="https://api.anthropic.com/api/oauth/usage"
log() { echo "[$(date '+%d-%b-%Y %H:%M:%S')] $*" >&2; }
TOKEN=$(jq -r '.claudeAiOauth.accessToken // empty' "$CREDENTIALS_FILE" 2>/dev/null)
if [[ -z "$TOKEN" ]]; then
log "No credentials available, aborting"
exit 1
fi
USAGE=$(curl -s \
-H "Authorization: Bearer $TOKEN" \
-H "anthropic-beta: oauth-2025-04-20" \
"$ANTHROPIC_USAGE_URL")
if ! echo "$USAGE" | jq -e '.five_hour' > /dev/null 2>&1; then
log "Invalid API response"
exit 1
fi
BLOK=$(echo "$USAGE" | jq '(.five_hour.utilization // 0) | round')
WEEK=$(echo "$USAGE" | jq '(.seven_day.utilization // 0) | round')
CREDITS_PCT=$(echo "$USAGE" | jq '(.extra_usage.utilization // 0) * 100 | round / 100')
CREDITS_USED=$(echo "$USAGE" | jq '(.extra_usage.used_credits // 0) / 100')
CREDITS_MAX=$(echo "$USAGE" | jq '(.extra_usage.monthly_limit // 0) / 100')
REMAINING=$(ccusage blocks --json 2>/dev/null | jq '
if (.blocks // []) | length > 0
and (.blocks[-1].projection.remainingMinutes // null) != null
then (.blocks[-1].projection.remainingMinutes / 60 * 10 | round / 10)
else 0
end' 2>/dev/null || echo 0)
printf '{"timestamp":"%s","blok_pct":%s,"week_pct":%s,"credits_pct":%s,"credits_used":%s,"credits_max":%s,"blok_remaining_hours":%s}\n' \
"$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
"$BLOK" "$WEEK" "$CREDITS_PCT" "$CREDITS_USED" "$CREDITS_MAX" "$REMAINING" \
>> "$LOGFILE"
log "ccusage logged: block=${BLOK}% week=${WEEK}% credits=${CREDITS_PCT}%"
Install
Dependencies:
apt install jq curl
npm install -g ccusage
Deploy:
cp ccusage_log.sh /usr/local/sbin/ccusage_log
chmod +x /usr/local/sbin/ccusage_log
Cron — every 5 minutes:
*/5 * * * * /usr/local/sbin/ccusage_log
Output
Each run appends one line to /var/log/ccusage.log:
{"timestamp":"2026-05-23T19:26:17Z","blok_pct":7,"week_pct":19,"credits_pct":11.18,"credits_used":1.9,"credits_max":17,"blok_remaining_hours":0}
Point a Loki scrape job at that file and you have time-series data for all six metrics. Setting up Loki and Grafana for this is a topic for a separate post.
Notes
- Tested on Claude Pro with Claude Code. May work with other Claude subscriptions, but I haven't verified.
- The OAuth endpoint is undocumented and could change without notice.
blok_remaining_hoursis0when no active session block is running — that's expected.- The full script with the latest version is available on GitHub: pven/scripts/claude
Written with assistance from Claude.
Want to reach out? Contact me.