Last active
May 6, 2026 10:32
-
-
Save andreagrandi/362c1fc77909b202476aba9b57cb0145 to your computer and use it in GitHub Desktop.
Claude Code Status Line Script: displays project info and cost information from ccusage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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}" |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Place the script in
~/.claude/and addto your
~/.claude/settings.jsonto use it.