Three-Line Cockpit
bash
Model, context, lines changed and branch on the first line; a context bar with token counts on the second; session cost on the third. No network calls, just stdin and local git.
MIT licensed · original source
Preview
Clean repo
🤖 Opus 4.8 │ 📊 22% │ ✏️ +128/-34 │ 🔀 main
📐 CTX ▰▰▱▱▱▱▱▱▱▱ 22% 44K / 200K tokens
💰 $0.41New session
🤖 Opus 4.8 │ 📊 0% │ 🔀 main
📐 CTX ▱▱▱▱▱▱▱▱▱▱ 0% 0 / 200K tokens
💰 --Dirty branch
🤖 Sonnet 4.6 │ 📊 48% │ ✏️ +128/-34 │ 🔀 feat/auth
📐 CTX ▰▰▰▰▰▱▱▱▱▱ 48% 96K / 200K tokens
💰 $0.41Near-full
🤖 Opus 4.8 │ 📊 91% │ ✏️ +128/-34 │ 🔀 main
📐 CTX ▰▰▰▰▰▰▰▰▰▱ 91% 182K / 200K tokens
💰 $4.121M context
🤖 Fable 5 │ 📊 64% │ ✏️ +128/-34 │ 🔀 main
📐 CTX ▰▰▰▰▰▰▱▱▱▱ 64% 640K / 1M tokens
💰 $0.41Post-compact
🤖 Haiku 4.5 │ 📊 0% │ ✏️ +128/-34 │ 🔀 main
📐 CTX ▱▱▱▱▱▱▱▱▱▱ 0% 0 / 200K tokens
💰 $0.41Worktree
🤖 Opus 4.8 │ 📊 37% │ ✏️ +128/-34 │ 🔀 worktree-feature
📐 CTX ▰▰▰▰▱▱▱▱▱▱ 37% 74K / 200K tokens
💰 $0.41Non-git
🤖 Opus 4.8 │ 📊 22% │ ✏️ +128/-34
📐 CTX ▰▰▱▱▱▱▱▱▱▱ 22% 44K / 200K tokens
💰 $0.41Source
#!/bin/bash
# Claude Code statusline script (ToS-safe version)
# Line 1: Model | Context% | +added/-removed | git branch
# Line 2: Context window progress bar (detailed)
# Line 3: Session cost | Version
#
# This version uses ONLY stdin data provided by Claude Code.
# No external API calls, no OAuth token extraction, no keychain access.
# Fully compliant with Anthropic Consumer Terms of Service.
set -euo pipefail
# ---------- Read stdin (Claude Code provides JSON) ----------
input=$(cat)
# ---------- ANSI Colors ----------
readonly GREEN=$'\e[38;2;151;201;195m'
readonly YELLOW=$'\e[38;2;229;192;123m'
readonly RED=$'\e[38;2;224;108;117m'
readonly GRAY=$'\e[38;2;74;88;92m'
readonly RESET=$'\e[0m'
readonly DIM=$'\e[2m'
# ---------- Color by percentage ----------
color_for_pct() {
local pct="${1:-0}"
if [[ -z "$pct" || "$pct" == "null" ]]; then
printf '%s' "$GRAY"
return
fi
local ipct
ipct=$(printf "%.0f" "$pct" 2>/dev/null) || ipct=0
if (( ipct >= 80 )); then
printf '%s' "$RED"
elif (( ipct >= 50 )); then
printf '%s' "$YELLOW"
else
printf '%s' "$GREEN"
fi
}
# ---------- Progress bar (10 segments) ----------
progress_bar() {
local pct="${1:-0}"
local filled
filled=$(awk "BEGIN{v=int($pct / 10 + 0.5); if(v>10)v=10; if(v<0)v=0; printf \"%d\", v}" 2>/dev/null) || filled=0
local bar=""
local i
for (( i=1; i<=10; i++ )); do
if (( i <= filled )); then
bar+="▰"
else
bar+="▱"
fi
done
printf '%s' "$bar"
}
# ---------- Safe JSON parsing (no eval) ----------
parse_json() {
local json="$1"
local query="$2"
local default="${3:-}"
local result
result=$(printf '%s' "$json" | jq -r "$query" 2>/dev/null) || result=""
if [[ -z "$result" || "$result" == "null" ]]; then
printf '%s' "$default"
else
printf '%s' "$result"
fi
}
# ---------- Parse stdin fields ----------
model_name=$(parse_json "$input" '.model.display_name // empty' 'Unknown')
used_pct=$(parse_json "$input" '.context_window.used_percentage // 0' '0')
remaining_pct=$(parse_json "$input" '.context_window.remaining_percentage // 100' '100')
ctx_size=$(parse_json "$input" '.context_window.context_window_size // 0' '0')
cwd=$(parse_json "$input" '.cwd // empty' '')
lines_added=$(parse_json "$input" '.cost.total_lines_added // 0' '0')
lines_removed=$(parse_json "$input" '.cost.total_lines_removed // 0' '0')
total_cost=$(parse_json "$input" '.cost.total_cost_usd // 0' '0')
# ---------- Git branch ----------
git_branch=""
if [[ -n "$cwd" && -d "$cwd" ]]; then
git_branch=$(git -C "$cwd" --no-optional-locks rev-parse --abbrev-ref HEAD 2>/dev/null) || true
fi
# ---------- Line stats ----------
git_stats=""
if (( ${lines_added:-0} > 0 )) 2>/dev/null || (( ${lines_removed:-0} > 0 )) 2>/dev/null; then
git_stats="+${lines_added}/-${lines_removed}"
fi
# ---------- Context window formatting ----------
ctx_pct_int=$(printf "%.0f" "${used_pct:-0}" 2>/dev/null) || ctx_pct_int=0
# Format context size (e.g., 200000 -> 200K)
format_tokens() {
local tokens="${1:-0}"
if (( tokens >= 1000000 )); then
awk "BEGIN{printf \"%.0fM\", $tokens / 1000000}"
elif (( tokens >= 1000 )); then
awk "BEGIN{printf \"%.0fK\", $tokens / 1000}"
else
printf '%s' "$tokens"
fi
}
ctx_size_display=$(format_tokens "$ctx_size")
# Used tokens (approximate)
used_tokens=0
if (( ctx_size > 0 )); then
used_tokens=$(awk "BEGIN{printf \"%.0f\", $ctx_size * $used_pct / 100}" 2>/dev/null) || used_tokens=0
fi
used_tokens_display=$(format_tokens "$used_tokens")
# ---------- Cost formatting ----------
cost_display=""
if [[ -n "$total_cost" && "$total_cost" != "0" ]]; then
cost_display=$(awk "BEGIN{printf \"\$%.2f\", $total_cost}" 2>/dev/null) || cost_display=""
fi
# ---------- Separator ----------
SEP="${GRAY} │ ${RESET}"
# ========== Line 1: Model | Context% | Changes | Branch ==========
ctx_color=$(color_for_pct "$ctx_pct_int")
line1="🤖 ${model_name}${SEP}${ctx_color}📊 ${ctx_pct_int}%${RESET}"
if [[ -n "$git_stats" ]]; then
line1+="${SEP}✏️ ${GREEN}${git_stats}${RESET}"
fi
if [[ -n "$git_branch" ]]; then
line1+="${SEP}🔀 ${git_branch}"
fi
# ========== Line 2: Context window progress bar ==========
ctx_bar_color=$(color_for_pct "$ctx_pct_int")
ctx_bar=$(progress_bar "$ctx_pct_int")
line2="${ctx_bar_color}📐 CTX ${ctx_bar} ${ctx_pct_int}%${RESET}"
if (( ctx_size > 0 )); then
line2+=" ${DIM}${used_tokens_display} / ${ctx_size_display} tokens${RESET}"
fi
# ========== Line 3: Session cost ==========
line3=""
if [[ -n "$cost_display" ]]; then
line3="${GREEN}💰 ${cost_display}${RESET}"
else
line3="${DIM}💰 --${RESET}"
fi
# ---------- Output ----------
printf '%s\n' "$line1"
printf '%s\n' "$line2"
printf '%s' "$line3"
What it shows
- Model display name
- Context window usage as a percentage
- Total lines added and removed in the session (+added/-removed)
- Current git branch of the working directory
- A 10-segment context window progress bar
- Approximate used tokens and total context window size (e.g. 44K / 200K tokens)
- Total session cost in US dollars
Requirements
- Bash
- jq, which the script uses for all JSON parsing
- git, used to read the current branch
- awk, used for rounding, token math, and cost formatting
- A terminal that supports 24-bit ANSI color escape codes
- A font that renders emoji (🤖 📊 ✏️ 🔀 📐 💰) and the ▰/▱ bar characters
- No network access; the script reads only stdin and the local git repository
Behavior notes
- The context percentage and bar are green below 50%, yellow from 50% to 79%, and red at 80% or above (48% renders green, 64% yellow, 91% red).
- The +added/-removed segment disappears when both line counts are zero, as in the brand-new session scenario.
- The git branch segment disappears when the working directory is not a git repository, as in the scratch-directory scenario.
- When used_percentage is null (brand-new session and just-after-/compact scenarios), the script falls back to 0%, an empty bar, and a 0-token count.
- When total cost is zero, line 3 shows a dim '💰 --' instead of a dollar amount.
- Token counts are shortened with K and M suffixes; the 1M-context scenario renders as 640K / 1M tokens.
- The used-token figure is computed from the context window size times the used percentage, not from the input-token fields in the JSON.
- The branch name comes from running git in the session's cwd, not from the JSON, so the worktree scenario shows the worktree's actual branch (worktree-feature).
- Fields such as rate limits, vim mode, effort level, PR info, and output style vary across the scenarios but never appear in the output.
More status lines
app · main · Opus-4.8 · effort high · ctx 22% · 5h 26% ↻2h6m · 7d 7% ↻2d0hOpus 4.8 | main | ██░░░░░░░░ 22.0% | 44k / 200k | 02:07 26% | Wed 7%
Opus 4.8 │ main │ app │ ▓▓░░░░░░░░ 44k/200k │ $0.41
app ⏱ 10m ▲ +128 -34 ▓░░░░░░░ 22% $0.41 ◆ Opus Opus 4.8 │ ▰▰▰▰▱▱▱▱▱▱▱▱▱▱▱▱ 22% │ $0.41
app │ main
Opus 4.8 high ✦ │ ctx 22% │ app (main) │ PR #1287 ● │ $0.41 · 10m +128 -34
Session ● ● ● ● ● ● ● ● ○ ○ ○ 74% left Resets in 2h 7m
Weekly ● ● ● ● ● ● ● ● ● ● ○ 93% left Resets in 2d 1h
◐ Read:index.ts ✓ Read×1 ✓ Bash×1 ✓ Edit×1 ✓ Grep×1
◐ code-reviewer Review the change for regressions
New to Claude Code status lines? Read the setup guide.