|
#!/bin/bash |
|
# |
|
# Show 5h + 7d API remaining capacity in your statusline |
|
# |
|
|
|
set -euo pipefail |
|
|
|
CACHE="$HOME/.cache/cc-usage.txt" |
|
LOCK="$HOME/.cache/cc-usage.lock" |
|
TTL="${CC_CACHE_TTL:-60}" |
|
|
|
get_mtime() { |
|
stat -f '%m' "$1" 2>/dev/null || echo 0 |
|
} |
|
|
|
# Build a 10-segment bar: ━ for remaining, ╌ for used |
|
make_bar() { |
|
local remaining=$1 |
|
local filled=$(( (remaining + 5) / 10 )) |
|
[[ $filled -gt 10 ]] && filled=10 |
|
[[ $filled -lt 0 ]] && filled=0 |
|
local empty=$(( 10 - filled )) |
|
if [[ $filled -gt 0 ]]; then printf '%0.s━' $(seq 1 $filled); fi |
|
if [[ $empty -gt 0 ]]; then printf '%0.s╌' $(seq 1 $empty); fi |
|
} |
|
|
|
# Return cached if fresh |
|
if [[ -f "$CACHE" ]]; then |
|
age=$(($(date +%s) - $(get_mtime "$CACHE"))) |
|
[[ $age -lt $TTL ]] && cat "$CACHE" && exit 0 |
|
fi |
|
|
|
# Rate limit API calls |
|
if [[ -f "$LOCK" ]]; then |
|
age=$(($(date +%s) - $(get_mtime "$LOCK"))) |
|
[[ $age -lt 30 ]] && { [[ -f "$CACHE" ]] && cat "$CACHE"; exit 0; } |
|
fi |
|
touch "$LOCK" |
|
|
|
# Get token from macOS Keychain |
|
creds=$(security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null) || true |
|
[[ -z "$creds" ]] && echo "[No creds]" && exit 1 |
|
token=$(echo "$creds" | jq -r '.claudeAiOauth.accessToken // empty' 2>/dev/null) |
|
[[ -z "$token" ]] && echo "[Bad token]" && exit 1 |
|
|
|
# Fetch usage |
|
resp=$(curl -s --max-time 5 \ |
|
"https://api.anthropic.com/api/oauth/usage" \ |
|
-H "Authorization: Bearer $token" \ |
|
-H "anthropic-beta: oauth-2025-04-20" 2>/dev/null) || true |
|
|
|
[[ -z "$resp" ]] && { [[ -f "$CACHE" ]] && cat "$CACHE"; echo "[Timeout]"; exit 1; } |
|
|
|
session=$(echo "$resp" | jq -r '.five_hour.utilization // empty' 2>/dev/null) |
|
weekly=$(echo "$resp" | jq -r '.seven_day.utilization // empty' 2>/dev/null) |
|
h5_resets=$(echo "$resp" | jq -r '.five_hour.resets_at // empty' 2>/dev/null) |
|
d7_resets=$(echo "$resp" | jq -r '.seven_day.resets_at // empty' 2>/dev/null) |
|
|
|
[[ -z "$session" || -z "$weekly" ]] && { [[ -f "$CACHE" ]] && cat "$CACHE"; echo "[Error]"; exit 1; } |
|
|
|
# Calculate remaining |
|
h5_left=$(awk "BEGIN { printf \"%.0f\", 100 - $session }") |
|
d7_left=$(awk "BEGIN { printf \"%.0f\", 100 - $weekly }") |
|
|
|
# Format reset times (convert UTC to local) |
|
h5_epoch=$(date -juf "%Y-%m-%dT%H:%M:%S" "${h5_resets%%.*}" "+%s" 2>/dev/null || echo "0") |
|
d7_epoch=$(date -juf "%Y-%m-%dT%H:%M:%S" "${d7_resets%%.*}" "+%s" 2>/dev/null || echo "0") |
|
h5_time=$(date -jf "%s" "$h5_epoch" "+%H:%M" 2>/dev/null || echo "?") |
|
d7_time=$(date -jf "%s" "$d7_epoch" "+%a %H:%M" 2>/dev/null || echo "?") |
|
|
|
h5_bar=$(make_bar "$h5_left") |
|
d7_bar=$(make_bar "$d7_left") |
|
|
|
echo "Usage: 5h ${h5_bar} ${h5_left}% (${h5_time}) │ 7d ${d7_bar} ${d7_left}% (${d7_time})" | tee "$CACHE" |