Skip to content

Instantly share code, notes, and snippets.

@AmosG
Created March 6, 2026 21:18
Show Gist options
  • Select an option

  • Save AmosG/1fcf264101dec49a4dc11304fa956bab to your computer and use it in GitHub Desktop.

Select an option

Save AmosG/1fcf264101dec49a4dc11304fa956bab to your computer and use it in GitHub Desktop.
Claude Code statusline: context window, session cost, and real-time 5h/7d plan rate limits via OAuth API
#!/bin/bash
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
# Context bar
BAR_WIDTH=10
FILLED=$((PCT * BAR_WIDTH / 100))
EMPTY=$((BAR_WIDTH - FILLED))
BAR=""
[ "$FILLED" -gt 0 ] && BAR=$(printf "%${FILLED}s" | tr ' ' '▓')
[ "$EMPTY" -gt 0 ] && BAR="${BAR}$(printf "%${EMPTY}s" | tr ' ' '░')"
if [ "$PCT" -ge 90 ]; then CTX_COLOR='\033[31m'
elif [ "$PCT" -ge 70 ]; then CTX_COLOR='\033[33m'
else CTX_COLOR='\033[32m'; fi
# Rate limits (cached 120s)
CACHE_FILE="/tmp/claude-rate-limits-cache"
CACHE_TTL=120
NOW=$(date +%s)
SHOULD_FETCH=true
if [ -f "$CACHE_FILE" ]; then
if [[ "$OSTYPE" == "darwin"* ]]; then
CACHE_AGE=$((NOW - $(stat -f %m "$CACHE_FILE" 2>/dev/null || echo 0)))
else
CACHE_AGE=$((NOW - $(stat -c %Y "$CACHE_FILE" 2>/dev/null || echo 0)))
fi
[ "$CACHE_AGE" -lt "$CACHE_TTL" ] && SHOULD_FETCH=false
fi
if [ "$SHOULD_FETCH" = "true" ]; then
RAW=$(security find-generic-password -s 'Claude Code-credentials' -w 2>/dev/null)
TOKEN=$(echo "$RAW" | jq -r '.claudeAiOauth.accessToken // empty' 2>/dev/null)
if [ -z "$TOKEN" ]; then
DECODED=$(echo "$RAW" | xxd -r -p 2>/dev/null)
TOKEN=$(echo "$DECODED" | jq -r '.claudeAiOauth.accessToken // empty' 2>/dev/null)
fi
if [ -n "$TOKEN" ]; then
USAGE=$(curl -s --max-time 5 "https://api.anthropic.com/api/oauth/usage" \
-H "Authorization: Bearer $TOKEN" \
-H "anthropic-beta: oauth-2025-04-20" \
-H "Accept: application/json" 2>/dev/null)
[ -n "$USAGE" ] && echo "$USAGE" > "$CACHE_FILE"
fi
fi
RATE_OUT=""
if [ -f "$CACHE_FILE" ]; then
CACHE=$(cat "$CACHE_FILE")
FH=$(echo "$CACHE" | jq -r '.five_hour.utilization // empty' 2>/dev/null)
SD=$(echo "$CACHE" | jq -r '.seven_day.utilization // empty' 2>/dev/null)
FH_RESET=$(echo "$CACHE" | jq -r '.five_hour.resets_at // empty' 2>/dev/null)
if [ -n "$FH" ] && [ -n "$SD" ]; then
FH_INT=$(printf "%.0f" "$FH")
SD_INT=$(printf "%.0f" "$SD")
# Color for 5h
if [ "$FH_INT" -ge 95 ]; then FH_COLOR='\033[31m'
elif [ "$FH_INT" -ge 75 ]; then FH_COLOR='\033[33m'
else FH_COLOR='\033[32m'; fi
# Color for 7d
if [ "$SD_INT" -ge 95 ]; then SD_COLOR='\033[31m'
elif [ "$SD_INT" -ge 75 ]; then SD_COLOR='\033[33m'
else SD_COLOR='\033[32m'; fi
# Time until 5h reset
RESET_STR=""
if [ -n "$FH_RESET" ]; then
RESET_EPOCH=$(date -u -j -f "%Y-%m-%dT%H:%M:%S" "${FH_RESET%%.*}" +%s 2>/dev/null || echo 0)
SECS_LEFT=$((RESET_EPOCH - NOW))
if [ "$SECS_LEFT" -gt 0 ]; then
MINS_LEFT=$((SECS_LEFT / 60))
if [ "$MINS_LEFT" -ge 60 ]; then
HRS=$((MINS_LEFT / 60)); MIN=$((MINS_LEFT % 60))
RESET_STR=" ↺${HRS}h${MIN}m"
else
RESET_STR=" ↺${MINS_LEFT}m"
fi
fi
fi
RESET='\033[0m'
RATE_OUT=" | ${FH_COLOR}5h:${FH_INT}%${RESET}${RESET_STR} ${SD_COLOR}7d:${SD_INT}%${RESET}"
fi
fi
COST_FMT=$(printf '$%.4f' "$COST")
RESET='\033[0m'
echo -e "[$MODEL] ${CTX_COLOR}${BAR} ${PCT}%${RESET} | ${COST_FMT}${RATE_OUT}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment