Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 82 additions & 8 deletions statusline-command.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,70 @@ model=$(echo "$input" | jq -r '.model.display_name')
CACHE_FILE="/tmp/claude-usage-cache.json"
CACHE_MAX_AGE=60

TOKEN_CACHE_FILE="/tmp/claude-oauth-token-cache.json"
TOKEN_CACHE_MAX_AGE=3600

get_access_token() {
# Check token cache first (refreshed tokens are cached here)
if [ -f "$TOKEN_CACHE_FILE" ]; then
token_cache_age=$(($(date +%s) - $(stat -f %m "$TOKEN_CACHE_FILE" 2>/dev/null || echo 0)))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stat -f is BSD/macOS-only; add Linux compatibility with stat -c

Prompt To Fix With AI
This is a comment left during a code review.
Path: statusline-command.sh
Line: 21:21

Comment:
`stat -f` is BSD/macOS-only; add Linux compatibility with `stat -c`

How can I resolve this? If you propose a fix, please make it concise.

if [ $token_cache_age -lt $TOKEN_CACHE_MAX_AGE ]; then
cached_token=$(jq -r '.access_token // empty' "$TOKEN_CACHE_FILE" 2>/dev/null)
if [ -n "$cached_token" ]; then
echo "$cached_token"
return
fi
fi
fi

# Read credentials from Keychain - try current user account first, then fallback
local acct
acct=$(whoami)
creds=$(security find-generic-password -s "Claude Code-credentials" -a "$acct" -w 2>/dev/null)
if [ -z "$creds" ] || ! echo "$creds" | jq -e '.claudeAiOauth' >/dev/null 2>&1; then
creds=$(security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null)
fi

access_token=$(echo "$creds" | jq -r '.claudeAiOauth.accessToken // empty' 2>/dev/null)
refresh_token=$(echo "$creds" | jq -r '.claudeAiOauth.refreshToken // empty' 2>/dev/null)
expires_at=$(echo "$creds" | jq -r '.claudeAiOauth.expiresAt // 0' 2>/dev/null)
now_ms=$(($(date +%s) * 1000))

# If token is still valid, use it
if [ -n "$access_token" ] && [ "$now_ms" -lt "$expires_at" ] 2>/dev/null; then
echo "$access_token"
return
fi

# Token expired - refresh it
if [ -n "$refresh_token" ]; then
refresh_result=$(curl -s -X POST "https://platform.claude.com/v1/oauth/token" \
-H "Content-Type: application/json" \
-d "{\"grant_type\":\"refresh_token\",\"refresh_token\":\"$refresh_token\",\"client_id\":\"9d1c250a-e61b-44d9-88ed-5944d1962f5e\",\"scope\":\"user:profile user:inference user:sessions:claude_code user:mcp_servers\"}" 2>/dev/null)

new_token=$(echo "$refresh_result" | jq -r '.access_token // empty' 2>/dev/null)
if [ -n "$new_token" ]; then
# Cache the refreshed token
echo "$refresh_result" > "$TOKEN_CACHE_FILE"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Critical

statusline-command.sh:59

OAuth tokens are written to /tmp/claude-oauth-token-cache.json with default (world-readable) permissions, allowing any local user to steal credentials. Consider restricting permissions with chmod 600 after writing or using a user-specific directory like ~/.cache/.

-      echo "$refresh_result" > "$TOKEN_CACHE_FILE"
+      echo "$refresh_result" > "$TOKEN_CACHE_FILE"
+      chmod 600 "$TOKEN_CACHE_FILE"

🚀 Want me to fix this? Reply ex: "fix it for me".

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix it for me

@cubic-dev-ai cubic-dev-ai Bot Feb 1, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: OAuth tokens written to /tmp are world-readable by default. This exposes the access token to other users on multi-user systems. Set restrictive permissions when writing sensitive credentials.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At statusline-command.sh, line 59:

<comment>OAuth tokens written to `/tmp` are world-readable by default. This exposes the access token to other users on multi-user systems. Set restrictive permissions when writing sensitive credentials.</comment>

<file context>
@@ -12,9 +12,70 @@ model=$(echo "$input" | jq -r '.model.display_name')
+    new_token=$(echo "$refresh_result" | jq -r '.access_token // empty' 2>/dev/null)
+    if [ -n "$new_token" ]; then
+      # Cache the refreshed token
+      echo "$refresh_result" > "$TOKEN_CACHE_FILE"
+
+      # Update Keychain with new credentials
</file context>
Suggested change
echo "$refresh_result" > "$TOKEN_CACHE_FILE"
echo "$refresh_result" > "$TOKEN_CACHE_FILE"
chmod 600 "$TOKEN_CACHE_FILE"
Fix with Cubic


# Update Keychain with new credentials
new_refresh=$(echo "$refresh_result" | jq -r '.refresh_token // empty' 2>/dev/null)
expires_in=$(echo "$refresh_result" | jq -r '.expires_in // 0' 2>/dev/null)
new_expires_at=$(( $(date +%s) * 1000 + expires_in * 1000 ))
[ -z "$new_refresh" ] && new_refresh="$refresh_token"
updated_creds=$(echo "$creds" | jq --arg at "$new_token" --arg rt "$new_refresh" --argjson ea "$new_expires_at" \
'.claudeAiOauth.accessToken = $at | .claudeAiOauth.refreshToken = $rt | .claudeAiOauth.expiresAt = $ea')
security delete-generic-password -s "Claude Code-credentials" -a "$acct" >/dev/null 2>&1
security add-generic-password -s "Claude Code-credentials" -a "$acct" -w "$updated_creds" 2>/dev/null
Comment on lines +68 to +69

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Race condition: keychain delete/add isn't atomic; concurrent statusline calls could corrupt credentials

Prompt To Fix With AI
This is a comment left during a code review.
Path: statusline-command.sh
Line: 68:69

Comment:
Race condition: keychain delete/add isn't atomic; concurrent statusline calls could corrupt credentials

How can I resolve this? If you propose a fix, please make it concise.


echo "$new_token"
return
fi
fi
}

fetch_usage() {
# Get OAuth token from Keychain
token=$(security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null | jq -r '.claudeAiOauth.accessToken // empty' 2>/dev/null)
token=$(get_access_token)
if [ -n "$token" ]; then
curl -s \
-H "Authorization: Bearer $token" \
Expand All @@ -40,10 +101,20 @@ if [ -z "$api_usage" ]; then
fi
fi

# Parse API usage
# Parse API usage - handle both old and new API response formats
five_hour_pct=$(echo "$api_usage" | jq -r '.five_hour.utilization // 0' 2>/dev/null | cut -d. -f1)
seven_day_pct=$(echo "$api_usage" | jq -r '.seven_day.utilization // 0' 2>/dev/null | cut -d. -f1)
opus_pct=$(echo "$api_usage" | jq -r '.seven_day_opus.utilization // 0' 2>/dev/null | cut -d. -f1)
# Try seven_day_opus first, fall back to seven_day_sonnet
opus_pct=$(echo "$api_usage" | jq -r '(.seven_day_opus.utilization // .seven_day_sonnet.utilization // 0)' 2>/dev/null | cut -d. -f1)

# Determine label for model-specific limit
if echo "$api_usage" | jq -e '.seven_day_opus.utilization' >/dev/null 2>&1; then
model_limit_label="Opus"
elif echo "$api_usage" | jq -e '.seven_day_sonnet.utilization' >/dev/null 2>&1; then
model_limit_label="Sonnet"
else
model_limit_label="Model"
fi

# Get git branch
cd "$project_dir" 2>/dev/null
Expand Down Expand Up @@ -91,9 +162,11 @@ fi
# Color code usage percentages (green < 60, yellow 60-89, red >= 90)
color_pct() {
local pct=$1
if [ "$pct" -ge 90 ]; then
if [ -z "$pct" ] || [ "$pct" = "0" ]; then
echo "\033[32m${pct}%\033[0m" # green

@cubic-dev-ai cubic-dev-ai Bot Feb 1, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When pct is empty, this outputs just % with no number. The empty check should substitute a default value to display 0% instead.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At statusline-command.sh, line 166:

<comment>When `pct` is empty, this outputs just `%` with no number. The empty check should substitute a default value to display `0%` instead.</comment>

<file context>
@@ -91,9 +162,11 @@ fi
   local pct=$1
-  if [ "$pct" -ge 90 ]; then
+  if [ -z "$pct" ] || [ "$pct" = "0" ]; then
+    echo "\033[32m${pct}%\033[0m"  # green
+  elif [ "$pct" -ge 90 ] 2>/dev/null; then
     echo "\033[31m${pct}%\033[0m"  # red
</file context>
Suggested change
echo "\033[32m${pct}%\033[0m" # green
echo "\033[32m${pct:-0}%\033[0m" # green
Fix with Cubic

elif [ "$pct" -ge 90 ] 2>/dev/null; then
echo "\033[31m${pct}%\033[0m" # red
elif [ "$pct" -ge 60 ]; then
elif [ "$pct" -ge 60 ] 2>/dev/null; then
echo "\033[33m${pct}%\033[0m" # yellow
else
echo "\033[32m${pct}%\033[0m" # green
Expand All @@ -105,13 +178,14 @@ seven_day_display=$(color_pct "$seven_day_pct")
opus_display=$(color_pct "$opus_pct")

# Output status line with clear labels
# Format: repo | model | Context [bar] % | Tokens: N | Limits: 5hr% 7day% Opus% | (branch)
printf "\033[33m%s\033[0m | %s | Context %b | Tokens: \033[36m%s\033[0m | Limits: 5hr %b · 7day %b · Opus %b | (\033[32m%s\033[0m)" \
# Format: repo | model | Context [bar] % | Tokens: N | Limits: 5hr% 7day% Model% | (branch)
printf "\033[33m%s\033[0m | %s | Context %b | Tokens: \033[36m%s\033[0m | Limits: 5hr %b · 7day %b · %s %b | (\033[32m%s\033[0m)" \
"$repo_name" \
"$model" \
"$context_display" \
"$session_display" \
"$five_hour_display" \
"$seven_day_display" \
"$model_limit_label" \
"$opus_display" \
"$branch"