4 Min. Lesezeit
Das fehlende Instrument
Lange Claude-Code-Sitzungen enden meist auf dieselbe Art. Das Kontextfenster läuft voll, Auto-Compact schlägt zu, und das Modell kommt zurück und hat die Hälfte von dem verloren, worauf ihr euch geeinigt hattet. Es fängt an, Dinge neu zu entscheiden, die du vor zwei Stunden abgehakt hast.
Nichts davon muss eine Überraschung sein. Claude Code berechnet bei jedem Rendern, wie voll das Fenster ist. Es zeichnet die Zahl nur nie.
Eine Statuszeile ändert das. Sie ist eine einzelne Zeile unter dem Prompt, erzeugt von einem Befehl deiner Wahl, und zeigt, was dir wichtig ist. Meine zeigt sechs Dinge.
Edit(statusline.py)
Updated 4 files · +312 -88
- 1ModellWelches Modell gerade antwortet. Praktisch, wenn mehrere Sitzungen mit verschiedenen Modellen laufen.
- 2Freier KontextSpielraum bis zum Auto-Compact. Diese Anzeige entscheidet, ob die Sitzung überlebt.
- 3BranchDer aktuelle Git-Branch. Das Sternchen bedeutet ungespeicherte Änderungen im Working Tree.
- 4ÄnderungenZeilen, die der Agent hinzugefügt und entfernt hat. Die Größe des Diffs, dessen Review noch aussteht.
- 5TokensVerbrauchter Kontext gegen die Fenstergröße. Die 1M-Variante wird zur Laufzeit erkannt, nie angenommen.
- 6ProjektDer Name des Projektverzeichnisses, damit vier Terminal-Tabs nie durcheinandergeraten.
Das zweite Segment ist der Grund, warum es die anderen fünf gibt.
Der Vertrag ist vier Zeilen breit
Du gibst Claude Code einen Befehl. Vor jedem Rendern bekommt er einen JSON-Schnappschuss der Sitzung auf stdin, und was der Befehl auf stdout schreibt, wird zur Statuszeile. Das ist die ganze API, das Ganze ist also ein Filter:
import json, sys
data = json.load(sys.stdin)
print(data["model"]["display_name"])Trag ihn in settings.json ein und du hast eine funktionierende Statuszeile:
{
"statusLine": {
"type": "command",
"command": "python3 ~/.claude/statusline.py"
}
}Alles danach ist nur noch die Entscheidung, was den Platz verdient.
Der eine Teil, der nicht offensichtlich ist
Der Token-Verbrauch liegt im Transkript, einer JSONL-Datei mit einer Nachricht pro Zeile. Der naheliegende Griff ist, input_tokens über alle Zeilen zu summieren. Das Ergebnis wächst schnell, wirkt plausibel und ist kräftig aufgebläht.
Der Grund: Das Modell hat zwischen den Runden kein Gedächtnis, jede Runde sendet also die gesamte Unterhaltung erneut als Eingabe. Der Verbrauch jeder Runde beschreibt deshalb schon alles bisher Gesendete: Kostet Runde eins 10k Tokens und Runde zwei legt 2k drauf, meldet Runde zwei 12k. Summierst du die Zeilen, bekommst du 22k für eine Unterhaltung, die 12k belegt. Prompt Caching teilt den Bericht nur in drei Töpfe: frische Tokens, aus dem Cache gelesene und gerade in den Cache geschriebene. Die drei Töpfe der neuesten Nachricht ergeben genau das, was jetzt im Fenster sitzt:
for line in reversed(lines):
usage = (json.loads(line).get("message") or {}).get("usage")
if usage:
return (usage["input_tokens"]
+ usage["cache_read_input_tokens"]
+ usage["cache_creation_input_tokens"])Rückwärts gehen, die erste Zeile mit Verbrauch nehmen, die drei Felder addieren, fertig.
Der Balken braucht außerdem einen Nenner: die Kapazität des Fensters, die das Sitzungs-JSON nie direkt nennt. Die meisten Modelle laufen mit 200k, manche mit 1M, also prüft das Skript zwei Hinweise und nimmt jeden von beiden: [1m] in der Modell-ID oder das Flag exceeds_200k_tokens in den Daten. Liegst du auf einer 1M-Sitzung falsch, zeigt der Balken bei 200k leer an, während 800k Platz übrig sind. Ein Balken, der über seine eigene Skala lügt, ist schlimmer als keiner.
Drei Regeln, die es langweilig halten
Das Skript läuft bei jedem Rendern, mitten in dem Terminal, in dem du arbeiten willst. Das ist ein feindlicher Ort für Cleverness, also folgt es drei Regeln.
Niemals werfen. Eine Statuszeile, die eine Exception wirft, ersetzt sechs nützliche Fakten durch einen Stacktrace, wieder und wieder. Jeder riskante Aufruf ist abgesichert; ein kaputter Payload endet damit, dass Claude Code ausgegeben wird, und weiter geht es.
Niemals hängen. Jeder git-Aufruf trägt timeout=0.25. Ein langsames Netzlaufwerk kostet eine Viertelsekunde, keinen eingefrorenen Prompt.
Niemals eine Installation brauchen. Nur die Standardbibliothek. Eine Datei, curl, fertig.
Was sich geändert hat
Auto-Compact passiert mir nicht mehr. Fällt der Balken unter zwei Kästchen, bringe ich den Gedanken zu Ende, committe und starte eine frische Sitzung mit dem Kontext, den ich behalten wollte, statt mit dem, was eine automatische Zusammenfassung im ungünstigsten Moment übrig ließ.
Alles zusammen in unter hundert Zeilen Python, die sich bei jeder Sitzung bezahlt machen.
Das Skript und die Installationsschritte liegen im Repo: status-line. Eine Datei, vier Zeilen Konfiguration, fertig.
Beitrag teilen