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

In Claude Desktop? Add this status line with statusline-anywhere.

Preview

Clean repo
📁 ~/app 🌿 main 🤖 Opus 4.8 📟 v2.1.155 🎨 default 🧠 Context Remaining: 78% [=======---] 💰 $0.41 ($2.41/h) 📊 45400 tok (4451 tpm)
New session
📁 ~/app 🌿 main 🤖 Opus 4.8 📟 v2.1.155 🎨 default 🧠 Context Remaining: TBD 💰 $0.00 ($0.00/h)
Dirty branch
📁 ~/app 🌿 feat/auth 🤖 Sonnet 4.6 📟 v2.1.155 🎨 default 🧠 Context Remaining: 52% [=====-----] 💰 $0.41 ($2.41/h) 📊 97400 tok (9549 tpm)
Near-full
📁 ~/app 🌿 main 🤖 Opus 4.8 📟 v2.1.155 🎨 Explanatory 🧠 Context Remaining: 9% [----------] 💰 $4.12 ($24.24/h) 📊 183400 tok (17980 tpm)
1M context
📁 ~/app 🌿 main 🤖 Fable 5 📟 v2.1.155 🎨 default 🧠 Context Remaining: 36% [===-------] 💰 $0.41 ($2.41/h) 📊 641400 tok (62882 tpm)
Post-compact
📁 ~/app 🌿 main 🤖 Haiku 4.5 📟 v2.1.155 🎨 default 🧠 Context Remaining: TBD 💰 $0.41 ($2.41/h)
Worktree
📁 ~/.wt/feature 🌿 worktree-feature 🤖 Opus 4.8 📟 v2.1.155 🎨 default 🧠 Context Remaining: 63% [======----] 💰 $0.41 ($2.41/h) 📊 75400 tok (7392 tpm)
Non-git
📁 ~/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

  1. Reads folder, model, Claude Code version, style, cost, duration and tokens from stdin.
  2. Gets the branch from git branch --show-current and shortens the home folder to ~.
  3. Context left counts input and cache tokens against the window, turning red at 20%.
  4. 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

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
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
📁 app 🌿 main 🧠 Opus 🧊 22% [==--------] 💰 $0.41 ($2.41/h) ⏳ 5h: 26% [==--------] 7d: 7% [----------]
📁 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

Deck in 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

Token Weather Usage in 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

Context Bar in 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

Burn Meter in Claude Desktop

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