Last active
August 8, 2026 03:49
-
-
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, session cost, and environment details. | |
| # | |
| # Session cost/credits usage is read from cost.total_cost_usd (the client-side | |
| # estimated spend for the current session). The 5h/7d rate-limit usage is | |
| # intentionally omitted: this is an enterprise account, where those fields are | |
| # not populated. Monthly/total spend is not available locally -- the Console | |
| # dashboard is the authoritative source for that figure. | |
| # 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 | |
| # Session cost / credits usage (π°). cost.total_cost_usd is the client-side | |
| # estimated spend for the current session (may differ from the actual bill). | |
| # Shown in place of the 5h/7d rate-limit usage, which enterprise accounts don't | |
| # populate. Monthly/total spend is NOT available to the statusline -- it is not | |
| # in the payload and not cached locally; the Console/dashboard is the source. | |
| cost_usd=$(echo "$input" | jq -r '.cost.total_cost_usd // empty') | |
| cost_info="" | |
| if [ -n "$cost_usd" ]; then | |
| cost_fmt=$(awk -v c="$cost_usd" 'BEGIN { printf "%.2f", c }') | |
| cost_info=" | π° \033[34m\$${cost_fmt}${RESET}" | |
| fi | |
| # Output the complete status line | |
| echo -e "π $folder${lang_info} | πΏ $branch | π€ $model${effort_info} | π ctx ${ctx_color}${ctx_pct_int}%${RESET}${cost_info}"% |
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.