|
#!/bin/bash |
|
|
|
# Claude Code Status Line Script |
|
# Displays project info, context usage, and environment details |
|
# |
|
# Rate limit usage (5-hour session and 7-day weekly) is available |
|
# via rate_limits.five_hour.used_percentage and rate_limits.seven_day.used_percentage |
|
# Only populated for Pro/Max subscribers after the first API response. |
|
|
|
# Read JSON input from stdin |
|
input=$(cat) |
|
|
|
# Extract basic information |
|
folder=$(basename "$(echo "$input" | jq -r '.workspace.current_dir')") |
|
model=$(echo "$input" | jq -r '.model.display_name') |
|
|
|
# Context window usage percentage (đ = library/context) |
|
ctx_pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0') |
|
ctx_pct_int=${ctx_pct%.*} |
|
if [ "$ctx_pct_int" -ge 80 ] 2>/dev/null; then |
|
ctx_color="\033[31m" |
|
elif [ "$ctx_pct_int" -ge 50 ] 2>/dev/null; then |
|
ctx_color="\033[33m" |
|
else |
|
ctx_color="\033[32m" |
|
fi |
|
RESET="\033[0m" |
|
|
|
# Detect project type and language info |
|
lang_info="" |
|
|
|
# Check for Python project (venv exists or Python files present) |
|
if [ -n "$VIRTUAL_ENV" ]; then |
|
venv_raw=$(echo "${VIRTUAL_ENV##*/}" | sed 's/-[0-9].*//') |
|
if [ "$venv_raw" = ".venv" ] || [ "$venv_raw" = "venv" ]; then |
|
venv="($folder)" |
|
else |
|
venv="($venv_raw)" |
|
fi |
|
pyver=$(python3 --version 2>/dev/null | cut -d' ' -f2 || echo 'N/A') |
|
lang_info=" | đŧ $venv | đ $pyver" |
|
elif [ -f "requirements.txt" ] || [ -f "setup.py" ] || [ -f "pyproject.toml" ] || [ -f "Pipfile" ]; then |
|
pyver=$(python3 --version 2>/dev/null | cut -d' ' -f2 || echo 'N/A') |
|
lang_info=" | đ $pyver" |
|
elif [ -f "go.mod" ] || [ -f "go.sum" ] || ls *.go >/dev/null 2>&1; then |
|
gover=$(go version 2>/dev/null | grep -oE 'go[0-9]+\.[0-9]+(\.[0-9]+)?' | sed 's/go//' || echo 'N/A') |
|
if [ "$gover" != "N/A" ]; then |
|
lang_info=" | đĻĢ $gover" |
|
fi |
|
fi |
|
|
|
# Git branch |
|
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'N/A') |
|
|
|
# Thinking effort level (đ§ = thinking). Absent if model doesn't support it. |
|
effort_level=$(echo "$input" | jq -r '.effort.level // empty') |
|
effort_info="" |
|
if [ -n "$effort_level" ]; then |
|
case "$effort_level" in |
|
low) effort_color="\033[32m" ;; |
|
medium) effort_color="\033[33m" ;; |
|
high|xhigh|max) effort_color="\033[31m" ;; |
|
*) effort_color="" ;; |
|
esac |
|
effort_info=" | đ§ ${effort_color}${effort_level}${RESET}" |
|
fi |
|
|
|
# Rate limit usage (session = 5-hour window, week = 7-day window) |
|
five_h=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty') |
|
seven_d=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty') |
|
|
|
rate_info="" |
|
if [ -n "$five_h" ] || [ -n "$seven_d" ]; then |
|
five_int=${five_h%.*} |
|
seven_int=${seven_d%.*} |
|
[ -z "$five_int" ] && five_int=0 |
|
[ -z "$seven_int" ] && seven_int=0 |
|
|
|
if [ "$five_int" -ge 80 ] 2>/dev/null; then |
|
five_color="\033[31m" |
|
elif [ "$five_int" -ge 50 ] 2>/dev/null; then |
|
five_color="\033[33m" |
|
else |
|
five_color="\033[32m" |
|
fi |
|
|
|
if [ "$seven_int" -ge 80 ] 2>/dev/null; then |
|
seven_color="\033[31m" |
|
elif [ "$seven_int" -ge 50 ] 2>/dev/null; then |
|
seven_color="\033[33m" |
|
else |
|
seven_color="\033[32m" |
|
fi |
|
|
|
# Calculate time remaining in 5-hour session from resets_at timestamp |
|
five_resets_at=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty') |
|
if [ -n "$five_resets_at" ]; then |
|
now_epoch=$(date +%s) |
|
remaining_seconds=$(( five_resets_at - now_epoch )) |
|
if [ "$remaining_seconds" -lt 0 ]; then |
|
remaining_seconds=0 |
|
fi |
|
remaining_h=$((remaining_seconds / 3600)) |
|
remaining_m=$(( (remaining_seconds % 3600) / 60 )) |
|
time_left=$(printf "%d:%02d" "$remaining_h" "$remaining_m") |
|
else |
|
time_left="--:--" |
|
fi |
|
|
|
# Calculate next weekly reset day from resets_at timestamp |
|
seven_resets_at=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty') |
|
if [ -n "$seven_resets_at" ]; then |
|
reset_date=$(date -r "$seven_resets_at" "+%b %-d") |
|
reset_day=$(date -r "$seven_resets_at" "+%-d") |
|
else |
|
# Fallback: next Sunday |
|
dow=$(date +%u) |
|
days_until_sun=$(( (7 - dow) % 7 )) |
|
[ "$days_until_sun" -eq 0 ] && days_until_sun=7 |
|
reset_date=$(date -v+"${days_until_sun}d" "+%b %-d") |
|
reset_day=$(date -v+"${days_until_sun}d" "+%-d") |
|
fi |
|
case "$reset_day" in |
|
1|21|31) reset_suffix="st" ;; |
|
2|22) reset_suffix="nd" ;; |
|
3|23) reset_suffix="rd" ;; |
|
*) reset_suffix="th" ;; |
|
esac |
|
reset_label="${reset_date}${reset_suffix}" |
|
|
|
rate_info=" | âą 5h ${five_color}${five_int}%${RESET} (${time_left} left) | đ
7d ${seven_color}${seven_int}%${RESET} (${reset_label})" |
|
fi |
|
|
|
# Output the complete status line |
|
echo -e "đ $folder${lang_info} | đŋ $branch | đ¤ $model${effort_info} | đ ctx ${ctx_color}${ctx_pct_int}%${RESET}${rate_info}" |