Skip to content

Instantly share code, notes, and snippets.

@QinMing
Last active June 13, 2026 05:39
Show Gist options
  • Select an option

  • Save QinMing/2a7861418cc0e80b1f0c72eef136d309 to your computer and use it in GitHub Desktop.

Select an option

Save QinMing/2a7861418cc0e80b1f0c72eef136d309 to your computer and use it in GitHub Desktop.
Claude Code Status Line Customization
#!/bin/bash
# Claude Code statusline command script
# Gist link: https://gist.github.com/QinMing/2a7861418cc0e80b1f0c72eef136d309
# When committing changes to this file, also update the gist.
# Read JSON input from stdin
input=$(cat)
# ---------------------------------------------------------------------------
# Extract all fields from JSON in a single jq call
# ---------------------------------------------------------------------------
eval "$(echo "$input" | jq -r '
@sh "cwd=\(.workspace.current_dir // "")",
@sh "used_pct=\(.context_window.used_percentage // "")",
@sh "ctx_size=\(.context_window.context_window_size // "")",
@sh "ctx_used=\((.context_window.current_usage | (.input_tokens // 0) + (.output_tokens // 0) + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0)) // "")",
@sh "model_name=\(.model.display_name // "")",
@sh "git_worktree=\(.workspace.git_worktree // "")"
')"
user=$(whoami)
host=$(hostname -s)
# ---------------------------------------------------------------------------
# ANSI color palette (all colors defined here)
# ---------------------------------------------------------------------------
C_RESET="\033[0m"
C_DIM_GREY="\033[38;5;240m"
C_BRIGHT_CYAN="\033[1;36m"
C_BOLD_BLUE="\033[1;34m"
C_PAREN="\033[38;5;240m" # grey for informationless delimiters () []
C_BRANCH="\033[38;2;210;153;34m" # GitHub #d29922
C_UNTRACKED="\033[38;5;139m" # mauve for untracked line count
C_DIM_WHITE="\033[2;37m"
C_GH_GREEN="\033[38;5;71m" # GitHub #3fb950
C_GH_RED="\033[38;5;203m" # GitHub #f85149
C_SUBDIR="\033[38;5;67m" # muted steel blue for subdirs below repo root
# Gradient endpoints for progress bar (GitHub palette, passed to awk)
GRAD_GREEN="63,185,80" # #3fb950
GRAD_YELLOW="210,153,34" # #d29922
GRAD_RED="248,81,73" # #f85149
# ---------------------------------------------------------------------------
# Path coloring: dim prefix, bright repo, steel-blue subdirs, grey slashes
# Derives dim prefix from git toplevel — works for any repo/worktree location.
# ---------------------------------------------------------------------------
# Detect git repo root (works the same for worktrees)
git_toplevel=""
if git -C "$cwd" rev-parse --show-toplevel &>/dev/null; then
git_toplevel=$(git -C "$cwd" rev-parse --show-toplevel)
fi
# Colorize /path/segments: grey slashes + per-segment color
_color_segs() {
local p="${1#/}" c="$2" out=""
while [ -n "$p" ]; do
out+="${C_DIM_GREY}/${c}${p%%/*}"
[[ "$p" == */* ]] && p="${p#*/}" || p=""
done
printf '%b' "$out"
}
if [ -n "$git_toplevel" ]; then
dim_prefix=$(dirname "$git_toplevel")
repo_name=$(basename "$git_toplevel")
subdir_path="${cwd#"$git_toplevel"}"
colored_sub=$(_color_segs "$subdir_path" "$C_SUBDIR")
if [ "$dim_prefix" = "/" ]; then
cwd_display=$(printf '%b' "${C_DIM_GREY}/${C_BRIGHT_CYAN}${repo_name}${colored_sub}${C_RESET}")
else
cwd_display=$(printf '%b' "${C_DIM_GREY}${dim_prefix}/${C_BRIGHT_CYAN}${repo_name}${colored_sub}${C_RESET}")
fi
else
# Not in a git repo — show full path in bright cyan
cwd_display=$(printf '%b' "${C_BRIGHT_CYAN}${cwd}${C_RESET}")
fi
# ---------------------------------------------------------------------------
# Git branch and line-based dirty summary
# Purple counts lines in untracked files.
# Green/red come from `git diff --numstat HEAD`, so rename detection stays enabled
# and pure renames collapse to 0 added / 0 deleted lines once staged.
# ---------------------------------------------------------------------------
git_info=""
if [ -n "$git_toplevel" ]; then
branch=$(git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null \
|| git -C "$cwd" rev-parse --short HEAD 2>/dev/null)
untracked_info=""
untracked_files=$(git -C "$cwd" --no-optional-locks ls-files --others --exclude-standard 2>/dev/null)
if [ -n "$untracked_files" ]; then
untracked_lines=$(echo "$untracked_files" | tr '\n' '\0' | xargs -0 wc -l 2>/dev/null | tail -1 | awk '{print $1+0}')
if [ "$untracked_lines" -gt 0 ]; then
untracked_info=$(printf " ${C_UNTRACKED}+%s${C_RESET}" "$untracked_lines")
fi
fi
diff_info=""
numstat=$(git -C "$cwd" --no-optional-locks diff --numstat HEAD 2>/dev/null)
if [ -n "$numstat" ]; then
read additions deletions <<< "$(echo "$numstat" | awk '{a+=$1; d+=$2} END {print a+0, d+0}')"
if [ "$additions" -gt 0 ] || [ "$deletions" -gt 0 ]; then
diff_info=$(printf " ${C_GH_GREEN}+%s${C_RESET} ${C_GH_RED}-%s${C_RESET}" "$additions" "$deletions")
fi
fi
# Hide branch name when it matches the worktree directory name
branch_label="$branch"
[ "$branch" = "$repo_name" ] && branch_label=""
[ -n "$branch_label" ] && branch_label="${C_BRANCH}${branch_label}${C_RESET}"
inner="${branch_label}${untracked_info}${diff_info}"
inner="${inner# }"
[ -n "$inner" ] && git_info=$(printf " ${C_PAREN}(${C_RESET}%b${C_PAREN})${C_RESET}" "$inner")
fi
# ---------------------------------------------------------------------------
# Context window progress bar
# ---------------------------------------------------------------------------
context_info=""
if [ -n "$used_pct" ]; then
used_pct_int=$(printf "%.0f" "$used_pct")
# Braille bar: 13 chars × 8 levels = 104 steps → ~1% precision
bar_width=13
total_eighths=$(echo "$used_pct $bar_width" | awk '{v=$1*$2*8/100; printf "%d",int(v+0.5)}')
max_eighths=$(( bar_width * 8 ))
[ "$total_eighths" -gt "$max_eighths" ] && total_eighths=$max_eighths
[ "$total_eighths" -lt 0 ] && total_eighths=0
full_cells=$(( total_eighths / 8 ))
remainder=$(( total_eighths % 8 ))
has_partial=0
[ "$remainder" -gt 0 ] && has_partial=1
empty_count=$(( bar_width - full_cells - has_partial ))
[ "$empty_count" -lt 0 ] && empty_count=0
# Percentage label (shown inside or outside bar)
pct_label="${used_pct_int}%"
label_len=${#pct_label}
space_needed=$(( label_len + 1 ))
# Build gradient bar + token suffix in a single awk call
context_and_tokens=$(awk \
-v full="$full_cells" -v rem="$remainder" \
-v empty_n="$empty_count" -v has_p="$has_partial" \
-v n="$bar_width" -v label="$pct_label" \
-v sp_need="$space_needed" \
-v grad_g="$GRAD_GREEN" -v grad_y="$GRAD_YELLOW" -v grad_r="$GRAD_RED" \
-v ctx_used="$ctx_used" -v ctx_total="$ctx_size" '
BEGIN {
esc = sprintf("%c", 27)
dim = esc "[38;5;240m"
rst = esc "[0m"
# Parse gradient endpoints
split(grad_g, gn, ","); split(grad_y, yl, ","); split(grad_r, rd, ",")
# Precompute gradient colors: green → yellow → red
for (i = 0; i < n; i++) {
frac = (n > 1) ? i / (n - 1) : 0
if (frac <= 0.5) {
f = frac * 2
r = int(gn[1] + (yl[1]-gn[1])*f + 0.5)
g = int(gn[2] + (yl[2]-gn[2])*f + 0.5)
b = int(gn[3] + (yl[3]-gn[3])*f + 0.5)
} else {
f = (frac - 0.5) * 2
r = int(yl[1] + (rd[1]-yl[1])*f + 0.5)
g = int(yl[2] + (rd[2]-yl[2])*f + 0.5)
b = int(yl[3] + (rd[3]-yl[3])*f + 0.5)
}
gc[i] = esc sprintf("[38;2;%d;%d;%dm", r, g, b)
}
# Braille partial chars by remainder (1-7)
br[1]="⡀"; br[2]="⡄"; br[3]="⡆"; br[4]="⡇"
br[5]="⣇"; br[6]="⣧"; br[7]="⣷"
# Filled cells with per-cell gradient
bar = ""
for (i = 0; i < full; i++) bar = bar gc[i] "⣿"
# Partial cell
if (has_p && rem > 0) bar = bar gc[full] br[rem]
# Label color = gradient at current fill edge
fe = full + has_p - 1
if (fe < 0) fe = 0
if (fe >= n) fe = n - 1
lc = gc[fe]
if (empty_n >= sp_need) {
# Right-align: [⣿⡄⣀⣀⣀⣀⣀⣀⣀ 10%]
remaining = empty_n - sp_need
for (i = 0; i < remaining; i++) bar = bar dim "⣀"
bar = bar " " lc label
printf " %s[%s%s%s]%s", dim, rst, bar, dim, rst
} else {
for (i = 0; i < empty_n; i++) bar = bar dim "⣀"
printf " %s[%s%s%s]%s %s%s%s", dim, rst, bar, dim, rst, lc, label, rst
}
# Token count suffix (same color as percentage label)
if (ctx_used > 0 || ctx_total > 0) {
if (ctx_used >= 1000000) u = sprintf("%.1fM", ctx_used/1000000)
else if (ctx_used >= 1000) u = sprintf("%.0fk", ctx_used/1000)
else u = sprintf("%d", ctx_used)
if (ctx_total >= 1000000) t = sprintf("%.0fM", ctx_total/1000000)
else if (ctx_total >= 1000) t = sprintf("%.0fk", ctx_total/1000)
else t = sprintf("%d", ctx_total)
# Dim the "/total" part: same hue but with ANSI dim attribute
dim_lc = esc "[2m" lc
printf " %s%s%s/%s%s", lc, u, dim_lc, t, rst
}
}')
context_info="$context_and_tokens"
fi
# ---------------------------------------------------------------------------
# Model name (muted/dim style)
# ---------------------------------------------------------------------------
model_info=""
if [ -n "$model_name" ]; then
model_info=$(printf " ${C_DIM_WHITE}%s${C_RESET}" "$model_name")
fi
# ---------------------------------------------------------------------------
# Assemble the status line
# ---------------------------------------------------------------------------
printf "${C_BOLD_BLUE}%s@%s${C_RESET}%s%s\n" "$user" "$host" "$model_info" "$context_info"
printf "%s%s\n" "$cwd_display" "$git_info"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment