statuslin.es

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.41
New 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.41
Near-full
🤖 Opus 4.8📊 91%✏️ +128/-34🔀 main 📐 CTX ▰▰▰▰▰▰▰▰▰▱ 91% 182K / 200K tokens 💰 $4.12
1M context
🤖 Fable 5📊 64%✏️ +128/-34🔀 main 📐 CTX ▰▰▰▰▰▰▱▱▱▱ 64% 640K / 1M tokens 💰 $0.41
Post-compact
🤖 Haiku 4.5📊 0%✏️ +128/-34🔀 main 📐 CTX ▱▱▱▱▱▱▱▱▱▱ 0% 0 / 200K tokens 💰 $0.41
Worktree
🤖 Opus 4.8📊 37%✏️ +128/-34🔀 worktree-feature 📐 CTX ▰▰▰▰▱▱▱▱▱▱ 37% 74K / 200K tokens 💰 $0.41
Non-git
🤖 Opus 4.8📊 22%✏️ +128/-34 📐 CTX ▰▰▱▱▱▱▱▱▱▱ 22% 44K / 200K tokens 💰 $0.41

Source

#!/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% ↻2d0h
Opus 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.