Three lines: directory, branch, model, Claude Code version and output style, then context remaining as a bar, then session cost with dollars per hour and total tokens with tokens per minute. From the cc-statusline generator.
0 copies
Preview
📁 ~/app 🌿 main 🤖 Opus 4.8 📟 v2.1.155 🎨 default
🧠 Context Remaining: 78% [=======---]
💰 $0.41 ($2.41/h) 📊 45400 tok (4451 tpm)
📁 ~/app 🌿 main 🤖 Opus 4.8 📟 v2.1.155 🎨 default
🧠 Context Remaining: TBD
💰 $0.00 ($0.00/h)
📁 ~/app 🌿 feat/auth 🤖 Sonnet 4.6 📟 v2.1.155 🎨 default
🧠 Context Remaining: 52% [=====-----]
💰 $0.41 ($2.41/h) 📊 97400 tok (9549 tpm)
📁 ~/app 🌿 main 🤖 Opus 4.8 📟 v2.1.155 🎨 Explanatory
🧠 Context Remaining: 9% [----------]
💰 $4.12 ($24.24/h) 📊 183400 tok (17980 tpm)
📁 ~/app 🌿 main 🤖 Fable 5 📟 v2.1.155 🎨 default
🧠 Context Remaining: 36% [===-------]
💰 $0.41 ($2.41/h) 📊 641400 tok (62882 tpm)
📁 ~/app 🌿 main 🤖 Haiku 4.5 📟 v2.1.155 🎨 default
🧠 Context Remaining: TBD
💰 $0.41 ($2.41/h)
📁 ~/.wt/feature 🌿 worktree-feature 🤖 Opus 4.8 📟 v2.1.155 🎨 default
🧠 Context Remaining: 63% [======----]
💰 $0.41 ($2.41/h) 📊 75400 tok (7392 tpm)
📁 ~/scratch 🤖 Opus 4.8 📟 v2.1.155 🎨 default
🧠 Context Remaining: 78% [=======---]
💰 $0.41 ($2.41/h) 📊 45400 tok (4451 tpm)
What it does
Three lines: folder, branch, model, Claude Code version and output style, then context left as a bar, then session cost with dollars per hour and total tokens with tokens per minute.
- Written in
- Bash
- Network access
- None
- Works in
- Terminal
How it works
- Reads folder, model, Claude Code version, style, cost, duration and tokens from stdin.
- Gets the branch from git branch --show-current and shortens the home folder to ~.
- Context left counts input and cache tokens against the window, turning red at 20%.
- Shows $2.41/h and 4451 tpm from session time. Before any tokens, context reads TBD.
Good to know
- Uses jq if installed. Without it, fields are parsed with grep and sed, and context always reads TBD.
- Rates divide by cost.total_duration_ms, the whole session time, so idle minutes pull them down.
- The token count adds total_input_tokens and total_output_tokens. Set NO_COLOR to turn colors off.
Source
#!/bin/bash
# [statuslin.es] trimmed: removed the two blocks that appended every stdin JSON and the extracted fields to statusline.log next to the script (it grew without limit); everything else is unmodified from the pinned source.
# Generated by cc-statusline v1.4.0 (https://www.npmjs.com/package/@chongdashu/cc-statusline)
# Custom Claude Code statusline - Created: 2025-12-24T08:30:00.000Z
# Theme: detailed | Colors: true | Features: directory, git, model, context, usage, tokens, burnrate
STATUSLINE_VERSION="1.4.0"
input=$(cat)
# ---- check jq availability ----
HAS_JQ=0
if command -v jq >/dev/null 2>&1; then
HAS_JQ=1
fi
# ---- color helpers (force colors for Claude Code) ----
use_color=1
[ -n "$NO_COLOR" ] && use_color=0
C() { if [ "$use_color" -eq 1 ]; then printf '\033[%sm' "$1"; fi; }
RST() { if [ "$use_color" -eq 1 ]; then printf '\033[0m'; fi; }
# ---- modern sleek colors ----
dir_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;117m'; fi; } # sky blue
model_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;147m'; fi; } # light purple
version_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;180m'; fi; } # soft yellow
cc_version_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;249m'; fi; } # light gray
style_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;245m'; fi; } # gray
rst() { if [ "$use_color" -eq 1 ]; then printf '\033[0m'; fi; }
# ---- time helpers ----
progress_bar() {
pct="${1:-0}"; width="${2:-10}"
[[ "$pct" =~ ^[0-9]+$ ]] || pct=0; ((pct<0))&&pct=0; ((pct>100))&&pct=100
filled=$(( pct * width / 100 )); empty=$(( width - filled ))
printf '%*s' "$filled" '' | tr ' ' '='
printf '%*s' "$empty" '' | tr ' ' '-'
}
# git utilities
num_or_zero() { v="$1"; [[ "$v" =~ ^[0-9]+$ ]] && echo "$v" || echo 0; }
# ---- JSON extraction utilities ----
extract_json_string() {
local json="$1"
local key="$2"
local default="${3:-}"
local field="${key##*.}"
field="${field%% *}"
local value=$(echo "$json" | grep -o "\"${field}\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | head -1 | sed 's/.*:[[:space:]]*"\([^"]*\)".*/\1/')
if [ -n "$value" ]; then
value=$(echo "$value" | sed 's/\\\\/\//g')
fi
if [ -z "$value" ] || [ "$value" = "null" ]; then
value=$(echo "$json" | grep -o "\"${field}\"[[:space:]]*:[[:space:]]*[0-9.]\+" | head -1 | sed 's/.*:[[:space:]]*\([0-9.]\+\).*/\1/')
fi
if [ -n "$value" ] && [ "$value" != "null" ]; then
echo "$value"
else
echo "$default"
fi
}
# ---- basics ----
if [ "$HAS_JQ" -eq 1 ]; then
current_dir=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // "unknown"' 2>/dev/null | sed "s|^$HOME|~|g")
model_name=$(echo "$input" | jq -r '.model.display_name // "Claude"' 2>/dev/null)
model_version=$(echo "$input" | jq -r '.model.version // ""' 2>/dev/null)
session_id=$(echo "$input" | jq -r '.session_id // ""' 2>/dev/null)
cc_version=$(echo "$input" | jq -r '.version // ""' 2>/dev/null)
output_style=$(echo "$input" | jq -r '.output_style.name // ""' 2>/dev/null)
else
current_dir=$(echo "$input" | grep -o '"workspace"[[:space:]]*:[[:space:]]*{[^}]*"current_dir"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"current_dir"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' | sed 's/\\\\/\//g')
if [ -z "$current_dir" ] || [ "$current_dir" = "null" ]; then
current_dir=$(echo "$input" | grep -o '"cwd"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"cwd"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' | sed 's/\\\\/\//g')
fi
[ -z "$current_dir" ] && current_dir="unknown"
current_dir=$(echo "$current_dir" | sed "s|^$HOME|~|g")
model_name=$(echo "$input" | grep -o '"model"[[:space:]]*:[[:space:]]*{[^}]*"display_name"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"display_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
[ -z "$model_name" ] && model_name="Claude"
model_version=""
session_id=$(extract_json_string "$input" "session_id" "")
cc_version=$(echo "$input" | grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
output_style=$(echo "$input" | grep -o '"output_style"[[:space:]]*:[[:space:]]*{[^}]*"name"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
fi
# ---- git colors ----
git_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;150m'; fi; } # soft green
# ---- git ----
git_branch=""
if git rev-parse --git-dir >/dev/null 2>&1; then
git_branch=$(git branch --show-current 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)
fi
# ---- context window calculation (native) ----
context_pct=""
context_remaining_pct=""
context_color() { if [ "$use_color" -eq 1 ]; then printf '\033[1;37m'; fi; } # default white
if [ "$HAS_JQ" -eq 1 ]; then
CONTEXT_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size // 200000' 2>/dev/null)
USAGE=$(echo "$input" | jq '.context_window.current_usage' 2>/dev/null)
if [ "$USAGE" != "null" ] && [ -n "$USAGE" ]; then
CURRENT_TOKENS=$(echo "$USAGE" | jq '(.input_tokens // 0) + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0)' 2>/dev/null)
if [ -n "$CURRENT_TOKENS" ] && [ "$CURRENT_TOKENS" -gt 0 ] 2>/dev/null; then
context_used_pct=$(( CURRENT_TOKENS * 100 / CONTEXT_SIZE ))
context_remaining_pct=$(( 100 - context_used_pct ))
(( context_remaining_pct < 0 )) && context_remaining_pct=0
(( context_remaining_pct > 100 )) && context_remaining_pct=100
if [ "$context_remaining_pct" -le 20 ]; then
context_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;203m'; fi; } # coral red
elif [ "$context_remaining_pct" -le 40 ]; then
context_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;215m'; fi; } # peach
else
context_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;158m'; fi; } # mint green
fi
context_pct="${context_remaining_pct}%"
fi
fi
fi
# ---- usage colors ----
usage_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;189m'; fi; } # lavender
cost_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;222m'; fi; } # light gold
burn_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;220m'; fi; } # bright gold
# ---- cost and usage extraction ----
cost_usd=""; cost_per_hour=""; tpm=""; tot_tokens=""
# Extract cost and token data from Claude Code's native input
if [ "$HAS_JQ" -eq 1 ]; then
# Cost data
cost_usd=$(echo "$input" | jq -r '.cost.total_cost_usd // empty' 2>/dev/null)
total_duration_ms=$(echo "$input" | jq -r '.cost.total_duration_ms // empty' 2>/dev/null)
# Calculate burn rate ($/hour) from cost and duration
if [ -n "$cost_usd" ] && [ -n "$total_duration_ms" ] && [ "$total_duration_ms" -gt 0 ]; then
cost_per_hour=$(echo "$cost_usd $total_duration_ms" | awk '{printf "%.2f", $1 * 3600000 / $2}')
fi
# Token data from native context_window (no ccusage needed)
input_tokens=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0' 2>/dev/null)
output_tokens=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0' 2>/dev/null)
if [ "$input_tokens" != "null" ] && [ "$output_tokens" != "null" ]; then
tot_tokens=$(( input_tokens + output_tokens ))
[ "$tot_tokens" -eq 0 ] && tot_tokens=""
fi
# Calculate tokens per minute from native data
if [ -n "$tot_tokens" ] && [ -n "$total_duration_ms" ] && [ "$total_duration_ms" -gt 0 ]; then
tpm=$(echo "$tot_tokens $total_duration_ms" | awk '{if ($2 > 0) printf "%.0f", $1 * 60000 / $2; else print ""}')
fi
else
# Bash fallback for cost extraction
cost_usd=$(echo "$input" | grep -o '"total_cost_usd"[[:space:]]*:[[:space:]]*[0-9.]*' | sed 's/.*:[[:space:]]*\([0-9.]*\).*/\1/')
total_duration_ms=$(echo "$input" | grep -o '"total_duration_ms"[[:space:]]*:[[:space:]]*[0-9]*' | sed 's/.*:[[:space:]]*\([0-9]*\).*/\1/')
if [ -n "$cost_usd" ] && [ -n "$total_duration_ms" ] && [ "$total_duration_ms" -gt 0 ]; then
cost_per_hour=$(echo "$cost_usd $total_duration_ms" | awk '{printf "%.2f", $1 * 3600000 / $2}')
fi
# Token data from native context_window (bash fallback)
input_tokens=$(echo "$input" | grep -o '"total_input_tokens"[[:space:]]*:[[:space:]]*[0-9]*' | sed 's/.*:[[:space:]]*\([0-9]*\).*/\1/')
output_tokens=$(echo "$input" | grep -o '"total_output_tokens"[[:space:]]*:[[:space:]]*[0-9]*' | sed 's/.*:[[:space:]]*\([0-9]*\).*/\1/')
if [ -n "$input_tokens" ] && [ -n "$output_tokens" ]; then
tot_tokens=$(( input_tokens + output_tokens ))
[ "$tot_tokens" -eq 0 ] && tot_tokens=""
fi
if [ -n "$tot_tokens" ] && [ -n "$total_duration_ms" ] && [ "$total_duration_ms" -gt 0 ]; then
tpm=$(echo "$tot_tokens $total_duration_ms" | awk '{if ($2 > 0) printf "%.0f", $1 * 60000 / $2; else print ""}')
fi
fi
# ---- render statusline ----
# Line 1: Core info (directory, git, model, claude code version, output style)
printf '📁 %s%s%s' "$(dir_color)" "$current_dir" "$(rst)"
if [ -n "$git_branch" ]; then
printf ' 🌿 %s%s%s' "$(git_color)" "$git_branch" "$(rst)"
fi
printf ' 🤖 %s%s%s' "$(model_color)" "$model_name" "$(rst)"
if [ -n "$model_version" ] && [ "$model_version" != "null" ]; then
printf ' 🏷️ %s%s%s' "$(version_color)" "$model_version" "$(rst)"
fi
if [ -n "$cc_version" ] && [ "$cc_version" != "null" ]; then
printf ' 📟 %sv%s%s' "$(cc_version_color)" "$cc_version" "$(rst)"
fi
if [ -n "$output_style" ] && [ "$output_style" != "null" ]; then
printf ' 🎨 %s%s%s' "$(style_color)" "$output_style" "$(rst)"
fi
# Line 2: Context and session time
line2=""
if [ -n "$context_pct" ]; then
context_bar=$(progress_bar "$context_remaining_pct" 10)
line2="🧠 $(context_color)Context Remaining: ${context_pct} [${context_bar}]$(rst)"
fi
if [ -z "$line2" ] && [ -z "$context_pct" ]; then
line2="🧠 $(context_color)Context Remaining: TBD$(rst)"
fi
# Line 3: Cost and usage analytics
line3=""
if [ -n "$cost_usd" ] && [[ "$cost_usd" =~ ^[0-9.]+$ ]]; then
if [ -n "$cost_per_hour" ] && [[ "$cost_per_hour" =~ ^[0-9.]+$ ]]; then
cost_per_hour_formatted=$(printf '%.2f' "$cost_per_hour")
line3="💰 $(cost_color)\$$(printf '%.2f' "$cost_usd")$(rst) ($(burn_color)\$${cost_per_hour_formatted}/h$(rst))"
else
line3="💰 $(cost_color)\$$(printf '%.2f' "$cost_usd")$(rst)"
fi
fi
if [ -n "$tot_tokens" ] && [[ "$tot_tokens" =~ ^[0-9]+$ ]]; then
if [ -n "$tpm" ] && [[ "$tpm" =~ ^[0-9.]+$ ]]; then
tpm_formatted=$(printf '%.0f' "$tpm")
if [ -n "$line3" ]; then
line3="$line3 📊 $(usage_color)${tot_tokens} tok (${tpm_formatted} tpm)$(rst)"
else
line3="📊 $(usage_color)${tot_tokens} tok (${tpm_formatted} tpm)$(rst)"
fi
else
if [ -n "$line3" ]; then
line3="$line3 📊 $(usage_color)${tot_tokens} tok$(rst)"
else
line3="📊 $(usage_color)${tot_tokens} tok$(rst)"
fi
fi
fi
# Print lines
if [ -n "$line2" ]; then
printf '\n%s' "$line2"
fi
if [ -n "$line3" ]; then
printf '\n%s' "$line3"
fi
printf '\n'
More status lines
Pace Dot Meters
94 copies
Opus 4.8 [high] ~/app main
16:20:55 | ⛁ ██░░░░░░░░ 22% | 5h ●◔○○○ 26% ↻2h7m | 7d ◔○○○○○○ 7% ↻2d1h │ $0.41 ⏱ 10m
Activity Feed
51 copies
Opus 4.8 high ✦ │ ctx 22% │ app (main) │ PR #1287 ● │ $0.41 · 10m +128 -34
Session ● ● ● ● ● ● ● ● ○ ○ ○ 74% left Resets in 2h 6m
Weekly ● ● ● ● ● ● ● ● ● ● ○ 93% left Resets in 2d 0h
Fable ● ● ● ● ● ● ● ● ● ○ ○ 85% left Resets in 2d 0h
◐ Read:index.ts ✓ Read×1 ✓ Bash×1 ✓ Edit×1 ✓ Grep×1
◐ code-reviewer Review the change for regressions
One Dark Triptych
15 copies
Model: Opus 4.8 | Thinking: high | Context: [▰▰▱▱▱▱▱▱▱▱] 45k/200k (22%) | cwd: ~/app | ⎇ main | (+0,-0)
Cost: $0.41 | Block: 2hr 6m | Weekly: 7.0% | Session: 10m | In: 916.7 t/s | Out: 29.2 t/s | Cached: 2k | Session: [▰▱▱▱▱] 26.0%
Mem: 0.8G/1.0G | (*゚∀゚*) | Session ID: b8e1c0d2-4a6f-4e2a-9c1b-3f5d7a9e2c10
Pace Arrows
5 copies
Opus 4.8 (200K) high | app (main)
██░░░░░░░░ 22% 200K | 5h 26% ⇣32% 2h 7d 7% ⇣63% 2d
Burn Rate Bars
4 copies
📁 app 🌿 main 🧠 Opus
🧊 22% [==--------] 💰 $0.41 ($2.41/h)
⏳ 5h: 26% [==--------] 7d: 7% [----------]
Hourly Burn Lines
0 copies
📁 app 🌿 main 🧠 Opus
🧊 22% [==--------] 💰 $0.41 ($2.41/h)
⏳ 5h: 26% [==--------] 7d: 7% [----------]
Related mods
Terminal
❯ /deck demo
⎿ deck: Sample plan running above the prompt, with sample routing until real ones arrive.
[-]
0: deck ▾ · 5 rows 22:11:41
⇄ Model route opus = opus jev: haiku · not applied effort ▁▃·· medi = kept ✕
✓ Orders module Done · 12/12 · 2/2 agents 100% ✕
● Context 44k / 200k 22% ✕
◔ Session · 5h 5h · 26% used ↻ 2:04:24 ✕
◔ Weekly · 7d 7d · 7% used ↻ 2d 0h 57m ✕
❯
⏵⏵ auto mode on (shift+tab to cycle) · ← for agents [ Deck 1 ]Claude Desktop

A cockpit for Claude Code: plan bars and subagent strips, context, usage limits with reset countdowns and burn rates, spend, the model route and a pet. Six bar styles, three collapsed looks. CLI and Desktop.
Terminal
❯ Run the tests again
● The repo is clean and the tests pass.
✻ Cooked for 0s · done 10:12 PM
☀ 44k │ 5h 26% │ 7d 7% │ cache 5% [-]
❯ Claude Desktop

One line above the prompt: context tokens with their weather, a bar per recent prompt, your 5-hour and 7-day limits against the time elapsed, the prompt cache with its time left, the session cost with the last prompt's share in dollars and in points of the 5-hour limit, and the subagents running. Labels in English, French or Russian. After Token Weather (Anthropic, Apache-2.0) and the ideas of usage-meter (HolyGrail) and prompt-cache-control (Daniel San).
Terminal
╭─────────────────────────────────────────────────────────────────────────────────────────────╮ [-]
│ ◆ context 44k of 200k · compacts at 167k 22% │
│ ████████████████████────────────────────────────────────────────────────────░░░░░░░░░░░░░░░ │
│ ■ system prompt 1.9k 1% ■ system tools 28k 14% ■ skills 2k 1% ■ messages 12k 6% │
│ ─ free space 123k ░ autocompact buffer 33k │
╰─────────────────────────────────────────────────────────────────────────────────────────────╯
❯ Claude Desktop

Your context window as a stacked bar above the prompt, a color per category, with token counts and the compaction point. /context-bar shows or hides it.
Terminal
BURN ▁ ▂ *▂▆ ▃ $0.41 = 0.04 burritos [-]
5h 26% in 2h 5m ▅▄█▅▅▆█▆███▅█ opus 4.8 44k in 1k out
wk 7% in 2d 0h █████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ lifetime $0.41 hide
❯ Claude Desktop

Live session cost odometer above the prompt: a burning fuse, real-world comparisons, threshold alerts