| #!/bin/bash |
| |
| |
|
|
| set -euo pipefail |
|
|
| CLAUDE_CREDS="$HOME/.claude/.credentials.json" |
| OPENCLAW_AUTH="$HOME/.openclaw/agents/main/agent/auth-profiles.json" |
|
|
| |
| RED='\033[0;31m' |
| YELLOW='\033[1;33m' |
| GREEN='\033[0;32m' |
| NC='\033[0m' |
|
|
| |
| OUTPUT_MODE="${1:-full}" |
|
|
| fetch_models_status_json() { |
| openclaw models status --json 2>/dev/null || true |
| } |
|
|
| STATUS_JSON="$(fetch_models_status_json)" |
| USE_JSON=0 |
| if [ -n "$STATUS_JSON" ]; then |
| USE_JSON=1 |
| fi |
|
|
| calc_status_from_expires() { |
| local expires_at="$1" |
| if ! [[ "$expires_at" =~ ^-?[0-9]+$ ]]; then |
| expires_at=0 |
| fi |
| local now_ms=$(( $(date +%s) * 1000 )) |
| local diff_ms=$((expires_at - now_ms)) |
| local hours=$((diff_ms / 3600000)) |
| local mins=$(((diff_ms % 3600000) / 60000)) |
|
|
| if [ "$expires_at" -le 0 ]; then |
| echo "MISSING" |
| return 1 |
| elif [ "$diff_ms" -lt 0 ]; then |
| echo "EXPIRED" |
| return 1 |
| elif [ "$diff_ms" -lt 3600000 ]; then |
| echo "EXPIRING:${mins}m" |
| return 2 |
| else |
| echo "OK:${hours}h${mins}m" |
| return 0 |
| fi |
| } |
|
|
| json_expires_for_claude_cli() { |
| echo "$STATUS_JSON" | jq -r ' |
| [.auth.oauth.profiles[] |
| | select(.provider == "anthropic" and (.type == "oauth" or .type == "token")) |
| | .expiresAt // 0] |
| | max // 0 |
| ' 2>/dev/null || echo "0" |
| } |
|
|
| json_expires_for_anthropic_any() { |
| echo "$STATUS_JSON" | jq -r ' |
| [.auth.oauth.profiles[] |
| | select(.provider == "anthropic" and .type == "oauth") |
| | .expiresAt // 0] |
| | max // 0 |
| ' 2>/dev/null || echo "0" |
| } |
|
|
| json_best_anthropic_profile() { |
| echo "$STATUS_JSON" | jq -r ' |
| [.auth.oauth.profiles[] |
| | select(.provider == "anthropic" and .type == "oauth") |
| | {id: .profileId, exp: (.expiresAt // 0)}] |
| | sort_by(.exp) | reverse | .[0].id // "none" |
| ' 2>/dev/null || echo "none" |
| } |
|
|
| json_anthropic_api_key_count() { |
| echo "$STATUS_JSON" | jq -r ' |
| [.auth.providers[] | select(.provider == "anthropic") | .profiles.apiKey] |
| | max // 0 |
| ' 2>/dev/null || echo "0" |
| } |
|
|
| check_claude_code_auth() { |
| if [ "$USE_JSON" -eq 1 ]; then |
| local expires_at |
| expires_at=$(json_expires_for_claude_cli) |
| calc_status_from_expires "$expires_at" |
| return $? |
| fi |
|
|
| if [ ! -f "$CLAUDE_CREDS" ]; then |
| echo "MISSING" |
| return 1 |
| fi |
|
|
| local expires_at |
| expires_at=$(jq -r '.claudeAiOauth.expiresAt // 0' "$CLAUDE_CREDS" 2>/dev/null || echo "0") |
| calc_status_from_expires "$expires_at" |
| } |
|
|
| check_openclaw_auth() { |
| if [ "$USE_JSON" -eq 1 ]; then |
| local api_keys |
| api_keys=$(json_anthropic_api_key_count) |
| if ! [[ "$api_keys" =~ ^[0-9]+$ ]]; then |
| api_keys=0 |
| fi |
| local expires_at |
| expires_at=$(json_expires_for_anthropic_any) |
|
|
| if [ "$expires_at" -le 0 ] && [ "$api_keys" -gt 0 ]; then |
| echo "OK:static" |
| return 0 |
| fi |
|
|
| calc_status_from_expires "$expires_at" |
| return $? |
| fi |
|
|
| if [ ! -f "$OPENCLAW_AUTH" ]; then |
| echo "MISSING" |
| return 1 |
| fi |
|
|
| local expires |
| expires=$(jq -r ' |
| [.profiles | to_entries[] | select(.value.provider == "anthropic") | .value.expires] |
| | max // 0 |
| ' "$OPENCLAW_AUTH" 2>/dev/null || echo "0") |
|
|
| calc_status_from_expires "$expires" |
| } |
|
|
| |
| if [ "$OUTPUT_MODE" = "json" ]; then |
| claude_status=$(check_claude_code_auth 2>/dev/null || true) |
| openclaw_status=$(check_openclaw_auth 2>/dev/null || true) |
|
|
| claude_expires=0 |
| openclaw_expires=0 |
| if [ "$USE_JSON" -eq 1 ]; then |
| claude_expires=$(json_expires_for_claude_cli) |
| openclaw_expires=$(json_expires_for_anthropic_any) |
| else |
| claude_expires=$(jq -r '.claudeAiOauth.expiresAt // 0' "$CLAUDE_CREDS" 2>/dev/null || echo "0") |
| openclaw_expires=$(jq -r '.profiles["anthropic:default"].expires // 0' "$OPENCLAW_AUTH" 2>/dev/null || echo "0") |
| fi |
|
|
| jq -n \ |
| --arg cs "$claude_status" \ |
| --arg ce "$claude_expires" \ |
| --arg bs "$openclaw_status" \ |
| --arg be "$openclaw_expires" \ |
| '{ |
| claude_code: {status: $cs, expires_at_ms: ($ce | tonumber)}, |
| openclaw: {status: $bs, expires_at_ms: ($be | tonumber)}, |
| needs_reauth: (($cs | startswith("EXPIRED") or startswith("EXPIRING") or startswith("MISSING")) or ($bs | startswith("EXPIRED") or startswith("EXPIRING") or startswith("MISSING"))) |
| }' |
| exit 0 |
| fi |
|
|
| |
| if [ "$OUTPUT_MODE" = "simple" ]; then |
| claude_status=$(check_claude_code_auth 2>/dev/null || true) |
| openclaw_status=$(check_openclaw_auth 2>/dev/null || true) |
|
|
| if [[ "$claude_status" == EXPIRED* ]] || [[ "$claude_status" == MISSING* ]]; then |
| echo "CLAUDE_EXPIRED" |
| exit 1 |
| elif [[ "$openclaw_status" == EXPIRED* ]] || [[ "$openclaw_status" == MISSING* ]]; then |
| echo "OPENCLAW_EXPIRED" |
| exit 1 |
| elif [[ "$claude_status" == EXPIRING* ]]; then |
| echo "CLAUDE_EXPIRING" |
| exit 2 |
| elif [[ "$openclaw_status" == EXPIRING* ]]; then |
| echo "OPENCLAW_EXPIRING" |
| exit 2 |
| else |
| echo "OK" |
| exit 0 |
| fi |
| fi |
|
|
| |
| echo "=== Claude Code Auth Status ===" |
| echo "" |
|
|
| |
| echo "Claude Code (~/.claude/.credentials.json):" |
| if [ "$USE_JSON" -eq 1 ]; then |
| expires_at=$(json_expires_for_claude_cli) |
| else |
| expires_at=$(jq -r '.claudeAiOauth.expiresAt // 0' "$CLAUDE_CREDS" 2>/dev/null || echo "0") |
| fi |
|
|
| if [ -f "$CLAUDE_CREDS" ]; then |
| sub_type=$(jq -r '.claudeAiOauth.subscriptionType // "unknown"' "$CLAUDE_CREDS" 2>/dev/null || echo "unknown") |
| rate_tier=$(jq -r '.claudeAiOauth.rateLimitTier // "unknown"' "$CLAUDE_CREDS" 2>/dev/null || echo "unknown") |
| echo " Subscription: $sub_type" |
| echo " Rate tier: $rate_tier" |
| fi |
|
|
| if [ "$expires_at" -le 0 ]; then |
| echo -e " Status: ${RED}NOT FOUND${NC}" |
| echo " Action needed: Run 'claude setup-token'" |
| else |
| now_ms=$(( $(date +%s) * 1000 )) |
| diff_ms=$((expires_at - now_ms)) |
| hours=$((diff_ms / 3600000)) |
| mins=$(((diff_ms % 3600000) / 60000)) |
|
|
| if [ "$diff_ms" -lt 0 ]; then |
| echo -e " Status: ${RED}EXPIRED${NC}" |
| echo " Action needed: Run 'claude setup-token' or re-authenticate" |
| elif [ "$diff_ms" -lt 3600000 ]; then |
| echo -e " Status: ${YELLOW}EXPIRING SOON (${mins}m remaining)${NC}" |
| echo " Consider running: claude setup-token" |
| else |
| echo -e " Status: ${GREEN}OK${NC}" |
| echo " Expires: $(date -d @$((expires_at/1000))) (${hours}h ${mins}m)" |
| fi |
| fi |
|
|
| echo "" |
| echo "OpenClaw Auth (~/.openclaw/agents/main/agent/auth-profiles.json):" |
| if [ "$USE_JSON" -eq 1 ]; then |
| best_profile=$(json_best_anthropic_profile) |
| expires=$(json_expires_for_anthropic_any) |
| api_keys=$(json_anthropic_api_key_count) |
| else |
| best_profile=$(jq -r ' |
| .profiles | to_entries |
| | map(select(.value.provider == "anthropic")) |
| | sort_by(.value.expires) | reverse |
| | .[0].key // "none" |
| ' "$OPENCLAW_AUTH" 2>/dev/null || echo "none") |
| expires=$(jq -r ' |
| [.profiles | to_entries[] | select(.value.provider == "anthropic") | .value.expires] |
| | max // 0 |
| ' "$OPENCLAW_AUTH" 2>/dev/null || echo "0") |
| api_keys=0 |
| fi |
|
|
| echo " Profile: $best_profile" |
|
|
| if [ "$expires" -le 0 ] && [ "$api_keys" -gt 0 ]; then |
| echo -e " Status: ${GREEN}OK${NC} (API key)" |
| elif [ "$expires" -le 0 ]; then |
| echo -e " Status: ${RED}NOT FOUND${NC}" |
| echo " Note: Run 'openclaw doctor --yes' to sync from Claude Code" |
| else |
| now_ms=$(( $(date +%s) * 1000 )) |
| diff_ms=$((expires - now_ms)) |
| hours=$((diff_ms / 3600000)) |
| mins=$(((diff_ms % 3600000) / 60000)) |
|
|
| if [ "$diff_ms" -lt 0 ]; then |
| echo -e " Status: ${RED}EXPIRED${NC}" |
| echo " Note: Run 'openclaw doctor --yes' to sync from Claude Code" |
| elif [ "$diff_ms" -lt 3600000 ]; then |
| echo -e " Status: ${YELLOW}EXPIRING SOON (${mins}m remaining)${NC}" |
| else |
| echo -e " Status: ${GREEN}OK${NC}" |
| echo " Expires: $(date -d @$((expires/1000))) (${hours}h ${mins}m)" |
| fi |
| fi |
|
|
| echo "" |
| echo "=== Service Status ===" |
| if systemctl --user is-active openclaw >/dev/null 2>&1; then |
| echo -e "OpenClaw service: ${GREEN}running${NC}" |
| else |
| echo -e "OpenClaw service: ${RED}NOT running${NC}" |
| fi |
|
|