Vibecoding Pro Review anfragen

Alle Artikel

Claude Code Kontext: Stack Traces und Test-Output filtern

Wie du mit CLAUDE.md-Regeln, PreToolUse- und PostToolUse-Hooks und Subagents verhinderst, dass Stack Traces und Test-Logs dein Kontextfenster fressen.

Auf einen BlickWo du lauten Output abfängst, bevor er im Kontext landet
WirkungGrenze
CLAUDE.md-Regel mit tailSchnell eingerichtet, kein SkriptEine Bitte ans Modell, keine Garantie
PreToolUse mit updatedInputSchreibt den Befehl vor dem Lauf umErsetzt das ganze Input-Objekt
PostToolUse mit updatedToolOutputErsetzt das Ergebnis, bevor Claude es siehtMuss die Output-Form des Tools treffen
Subagent für schwere LäufeTrace bleibt im Subagent-KontextEigene Requests zählen weiter zur Nutzung
/clear nach dem FixKostet nichtsKontinuität der Session ist weg

Grafik: Vibecoding Pro · Grundlage: die Quellen unten

Ein npm test schlägt fehl, Claude liest den kompletten Stack Trace, rät einen Fix, lässt die Tests wieder laufen und liest den nächsten. In einer aktuellen Diskussion auf Reddit beschreibt ein Entwickler genau das: Die Hälfte seines Kontextfensters geht für rohes stderr drauf, und am Ende war das Problem eine kaputte Umgebungsvariable. Die Antworten im Thread sind sich erstaunlich einig, und fast alles davon lässt sich mit Bordmitteln von Claude Code sauber bauen.

Warum ein Stack Trace mehrfach kostet

Die Claude-Code-Doku ist da nüchtern: Token-Kosten skalieren mit der Kontextgröße. Ein Trace, der einmal im Kontext liegt, fährt bei jedem folgenden Request mit. Ein Kommentator im Thread bringt es auf den Punkt: Auch als Cache-Read zieht der nutzlose Trace bei jedem Call erneut an deinem Kontingent, mehrmals pro Turn.

Dazu kommt der Qualitätsschaden. Mehrere Antworten berichten, dass das Modell bei viel Framework-Rauschen anfängt, Fixes für das Rauschen zu erfinden, statt auf die eine Fehlerzeile zu schauen. Kontext-Disziplin ist also nicht nur eine Kostenfrage. Mit /context siehst du, was gerade Platz frisst.

Stufe 1: Regel in CLAUDE.md

Der schnellste Hebel aus dem Thread: Build- und Test-Output vor dem Agenten durch tail oder grep schicken und das in CLAUDE.md festschreiben.

## Befehle
- Tests immer so: `npm test 2>&1 | tail -40`
- Testrunner mit quiet- oder dot-Reporter starten, passende Tests sollen nichts ausgeben.
- Sieht ein Fehler nach Env oder Config aus: stoppen und fragen, keinen Code ändern.
- Maximal drei Fix-Versuche, danach Diff und Hypothese berichten.

Die letzten beiden Zeilen zielen auf die Fix-Spirale. Im Thread empfiehlt jemand außerdem eine kurze Liste bekannter Env- und Config-Fallen in CLAUDE.md, damit der Agent die zuerst prüft. Halte die Datei trotzdem knapp, die Doku empfiehlt unter 200 Zeilen, weil CLAUDE.md bei jedem Session-Start komplett geladen wird. Wie du Kontext auf Regeldateien verteilst, steht im Artikel zu CLAUDE.md und .claude/rules.

Die Grenze: Das ist eine Bitte ans Modell. Meistens hält es sich dran.

Stufe 2: PreToolUse-Hook schreibt den Befehl um

Die Kostenseite der Doku nennt genau diesen Fall als Beispiel: ein PreToolUse-Hook, der prüft, ob der Bash-Befehl ein Testrunner ist, und ihn so umschreibt, dass nur Fehler durchkommen. Der Mechanismus dahinter ist updatedInput in hookSpecificOutput.

Eine Variante mit dem Log-Pointer-Muster aus dem Thread: voller Output in eine Datei, Claude bekommt das Ende und den Pfad.

#!/usr/bin/env bash
# ~/.claude/hooks/trim-test-output.sh
input=$(cat)
cmd=$(jq -r '.tool_input.command // empty' <<<"$input")
case "$cmd" in *"npm test"*|*pytest*|*"go test"*) ;; *) exit 0 ;; esac
case "$cmd" in *"| tail"*) exit 0 ;; esac
log=".claude/last-test.log"
new="($cmd) > $log 2>&1; rc=\$?; tail -40 $log; echo \"[voller Output: $log]\"; exit \$rc"
jq -n --argjson ti "$(jq '.tool_input' <<<"$input")" --arg c "$new" \
  '{hookSpecificOutput: {hookEventName: "PreToolUse", permissionDecision: "allow", updatedInput: ($ti + {command: $c})}}'
{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [{ "type": "command", "command": "~/.claude/hooks/trim-test-output.sh" }] }
    ]
  }
}

Drei Details aus der Hooks-Referenz, an denen das gern scheitert:

  • updatedInput ersetzt das ganze Input-Objekt. Deshalb $ti + {command: $c}, damit die übrigen Felder erhalten bleiben.
  • Permission-Regeln werden gegen den umgeschriebenen Befehl ausgewertet, nicht gegen den Original-Call. allow überspringt den Prompt, Deny- und Ask-Regeln greifen trotzdem. Wer den Prompt sehen will, nimmt ask.
  • Auf stdout darf nur das JSON stehen. Ein echo aus deinem Shell-Profil reicht, damit Claude Code das Objekt ignoriert.

Prüfen: /hooks zeigt, ob der Hook unter PreToolUse hängt. Mit claude --debug-file ./claude-debug.txt und einem Testlauf steht im Log eine Zeile modified tool input keys, wenn das Umschreiben gegriffen hat. Die Log-Datei gehört in .gitignore. Mehr zu Exit-Codes und Fallen im Claude Code Hooks Guide.

Stufe 3: Output nachträglich ersetzen

Willst du den Befehl nicht anfassen, bleibt PostToolUse. Hier gibt es eine Falle: decision: "block" hängt nur einen reason an, Claude sieht den Original-Output trotzdem. Ersetzen geht nur mit updatedToolOutput, und der Wert muss die Output-Form des jeweiligen Tools treffen. Das ist fragiler als das Umschreiben vorher, weil du dich an diese Form koppelst.

Gut zu wissen für eigene Hooks, die Kontext per additionalContext liefern: Der ist auf 10.000 Zeichen gedeckelt. Darüber schreibt Claude Code den Text in eine Datei im Session-Verzeichnis und gibt Claude nur den Pfad plus eine Vorschau von bis zu 2.000 Zeichen.

Stufe 4: Schwere Läufe in einen Subagent

Wenn du vorher nicht weißt, welcher Teil des Traces zählt, filtert kein Skript zuverlässig. Dann delegieren: Die Doku empfiehlt, Tests, Log-Analyse und Doku-Fetches an Subagents zu geben. Der volle Output bleibt in deren Kontext, zurück kommt eine Zusammenfassung. Im Thread schwören mehrere genau darauf, einer mit einem Haiku-Subagent als Zusammenfasser. Die Doku sagt dazu ehrlich: Die Requests des Subagents zählen weiter zu deiner Nutzung, für einfache Aufgaben lohnt model: haiku in der Subagent-Datei.

Nach dem Fix: /clear kostet nichts. /compact dagegen liest die ganze Konversation, die es zusammenfasst, und ist bei großem Kontext selbst ein großer Request.

Was das für deinen Workflow bedeutet

Behandle Tool-Output wie Eingabe, die du kuratierst. Konkret:

  1. Quiet-Reporter und eine tail-Regel in CLAUDE.md, heute noch.
  2. Ein PreToolUse-Hook für deine Testrunner mit Log-Datei und Pfad im Output, damit die Regel nicht vom Modell abhängt.
  3. Ein Research- oder Test-Subagent mit kleinem Modell für alles, wo du den Output nicht vorab filtern kannst.
  4. Eine Stopp-Regel für Env- und Config-Fehler plus ein Limit für Fix-Versuche.

Welche Dateien zu einem vollständigen Setup gehören, findest du auf der Setup-Seite.

Du willst wissen, wo in deinem Repo Kontext verbrannt wird und ob deine Hooks den Output wirklich kürzen? Frag ein Agent-Setup-Review an: Wir gehen CLAUDE.md, settings.json, Hook-Skripte und Subagents schriftlich durch.

Häufige Fragen

Warum kostet ein einmal gelesener Stack Trace mehr als einmal?

Token-Kosten skalieren mit der Kontextgröße. Was einmal im Kontext liegt, wird bei jedem weiteren Request der Session mitgeschickt, auch wenn es nur noch als Cache-Read zählt.

Kann ein Claude Code Hook die Ausgabe eines Bash-Befehls kürzen?

Ja, auf zwei Wegen. Ein PreToolUse-Hook kann per updatedInput den Befehl umschreiben, etwa mit einer Pipe auf tail. Ein PostToolUse-Hook kann per updatedToolOutput das Ergebnis ersetzen, bevor es an Claude geht, wobei der Wert die Output-Form des Tools treffen muss.

Reicht decision block in einem PostToolUse-Hook, um den Output zu verstecken?

Nein. Mit decision block hängt Claude Code nur den reason an das Tool-Ergebnis an, Claude sieht den ursprünglichen Output trotzdem. Zum Ersetzen brauchst du updatedToolOutput.

Wie prüfe ich, ob mein Hook den Befehl wirklich umschreibt?

Mit /hooks siehst du, ob der Hook unter PreToolUse registriert ist. Startest du Claude Code mit --debug-file und lässt einen Test laufen, steht im Log eine Zeile modified tool input keys, sobald der Hook den Befehl umgeschrieben hat.

Wann ist ein Subagent besser als ein Filter-Hook?

Wenn du nicht vorher weißt, welcher Teil des Outputs wichtig ist. Der Subagent liest den vollen Trace in seinem eigenen Kontext und gibt nur eine Zusammenfassung zurück, seine Requests zählen aber weiter zu deiner Nutzung.

Beitrag teilen

Weiterlesen

Weitere Artikel

  1. hooks Parallele Subagents ohne Sandbox: Ein Test startet Prozesse
  2. hooks Claude Code Sandbox: Bash per settings.json einsperren
  3. hooks Claude Code Hooks: deterministische Regeln für Agenten
Kontakt · Warteliste

Setup-Review anfragen

Das Agent-Setup-Review startet gerade. Sag kurz, wo dein Setup steht und was du lösen willst. Wir melden uns, sobald es losgeht, und vorher nur, wenn wir Rückfragen haben.

  1. Anfrage mit Rolle, Tool und größter Baustelle
  2. Rückfrage nur, wenn etwas unklar ist
  3. Nachricht, sobald das Review startet

Du willst ein ganzes Team schulen? Dann ist vibecodingtraining.de die richtige Adresse.

Kein Newsletter, nur eine Nachricht, wenn Review oder Repo starten. Keine Weitergabe. Keine Secrets ins Formular.

Wir nutzen deine Angaben nur, um deine Anfrage zu beantworten. Details in der Datenschutzerklärung.