Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

claude/STATUSLINE.md

Raw
Rendered preview

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 Renderer. Liest stdin-JSON, gibt eine Zeile aus.
cc-statusline-hook.js Hook. Setzt Turn-Marker + Workflow-Badge.

Beide nach ~/.claude/ kopieren oder symlinken:

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)

{
  "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-<session> 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.
# 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-<session>` 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`. |