ai:platformy:claude-code:statusline

Toto je starší verze dokumentu!


Status line pro Claude Code

Vytvořeno: | Aktualizováno: 08.05.2026 21:28

Claude Code umí vykreslovat vlastní status line spuštěný jako externí příkaz. Tohle je moje varianta, která drží stabilní pořadí polí a na jeden pohled ukazuje pracovní adresář, model, session ID, využití kontextu, 5h a 7d limity i absolutní spotřebu tokenů context window se zvýrazněním nad hranicí 200k.

  • Aktuální pracovní adresář projektu (root, kde byl Claude Code spuštěn) zkrácený relativně k $HOME, takže místo celé cesty vidím jen ~ nebo ~/…. Adresář se v průběhu session nemění, i když shell přejde do podadresáře.
  • Použitý model a session ID přímo ve status line.
  • Využití context window v procentech, počítané dynamicky ze skutečně vrácených polí JSONu.
  • 5hodinový a 7denní limit, včetně času resetu, pokud je Claude Code pošle v JSONu.
  • Absolutní spotřebu tokenů context window ve formátu XYZk/TOTALk. Hodnota celkového okna se čte dynamicky, takže funguje i pro 1M context window. Červeně se rozsvítí při překročení 200k tokenů.
  • Barevné zvýraznění podle vytížení: zelená pod 70 %, žlutá od 70 %, červená od 90 %.

V ~/.claude/settings.json mám status line zapojený takto:

"statusLine": {
  "type": "command",
  "command": "bash /home/ubuntu/.claude/statusline-command.sh"
}

Skript čte JSON ze standardního vstupu, parsuje ho přes jq a složí z něj jednu barevnou řádku.

Když Claude Code neposílá data o rate_limits, výstup vypadá zhruba takto:

~/scratch │ Sonnet 4.6 | sid:<id> │ ctx:23% │ 92k/400k

Když jsou limity v JSONu k dispozici, řádka se rozšíří o 5h a 7d přehled:

~/project-procesniaudit-website │ Sonnet 4.6 │ ctx:55% │ 5h:4% ↺ 00:50 │ 7d:45% ↺ Po 08:00 │ 220k/400k

Barvy jsou rozdělené takto:

  • cwd → cyan + bold
  • model → magenta
  • sid → dim
  • ctx, 5h a 7d → zelená pod 70 %, žlutá od 70 %, červená od 90 %
  • token counter XYZk/TOTALk → červeně a tučně při překročení 200k, jinak dim
#!/usr/bin/env bash
# Claude Code status line
# Order: cwd | model | context used | 5h limit | 7d limit
 
input=$(cat)
 
# ── helpers ────────────────────────────────────────────────────────────────────
RESET='\033[0m'
BOLD='\033[1m'
DIM='\033[2m'
RED='\033[31m'
YELLOW='\033[33m'
GREEN='\033[32m'
CYAN='\033[36m'
MAGENTA='\033[35m'
WHITE='\033[37m'
 
# ── 1) cwd ─────────────────────────────────────────────────────────────────────
cwd=$(echo "$input" | jq -r '.workspace.project_dir // .workspace.current_dir // .cwd // ""')
# Show path relative to home dir
home_dir="$HOME"
if [[ "$cwd" == "$home_dir" ]]; then
  short_cwd="~"
elif [[ "$cwd" == "$home_dir/"* ]]; then
  short_cwd="~/${cwd#$home_dir/}"
else
  short_cwd="$cwd"
fi
[ "$short_cwd" = "/" ] && short_cwd="/"
 
# ── 2) model ───────────────────────────────────────────────────────────────────
model_name=$(echo "$input" | jq -r '.model.display_name // .model.id // ""')
session_id=$(echo "$input" | jq -r '.session_id // .conversation_id // empty')
 
# ── rate limit helpers ─────────────────────────────────────────────────────────
five_pct=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage  // empty')
five_rst=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at        // empty')
week_pct=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage  // empty')
week_rst=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at        // empty')
 
fmt_reset_short() {
  local v="$1"
  [ -z "$v" ] && return
  # Try as epoch first, then as ISO-8601 string
  if [[ "$v" =~ ^[0-9]+$ ]]; then
    date -d "@$v" +%H:%M 2>/dev/null || date -r "$v" +%H:%M 2>/dev/null || echo "?"
  else
    date -d "$v" +%H:%M 2>/dev/null || echo "?"
  fi
}
 
fmt_reset_long() {
  local v="$1"
  [ -z "$v" ] && return
  if [[ "$v" =~ ^[0-9]+$ ]]; then
    date -d "@$v" +"%a %H:%M" 2>/dev/null || date -r "$v" +"%a %H:%M" 2>/dev/null || echo "?"
  else
    date -d "$v" +"%a %H:%M" 2>/dev/null || echo "?"
  fi
}
 
# Choose colour based on used %
pct_color_used() {
  local used="$1"
  [ -z "$used" ] && echo "$WHITE" && return
  local u
  u=$(printf "%.0f" "$used")
  if   [ "$u" -ge 90 ]; then echo "$RED"
  elif [ "$u" -ge 70 ]; then echo "$YELLOW"
  else echo "$GREEN"
  fi
}
 
 
# ── 3) context used ────────────────────────────────────────────────────────────
ctx_used_tokens=$(echo "$input" | jq -r '.context_window.total_input_tokens // empty')
ctx_window_size=$(echo "$input" | jq -r '.context_window.context_window_size // empty')
ctx_str=""
if [ -n "$ctx_used_tokens" ] && [ -n "$ctx_window_size" ] && [ "$ctx_window_size" -gt 0 ]; then
  ctx_pct=$(python3 -c "print(round($ctx_used_tokens / $ctx_window_size * 100))")
  if   [ "$ctx_pct" -ge 90 ]; then
    ctx_str="$(printf "${RED}${BOLD}ctx:%s%%!${RESET}" "$ctx_pct")"
  elif [ "$ctx_pct" -ge 70 ]; then
    ctx_str="$(printf "${YELLOW}ctx:%s%%${RESET}" "$ctx_pct")"
  else
    ctx_str="$(printf "${GREEN}ctx:%s%%${RESET}" "$ctx_pct")"
  fi
fi
 
# ── assemble line ──────────────────────────────────────────────────────────────
parts=()
 
# 1) cwd
parts+=("$(printf "${CYAN}${BOLD}%s${RESET}" "$short_cwd")")
 
# 2) model + session id
if [ -n "$model_name" ] || [ -n "$session_id" ]; then
  parts+=("$(printf "${MAGENTA}%s${RESET}" "$model_name")${session_id:+ $(printf "${DIM}| sid:%s${RESET}" "$session_id")}")
fi
 
# 3) context used (always shown when data available)
[ -n "$ctx_str" ] && parts+=("$ctx_str")
 
# 4) 5h rate limit (only when data is available)
if [ -n "$five_pct" ]; then
  five_int=$(printf "%.0f" "$five_pct")
  col=$(pct_color_used "$five_pct")
  rst=$(fmt_reset_short "$five_rst")
  parts+=("$(printf "${col}5h:%s%%%s${RESET}" "$five_int" "${rst:+ ↺ $rst}")")
fi
 
# 5) 7d rate limit (only when data is available)
if [ -n "$week_pct" ]; then
  week_int=$(printf "%.0f" "$week_pct")
  col=$(pct_color_used "$week_pct")
  rst=$(fmt_reset_long "$week_rst")
  parts+=("$(printf "${col}7d:%s%%%s${RESET}" "$week_int" "${rst:+ ↺ $rst}")")
fi
 
# 6) token counter — červeně od 200k
if [ -n "$ctx_used_tokens" ] && [ -n "$ctx_window_size" ] && [ "$ctx_window_size" -gt 0 ]; then
  ctx_used_k=$(python3 -c "print(round($ctx_used_tokens / 1000))")
  ctx_total_k=$(python3 -c "print(round($ctx_window_size / 1000))")
  if [ "$ctx_used_tokens" -gt 200000 ]; then
    parts+=("$(printf "${RED}${BOLD}%sk/%sk${RESET}" "$ctx_used_k" "$ctx_total_k")")
  else
    parts+=("$(printf "${DIM}%sk/%sk${RESET}" "$ctx_used_k" "$ctx_total_k")")
  fi
fi
 
# ── print ──────────────────────────────────────────────────────────────────────
# Join with separator " │ "
sep="$(printf "${DIM} │ ${RESET}")"
out=""
for p in "${parts[@]}"; do
  [ -z "$out" ] && out="$p" || out="${out}${sep}${p}"
done
 
printf "%b\n" "$out"
  • Pole 5h a 7d se zobrazí jen když Claude Code skutečně pošle rate_limits.
  • Funkce fmt_reset_short() a fmt_reset_long() zvládnou jak unix epoch, tak ISO-8601 string.
  • Pro cwd se primárně čte .workspace.project_dir — pole, které Claude Code nastavuje na root projektu (kde byl spuštěn) a nemění se v průběhu session, i když shell přejde do podadresáře. Pole .workspace.current_dir a .cwd jsou jen fallback.
  • Procento využití context window se počítá dynamicky z context_window.total_input_tokens a context_window.context_window_size. Pole context_window.used_percentage v JSONu od Claude Code neexistuje, proto ho skript nepoužívá.
  • Skript záměrně nepoužívá příznak exceeds_200k_tokens — ten se počítá z kumulativní spotřeby tokenů přes celou session (součet všech inputů přes všechny turny) a v dlouhé session zůstane natrvalo true. Místo toho skript ukazuje aktuální stav context window v segmentu XYZk/TOTALk.
  • Když některé pole v JSONu chybí, skript se nerozbije a prostě ho přeskočí.
  • Pořadí polí je pevné: cwdmodel + sidctx5h7dXYZk/TOTALk.
  • ai/platformy/claude-code/statusline.1778268516.txt.gz
  • Poslední úprava: 08.05.2026 21:28
  • autor: Petr Nosek