Vier Prompts, die du neu tippst, werden vier Dateien
Claude Code Extensions sind die Dateien, die ein Repo enthalten kann, damit du nicht mehr denselben Prompt neu tippst: ein Skill, ein Hook, ein Subagent und ein MCP-Server. Wir haben vier wiederkehrende Jobs an einem echten Repo ausgeführt, einer kleinen Rechnungs-API mit einer JSON-Datei als Datenbank. Jeder Job bekam zuerst die falsche Extension, und die falsche Wahl scheiterte jedes Mal auf dem Bildschirm. Danach wurde jeder Job zu einer committeten Datei. Diese Seite behandelt die vier Handgriffe und die Entscheidungskarte, die bestimmt, welche Art du nimmst.
Zwei Ergebnisse rahmen alles Folgende. Ein Hook wird oft als Garantie beschrieben und eine Regel in der Memory-Datei als Bitte, doch unser erster Hook lief, gab seine Warnung aus, und der Schreibzugriff ging trotzdem durch. Was aus einem Hook, der läuft, einen Hook macht, der blockiert, steht im Abschnitt zum Hook. Der erste Docs-Server, den wir anschlossen, änderte nichts, und der, der antwortete, war der Docs-Server des Tools selbst. Das Hook-Rezept, das die meisten kopieren, braucht außerdem eine separate Skriptdatei, unseres passt dagegen komplett in die Settings-Datei.
Bevor du eine der vier Dateien schreibst, musst du wissen, was deine Session schon lädt.
Was die vier sind und was deine Session schon lädt
Eine Claude Code Extension ist eine Datei, die du deinem Repo hinzufügst, damit du dieselben Anweisungen nicht mehr in die Prompt-Box tippst. Es gibt vier Arten, und wer sie schon kennt, kann zum nächsten Abschnitt springen.
- Ein Skill ist ein Ablaufplan, der in deinem Repo abgelegt ist. Claude lädt seine Schritte nur, wenn dieser Job ansteht, und du kannst ihn starten, indem du seinen Namen tippst.
- Ein Hook ist wie ein Commit-Hook in git, aber für Claudes eigene Aktionen. Er ist ein Skript, das bei einem Ereignis läuft, etwa bei einer Änderung, egal was Claude vorhatte.
- Ein Subagent ist ein Auftragnehmer mit leerem Schreibtisch. Er bekommt dein Briefing, übernimmt das Lesen und schickt einen Bericht zurück statt des ganzen Stapels.
- Ein MCP-Server ist ein API-Client, den Claude aufrufen kann, für Daten, die nicht auf deiner Platte liegen, etwa eine Datenbank oder die Docs eines Tools.
Um irgendetwas zu messen, brauchst du zuerst eine Baseline. Öffne eine frische Session und führe den Context-Befehl aus. Er gibt eine Tabelle von allem aus, was vor deinem ersten Wort geladen ist. In unserem Test lag die Summe bei 26,2k Tokens von einem 1m-Fenster, ohne Zeile für Memory-Dateien und ganz ohne MCP-Zeile. Jeder Job, den du Claude ab jetzt gibst, fügt dieser Tabelle entweder eine Zeile hinzu oder lässt sie unverändert.
Der erste Job: die Release-Checkliste wird ein Skill
Ein Skill ist eine Checkliste, die in einem eigenen Ordner liegt und die Claude nur liest, wenn du sie aufrufst. Der erste Job ist eine Release-Checkliste, die du ständig in die Prompt-Box einfügst: Typecheck, Tests, Version erhöhen, eine Changelog-Zeile ergänzen, Commit und Tag.
Der naheliegende Ort dafür ist die Memory-Datei, und das ist die falsche Wahl, denn alles in dieser Datei wird bei jedem Turn jeder Session geladen. Wir haben die Schritte dort eingetragen und die Context-Tabelle erneut gelesen. Sie hatte eine Memory-files-Zeile von 210 Tokens bekommen, geladen, ob du gerade ein Release machst oder nicht. Die Docs sagen genau das: Wenn ein Abschnitt dieser Datei zu einer Prozedur geworden ist, gehört er in einen Skill.
Die richtige Wahl ist ein Ordner im Skills-Verzeichnis mit den Schritten in .claude/skills/release/SKILL.md, einer kurzen Beschreibung oben und einer zusätzlichen Frontmatter-Zeile, disable-model-invocation: true. Diese Zeile hält den Skill von Claudes eigener Liste fern, sodass nur du ihn starten kannst, was du für etwas willst, das committet und taggt. Dann tippst du einen Schrägstrich und seinen Namen, und die Checkliste läuft.
| Context-Messung | Summe | Memory-files-Zeile |
|---|---|---|
| Baseline, frische Session | 26.2k / 1m | keine |
| Checkliste in der Memory-Datei | 26.4k / 1m | 210 tokens |
| Checkliste als Skill | 26.2k / 1m | keine, Skill nicht aufgelistet |
Als wir ihn ausführten, schloss Claude alle sechs Schritte in unter einer Minute ab: Typecheck, 34 Tests, Version von 0.4.0 auf 0.4.1, Changelog-Zeile, Commit und Tag. Dabei fand es auch einen Fehler in unserer eigenen Checkliste. Der Commit-Befehl, wie er geschrieben war, überspringt nicht verfolgte Dateien, also stagte Claude zuerst den neuen Changelog und sagte das dazu. Das Release ist jetzt ein Befehl, den du tippst, es liegt im Repo für das ganze Team und kostet keinen Context, bis du ihn tippst.
Der zweite Job: die Regel, die gelten muss, wird ein Hook
Ein Hook ist ein Skript, das Claude Code ausführt, bevor ein Tool feuert, hier vor jeder Änderung oder jedem Schreibzugriff, und was dieses Skript antwortet, entscheidet, was als Nächstes passiert. Der zweite Job ist eine Regel, die nie brechen darf: In diesem Repo wird die gespeicherte Datendatei nie von Hand bearbeitet, und jede Änderung läuft über eine Migration.
Diese Regel in Großbuchstaben in die Memory-Datei zu schreiben, erzwingt sie nicht. Die Docs sind da direkt: Diese Datei ist Kontext, keine erzwungene Konfiguration, und eine Anweisung wie "never edit this file" ist eine Bitte, keine Garantie, während ein Hook, der die Änderung blockiert, Durchsetzung ist.
Der naheliegende erste Hook ist der, den wir geschrieben haben. In der Settings-Datei beobachtet er Schreibzugriffe auf die Datendatei, gibt eine Warnung aus und beendet sich mit Exit-Code null, wie ein Logging-Skript. Dann baten wir Claude, einen Rechnungsbetrag direkt in der Datei zu ändern, ohne Migration. Der Hook lief und die Warnung erschien, aber der Schreibzugriff ging durch: Der Stückpreis der dritten Rechnung ging von 8000 auf 12000. Claudes Antwort erwähnte den Hook nie, denn ein Hook, der sauber endet und nichts ausgibt, hat keine Entscheidung getroffen, und seine Warnungen erreichen Claude nie.
Die Garantie ist nicht, dass der Hook läuft, sondern die Antwort, die er zurückgibt. Die Lösung behält denselben Hook und lässt ihn eine Deny-Entscheidung zurückgeben: eine kurze JSON-Zeile mit dem Grund, den Claude lesen soll. Ein Exit mit Code zwei blockiert genauso. Der ganze Hook ist ein einziger Inline-Befehl in .claude/settings.json, ohne Skriptdatei:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -c 'if (.tool_input.file_path // \"\") | test(\"data/.*\\\\.json$\") then {hookSpecificOutput: {hookEventName: \"PreToolUse\", permissionDecision: \"deny\", permissionDecisionReason: \"Stored data is never edited by hand: write a migration in src/store/migrations.ts (README § Conventions).\"}} else empty end'"
}
]
}
]
}
}
Bei derselben Anfrage wurde die Änderung abgelehnt, und die Datendatei blieb unberührt. Claude sah diesen Fehler: PreToolUse:Edit hook error: Stored data is never edited by hand: write a migration in src/store/migrations.ts (README § Conventions). Es sagte, es habe nichts geändert, und fragte, ob es die Schutzregel übergehen oder die Migration schreiben solle.
Die Grenze, die Claude selbst benannte: Dieser Hook beobachtet nur die Edit- und Write-Tools, und in einem späteren Lauf bot Claude an, die Änderung stattdessen über die Shell zu machen. Ein Hook muss auch die Shell abdecken, oder die Shell muss von deiner Allow-Liste fernbleiben, denn ein Schutz, der nur eine Tür abdeckt, ist immer noch eine Bitte. Der Hook kostet keinen Context, weil er außerhalb deiner Unterhaltung läuft.
Der dritte Job: das Audit, das flutet, wird ein Subagent
Ein Subagent ist eine separate Claude-Session mit eigenem, leerem Context. Er bekommt dein Briefing, liest, was er braucht, und nur eine Zusammenfassung kommt zurück. Der dritte Job ist ein Audit, das deinen Thread flutet: jede Datei im Quellordner gegen die README-Konventionen prüfen und jeden Verstoß mit Datei und Zeile auflisten.
Inline gefragt, liest Claude jede Datei in deine Unterhaltung, und all dieser Inhalt bleibt dort für den Rest der Session. In unserem Lauf las Claude alle 19 Quelldateien, die Messages-Zeile der Context-Tabelle blähte sich auf, und die Ergebnisse gingen unter dem Stapel unter.
Die richtige Wahl ist eine Datei unter .claude/agents/, hier .claude/agents/conventions-auditor.md, mit einem Namen, einer Beschreibung, wann er zu nutzen ist, den Tools, die er verwenden darf, und einem festgelegten Modell. Das Modell festzulegen ist wichtig, denn ein Subagent erbt sonst, was auch immer deine Session nutzt, und die meisten Leseaufgaben brauchen nicht das große.
Wir stellten genau dieselbe Frage noch einmal, und Claude las die Dateien selbst. In beiden Versuchen rief es den Agent nie auf, obwohl er aufgelistet war: 0 von 2 Delegationen. Was funktionierte, war, ihn gleich am Anfang des Prompts zu nennen: "use the conventions auditor subagent". Ein einziger Aufruf ging raus, und eine kurze Zusammenfassung kam zurück.
| Lauf | Gesamter Context | Messages-Zeile |
|---|---|---|
| Inline-Audit | 46.1k | 19.3k |
| Benannter Subagent | 34.1k | 7.2k |
Die Ergebnisse waren genauso gut: Der Subagent fand einen Pfadfehler, den der Inline-Lauf übersehen hatte, und übersah einen, den der Inline-Lauf fand. Die Datei lässt den Subagent also existieren, und dein Prompt lässt Claude ihn nutzen; bis Claude ihn von selbst wählt, nennst du ihn. Eine Grenze: Die Rechnung bewegte sich nicht. Beide Läufe kosteten gleich viel, denn das Lesen findet weiterhin statt, nur nicht in deinem Fenster.
Der vierte Job: die unerreichbaren Daten werden ein MCP-Server
Ein MCP-Server ist ein API-Client, den Claude aufrufen kann, und die Aufgabe, für die er existiert, sind Daten, die neuer sind als das Modell oder die außerhalb deiner Platte liegen. Die Reflex-Wahl ist hier falsch, also haben wir sie zuerst getroffen.
Wir schlossen einen öffentlichen Docs-Server für unsere Testbibliothek an und baten Claude um einen Test mit Fake-Timern. Nichts änderte sich: Claude kannte diese Bibliothek schon und rief den Server nur auf, als wir ihn nannten. Docs, die das Modell schon kennt, sind keine Daten, an die es nicht herankommt.
Der echte Test ist eine Frage zu Claude Code selbst, zu einer Hook-Einstellung, die neuer ist als das Modell: Welche Einstellung lässt einen fehlgeschlagenen Hook blockieren, welche Version hat sie eingeführt, und wie lautet das exakte JSON. Ohne Server las Claude das Settings-Schema seiner eigenen Installation, fand nichts und antwortete, es könne die Einstellung nicht finden und werde keine raten. Diese Antwort ist ehrlich und nutzlos, denn die Einstellung existiert; sie kam nur nach dem Wissensstand des Modells.
Die Lösung ist, den eigenen Docs-Server von Claude Code zum Repo hinzuzufügen, mit Projekt-Scope, sodass die Konfiguration in einer Datei im Repo-Root landet, die dein ganzes Team bekommt:
claude mcp add --transport http claude-docs --scope project https://code.claude.com/docs/mcp
Das schreibt .mcp.json. Claude Code listet den Server als ausstehend, bis du ihn in deiner nächsten Session freigibst, und von da an stehen seine Tools Claude zur Verfügung. Wir stellten dieselbe Frage in einfachen Worten, ohne den Server zu nennen. Claude durchsuchte die Docs, fand die Seite und antwortete mit der Einstellung, der Version und dem JSON zum Hinzufügen, samt Link.
Die Einstellung ist "onFailure": "block", die einen fehlschlagenden Hook die Aktion blockieren lässt, statt sie durchzulassen. Sie kam in v2.1.295, während unsere Installation noch auf 2.1.294 war. Das ist die Grenze: Claude sagte nie, dass unsere Installation sie nicht nutzen kann, weil es die Version nicht prüfte, also prüfst du deine Version selbst. In der Context-Tabelle erscheint der Server nur mit seinen Tool-Namen, bei Bedarf geladen, bis Claude nach einem greift.
Vier Dateien, eine Entscheidungskarte
Nach den vier Jobs zeigt git status genau vier Dateien, weil der Hook kein eigenes Skript braucht:
.claude/skills/release/SKILL.md.claude/settings.json.claude/agents/conventions-auditor.md.mcp.json
Committe sie, und die nächste Session in diesem Repo hat alle, ebenso jeder, der es klont.
Der Grund, warum jede Wahl richtig war, ist eine Tabelle, die die Docs mitliefern und die du als Entscheidungskarte behalten kannst:
| Situation | Extension |
|---|---|
| Eine Prozedur, die du schon wieder einfügst | Skill |
| Etwas, das jedes Mal passieren muss, ohne nachzufragen | Hook |
| Eine Nebenaufgabe, die deine Unterhaltung mit Ausgaben flutet, die du nicht noch einmal lesen wirst | Subagent |
| Daten, die du immer wieder von einem Ort kopierst, den Claude nicht sehen kann | MCP-Server |
Die Arten lassen sich auch kombinieren. Die Docs koppeln einen Skill mit einem MCP-Server: Der Server liefert die Verbindung, und der Skill bringt Claude bei, sie gut zu nutzen. Ein Skill kann auch in einem geforkten Subagent laufen, sodass sein Lesen aus deinem Fenster bleibt. Wenn ein anderes Repo dasselbe Setup braucht, ist ein Plugin die Kiste, die alle zusammen ausliefert.
Die Karte entscheidet die Art, nicht die Qualität. Ein Hook, der nur loggt, ein Subagent, den du nie nennst, und ein Server für Docs, die das Modell schon kennt, saßen jeweils in der richtigen Art und scheiterten trotzdem. Wähle die Art nach der Karte, und sorge dann dafür, dass die Datei antwortet, nicht nur existiert.
Fazit: wann welches, wann keins, die eine Regel
Alle vier Jobs, die du früher neu getippt hast, wurden zuerst auf die falsche Art versucht, scheiterten auf dem Bildschirm und sind jetzt Dateien im Repo, die funktionieren. Das Release ist ein Befehl, den du tippst. Die Datenregel ist ein Hook, der die Änderung ablehnt und Claude nachfragen lässt. Das Audit kommt als Zusammenfassung zurück. Die Docs-Frage bekommt die Einstellung und die Version, die Claude allein nicht finden konnte.
Der Hook, mit dem wir begonnen haben, der lief und den Schreibzugriff durchließ, hat die Regel unter all dem gelehrt: Ein Hook entscheidet nur durch das, was sein Befehl zurückgibt, also ist ein Hook, der nur loggt, eine Bitte im Kostüm.
Manche Fälle brauchen keines davon:
- Eine Konvention, die Claude immer wieder falsch macht, gehört weiterhin in die Memory-Datei, als eine Zeile, nicht als Prozedur.
- Ein Job, den du hin und her steuern musst, mit deinem Verlauf im Blick, bleibt im Haupt-Thread und nicht in einem Subagent.
- Ein Docs-Server für eine Bibliothek, die das Modell schon kennt, kostet Context und ändert nichts. Verbinde, was das Modell nicht haben kann, nicht das, was es schon hat.
Die Regel zum Merken: Gib jedem Job, den du neu tippst, seine eigene Datei, wähle die Art nach der Karte, und wisse, dass von ihnen nur der Hook nie nachfragt.
AIDive