Created
May 12, 2026 22:36
-
-
Save inchoate/ac6c576adef1e79ca630054fc8050755 to your computer and use it in GitHub Desktop.
Claude Code Status Line
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 — single line, utility-first | |
| input=$(cat) | |
| # ── Extract fields (single jq call for speed) ──────────────────────────────── | |
| eval "$(echo "$input" | jq -r ' | |
| @sh "MODEL=\(.model.display_name // "?")", | |
| @sh "DIR=\(.workspace.current_dir // "?")", | |
| @sh "DURATION_MS=\(.cost.total_duration_ms // 0)", | |
| @sh "ADDED=\(.cost.total_lines_added // 0)", | |
| @sh "REMOVED=\(.cost.total_lines_removed // 0)", | |
| @sh "PCT=\(.context_window.used_percentage // 0 | floor)", | |
| @sh "CTX_SIZE=\(.context_window.context_window_size // 0)", | |
| @sh "AGENT=\(.agent.name // "")", | |
| @sh "WORKTREE=\(.worktree.name // "")", | |
| @sh "SESSION_PCT=\(.rate_limits.five_hour.used_percentage // "" | if . == "" then "" else floor end)", | |
| @sh "SESSION_RESET=\(.rate_limits.five_hour.resets_at // "")", | |
| @sh "WEEK_PCT=\(.rate_limits.seven_day.used_percentage // "" | if . == "" then "" else floor end)", | |
| @sh "WEEK_RESET=\(.rate_limits.seven_day.resets_at // "")", | |
| @sh "STYLE=\(.output_style.name // "")", | |
| @sh "INPUT_TOKENS=\(.context_window.current_usage.input_tokens // 0)", | |
| @sh "CACHE_READ=\(.context_window.current_usage.cache_read_input_tokens // 0)", | |
| @sh "CACHE_CREATE=\(.context_window.current_usage.cache_creation_input_tokens // 0)" | |
| ')" | |
| # ── Derived values ──────────────────────────────────────────────────────────── | |
| DIR_SHORT="${DIR##*/}" | |
| DURATION_S=$((DURATION_MS / 1000)) | |
| MINUTES=$((DURATION_S / 60)) | |
| SECONDS=$((DURATION_S % 60)) | |
| if [ "$CTX_SIZE" -ge 1000000 ]; then | |
| CTX_LABEL="$((CTX_SIZE / 1000000))M" | |
| else | |
| CTX_LABEL="$((CTX_SIZE / 1000))k" | |
| fi | |
| if [ "$MINUTES" -gt 0 ]; then | |
| TIME="${MINUTES}m${SECONDS}s" | |
| else | |
| TIME="${SECONDS}s" | |
| fi | |
| # ── Colors ──────────────────────────────────────────────────────────────────── | |
| R='\033[0m'; D='\033[2m'; B='\033[1m' | |
| GRN='\033[32m'; YEL='\033[33m'; RED='\033[31m' | |
| CYN='\033[36m'; MAG='\033[35m'; BLU='\033[34m' | |
| if [ "$PCT" -lt 50 ]; then PC="$GRN" | |
| elif [ "$PCT" -lt 75 ]; then PC="$YEL" | |
| else PC="$RED"; fi | |
| # ── Rate limits (5h session + 7d weekly) ────────────────────────────────────── | |
| pct_color() { | |
| if [ "$1" -lt 50 ]; then printf '%s' "$GRN" | |
| elif [ "$1" -lt 75 ]; then printf '%s' "$YEL" | |
| else printf '%s' "$RED"; fi | |
| } | |
| # 8-cell bar, filled proportionally to percent (0-100) | |
| bar() { | |
| local pct=$1 len=8 filled i out="" | |
| filled=$(( (pct * len + 50) / 100 )) | |
| [ "$filled" -gt "$len" ] && filled=$len | |
| [ "$filled" -lt 0 ] && filled=0 | |
| for ((i=0; i<filled; i++)); do out="${out}▰"; done | |
| for ((i=filled; i<len; i++)); do out="${out}▱"; done | |
| printf '%s' "$out" | |
| } | |
| # Compact duration from seconds: 42m · 2h18m · 4d12h | |
| dur_until() { | |
| local target=$1 now s | |
| now=$(date +%s) | |
| s=$(( target - now )) | |
| if [ "$s" -le 0 ]; then printf 'now' | |
| elif [ "$s" -lt 3600 ]; then printf '%dm' $(( s / 60 )) | |
| elif [ "$s" -lt 86400 ]; then printf '%dh%02dm' $(( s / 3600 )) $(( (s % 3600) / 60 )) | |
| else printf '%dd%02dh' $(( s / 86400 )) $(( (s % 86400) / 3600 )) | |
| fi | |
| } | |
| LIMITS="" | |
| if [ -n "$SESSION_PCT" ]; then | |
| SC=$(pct_color "$SESSION_PCT") | |
| SB=$(bar "$SESSION_PCT") | |
| if [ -n "$SESSION_RESET" ]; then | |
| LIMITS="${D}5h${R} ${SC}${SB}${R} ${D}$(dur_until "$SESSION_RESET")${R}" | |
| else | |
| LIMITS="${D}5h${R} ${SC}${SB}${R}" | |
| fi | |
| fi | |
| if [ -n "$WEEK_PCT" ]; then | |
| WC=$(pct_color "$WEEK_PCT") | |
| WB=$(bar "$WEEK_PCT") | |
| if [ -n "$WEEK_RESET" ]; then | |
| WSEG="${D}7d${R} ${WC}${WB}${R} ${D}$(dur_until "$WEEK_RESET")${R}" | |
| else | |
| WSEG="${D}7d${R} ${WC}${WB}${R}" | |
| fi | |
| [ -n "$LIMITS" ] && LIMITS="${LIMITS} ${WSEG}" || LIMITS="$WSEG" | |
| fi | |
| # ── Auth identity (cached daily from ~/.claude.json) ────────────────────────── | |
| IDENT_CACHE="$HOME/.claude/.statusline-identity" | |
| IDENT_MAX_AGE=86400 | |
| IDENT_AGE=$IDENT_MAX_AGE | |
| if [ -f "$IDENT_CACHE" ]; then | |
| IDENT_MTIME=$(stat -f %m "$IDENT_CACHE" 2>/dev/null || echo 0) | |
| IDENT_AGE=$(( $(date +%s) - IDENT_MTIME )) | |
| fi | |
| if [ "$IDENT_AGE" -ge "$IDENT_MAX_AGE" ] && [ -f "$HOME/.claude.json" ]; then | |
| jq -r '.oauthAccount.emailAddress // .oauthAccount.displayName // ""' "$HOME/.claude.json" 2>/dev/null > "$IDENT_CACHE" | |
| fi | |
| USER_RAW=$(cat "$IDENT_CACHE" 2>/dev/null) | |
| # Elide email for shoulder-surfers: jason.vertrees@venlink.com → jas…@ven…k.com | |
| elide_email() { | |
| local s=$1 local_part domain | |
| case "$s" in | |
| *@*) | |
| local_part="${s%@*}" | |
| domain="${s#*@}" | |
| [ ${#local_part} -gt 3 ] && local_part="${local_part:0:3}…" | |
| [ ${#domain} -gt 8 ] && domain="${domain:0:3}…${domain: -5}" | |
| printf '%s@%s' "$local_part" "$domain" | |
| ;; | |
| *) | |
| printf '%s' "$s" | |
| ;; | |
| esac | |
| } | |
| USER_NAME=$(elide_email "$USER_RAW") | |
| # ── Git branch ──────────────────────────────────────────────────────────────── | |
| BRANCH=$(git -C "$DIR" symbolic-ref --short HEAD 2>/dev/null) | |
| GIT="" | |
| if [ -n "$BRANCH" ]; then | |
| DIRTY="" | |
| git -C "$DIR" diff --quiet HEAD 2>/dev/null || DIRTY="${YEL}*${R}" | |
| GIT=" ${MAG}${BRANCH}${DIRTY}" | |
| fi | |
| # ── Badges ──────────────────────────────────────────────────────────────────── | |
| BADGES="" | |
| [ -n "$AGENT" ] && BADGES="${BADGES} ${CYN}[${AGENT}]${R}" | |
| [ -n "$WORKTREE" ] && BADGES="${BADGES} ${BLU}[wt:${WORKTREE}]${R}" | |
| if [ -n "$STYLE" ] && [ "$STYLE" != "default" ]; then | |
| BADGES="${BADGES} ${MAG}[${STYLE}]${R}" | |
| fi | |
| # ── Cache hit rate (how much of input was served from prompt cache) ────────── | |
| CACHE_TOTAL=$(( INPUT_TOKENS + CACHE_READ + CACHE_CREATE )) | |
| CACHE_HIT="" | |
| if [ "$CACHE_TOTAL" -gt 0 ]; then | |
| CACHE_HIT=$(( CACHE_READ * 100 / CACHE_TOTAL )) | |
| if [ "$CACHE_HIT" -ge 75 ]; then CHC="$GRN" | |
| elif [ "$CACHE_HIT" -ge 50 ]; then CHC="$YEL" | |
| else CHC="$RED"; fi | |
| fi | |
| # ── Single line output ──────────────────────────────────────────────────────── | |
| LIMITS_SEG="" | |
| [ -n "$LIMITS" ] && LIMITS_SEG=" ${D}│${R} ${LIMITS}" | |
| USER_SEG="" | |
| [ -n "$USER_NAME" ] && USER_SEG=" ${D}${USER_NAME}${R}" | |
| CACHE_SEG="" | |
| [ -n "$CACHE_HIT" ] && CACHE_SEG=" ${D}·${R} ${CHC}cache ${CACHE_HIT}%${R}" | |
| echo -e "${B}${MODEL}${R}${USER_SEG} ${D}│${R} ${DIR_SHORT}${GIT}${BADGES} ${D}│${R} ${PC}${PCT}%${R}${D}/${R}${CTX_LABEL}${CACHE_SEG}${LIMITS_SEG} ${D}│${R} ${GRN}+${ADDED}${R}${D}/${R}${RED}-${REMOVED}${R} ${D}│${R} ${D}${TIME}${R}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment