Skip to content

Instantly share code, notes, and snippets.

@inchoate
Created May 12, 2026 22:36
Show Gist options
  • Select an option

  • Save inchoate/ac6c576adef1e79ca630054fc8050755 to your computer and use it in GitHub Desktop.

Select an option

Save inchoate/ac6c576adef1e79ca630054fc8050755 to your computer and use it in GitHub Desktop.
Claude Code Status Line
#!/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