Erkunden statt loslegen — Plan Mode mit Subagents
Artikel 2 · Serie: Agentic Coding mit Claude Code
Das Setup aus Artikel 1 steht: CLAUDE.md mit Konventionen und Verboten, Permissions-Datei, siebzehn amtliche PDFs in daten/, Tag v0.1 auf Codeberg. Die eigentliche Arbeit fängt jetzt an: der bayerische Haushalt 2026/27 liegt als ~10.000 Seiten Tabellen und Erläuterungen vor, und wir wollen ihn maschinell lesbar machen.
Der naheliegende nächste Schritt: eine PDF-Datei öffnen und mit dem Schreiben eines Parsers beginnen. Das ist genau der Schritt, den wir nicht gemacht haben.
Ein PDF sieht nach einem gelösten Problem aus. Es ist gedruckt, strukturiert, mit Seitenköpfen, Spaltentiteln, nummerierten Zeilen. Das Modell weiß, was Tabellen sind. Warum nicht einfach parsen? — Weil der Agent ohne Grundlage Annahmen trifft: die Spaltenbreite bleibt gleich, Kapitel-Nummern sind lückenlos, mehrseitige Tabellen setzen Kopfzeilen fort. Keine dieser Annahmen ist zuverlässig. Wer darauf baut, baut auf Sand.
Plan Mode verhindert diesen Fehlschluss, bevor er Code produziert.
Was Plan Mode ist
Plan Mode ist eine Betriebsart von Claude Code, in der der Agent lesen und planen, aber nichts schreiben darf. Read, Bash für schreibgeschützte Befehle, Grep, Glob — ja. Write, Edit, alles, was den Zustand des Repositories verändert — nein.
Aktivieren: /plan in der Session-Eingabe eingeben, oder Shift+Tab drücken. Claude Code zeigt an, dass Plan Mode aktiv ist. Der Output der Session ist ein Plan — kein Code, keine Dateien, kein Commit. Erst wenn der Mensch den Plan explizit bestätigt und Plan Mode verlässt, kann der Agent anfangen zu schreiben.
Der praktische Effekt ist nicht die Einschränkung, sondern die Verlangsamung. Plan Mode erzwingt eine Phase, in der der Agent beschreibt, was er zu tun plant. Wenn der Plan nicht passt — falsche Annahmen, fehlende Schritte, Scope zu groß — fällt es vor dem ersten Tool-Call auf.
Ein Plan Mode, dessen Output man „so ungefähr" durchwinkt, bringt nichts. Der Wert liegt im Review, nicht im Feature.
Plan Mode am byhaushalt
Wir haben Plan Mode aktiviert (Shift+Tab) und dann den Auftrag formuliert. Der Auftrag ist entscheidend: Plan Mode schränkt Claude ein, aber er gibt keine Richtung vor. Ohne präzise Aufgabe produziert Plan Mode einen präzise formulierten Plan für das Falsche.
Der Prompt, den wir verwendet haben:
Kartiere die Dokumentstruktur der PDFs in daten/ — bevor wir einen Parser schreiben.
Lies Stichproben aus mindestens drei Einzelplänen unterschiedlicher Größe.
Ich will wissen:
1. Welche Sektionen hat jeder Einzelplan, welche sind Pflicht?
2. Wie ist eine Titelübersicht-Seite aufgebaut — Spalten, Header, Nummerierung?
3. Was passiert an Seitenumbrüchen innerhalb eines Kapitels?
4. Gibt es Muster, die nicht über alle Einzelpläne konsistent sind?
Output: strukturierter Bericht. Kein Code, keine Dateien anlegen.
Claude Code hat daraufhin einen Plan ausgegeben — keine Datei, kein Bash-Aufruf, nur Beschreibung der geplanten Schritte:
Plan: PDF-Strukturanalyse für byhaushalt
Schritt 1 Epl11.pdf (30 S.) — kleinster Einzelplan als Skelett-Sample
Seiten 1–3: Titel, TOC, Vorwort
Seiten 6–10: erste Titelübersicht + Erläuterungen (Kap. 11 01)
Schritt 2 Epl01.pdf (58 S.) — Vergleich für optionale Sektionen
Seiten 1–3: TOC gegen Epl11 abgleichen
Schritt 3 Epl05.pdf (448 S.) — mehrseitige Tabellen und Titelgruppen
Seiten 30–35: Kapitel mit TG, Erläuterungen, Abschluss-Seite
Schritt 4 Gesamthaushalt.pdf — Übersicht und Gesetzestext
Vollständig lesen für Struktur-Überblick
Ergebnis: Bericht über Seitentypen, Spaltenformat, Mehrseiten-Verhalten,
Inkonsistenzen über Einzelpläne hinweg.
Schritt 4 war falsch. „Vollständig lesen" bei 5.272 Seiten macht keinen Sinn — der Gesamthaushalt enthält hauptsächlich Gesetzestext, die strukturell relevanten Übersichtsseiten sind in den ersten 60 Seiten. Wir haben den Plan vor der Ausführung korrigiert:
Schritt 4 anpassen: Gesamthaushalt.pdf nur erste 60 Seiten.
Wir brauchen TOC und Haushaltsübersicht, nicht den Gesetzestext.
Das ist der Review-Schritt. Claude Code hat den Plan aktualisiert und auf Bestätigung gewartet. Erst dann hat die eigentliche Arbeit begonnen.
Das Ergebnis der Plan Mode Session war kein Parsing-Skript, sondern eine strukturelle Beschreibung:
Jeder Einzelplan folgt demselben Skelett: Titelseite, Inhaltsverzeichnis, Vorwort, Allgemeine Erläuterungen, dann die Kapitel-Serie, dann Stellenplan. Vier Sektionen sind Pflicht, sechs optional. Die Reihenfolge ist deterministisch.
Kapitel-Nummern haben Lücken. Epl11 hat Kapitel 11/01, 11/02, 11/04 — kein 11/03. Epl01 hat 01/01, 01/02, 01/04. Ein Parser, der auf Lückenlosigkeit baut, würde an jedem zweiten Einzelplan scheitern.
Jede Titelübersicht-Seite verwendet eine 6-spaltige Tabelle:
Titel | FKZ | Zweckbestimmung | 2026 | 2027 | A/B/C
1 2 3 4 5 6
Spalte 6 enthält drei gestapelte Vergleichswerte: A = Soll 2025, B = Ist 2024, C = Ist 2023 — drei Zeilen pro Tabellenzeile. Eine Tabellenzeile im rechtlichen Sinne ist also drei Zeilen im PDF-Sinne.
Mehrseitige Kapitel — Epl15/Kapitel 01 ist mit Abstand das größte — wiederholen den Header auf jeder neuen Seite: Kapitelnummer, Kapitelname, Spaltenkopf, Spalten-Nummernzeile. Eine logische Zeile überspannt keinen Seitenumbruch.
Innerhalb eines Kapitels wechseln sich drei Seitentypen ab: Titelübersicht-Seiten, Erläuterungen-Seiten (pro Titel ein Block Zu XX YY/<TitelNr>) und eine Abschluss-Seite, die Kategorien-Summen aggregiert.
Erst als dieses Bild vollständig war, haben wir den Plan bestätigt und docs/architecture.md geschrieben.
Subagent dispatchen
Die PDF-Sichtung — mehrere Dateien, gezielt über Seitenbereiche hinweg, mit Layouterhaltung — produziert viel Rohtext. Jeder pdftotext-Aufruf liefert Hunderte Zeilen. Das alles im Hauptkontext zu halten, bevor der erste Schluss gezogen ist, füllt das Kontextfenster mit Material, das nach der Analyse obsolet wird.
Hier liegt der praktische Grund für einen Explore-Subagent: man schickt die Recherche-Arbeit in eine isolierte Session, bekommt ein kompaktes Ergebnis zurück und behält den Hauptkontext für Entscheidungen frei.
Einen Subagent dispatchen heißt: Claude Code anweisen, eine Teilaufgabe in einer isolierten Session auszuführen. Das kann explizit passieren — man schreibt in den Prompt, dass ein Subagent genutzt werden soll — oder Claude Code entscheidet bei entsprechend formulierter Aufgabe selbst.
Für die Tiefeninspektion von Epl05 haben wir das explizit gemacht:
Schick einen Explore-Subagent für Schritt 3 los:
Lies Epl05.pdf Seiten 30–35 mit pdftotext -layout.
Der Subagent soll berichten:
- Spaltenköpfe der Titelübersicht (exakter Wortlaut)
- Wie A/B/C-Werte je Tabellenzeile im Text angeordnet sind
- Ob der Kapitel-Header auf Seite 31 wiederholt wird
- Was die Zeile "Summe der Titelgruppe" direkt enthält
Rückgabe: strukturierter Bericht. Kein Raw-Text, keine Erklärungen
darüber hinaus.
Der Subagent hat den Auftrag ausgeführt, Hunderte Zeilen pdftotext-Output analysiert und einen kompakten Bericht zurückgegeben. Dieser Bericht ist in den Hauptkontext geflossen — nicht der Raw-Text.
Die Qualität des Subagent-Ergebnisses hängt direkt an der Qualität des Briefs. Vage Aufgabe liefert vagen Bericht:
# Zu vage — Agent entscheidet selbst, was relevant ist:
"Schau dir Epl05 an und sag mir, wie es aufgebaut ist."
# Präzise — klare Fragen, klares Output-Format:
"Lies Epl05.pdf Seiten 30–35. Berichte Spaltenköpfe, A/B/C-Anordnung,
Header-Reprint an Seitenwechsel. Strukturierter Bericht, kein Raw-Text."
Der Subagent bestimmt selbst, wie er die Aufgabe löst (Werkzeugwahl, Reihenfolge). Die Entscheidung, was das Ergebnis bedeutet, bleibt im Hauptkontext.
Wann kein Subagent: wenn die Recherche in wenige Tool-Calls passt und das Ergebnis direkt weiterverarbeitet wird, lohnt sich die Isolierung nicht. Subagents kosten Overhead — Context-Übergabe, Spawning, Ergebnis-Aggregation. Sie rechnen sich, wenn das Recherche-Volumen den Overhead überwiegt, oder wenn mehrere unabhängige Recherchen parallel laufen sollen.
TodoWrite
TodoWrite ist das Tool, mit dem Claude Code Aufgaben innerhalb einer Session trackt — Schritte als in_progress, completed oder pending markieren, einen Zustand über längere Sequenzen hinweg halten.
Für die Plan Mode Session bei byhaushalt haben wir es nicht genutzt. Die Aufgabe war klar eingegrenzt: vier PDFs samplen, Struktur kartieren, Plan ausgeben. Single-Session, eindeutiges Abschlusskriterium. TodoWrite wäre Verwaltungsaufwand ohne Mehrwert.
Sinnvoll ist es bei Sessions mit sechs oder mehr Teilschritten, bei denen Abhängigkeiten zwischen Schritten bestehen, oder wenn eine Session unterbrochen wird und beim nächsten Start der Kontext wieder hergestellt werden muss. Als Projektmanagement-Tool für einfache Sequenzen ist es überdimensioniert.
docs/architecture.md
Der Output der Plan Mode Session ist docs/architecture.md. Die Datei enthält:
- Quelldaten-Inventar: alle 17 PDFs mit Seitenzahl, Dateigröße und Resort-Bezeichnung
- Datenhierarchie: Gesamthaushalt → Einzelplan → Kapitel → Titelgruppe → Titel
- Einzelplan-Skelett mit Pflicht- und optionalen Sektionen
- Die drei Kapitel-Seitentypen mit Header-Format und Spalten-Spezifikation
- Verhalten bei mehrseitigen Tabellen (Header-Reprint, kein Zeilenumbruch über Seitengrenzen)
- Zielmodell als Markdown-Schema: alle Felder des Titel-Datensatzes mit Typen und Nullable-Kennzeichnung
- Drei offene Fragen für Artikel 3: Sektionierung per Texterkennung vs. Titelnummer-Heuristik, Mehrzeilen-Zweckbestimmungen, vorläufige Einzelpläne
Die offenen Fragen gehören dazu. Ein Teil des Werts von Plan Mode liegt darin, explizit zu benennen, was man noch nicht weiß — die Stellen, an denen der Parser in Artikel 3 scheitern könnte, wenn man sie nicht adressiert.
179 Zeilen Markdown, kein Code.
docs/adr/001-stack-choice.md
Der zweite Output ist der Architecture Decision Record für den Stack.
Ein ADR im Nygard-Format hat vier Sektionen: Status, Context (warum eine Entscheidung nötig ist), Decision (was gewählt wird und warum), Consequences (Kompromisse, die akzeptiert werden). Er ist weder README noch Tutorial — er ist ein Entscheidungsprotokoll mit der Begründung, die sie zum Zeitpunkt der Entscheidung vertretbar macht.
Für byhaushalt: Python 3.12 + uv + pdfplumber + polars + Parquet/JSON-Manifest.
Das ADR nennt, was verworfen wurde:
- PyMuPDF: schneller, aber AGPL-Lizenz erfordert Aufmerksamkeit für ein offen veröffentlichtes Projekt
- tabula-py: benötigt eine Java-Runtime, schlechtere Strukturerkennung
- pandas statt polars: polars’ Lazy-API und Rust-Core geben bei den Aggregations-Queries für die Cross-Validation einen messbaren Vorteil
- SQLite statt Parquet: für ein read-only Dataset überdimensioniert; Parquet ist zustandslos und Browser-kompatibel
Ein ADR ohne verworfene Alternativen ist eine Präferenzaussage, kein Entscheidungsprotokoll. Ohne die verworfenen Optionen lässt sich in drei Monaten nicht mehr nachvollziehen, ob die Entscheidung für die damaligen Randbedingungen richtig war.
Stand am Ende dieses Artikels
git clone https://codeberg.org/rotecodefraktion/byhaushalt.git
cd byhaushalt
git checkout v0.2
Der vollständige Stand liegt unter byhaushalt @ v0.2.
Tag v0.2 markiert einen Commit mit 263 Zeilen Markdown-Dokumentation und null Zeilen Anwendungscode. Das ist kein Zwischenzustand — das ist der Wert dieser Phase. Wer hier einen Parser schreibt, schreibt ihn auf eine kartierte Grundlage. Wer die Phase überspringt, schreibt ihn auf Annahmen.
CLAUDE.md nachschärfen
Die Plan Mode Session hat die Quelldaten kartiert. Sie hat auch deutlich gemacht, was CLAUDE.md noch fehlt: Konventionen und Verbote aus Artikel 1 beschreiben das Was — Sprache, Stack, Verzeichnisse. Für die Implementierungsphase ab Artikel 3 braucht der Agent auch das Wie.
Parser-Code ist keine triviale Aufgabe. Der Agent trifft Abwägungen: Wie viel soll eine Funktion tun? Soll er bei Unklarheit raten oder fragen? Darf er angrenzenden Code „verbessern", wenn er gerade ohnehin editiert? Ohne Antworten auf diese Fragen füllt der Agent die Lücken mit Defaults, die nicht immer passen.
Wir haben eine neue Sektion ## Arbeitsweise eingefügt:
- Vor dem Code: Annahmen explizit machen. Bei Unklarheit fragen, nicht raten.
Bei mehreren Interpretationen Optionen nennen, nicht stillschweigend wählen.
- Minimum, das das Problem löst: keine Spekulations-Features, keine Abstraktion
für Single-Use-Code, kein Error-Handling für unmögliche Fälle.
- Chirurgische Änderungen: nur anfassen, was die Aufgabe erfordert.
Eigene Änderungen aufräumen, fremden toten Code stehen lassen.
- Zielgetriebene Ausführung: Erfolgskriterien vor der Implementierung.
Bei mehrstufigen Tasks kurzen Plan ansagen — pro Schritt eine Verifikation.
Diese Regeln sind nach Tag v0.2 committed — wer git checkout v0.2 macht, bekommt die alte CLAUDE.md. Die neue Arbeitsweise-Sektion liegt auf main und gilt ab dem ersten Parser-Commit.
Wie es weitergeht
Im nächsten Artikel entsteht der erste Parser-Skill mit pytest und Test-Driven Development. Die Datenhierarchie aus docs/architecture.md liefert dabei den Kontext: Was ein Einzelplan ist, was ein Kapitel ist, was ein Titel ist — das muss dem Agenten nicht mehr erklärt werden. Es steht im Repo.
Wie CLAUDE.md und das Permissions-Modell das Fundament legen, zeigt Artikel 1.