# Claude Code Statusline Eine einzeilige, Statusline für Claude Code. Reines Node (stdlib), ein Renderer + ein Hook. Cross-Plattform (win/mac/linux). Beispielausgabe: ``` RD-1950 · Opus 4.8 · xhigh · RD-1950 · 5h ██▋░░░░░ 33%·2h44m · 7d █▏░░░░░░ 14% · 🔥$26.68/hr · $0.499 $136.54Σ $486.13☾ · caveman:full ``` Segmente (v.l.n.r.): Verzeichnis · Modell · Effort · Git/JJ-Branch · 5h-Limit · 7d-Limit · Burn-Rate ($/h) · Kosten (Turn / Session Σ / Monat ☾) · Caveman-Badge. --- ## Voraussetzungen | Dep | Pflicht | Zweck | |-----|---------|-------| | **Node ≥ 18** | ✅ | Laufzeit. Nur stdlib (`fs/os/path/crypto/child_process`), keine npm-Pakete. | | **Claude Code** | ✅ | Liefert den JSON-Payload (inkl. Kosten) via stdin. | | **git** oder **jj** | ➖ | Branch-Segment. Muss im `PATH` sein. Ohne → Segment entfällt. | | **Nerd Font** | ➖ (empfohlen) | Glyphen ``, Balken `█▏░`, Icons. Ohne → Tofu (`□`). | | **caveman-Plugin** | ➖ | Caveman-Badge. Ohne → Badge entfällt. | --- ## Dateien | Datei | Rolle | |-------|-------| | [`statusline.js`](./statusline.js) | Renderer. Liest stdin-JSON, gibt eine Zeile aus. | | [`cc-statusline-hook.js`](./cc-statusline-hook.js) | Hook. Setzt Turn-Marker + Workflow-Badge. | Beide nach `~/.claude/` kopieren oder symlinken: ```bash ln -s "$PWD/statusline.js" ~/.claude/statusline.js ln -s "$PWD/cc-statusline-hook.js" ~/.claude/cc-statusline-hook.js ``` --- ## Installation 1. Node ≥ 18 installieren, im `PATH`. 2. Beide Dateien nach `~/.claude/` (s.o.). 3. `~/.claude/settings.json` ergänzen (Auszug unten). 4. Nerd Font im Terminal aktivieren (sonst Tofu statt Glyphen). 5. Claude Code neu starten. ### settings.json (Auszug) ```jsonc { "statusLine": { "type": "command", "command": "node ~/.claude/statusline.js" }, "hooks": { // Turn-Marker: Basis für die "Turn"-Kosten (Δ seit letztem Prompt) "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "node ~/.claude/cc-statusline-hook.js" } ] } ], // Workflow-Badge: NUR beim Workflow-Tool feuern (matcher scoped!) "PreToolUse": [ { "matcher": "Workflow", "hooks": [ { "type": "command", "command": "node ~/.claude/cc-statusline-hook.js" } ] } ] } } ``` Der Hook ist **ein** Skript für beide Events; es verzweigt über `hook_event_name`. --- ## Funktionsweise - Claude Code spawnt `statusline.js` **pro Render** (frischer Prozess, Payload via stdin, 300 ms Debounce, event-getriggert: neue Assistant-Nachricht, `/compact`, Permission-/Vim-Mode-Wechsel). Per-Render-Spawn ist von der API erzwungen. - Renderer baut Segmente, jeweils eigener `try/catch` (ein Crash darf die Zeile nicht leeren), und schreibt **ohne** Trailing-Newline. - **Turn-Kosten**: Der Hook legt bei `UserPromptSubmit` eine Marker-Datei `~/.claude/.cc-turn-` an. Der nächste Render liest sie, rebaselined den Turn-Start und löscht den Marker. - **Workflow-Badge**: Bei `PreToolUse(Workflow)` schreibt der Hook eine selbst- ablaufende Zeile nach `~/.claude/.cc-statusline-extra` (TTL 120 s), die der Renderer rendert. - **Kosten-Ledger** `~/.claude/.cc-cost-ledger.json`: Turn / Session / Monat (monats- übergreifend kumuliert). Idle-Renders (keine Kostenänderung) schreiben nicht. Selbst-GC räumt alte `.cc-*.tmp` / `.cc-turn-*` (> 1 Tag) auf. --- ## Anpassung Tunables stehen oben in `statusline.js` im `CONFIG`-Block: | Schlüssel | Default | Bedeutung | |-----------|---------|-----------| | `sep` | `" · "` | Trenner zwischen Segmenten. | | `barWidth` | `8` | Zellen pro Usage-Balken. | | `costStyle` | `"icon"` | `"icon"` = helle `$Zahl` + gedämpftes Glyph; `"slash"` = `$x/turn`. | | `gitCacheTtlMs` | `8000` | Cache für `git status` (Spawn ist ~400 ms kalt auf win32). | | `contextWarnPct`/`CritPct` | `70`/`90` | Schwellen Kontext-Balken (gelb/rot). | | `usageWarnPct`/`CritPct` | `50`/`80` | Schwellen Rate-Limit-Balken. | | `burnWindowMs` | `10 min` | Fenster für die Burn-Rate ($/h). | --- ## Performance (win32) - Harte Untergrenze ist **nicht** das Skript, sondern der Node-Kaltstart: `node -e 0` ≈ **120 ms** (Prozess-Spawn + V8-Init). Nicht durch Flags reduzierbar. - **< 100 ms ist mit Node unmöglich.** Nur ein kompiliertes Binary (Go/Rust ~10–20 ms) unterbietet das — kostet aber Cross-Plattform (per-OS-Builds) + zweite Codebase. Bun (win32) und Deno sind langsamer als Node; LLRT kann kein stdin lesen. → Node. - Die Bar ist asynchron und blockiert keine Eingabe; ~120–140 ms sind unsichtbar. --- ## Troubleshooting | Symptom | Ursache / Fix | |---------|---------------| | `□`/Tofu statt Glyphen | Nerd Font nicht aktiv im Terminal. | | Keine Kosten | Alte Claude-Code-Version ohne `cost` im Payload. | | Kein Branch-Segment | `git`/`jj` nicht im `PATH`, oder nicht in einem Repo. | | Keine Turn-Kosten | Hook nicht in `UserPromptSubmit` registriert. | | Statusline leer | `statusline.js` wirft beim Start — manuell testen: `echo '{}' \| node ~/.claude/statusline.js`. |