Skip to content

Instantly share code, notes, and snippets.

@kerray
Last active April 14, 2026 13:56
Show Gist options
  • Select an option

  • Save kerray/a65a95a0d4931e19bf83cf19ab040e64 to your computer and use it in GitHub Desktop.

Select an option

Save kerray/a65a95a0d4931e19bf83cf19ab040e64 to your computer and use it in GitHub Desktop.
Claude Code statusline — model, git branch, API usage (5h/7d), context window. Cross-platform (macOS + Linux). Based on https://www.reddit.com/r/ClaudeCode/comments/1rg3nmt/

Claude Code Statusline

Minimal two-line statusline for Claude Code showing model, project, git branch, API usage, and context window.

Claude Opus 4.6 | my-project • main
5h 16% (2h 43m) • 7d 20% (6d 9h) | ctx 12% (11k/200k)

Based on this Reddit post by u/xleddyl — adapted to work cross-platform (macOS + Linux/WSL).

What it shows

Element Description
Model Current Claude model (orange)
Folder Project directory name (cyan)
Branch Git branch or short SHA (purple)
5h / 7d API usage percentage with time until reset
ctx Context window usage % and token count

Install

1. Copy scripts

curl -sL https://gist.githubusercontent.com/RAW_URL/fetch-usage.sh -o ~/.claude/fetch-usage.sh
curl -sL https://gist.githubusercontent.com/RAW_URL/statusline-command.sh -o ~/.claude/statusline-command.sh
chmod +x ~/.claude/fetch-usage.sh ~/.claude/statusline-command.sh

Or just copy the two .sh files into ~/.claude/.

2. Update settings

Add this to ~/.claude/settings.json (merge with existing config if you have one):

{
  "statusLine": {
    "type": "command",
    "command": "bash ~/.claude/statusline-command.sh"
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/fetch-usage.sh > /dev/null 2>&1 &"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/fetch-usage.sh > /dev/null 2>&1 &"
          }
        ]
      }
    ]
  }
}

3. Restart Claude Code

The statusline appears on the next session. Usage stats populate after the first tool use.

Requirements

  • curl and jq (both widely available)
  • git (for branch display)

How it works

  1. Hooks run fetch-usage.sh in the background on every tool use and when Claude stops
  2. fetch-usage.sh reads your OAuth token and calls the Anthropic usage API, caching results to /tmp/.claude_usage_cache
  3. The statusline command reads the cache (instant) plus stdin JSON from Claude Code to render the display

Token retrieval is platform-aware:

  • macOS — reads from Keychain via security find-generic-password
  • Linux/WSL — reads from ~/.claude/.credentials.json

Troubleshooting

  • No usage stats — run bash ~/.claude/fetch-usage.sh manually, then check cat /tmp/.claude_usage_cache
  • Token not found — on Linux, verify ~/.claude/.credentials.json exists; on macOS, check Keychain access
  • Stale data — delete /tmp/.claude_usage_cache; it refreshes on next tool use
#!/bin/sh
# Fetches Claude API usage stats and writes them to /tmp/.claude_usage_cache.
# Line 1: five_hour.utilization (integer %)
# Line 2: seven_day.utilization (integer %)
# Line 3: five_hour.resets_at (raw ISO string)
# Line 4: seven_day.resets_at (raw ISO string)
# All output is suppressed; meant to be run in background.
#
# Cross-platform (macOS + Linux). Requires: curl, jq
# Based on: https://www.reddit.com/r/ClaudeCode/comments/1rg3nmt/my_minimal_claude_code_statusline_config/
CACHE_FILE="/tmp/.claude_usage_cache"
# --- get OAuth token (platform-specific) ---
token=""
case "$(uname -s)" in
Darwin)
# macOS: read from Keychain
raw_creds=$(security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null)
if [ -n "$raw_creds" ]; then
token=$(printf '%s' "$raw_creds" | xxd -r -p 2>/dev/null | grep -o 'sk-ant-oat01-[A-Za-z0-9_-]*' | head -1)
fi
;;
*)
# Linux/WSL: read from credentials JSON file
CREDS_FILE="$HOME/.claude/.credentials.json"
if [ -f "$CREDS_FILE" ]; then
token=$(jq -r '.claudeAiOauth.accessToken // empty' "$CREDS_FILE" 2>/dev/null)
fi
;;
esac
if [ -z "$token" ]; then
exit 0
fi
usage_json=$(curl -s -m 10 \
-H "accept: application/json" \
-H "anthropic-beta: oauth-2025-04-20" \
-H "authorization: Bearer $token" \
-H "user-agent: claude-code/2.1.11" \
"https://api.anthropic.com/oauth/usage" 2>/dev/null)
if [ -z "$usage_json" ]; then
exit 0
fi
five_h_raw=$(printf '%s' "$usage_json" | jq -r '.five_hour.utilization // empty' 2>/dev/null)
seven_d_raw=$(printf '%s' "$usage_json" | jq -r '.seven_day.utilization // empty' 2>/dev/null)
five_h_reset=$(printf '%s' "$usage_json" | jq -r '.five_hour.resets_at // ""' 2>/dev/null)
seven_d_reset=$(printf '%s' "$usage_json" | jq -r '.seven_day.resets_at // ""' 2>/dev/null)
if [ -n "$five_h_raw" ] && [ -n "$seven_d_raw" ]; then
five_h=$(printf "%.0f" "$five_h_raw")
seven_d=$(printf "%.0f" "$seven_d_raw")
printf '%s\n%s\n%s\n%s\n' "$five_h" "$seven_d" "$five_h_reset" "$seven_d_reset" > "$CACHE_FILE"
fi
#!/bin/sh
# Claude Code statusline command — reads JSON from stdin, renders two-line status.
#
# Line 1: Model | Folder • Branch
# Line 2: 5h usage% (reset) • 7d usage% (reset) | ctx usage% (tokens)
#
# Cross-platform (macOS + Linux). Requires: jq, git
# Based on: https://www.reddit.com/r/ClaudeCode/comments/1rg3nmt/my_minimal_claude_code_statusline_config/
input=$(cat)
# --- model ---
model=$(echo "$input" | jq -r '.model.display_name // ""')
# --- folder ---
dir=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // ""')
dir_name=$(basename "$dir")
# --- git branch ---
branch=""
if [ -d "${dir}/.git" ] || git -C "$dir" rev-parse --git-dir > /dev/null 2>&1; then
branch=$(git -C "$dir" symbolic-ref --short HEAD 2>/dev/null || git -C "$dir" rev-parse --short HEAD 2>/dev/null)
fi
# --- usage stats (5h / 7d) from cache ---
CACHE_FILE="/tmp/.claude_usage_cache"
five_h=""
seven_d=""
five_h_reset=""
seven_d_reset=""
if [ -f "$CACHE_FILE" ]; then
five_h=$(sed -n '1p' "$CACHE_FILE")
seven_d=$(sed -n '2p' "$CACHE_FILE")
five_h_reset=$(sed -n '3p' "$CACHE_FILE")
seven_d_reset=$(sed -n '4p' "$CACHE_FILE")
else
bash ~/.claude/fetch-usage.sh > /dev/null 2>&1 &
fi
# --- compute_delta: given a raw ISO timestamp, returns human-readable time until reset ---
compute_delta() {
clean=$(echo "$1" | sed 's/\.[0-9]*//')
case "$(uname -s)" in
Darwin)
# macOS (BSD date): strip timezone suffix, parse with -j -f
clean=$(echo "$clean" | sed 's/[+-][0-9][0-9]:[0-9][0-9]$//' | sed 's/Z$//')
reset_epoch=$(TZ=UTC date -j -f "%Y-%m-%dT%H:%M:%S" "$clean" "+%s" 2>/dev/null)
;;
*)
# Linux (GNU date): handles ISO 8601 natively
reset_epoch=$(date -d "$clean" "+%s" 2>/dev/null)
;;
esac
if [ -z "$reset_epoch" ]; then return; fi
now_epoch=$(date -u "+%s")
diff=$(( reset_epoch - now_epoch ))
if [ "$diff" -le 0 ]; then echo "now"; return; fi
days=$(( diff / 86400 ))
hours=$(( (diff % 86400) / 3600 ))
minutes=$(( (diff % 3600) / 60 ))
if [ "$days" -gt 0 ]; then
echo "${days}d ${hours}h"
elif [ "$hours" -gt 0 ]; then
echo "${hours}h ${minutes}m"
else
echo "${minutes}m"
fi
}
# --- context window ---
used=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
ctx_str=""
ctx_tokens_str=""
if [ -n "$used" ]; then
used_int=$(printf "%.0f" "$used")
ctx_str="${used_int}%"
ctx_used=$(echo "$input" | jq -r '(.context_window.current_usage.cache_read_input_tokens + .context_window.current_usage.cache_creation_input_tokens + .context_window.current_usage.input_tokens + .context_window.current_usage.output_tokens) // empty' 2>/dev/null)
ctx_total=$(echo "$input" | jq -r '.context_window.context_window_size // empty' 2>/dev/null)
if [ -n "$ctx_used" ] && [ -n "$ctx_total" ]; then
ctx_used_k=$(( ctx_used / 1000 ))
ctx_total_k=$(( ctx_total / 1000 ))
ctx_tokens_str="${ctx_used_k}k/${ctx_total_k}k"
fi
fi
# --- assemble output ---
SEP="\033[90m • \033[0m"
# line 1: model | folder • branch
printf "\033[38;5;208m\033[1m%s\033[22m\033[0m" "$model"
printf "\033[90m | \033[0m"
printf "\033[1m\033[38;2;76;208;222m%s\033[22m\033[0m" "$dir_name"
if [ -n "$branch" ]; then
printf "%b" "$SEP"
printf "\033[1m\033[38;2;192;103;222m%s\033[22m\033[0m" "$branch"
fi
# line 2: usage | ctx
printf "\n"
if [ -n "$five_h" ]; then
printf "\033[38;2;156;162;175m5h %s%%\033[0m" "$five_h"
if [ -n "$five_h_reset" ]; then
delta=$(compute_delta "$five_h_reset")
[ -n "$delta" ] && printf " \033[2m\033[38;2;156;162;175m(%s)\033[0m" "$delta"
fi
fi
if [ -n "$seven_d" ]; then
[ -n "$five_h" ] && printf "%b" "$SEP"
printf "\033[38;2;156;162;175m7d %s%%\033[0m" "$seven_d"
if [ -n "$seven_d_reset" ]; then
delta=$(compute_delta "$seven_d_reset")
[ -n "$delta" ] && printf " \033[2m\033[38;2;156;162;175m(%s)\033[0m" "$delta"
fi
fi
if [ -n "$ctx_str" ]; then
printf "\033[90m | \033[0m"
printf "\033[38;2;156;162;175mctx %s\033[0m" "$ctx_str"
[ -n "$ctx_tokens_str" ] && printf " \033[2m\033[38;2;156;162;175m(%s)\033[0m" "$ctx_tokens_str"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment