Created
June 2, 2026 21:30
-
-
Save clarkmcc/ec01cb469f566b88d1752178bb651f8c to your computer and use it in GitHub Desktop.
Claude 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
| #!/usr/bin/env bash | |
| # ~/.claude/statusline.sh | |
| # Claude Code status line — polished dev-tool aesthetic | |
| input=$(cat) | |
| # ── Parse JSON fields ──────────────────────────────────────────────────────── | |
| cwd=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // ""') | |
| model=$(echo "$input" | jq -r '.model.display_name // ""') | |
| used_pct=$(echo "$input" | jq -r '.context_window.used_percentage // empty') | |
| in_tok=$(echo "$input" | jq -r '.context_window.current_usage.input_tokens // empty') | |
| out_tok=$(echo "$input" | jq -r '.context_window.current_usage.output_tokens // empty') | |
| total_in=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0') | |
| total_out=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0') | |
| vim_mode=$(echo "$input" | jq -r '.vim.mode // empty') | |
| effort=$(echo "$input" | jq -r '.effort.level // empty') | |
| model_id=$(echo "$input" | jq -r '.model.id // ""') | |
| # ── Derived values ──────────────────────────────────────────────────────────── | |
| dir=$(basename "$cwd") | |
| [ -z "$dir" ] && dir="~" | |
| # Per-model pricing ($/M tokens). Match on model id first, fall back to display name. | |
| # Note: ignores the 1M-context premium tier above ~200k input tokens. | |
| model_key=$(printf '%s %s' "$model_id" "$model" | tr '[:upper:]' '[:lower:]') | |
| case "$model_key" in | |
| *opus*) in_rate=15.00; out_rate=75.00 ;; | |
| *haiku*) in_rate=1.00; out_rate=5.00 ;; | |
| *sonnet*) in_rate=3.00; out_rate=15.00 ;; | |
| *) in_rate=3.00; out_rate=15.00 ;; | |
| esac | |
| # Session cost estimate from cumulative session totals | |
| cost="" | |
| if [ -n "$total_in" ] && [ "$total_in" != "0" ]; then | |
| cost=$(awk "BEGIN { | |
| input_cost = ($total_in / 1000000) * $in_rate; | |
| output_cost = ($total_out / 1000000) * $out_rate; | |
| total = input_cost + output_cost; | |
| if (total < 0.01) printf \"\$0.00\"; | |
| else if (total < 1.00) printf \"\$%.3f\", total; | |
| else printf \"\$%.2f\", total; | |
| }") | |
| fi | |
| # Token display (session totals, human-readable) | |
| tok_display="" | |
| total_tok=$((total_in + total_out)) | |
| if [ "$total_tok" -gt 0 ]; then | |
| tok_display=$(awk "BEGIN { | |
| t = $total_tok; | |
| if (t >= 1000000) printf \"%.1fM\", t/1000000; | |
| else if (t >= 1000) printf \"%.0fk\", t/1000; | |
| else printf \"%d\", t; | |
| }") | |
| fi | |
| # Context used bar (5-segment mini bar) | |
| ctx_bar="" | |
| if [ -n "$used_pct" ]; then | |
| segments=$(awk "BEGIN { printf \"%d\", ($used_pct / 100) * 5 + 0.5 }") | |
| [ "$segments" -gt 5 ] && segments=5 | |
| [ "$segments" -lt 0 ] && segments=0 | |
| empty_count=$((5 - segments)) | |
| filled="" | |
| empty="" | |
| [ "$segments" -gt 0 ] && filled=$(printf '%.0s█' $(seq 1 "$segments")) | |
| [ "$empty_count" -gt 0 ] && empty=$(printf '%.0s░' $(seq 1 "$empty_count")) | |
| ctx_bar="${filled}${empty}" | |
| fi | |
| # ── ANSI color helpers (256-color) ──────────────────────────────────────────── | |
| # Foreground: \e[38;5;<n>m Background: \e[48;5;<n>m Reset: \e[0m | |
| R='\e[0m' | |
| # Palette | |
| c_dim='\e[38;5;240m' # muted grey — separators, labels | |
| c_dir='\e[38;5;75m' # soft blue — directory | |
| c_cost='\e[38;5;215m' # warm amber — cost | |
| c_tok='\e[38;5;109m' # steel blue — tokens | |
| c_ctx_filled='\e[38;5;67m' # muted teal — used context | |
| c_ctx_empty='\e[38;5;236m' # very dark — empty context | |
| c_model='\e[38;5;238m' # near-invisible grey — model (subtle) | |
| c_vim='\e[38;5;185m' # soft yellow — vim mode | |
| c_sep='\e[38;5;237m' # dark separator | |
| SEP="${c_sep}│${R}" | |
| # ── Build segments ──────────────────────────────────────────────────────────── | |
| parts=() | |
| # 1. Directory | |
| parts+=("${c_dir}${dir}${R}") | |
| # 2. Cost | |
| if [ -n "$cost" ]; then | |
| parts+=("${c_cost}${cost}${R}") | |
| fi | |
| # 3. Tokens + context bar | |
| if [ -n "$tok_display" ]; then | |
| tok_seg="${c_tok}${tok_display}${R}" | |
| if [ -n "$ctx_bar" ]; then | |
| # Color filled vs empty block chars via sed substitution | |
| esc=$(printf '\033') | |
| filled_color="${esc}[38;5;67m" | |
| empty_color="${esc}[38;5;236m" | |
| reset_color="${esc}[0m" | |
| colored_bar=$(printf '%s' "$ctx_bar" \ | |
| | sed "s/█/${filled_color}█${reset_color}/g;s/░/${empty_color}░${reset_color}/g") | |
| tok_seg+=" ${c_dim}[${R}${colored_bar}${c_dim}]${R}" | |
| fi | |
| parts+=("$tok_seg") | |
| fi | |
| # 4. Effort level (only when non-default / interesting) | |
| if [ -n "$effort" ] && [ "$effort" != "medium" ]; then | |
| parts+=("${c_dim}effort:${effort}${R}") | |
| fi | |
| # 5. Vim mode | |
| if [ -n "$vim_mode" ]; then | |
| parts+=("${c_vim}${vim_mode}${R}") | |
| fi | |
| # 6. Model (subtle, rightmost) | |
| if [ -n "$model" ]; then | |
| parts+=("${c_model}${model}${R}") | |
| fi | |
| # ── Join with separator ─────────────────────────────────────────────────────── | |
| output="" | |
| for i in "${!parts[@]}"; do | |
| if [ $i -gt 0 ]; then | |
| output+=" ${SEP} " | |
| fi | |
| output+="${parts[$i]}" | |
| done | |
| printf "%b\n" "$output" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment