====== Status line pro Claude Code ======
[[software:vyvoj:claude-code:start|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 informaci, jestli session nepřelezla hranici 200k tokenů.
===== Co z toho získám =====
* Aktuální pracovní adresář zkrácený relativně k ''$HOME'', takže místo celé cesty vidím jen ''~'' nebo ''~/...''.
* Použitý model a session ID přímo ve status line.
* Využití context window v procentech.
* 5hodinový a 7denní limit, včetně času resetu, pokud je Claude Code pošle v JSONu.
* Rychlý signál, jestli session už překročila hranici 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: │ ctx:23% │ <200k
Když jsou limity v JSONu k dispozici, řádka se rozšíří o 5h a 7d přehled:
~/project-dokuwiki │ Sonnet 4.6 | sid: │ ctx:23% │ 5h:41% ↺ 01:15 │ 7d:68% ↺ Ne 10:00 │ <200k
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 %
* ''>200k'' → červeně a tučně
* ''<200k'' → 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.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
}
# ── exceeds_200k ───────────────────────────────────────────────────────────────
exceeds=$(echo "$input" | jq -r '.exceeds_200k_tokens // false')
# ── 3) context used ────────────────────────────────────────────────────────────
ctx_used_pct=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
ctx_str=""
if [ -n "$ctx_used_pct" ]; then
ctx_int=$(printf "%.0f" "$ctx_used_pct")
if [ "$ctx_int" -ge 90 ]; then
ctx_str="$(printf "${RED}${BOLD}ctx:%s%%!${RESET}" "$ctx_int")"
elif [ "$ctx_int" -ge 70 ]; then
ctx_str="$(printf "${YELLOW}ctx:%s%%${RESET}" "$ctx_int")"
else
ctx_str="$(printf "${GREEN}ctx:%s%%${RESET}" "$ctx_int")"
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) exceeds_200k signal
if [ "$exceeds" = "true" ]; then
parts+=("$(printf "${RED}${BOLD}>200k${RESET}")")
else
parts+=("$(printf "${DIM}<200k${RESET}")")
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 ''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.
* 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'' → ''>200k/<200k''.