Skip to content

Instantly share code, notes, and snippets.

@omachala
Created February 22, 2026 09:44
Show Gist options
  • Select an option

  • Save omachala/5ea5af4bfa0b194a1d48d6f2eedd6274 to your computer and use it in GitHub Desktop.

Select an option

Save omachala/5ea5af4bfa0b194a1d48d6f2eedd6274 to your computer and use it in GitHub Desktop.
Claude Code Usage CLI - check your session, weekly, and extra usage limits from the terminal
#!/bin/bash
# Claude Code Usage CLI
# Fetches usage data from Anthropic API and displays it in a readable format
#
# Setup:
# 1. Make sure you're logged into Claude Code (credentials stored in macOS Keychain)
# 2. If you're behind a firewall, configure PROXY_PORT and SSH_HOST below
# 3. chmod +x claude-usage && ./claude-usage
#
# Optional: alias usage="~/path/to/claude-usage"
set -e
# --- Configuration ---
# If you need a SOCKS5 proxy to reach api.anthropic.com, set these.
# Leave SSH_HOST empty to connect directly without a proxy.
PROXY_PORT=1080
SSH_HOST="" # e.g. "user@your-server.com"
SSH_PORT=22
USE_PROXY=false
# ---------------------
# Start SSH SOCKS5 proxy if configured and not running
start_proxy() {
if [[ "$USE_PROXY" != "true" ]] || [[ -z "$SSH_HOST" ]]; then
return
fi
if ! nc -z localhost $PROXY_PORT 2>/dev/null; then
ssh -o ConnectTimeout=5 -D $PROXY_PORT -f -N $SSH_HOST -p$SSH_PORT 2>/dev/null || {
echo "Error: Could not establish SSH tunnel to $SSH_HOST" >&2
exit 1
}
sleep 1
fi
}
# Get token from Keychain (macOS)
get_token() {
local creds
creds=$(security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null) || {
echo "Error: Could not retrieve Claude Code credentials from Keychain" >&2
echo "Make sure you're logged into Claude Code" >&2
exit 1
}
echo "$creds" | jq -r '.claudeAiOauth.accessToken'
}
# Fetch usage from API
fetch_usage() {
local token="$1"
local curl_args=(-s)
if [[ "$USE_PROXY" == "true" ]] && [[ -n "$SSH_HOST" ]]; then
curl_args+=(--proxy "socks5h://localhost:$PROXY_PORT")
fi
curl "${curl_args[@]}" "https://api.anthropic.com/api/oauth/usage" \
-H "Authorization: Bearer $token" \
-H "anthropic-beta: oauth-2025-04-20" \
-H "User-Agent: claude-code/2.0.32"
}
# Format ISO date to readable format
format_iso_date() {
local iso_date="$1"
if [[ "$OSTYPE" == "darwin"* ]]; then
date -j -f "%Y-%m-%dT%H:%M:%S" "${iso_date%%.*}" "+%Y-%m-%d %H:%M" 2>/dev/null || echo "$iso_date"
else
date -d "$iso_date" "+%Y-%m-%d %H:%M" 2>/dev/null || echo "$iso_date"
fi
}
# Convert ISO to epoch
iso_to_epoch() {
local iso_date="$1"
if [[ "$OSTYPE" == "darwin"* ]]; then
date -j -f "%Y-%m-%dT%H:%M:%S" "${iso_date%%.*}" "+%s" 2>/dev/null || echo "0"
else
date -d "$iso_date" "+%s" 2>/dev/null || echo "0"
fi
}
# Calculate week start from reset date (7 days before)
calc_week_start() {
local reset_iso="$1"
if [[ "$OSTYPE" == "darwin"* ]]; then
local reset_epoch
reset_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%S" "${reset_iso%%.*}" "+%s" 2>/dev/null) || { echo "$reset_iso"; return; }
local start_epoch=$((reset_epoch - 604800))
date -r "$start_epoch" "+%Y-%m-%d %H:%M"
else
date -d "$reset_iso - 7 days" "+%Y-%m-%d %H:%M" 2>/dev/null || echo "$reset_iso"
fi
}
# Draw progress bar
progress_bar() {
local pct="$1"
local width=30
local filled=$(echo "scale=0; $pct * $width / 100" | bc)
[[ $filled -gt $width ]] && filled=$width
local empty=$((width - filled))
printf "["
printf "%${filled}s" | tr ' ' '='
printf "%${empty}s" | tr ' ' ' '
printf "]"
}
# Main
main() {
local token usage
start_proxy
token=$(get_token)
usage=$(fetch_usage "$token")
if echo "$usage" | jq -e '.error' > /dev/null 2>&1; then
echo "API Error: $(echo "$usage" | jq -r '.error.message // .error')" >&2
exit 1
fi
# Extract data
local five_hour_pct five_hour_reset seven_day_pct seven_day_reset
five_hour_pct=$(echo "$usage" | jq -r '.five_hour.utilization // 0')
five_hour_reset=$(echo "$usage" | jq -r '.five_hour.resets_at // ""')
seven_day_pct=$(echo "$usage" | jq -r '.seven_day.utilization // 0')
seven_day_reset=$(echo "$usage" | jq -r '.seven_day.resets_at // ""')
# Extract extra usage (pay-as-you-go) - API returns cents, convert to dollars
local extra_enabled extra_limit_cents extra_used_cents extra_pct extra_limit extra_used
extra_enabled=$(echo "$usage" | jq -r '.extra_usage.is_enabled // false')
extra_limit_cents=$(echo "$usage" | jq -r '.extra_usage.monthly_limit // 0')
extra_used_cents=$(echo "$usage" | jq -r '.extra_usage.used_credits // 0')
extra_pct=$(echo "$usage" | jq -r '.extra_usage.utilization // 0')
extra_limit=$(echo "scale=2; $extra_limit_cents / 100" | bc)
extra_used=$(echo "scale=2; $extra_used_cents / 100" | bc)
# Calculate pace info
local now_epoch reset_epoch start_epoch
now_epoch=$(date +%s)
reset_epoch=$(iso_to_epoch "$seven_day_reset")
start_epoch=$((reset_epoch - 604800))
local elapsed_seconds time_pct expected_pct diff
elapsed_seconds=$((now_epoch - start_epoch))
time_pct=$(echo "scale=1; $elapsed_seconds * 100 / 604800" | bc)
expected_pct="$time_pct"
diff=$(echo "scale=1; $seven_day_pct - $expected_pct" | bc)
# Days/hours remaining
local remaining_seconds days_remaining hours_remaining
remaining_seconds=$((reset_epoch - now_epoch))
days_remaining=$((remaining_seconds / 86400))
hours_remaining=$(( (remaining_seconds % 86400) / 3600 ))
echo ""
echo "Claude Code Usage"
echo "─────────────────────────────────────────────"
echo ""
# Session (5-hour)
echo "Session (5-hour window)"
printf " Usage: %s%% " "$five_hour_pct"
progress_bar "$five_hour_pct"
echo ""
echo " Resets: $(format_iso_date "$five_hour_reset")"
echo ""
# Weekly (7-day)
echo "Weekly (7-day window)"
printf " Usage: %s%% " "$seven_day_pct"
progress_bar "$seven_day_pct"
echo ""
echo " Period: $(calc_week_start "$seven_day_reset") -> $(format_iso_date "$seven_day_reset")"
echo " Time left: ${days_remaining}d ${hours_remaining}h"
echo ""
# Extra usage (pay-as-you-go)
if [[ "$extra_enabled" == "true" ]]; then
echo "Extra Usage (Monthly)"
printf " Used: \$%.2f / \$%s (%s%%)\n" "$extra_used" "$extra_limit" "$extra_pct"
progress_bar "$extra_pct"
echo ""
echo ""
fi
# Pace status
echo "Pace"
printf " Expected: %s%% (linear) | Actual: %s%%\n" "$expected_pct" "$seven_day_pct"
if (( $(echo "$diff > 5" | bc -l) )); then
printf " Status: AHEAD by %s%% - consider slowing down\n" "$diff"
elif (( $(echo "$diff < -5" | bc -l) )); then
local behind
behind=$(echo "scale=1; $diff * -1" | bc)
printf " Status: BEHIND by %s%% - you have headroom\n" "$behind"
else
echo " Status: ON TRACK"
fi
echo ""
# JSON output option
if [[ "$1" == "--json" ]]; then
echo "Raw API Response:"
echo "$usage" | jq
fi
}
main "$@"
@bdavidzhang
Copy link

https://gist.github.com/bdavidzhang/23c1448fa2c798e76d2145a689036c0e

made some quick UI updates and quality of life check that encourages the user to refresh their token if it's not showing up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment