Created
December 24, 2025 18:37
-
-
Save dpaluy/3e83c6b1749c03e169c74d58237806f8 to your computer and use it in GitHub Desktop.
Claude Code Statusline
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 | |
| # Read JSON input | |
| input=$(cat) | |
| # Extract session data | |
| model=$(echo "$input" | jq -r '.model.display_name') | |
| limit=$(echo "$input" | jq -r '.context_window.context_window_size // 200000') | |
| current_dir=$(echo "$input" | jq -r '.workspace.current_dir // "."') | |
| current_usage=$(echo "$input" | jq '.context_window.current_usage') | |
| # Colors | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[0;33m' | |
| CYAN='\033[0;36m' | |
| GRAY='\033[0;90m' | |
| ORANGE='\033[38;5;214m' | |
| NC='\033[0m' | |
| # Calculate context from JSON input (preferred) or fallback to transcript | |
| if [ "$current_usage" != "null" ] && [ -n "$current_usage" ]; then | |
| context_tokens=$(echo "$current_usage" | jq '(.input_tokens // 0) + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0)') | |
| else | |
| # Fallback: parse transcript file | |
| transcript_path=$(echo "$input" | jq -r '.transcript_path') | |
| if [ -f "$transcript_path" ]; then | |
| context_tokens=$(tac "$transcript_path" | grep -m1 '"assistant"' | jq -r ' | |
| (.message.usage.input_tokens // 0) + | |
| (.message.usage.cache_creation_input_tokens // 0) + | |
| (.message.usage.cache_read_input_tokens // 0) | |
| ' 2>/dev/null || echo "0") | |
| else | |
| context_tokens=0 | |
| fi | |
| fi | |
| # Ensure context_tokens is a valid number | |
| context_tokens=${context_tokens:-0} | |
| [ "$context_tokens" = "null" ] && context_tokens=0 | |
| # Calculate context percentage (guard against division by zero) | |
| if [ "$limit" -gt 0 ] 2>/dev/null; then | |
| context_pct=$((context_tokens * 100 / limit)) | |
| else | |
| context_pct=0 | |
| fi | |
| # Build progress bar (10 chars wide) | |
| bar_width=10 | |
| filled=$((context_pct * bar_width / 100)) | |
| [ $filled -gt $bar_width ] && filled=$bar_width | |
| empty=$((bar_width - filled)) | |
| bar="" | |
| for ((i=0; i<filled; i++)); do bar+="█"; done | |
| for ((i=0; i<empty; i++)); do bar+="░"; done | |
| # Calculate tokens until auto-compact (45k buffer) | |
| compact_buffer=45000 | |
| compact_threshold=$((limit - compact_buffer)) | |
| until_compact=$((compact_threshold - context_tokens)) | |
| if [ $until_compact -lt 0 ]; then | |
| compact_display="0k" | |
| else | |
| compact_display="$((until_compact / 1000))k" | |
| fi | |
| # Get current task from project-scoped file | |
| task_display="" | |
| task_file="${current_dir}/.claude/current_task.txt" | |
| if [ -f "$task_file" ]; then | |
| current_task=$(tr -d '\n' < "$task_file") | |
| if [ -n "$current_task" ]; then | |
| [ ${#current_task} -gt 30 ] && current_task="${current_task:0:27}..." | |
| task_display=" ${GRAY}|${NC} ${CYAN}${current_task}${NC}" | |
| fi | |
| fi | |
| # Get git info (branch + changes) | |
| git_display="" | |
| cd "$current_dir" 2>/dev/null || cd / | |
| if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then | |
| branch=$(git branch --show-current 2>/dev/null || echo "detached") | |
| status_output=$(git status --porcelain 2>/dev/null) | |
| if [ -n "$status_output" ]; then | |
| total_files=$(echo "$status_output" | wc -l | xargs) | |
| # Get line changes | |
| staged_stats=$(git diff --numstat --cached 2>/dev/null | awk '{a+=$1; r+=$2} END {print a+0, r+0}') | |
| unstaged_stats=$(git diff --numstat 2>/dev/null | awk '{a+=$1; r+=$2} END {print a+0, r+0}') | |
| staged_added=$(echo $staged_stats | cut -d' ' -f1) | |
| staged_removed=$(echo $staged_stats | cut -d' ' -f2) | |
| unstaged_added=$(echo $unstaged_stats | cut -d' ' -f1) | |
| unstaged_removed=$(echo $unstaged_stats | cut -d' ' -f2) | |
| added=$((staged_added + unstaged_added)) | |
| removed=$((staged_removed + unstaged_removed)) | |
| git_display=" ${GRAY}|${NC} ${ORANGE}${branch}${NC} ${GRAY}${total_files}f${NC}" | |
| [ "$added" -gt 0 ] && git_display="${git_display} ${GREEN}+${added}${NC}" | |
| [ "$removed" -gt 0 ] && git_display="${git_display} ${RED}-${removed}${NC}" | |
| else | |
| git_display=" ${GRAY}|${NC} ${ORANGE}${branch}${NC}" | |
| fi | |
| fi | |
| # Build output | |
| echo -e "${model}${task_display}${git_display} ${GRAY}|${NC} ${GRAY}${bar}${NC} ${compact_display}" |
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 | |
| # Read JSON input | |
| input=$(cat) | |
| # Extract session data | |
| model=$(echo "$input" | jq -r '.model.display_name') | |
| limit=$(echo "$input" | jq -r '.context_window.context_window_size') | |
| transcript_path=$(echo "$input" | jq -r '.transcript_path') | |
| # Calculate current context usage from transcript (like ccusage does) | |
| # Read last assistant message and sum input tokens (excluding output tokens) | |
| if [ -f "$transcript_path" ]; then | |
| context_tokens=$(tac "$transcript_path" | grep -m1 '"assistant"' | jq -r ' | |
| (.message.usage.input_tokens // 0) + | |
| (.message.usage.cache_creation_input_tokens // 0) + | |
| (.message.usage.cache_read_input_tokens // 0) | |
| ' 2>/dev/null || echo "0") | |
| else | |
| context_tokens=0 | |
| fi | |
| # Calculate context percentage (progress bar) | |
| context_pct=$((context_tokens * 100 / limit)) | |
| # Calculate tokens until auto-compact (45k buffer) | |
| compact_buffer=45000 | |
| compact_threshold=$((limit - compact_buffer)) | |
| until_compact=$((compact_threshold - context_tokens)) | |
| # Format for display (in thousands) | |
| if [ $until_compact -lt 0 ]; then | |
| compact_display="0k" | |
| else | |
| compact_k=$((until_compact / 1000)) | |
| compact_display="${compact_k}k" | |
| fi | |
| # Get current task from project-scoped file | |
| task_display="" | |
| task_file=".claude/current_task.txt" | |
| if [ -f "$task_file" ]; then | |
| current_task=$(cat "$task_file" | tr -d '\n') | |
| if [ -n "$current_task" ]; then | |
| # Truncate if too long (max 40 chars) | |
| if [ ${#current_task} -gt 40 ]; then | |
| current_task="${current_task:0:37}..." | |
| fi | |
| task_display=" | Task: $current_task" | |
| fi | |
| fi | |
| # Get current git branch | |
| branch_display="" | |
| if git rev-parse --git-dir > /dev/null 2>&1; then | |
| branch=$(git branch --show-current 2>/dev/null) | |
| if [ -n "$branch" ]; then | |
| # Orange color (Claude color): RGB(255, 138, 0) ≈ 214 in 256-color | |
| orange=$'\033[38;5;214m' | |
| reset=$'\033[0m' | |
| branch_display=" | Branch: ${orange}${branch}${reset}" | |
| fi | |
| fi | |
| # Build output (no progress bar - can't accurately calculate from transcript) | |
| printf "%s" "$model" | |
| printf "%s" "$task_display" | |
| printf "%b" "$branch_display" | |
| printf " | Context: %s" "$compact_display" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Reference: https://gist.github.com/frankdilo/e49a680a2c946143868f7f61b45127e1