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.
Co z toho získám
- 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 %.
Zapojení do konfigurace
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.
Jak vypadá výstup
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,5ha7d→ 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
Celý skript
#!/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"
Poznámky k chování
- Pole
5ha7dse zobrazí jen když Claude Code skutečně pošlerate_limits. - Funkce
fmt_reset_short()afmt_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_dira.cwdjsou jen fallback. - Procento využití context window se počítá dynamicky z
context_window.total_input_tokensacontext_window.context_window_size. Polecontext_window.used_percentagev 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 natrvalotrue. Místo toho skript ukazuje aktuální stav context window v segmentuXYZk/TOTALk. - Když některé pole v JSONu chybí, skript se nerozbije a prostě ho přeskočí.
- Pořadí polí je pevné:
cwd→model + sid→ctx→5h→7d→XYZk/TOTALk.