Slash Commands — Wiederholung wegautomatisieren

Slash Commands — Wiederholung wegautomatisieren

Artikel 4 · Serie: Agentic Coding mit Claude Code

v0.3 hat einen funktionierenden Parser — aber nur für Epl11. Sechzehn Einzelpläne liegen in daten/, und für jeden davon dieselbe Sequenz von Hand ausführen — Parser aufrufen, JSON ausgeben, Summen prüfen — ist genau das, was Claude Code ersetzen soll. Das Werkzeug dafür sind Slash Commands.

Slash Command, Skill oder direkter Prompt

Drei Werkzeuge, drei Kontexte. Die Abgrenzung ist präzise:

Direkter Prompt — für einmalige, nicht wiederholbare Aufgaben. Funktioniert, wenn der Kontext klar ist und der Schritt nicht erneut gebraucht wird.

Skill — definiert wie eine Aufgabe anzugehen ist: Ablauf, Werkzeuge, Verifikations-Kriterien. Claude Code lädt ihn automatisch wenn die Situation passt. Der Skill für parse-haushalt aus Art. 3 beschreibt, welche Tests grün sein müssen, welche PDF-Seiten geparst werden und was nicht.

Slash Command — definiert was ausgeführt wird, mit einem festen Argument, einem definierten Output und einem fest eingebauten Abschluss-Schritt. Er heißt /parse-epl Epl05, nicht „bitte parse jetzt Epl05". Die Ausführung ist deterministisch — wer /parse-epl Epl11 aufruft und /parse-epl Epl05, bekommt denselben Ablauf mit anderem Argument.

Commands und Skills schließen sich nicht aus. /parse-epl ruft am Ende /check-totals auf — Command-Komposition. /check-totals ruft uv run pytest auf — Skill-Wissen über Verifikation, in einen Command eingebaut.

Der erste Command: /parse-epl

Dateistruktur

Slash Commands liegen unter .claude/commands/<name>.md. Der Inhalt ist eine Prompt-Vorlage — $ARGUMENTS wird beim Aufruf durch das Argument ersetzt.

Erstellungs-Prompt

Erstelle .claude/commands/parse-epl.md.
Der Command nimmt $ARGUMENTS als Einzelplan-Name (z. B. Epl05).
Ablauf:
1. Prüfe ob ../daten/$ARGUMENTS.pdf existiert — bei Fehler verfügbare Dateien
   auflisten und abbrechen.
2. cd parser && uv sync --extra dev
3. extract_titles aus daten/$ARGUMENTS.pdf, JSON nach output/$ARGUMENTS.json,
   Decimal als float serialisieren.
4. Ausgabe: Anzahl Titel, erste 3 Titel-Nummern.
5. Danach /check-totals $ARGUMENTS aufrufen.
Scope: nur Titelübersicht-Seiten.

Erste Ausführung

/parse-epl Epl05

Claude Code öffnet .claude/commands/parse-epl.md, setzt $ARGUMENTS = "Epl05" ein und führt den Ablauf aus. Output:

448 Seiten — starte Extraktion...
271 Titel → parser/output/Epl05.json
Erste Einträge: ['111 01-0', '119 49-4', '119 49-6']
→ /check-totals Epl05

Der Command-Aufruf ist kürzer als jeder Prompt, der dasselbe beschreibt — und er ist wiederholbar.

Argument-Handling

$ARGUMENTS ist die Zeichenkette, die nach dem Command-Namen steht. Bei /parse-epl Epl05 ist $ARGUMENTS = "Epl05". Bei /parse-epl Epl05 --verbose ist $ARGUMENTS = "Epl05 --verbose" — der Command entscheidet selbst, wie er das weiterverarbeitet.

Das erste, was jeder Command tut: Argument validieren.

1. Prüfe dass ../daten/$ARGUMENTS.pdf existiert. Wenn nicht:
   Fehlermeldung + Liste verfügbarer Dateien → abbrechen.

Diese zwei Zeilen verhindern, dass der Command mit einem leeren oder falschen Argument lautlos durch läuft und ein leeres JSON hinterlässt. Die Validierung kostet zwei Zeilen Prompt, spart aber stilles Fehlverhalten.

/check-totals — Verifikation im Command

/check-totals Epl11 liest parser/output/Epl11.json, berechnet Summen, vergleicht mit der Referenz-Tabelle im Command-Body und ruft dann uv run pytest tests/ -v auf:

/check-totals Epl11

Output:

  Ausgaben  2026:     47.379,0 Tsd. €  ✓ (Ref 47.379,0, Delta 0,0)
  Einnahmen 2026:         11,9 Tsd. €  ✓ (Ref 11,9, Delta 0,0)

7 passed, 2 xfailed in 0.37s
→ Grün. Kann committed werden.

Warum steht die Verifikation im Command und nicht im Skill? Der Skill parse-haushalt beschreibt den Ablauf und die Kriterien — er ist generisch. /check-totals ist spezifisch: er prüft genau diesen Einzelplan, mit genau dieser Referenztabelle, mit genau diesem Test-Lauf. Die Referenzwerte für Epl11, Epl01 und Epl16 stehen direkt in der Command-Datei — dort wo sie gebraucht werden, nicht in CLAUDE.md.

/diff-vs-gesamt — Commands, die Commands aufrufen

/diff-vs-gesamt

Dieser Command hat kein Argument. Er liest alle parser/output/Epl*.json, summiert Ausgaben und Einnahmen pro Einzelplan und gibt eine Tabelle aus:

Epl | Titel | Ausgaben 2026 (Tsd. €) | Einnahmen 2026 (Tsd. €)
----|-------|------------------------|------------------------
Epl05 |  271 |         5.399.366,2  |              42,0
Epl11 |   81 |            47.379,0  |              11,9
Epl01 |  138 |           183.477,8  | ⚠ xfail        756,5
Epl16 |  158 |           121.804,4  | ⚠ xfail      2.111,6
...
Gesamt: X geparste Epls | Σ Ausgaben Y | Σ Einnahmen Z
Referenz Gesamthaushalt 2026: 84.647.400 Tsd. € (formales Ausgabevolumen)
Fehlend: A Einzelpläne — /parse-epl EplNN für jeden ausführen.

Die Komposition: /diff-vs-gesamt ruft intern /check-totals für die bekannten Referenz-Epls auf, bevor es die Gesamttabelle ausgibt. Ein Command, der weiß, dass er eine andere Aufgabe zusammenfasst, delegiert die Teilprüfung.

Alle Einzelpläne — was die Commands aufdecken

Der Loop über alle 16 Einzelpläne bringt das erste echte Problem ans Licht. Wir führen /parse-epl für Epl01 und Epl16 aus und rufen danach /check-totals auf:

/parse-epl Epl01
→ /check-totals Epl01

Output:

  Ausgaben  2026:    183.477,8 Tsd. €  ✗ (Ref 219.371,8, Delta -35.894,0)
  Einnahmen 2026:        756,5 Tsd. €  ✗ (Ref 1.258,5, Delta -502,0)

7 passed, 2 xfailed in 0.37s
→ Rot. Summen weichen ab — kein Commit.

Der Command gibt den Fehler klar aus: 35.894 Tsd. € Ausgaben fehlen. Die Test-Suite zeigt xfailed für Epl01 — das bedeutet: dieser Fehler ist bekannt, dokumentiert und noch nicht behoben.

Die Ursache, die wir durch Inspektion des Parsers finden: on_titelseite wird auf False gesetzt, sobald das Wort „Abschluss" irgendwo in einer Zeile vorkommt — auch mitten in einer Zweckbestimmung wie „Rechnungsabschluss". Das stoppt die Titelübersicht-Erkennung vorzeitig. Alle Titel nach dieser Zeile bis zum nächsten Kapitel-Header fehlen im Output.

Für Epl16 kommt ein zweites Problem dazu: Einnahmen-Kapitel mit leicht abweichendem Header-Format werden gar nicht erkannt — 1.870 Tsd. € Einnahmen fehlen.

# xfail — bekannte Lücke, v0.5
pytest.param("Epl01", Decimal("219371.8"), Decimal("1258.5"),
             marks=pytest.mark.xfail(reason="Parser-Lücke: nicht alle Kapitel erkannt — v0.5"),
             id="Epl01"),

xfail in pytest hat zwei Funktionen: Es verhindert, dass ein bekannter Fehler die Suite rot macht. Und es erzwingt, dass der Fehler explizit dokumentiert wird — mit Grund und Version. Wenn v0.5 den Parser korrigiert, werden diese Tests automatisch von xfailed auf passed wechseln.

Stand am Ende dieses Artikels

git clone https://codeberg.org/rotecodefraktion/byhaushalt.git
cd byhaushalt
git checkout v0.4

Vollständiger Stand unter byhaushalt @ v0.4.

v0.4 enthält: drei Slash Commands, erweiterte Test-Suite (7 passed, 2 xfailed), JSON-Output für Epl11, Epl01 und Epl16. Die xfail-Markierungen dokumentieren, was v0.5 zu reparieren hat.

Wie es weitergeht

Der nächste Artikel behandelt Subagent-Driven Development. Die Parser-Lücke aus v0.4 wird dabei nicht manuell gefixed — sondern durch mehrere parallel laufende Subagents untersucht und behoben. Jeder Agent bekommt einen Einzelplan, analysiert seine Kapitel-Typen und liefert einen strukturierten Bericht. Das Ergebnis landet in einem neuen Commit.

Wie Custom Skills und der TDD-Loop in v0.3 aufgebaut wurden, beschreibt Artikel 3. Die PDF-Strukturanalyse mit Plan Mode steht in Artikel 2.