27 Regel-Dateien statt einer CLAUDE.md — was sich dadurch geändert hat

Es gibt einen Moment, in dem eine CLAUDE.md kippt. Dieser Moment steht in keinem Kalender, er zeigt sich im Verhalten: Die Datei wird immer länger, und die Regeln darin werden immer schlechter befolgt. Jede neue Konvention, die man hineinschreibt, verdünnt die vorhandenen. Genau an diesem Punkt stand das Projekt hinter diesem Artikel — und die Antwort war nicht eine bessere CLAUDE.md, sondern ihre Auflösung in einzelne Regel-Dateien. Heute sind es 27.

Dieser Artikel ist der Erfahrungsbericht dazu: Wie Claude Code Regeln strukturiert sein müssen, damit sie über Monate halten, was eine einzelne Regel-Datei tragen muss und warum die wichtigsten Bestandteile nicht die Regeln selbst sind. Es sind die Don’ts und die Inventuren.

Das Wichtigste vorab:

  • Eine Datei pro Konvention — 27 Regel-Dateien statt einer CLAUDE.md, jede mit einem Thema.
  • Anatomie einer Regel, die hält: Regel, Begründung, Don’ts, Inventur, Cross-References.
  • Don’ts schlagen Vorschriften — zumindest im DI²-Projekt: Ein Negativbeispiel ist konkret und wiedererkennbar, eine Vorschrift konkurriert gegen das Trainings-Prior.
  • Inventuren sind das Drift-Radar: der Teil einer Regel, der einen Ist-Zustand des Codes behauptet — und deshalb als Erster auffällt, wenn Code und Doku auseinanderlaufen.
  • paths:-Scoping lässt große Regeln nur dort laden, wo sie gelten — 3 der 27 Dateien nutzen es.
  • Die ehrliche Kehrseite: Pflegeaufwand, Regel-Konflikte und ein Zustand, in dem die Doku dem Code bewusst voraus ist.

Voraussetzung. Ein Projekt mit Claude Code und einem .claude/rules/-Verzeichnis. Das Muster überträgt sich auf jeden Coding-Agenten, der Konventions-Dateien in seinen Kontext lädt — die Rules von Cursor oder vergleichbare Mechanismen anderer Tools funktionieren nach demselben Prinzip. Was wann in den Kontext lädt und was das kostet, erklärt der Schwester-Artikel Skills vs. Rules in Claude Code — dieser Artikel hier setzt eine Ebene früher an: bei der Frage, wie die Regel-Dateien selbst aussehen müssen.

Inhalt

Die Ausgangslage: eine Datei, die immer länger wurde

Das Projekt hinter den Zahlen ist DI², ein ETL-Generator auf Next.js und PostgreSQL, dessen Code fast vollständig KI-gestützt mit Claude Code entstanden ist. Am Anfang lebten alle Konventionen dort, wo sie jedes Claude-Code-Projekt zuerst sammelt: in der CLAUDE.md. Das funktioniert, solange die Datei kurz ist. Es hört auf zu funktionieren, wenn sie zu einem Sammelcontainer wird, in dem Datenbank-Konventionen, Farb-Tokens und Commit-Regeln nebeneinander stehen.

Dieser Effekt lässt sich nur schwer messen, aber er ist deutlich zu spüren. Er passt zu dem, was die Forschung über lange Kontexte zeigt: Informationen in der Mitte langer Eingaben werden von Sprachmodellen messbar schlechter genutzt („Lost in the Middle“, Liu et al. 2023). Eine Regel, die in Zeile 40 einer langen Datei steht, wird erfahrungsgemäß seltener befolgt als dieselbe Regel in einer eigenen, thematisch benannten Datei. Dazu kommt ein zweiter Effekt, der weniger mit dem Modell zu tun hat als mit den Menschen: In einer 400-Zeilen-Datei findet auch der Autor selbst eine Regel nicht wieder, wenn er prüfen will, ob sie noch stimmt. Warum eine einzelne Datei strukturell nicht skaliert und welche Lade-Mechanik dahintersteht, gehört in den Skills-vs.-Rules-Artikel — hier geht es um das, was danach kommt.

Die Konsequenz im Projekt: ein .claude/rules/-Verzeichnis mit 27 Regel-Dateien, eine pro Konvention (Stand: 22. Juli 2026). Dieselbe Zählung gilt für die öffentliche Ausgabe dieser Regel-Struktur, das di2-starter-kit auf GitHub — dort lässt sie sich nachprüfen, die READMEs der Unterordner nicht mitgerechnet. Es gibt eine Datei für die Tabellen-Konventionen, eine für Dialoge, eine für Ladezustände, eine für das Sicherheits-Modell. Das Verzeichnis wächst mit dem Projekt weiter. Allein in der Woche, in der dieser Artikel entstand, kamen drei neue Dateien dazu, für Views, Trigger und Datenbank-Policies. Ein Regel-System ist fertig, wenn das Projekt fertig ist, also nie.

Anatomie einer Regel, die hält

Nach mehreren Monaten mit diesem System hat sich eine feste Struktur herausgebildet. Eine Regel-Datei, die hält, besteht aus fünf Teilen:

  1: # <Konvention> (<Projekt>)
  2:
  3: > Ein Satz Zusammenfassung: Was erzwingt diese Regel, und wo gilt sie?
  4:
  5: ## Die Regel
  6:
  7: Jede <Struktur/Komponente/Prozedur> <tut genau eines, imperativ formuliert>.
  8: Eine Konvention pro Datei — nicht mehrere Themen mischen.
  9:
 10: ## Begründung
 11:
 12: Warum es diese Regel gibt: der konkrete Vorfall, Bug oder Review-Befund,
 13: der sie ausgelöst hat. Eine Regel ohne Grund wird bei Zielkonflikten
 14: weggewogen — der Grund ist Teil der Regel, nicht Zierde.
 15:
 16: ## Don'ts
 17:
 18: - ❌ `<konkretes Negativbeispiel aus dem eigenen Code>` — warum es driftet.
 19: - ❌ `<zweites Negativbeispiel>` — was stattdessen gilt (mit Ziel-Schreibweise).
 20:
 21: ## Inventur
 22:
 23: | Verwendungsstelle | Datei | Stand |
 24: |---|---|---|
 25: | <Stelle A> | `components/stelle-a.tsx` | ✅ konform |
 26: | <Stelle B> | `components/stelle-b.tsx` | ⏳ Retrofit offen |
 27:
 28: ## Cross-References
 29:
 30: - [nachbar-regel.md](nachbar-regel.md) — Abgrenzung: was dort geregelt ist, nicht hier.

Die Regel selbst (Zeilen 5 bis 8) ist der kleinste Teil, und das ist kein Zufall. Sie formuliert imperativ, was gilt, in zwei bis drei Sätzen. Alles darüber hinaus gehört in die anderen vier Teile.

Die Begründung (Zeilen 10 bis 14) ist keine Höflichkeit gegenüber dem Leser. Ein Agent wägt bei Zielkonflikten ab, und nach der Beobachtung im DI²-Projekt verliert eine Regel ohne Grund diese Abwägung leichter gegen ein plausibles Gegenargument aus dem konkreten Fall. Eine Regel mit Grund verankert, wogegen der konkrete Fall antreten muss. Der Unterschied zeigt sich genau in den Momenten, in denen es darauf ankommt: dann nämlich, wenn das Modell eine Ausnahme für gerechtfertigt hält. Wie eine Konvention samt Begründung überhaupt entsteht, beschreibt der Methodik-Artikel SQL-Konventionen mit Claude Code ableiten.

Die verbleibenden drei Teile sind die eigentliche Substanz dieses Artikels. Die Don’ts und die Inventur bekommen deshalb je eine eigene Sektion, die Cross-References erklären sich fast von selbst: Sie ziehen die Grenze zur Nachbar-Regel, damit zwei Dateien nicht schleichend dasselbe Thema regeln. Jede Grenz-Verletzung, die später auffällt, wird dort als expliziter Verweis nachgetragen.

Warum Don’ts stärker wirken als Vorschriften

Das ist die zentrale Beobachtung aus mehreren Monaten Regel-Pflege im DI²-Projekt. Ob sie sich auf andere Projekte übertragen lässt, ist nicht untersucht — sie ist Projekt-Erfahrung, keine Studie. Eine Vorschrift sagt, was sein soll. Ein Negativbeispiel zeigt, was nicht sein darf — mit einer konkreten, wiedererkennbaren Schreibweise. Der Unterschied wirkt auf den ersten Blick klein. In der Praxis ist er es nicht:

  1: <!-- Vorher: Vorschrift ohne Anker -->
  2:
  3: Verwende für Schriftgrößen ausschließlich die Projekt-Tokens.
  4:
  5: <!-- Nachher: Negativbeispiele mit Wiedererkennungswert -->
  6:
  7: **Don'ts:**
  8:
  9: - ❌ `text-[12px]` — roher Pixel-Wert, driftet; Snap-Ziel ist `text-token-meta`.
 10: - ❌ `text-sm` — Framework-Default statt Projekt-Skala; im App-Bereich
 11:   flaggt der Linter-Guard das als Error.
 12: - ❌ Inline-`line-height`-Override via `[line-height:Xpx]` — die Skala bringt
 13:   ihre Zeilenhöhe mit; ein bewusster Override braucht einen Code-Kommentar
 14:   mit Begründung.

Die Vorschrift in Zeile 3 ist inhaltlich richtig, und trotzdem bewirkt sie wenig. Sie konkurriert bei jeder Generierung gegen das Trainings-Prior des Modells, und in dem ist text-sm die statistisch häufigste Art, kleinen Text zu schreiben. „Ausschließlich Projekt-Tokens“ muss das Modell erst auf den konkreten Fall übersetzen, und in dieser Übersetzung geht die Regel verloren.

Das Negativbeispiel überspringt die Übersetzung. text-[12px] ist genau die Zeichenkette, die das Modell gleich schreiben würde — sie steht wörtlich in der Regel, markiert mit einem ❌ und dem Grund. Ein Don’t lässt keinen Spielraum für Interpretation. Es benennt zusätzlich das Snap-Ziel, also die Schreibweise, die stattdessen gilt. Wer das Don’t liest, ob Mensch oder Modell, weiß danach beide Dinge: was falsch ist und was an diese Stelle gehört. Dahinter steckt kein Geheimnis der Don’ts, sondern ein bekannter Effekt aus der Prompt-Forschung: Konkrete Beispiele sind für Sprachmodelle leichter umzusetzen als abstrakte Vorschriften. Negativbeispiele sind schlicht die Form, in der eine Regel-Datei diesen Effekt nutzen kann.

Die besten Don’ts stammen dabei nicht aus der Vorstellungskraft des Regel-Autors, sondern aus echten Funden. Jedes Mal, wenn ein Review oder ein Bug eine neue Umgehungs-Variante zutage fördert, wandert genau diese Variante als Don’t in die Regel-Datei. Das Regel-System lernt damit dieselben Fehler, die der Code schon einmal gemacht hat. An Material dafür herrschte kein Mangel: Der Schwester-Artikel 799 hartkodierte Schriftgrößen dokumentiert den Drift-Befund, aus dem die Schriftgrößen-Don’ts entstanden sind.

Inventuren als Drift-Radar

Eine Regel formuliert einen Soll-Zustand, und Soll-Zustände haben eine unangenehme Eigenschaft: Sie können nicht falsch werden. „Jeder Dialog trägt ein führendes Icon“ bleibt als Satz korrekt, auch wenn längst sechs Dialoge ohne Icon im Code stehen. Die Regel merkt davon nichts.

Eine Inventur ändert das. Sie listet die konkreten Verwendungsstellen der Konvention mit ihrem Ist-Zustand:

  1: ## Inventur + Retrofit-Backlog
  2:
  3: Diese Regel ist ab sofort die dokumentierte Wahrheit. Bestands-Stellen ohne
  4: <Konvention> werden als getrackter Folge-Schritt nachgezogen (Retrofit) —
  5: bis dahin hinkt der Code der Doku bewusst hinterher.
  6:
  7: | Dialog | Datei | Stand |
  8: |---|---|---|
  9: | Editor (Fachobjekt A) | `components/objekt-a-editor-dialog.tsx` | ✅ Icon führt links |
 10: | Inspektor (Fachobjekt B) | `components/objekt-b-inspector.tsx` | ✅ Icon führt links |
 11: | Nutzer einladen | `components/user-invite-dialog.tsx` | ⏳ Retrofit offen |
 12: | Bulk-Löschen | `components/bulk-delete-dialogs.tsx` | ⏳ Retrofit offen (Destructive-Tone) |

Die Tabelle ist der Teil einer Regel-Datei, der am Ist-Zustand des Codes scheitern kann. Auch eine Begründung oder ein Cross-Reference kann veralten, aber nur die Inventur behauptet überprüfbar, wie der Code gerade aussieht. Kommt ein neuer Dialog dazu und fehlt in der Tabelle, ist die Inventur unvollständig. Wird ein gelisteter Dialog umgebaut und der Stand nicht nachgezogen, ist sie veraltet. Genau diese Verwundbarkeit macht ihren Wert aus: Eine Regel ohne Inventur kann jahrelang unbemerkt am Code vorbei-existieren, während der Rückstand einer Regel mit Inventur spätestens beim nächsten Abgleich sichtbar wird.

Im Projekt führen 9 der 27 Regel-Dateien solche Abschnitte. Sie kommen in zwei Ausprägungen vor. Die Caller-Inventur listet, wer eine Komponente oder Konvention verwendet — sie beantwortet die Frage „wenn ich das ändere, was ist betroffen?“, bevor jemand suchen muss. Der Retrofit-Backlog listet, welche Bestands-Stellen die Konvention noch nicht erfüllen. Beide Formen teilen die Mechanik, unterscheiden sich aber in der Blickrichtung: Die eine schaut auf die Nutzer der Regel, die andere auf ihre offenen Schulden.

Gepflegt wird die Inventur nicht in einem separaten Doku-Termin, sondern im selben Commit wie die Code-Änderung. Wer einen Dialog anlegt, trägt ihn in die Tabelle ein. Wer einen Retrofit erledigt, setzt den Stand auf ✅. Das klingt nach einem hohen Anspruch an die Disziplin. Im Agent-Workflow ist es aber der günstigste Zeitpunkt, denn der Agent hat die Regel-Datei meist ohnehin im Kontext, wenn er im Geltungsbereich arbeitet.

Regeln, die nur laden, wo sie gelten

Mit wachsender Datei-Zahl stellt sich die Kontextkosten-Frage neu. 27 Dateien, die alle immer laden, wären nur eine zerteilte CLAUDE.md mit denselben Kosten. Der Hebel dagegen ist ein paths:-Frontmatter, das eine Regel an ihren Pfad-Scope bindet:

  1: ---
  2: paths:
  3:   - "src/app/api/**"
  4:   - "src/lib/db*"
  5: ---
  6:
  7: # Backend-Konventionen
  8:
  9: Diese Regel lädt nur, wenn die Aufgabe Dateien in ihrem Pfad-Scope berührt —
 10: API-Routen und die Datenbank-Zugriffsschicht. Ein Frontend-Task bezahlt
 11: ihre Kontextkosten nicht.
 

Im Projekt tragen 3 der 27 Dateien dieses Frontmatter: die Backend-Regeln, die Frontend-Regeln und das Sicherheits-Modell. Die Auswahl folgt einem einfachen Kriterium. Diese drei Dateien sind groß, und ihr Geltungsbereich ist ein klar abgegrenzter Teilbaum des Projekts. Eine Backend-Regel in einem reinen Frontend-Task ist toter Kontext. Die übrigen 24 Dateien laden ungescoped, weil sie entweder klein sind oder quer durch das Projekt gelten, wie die Commit-Konventionen.

Tiefer steigt dieser Artikel an dieser Stelle bewusst nicht ein. Die Mechanik dahinter — was Claude Code wann in den Kontext lädt, was Rules von Skills unterscheidet und wie sich die Kosten summieren — ist das Thema von Skills vs. Rules in Claude Code. Für die Struktur-Frage dieses Artikels reicht der Befund: paths:-Scoping ist der wichtigste Grund, warum 27 Dateien nicht 27-fache Kosten bedeuten.

Die ehrliche Kehrseite

Ein Regel-System dieser Größe ist nicht gratis, und ein Erfahrungsbericht, der das verschweigt, wäre Werbung.

Die Pflege ist echte Arbeit. Jede Regel-Datei will bei jeder Konventions-Änderung angefasst werden, Inventuren wollen im selben Commit nachgezogen werden, und die Cross-References zwischen den Dateien veralten, wenn eine Regel umzieht. Der Aufwand ist kein Einmal-Investment, sondern ein laufender Posten. Er ist im Projekt die Sorte Arbeit, die sich lohnt, aber er verschwindet nicht dadurch, dass man ihn gut findet.

Regeln geraten in Konflikt. Bei 27 Dateien passiert es, dass zwei Regeln denselben Fall aus verschiedenen Blickwinkeln regeln — die Dialog-Regel will ein Icon, die Bestätigungs-Dialog-Regel verbietet es für ihren Spezialfall. Die Lösung ist jedes Mal dieselbe: Der Konflikt wird als expliziter Carve-out in beide Dateien geschrieben, mit Verweis aufeinander. Unentschiedene Konflikte sind das Schlimmste, was einem Regel-System passieren kann, denn dann bleibt die Priorisierung uneindeutig — welche Regel sich durchsetzt, hängt vom jeweiligen Kontext und der Aufgabenstellung ab.

Die Doku läuft dem Code voraus — bewusst. Wenn eine neue Konvention beschlossen wird, gilt sie ab sofort für neuen Code. Die Bestands-Stellen werden nicht in derselben Stunde umgebaut, sondern als Retrofit-Backlog in der Inventur getrackt und schrittweise nachgezogen. Dieser Zustand ist kein Versagen, solange er dokumentiert ist. Die Regel-Datei sagt ehrlich: Das hier ist die Wahrheit, der Code hinkt an diesen gelisteten Stellen bewusst hinterher. Ungetrackt wäre derselbe Zustand eine Lüge, denn dann behauptet die Doku einen Ist-Zustand, den es nicht gibt.

Wann eine Regel einen Linter braucht

Prosa hat eine Grenze, und sie ist im Schwester-Artikel 799 hartkodierte Schriftgrößen ausführlich vermessen: Eine dokumentierte Regel erhöht die Trefferquote der Generierung, garantiert sie aber nicht. Bei hohem Volumen wird jede Restquote zu sichtbarem Drift.

Daraus folgt eine Arbeitsteilung, die sich im Projekt bewährt hat. Was maschinell prüfbar ist, bekommt zusätzlich zur Regel einen Guard — im Schriftgrößen-Fall eine ESLint-Rule auf Error-Level, die genau die Schreibweisen aus den Don’ts flaggt. Die Regel-Datei bleibt trotzdem die Quelle: Sie erklärt das Warum, definiert das Mapping und listet die bewussten Ausnahmen, der Linter erzwingt nur die prüfbare Teilmenge.

Was nicht maschinell prüfbar ist, bleibt reine Prosa-Regel und braucht dafür die Inventur als Ersatz-Radar. Ob ein Dialog-Icon fachlich das richtige ist, kann kein Linter entscheiden. Ob alle Dialoge eines haben, steht in der Inventur-Tabelle. Die Faustregel aus dem Projekt: Eine Regel, deren Verletzung sich als Suchmuster ausdrücken lässt, ist ein Linter-Kandidat. Eine Regel, deren Verletzung ein Mensch erkennen muss, braucht eine Inventur.

Was ich heute anders machen würde

Drei Punkte würde ich rückblickend anders angehen, und alle drei lassen sich konkret benennen.

Zu früh zu viele Dateien. Die ersten Wochen produzierten Regel-Dateien für Themen, die noch gar keine zweite Verwendungsstelle hatten. Eine Konvention für einen Einzelfall ist keine Konvention, sondern eine Notiz. Heute entsteht eine neue Regel-Datei erst, wenn dieselbe Entscheidung zum zweiten Mal ansteht. Und das Aufräumen gehört dazu: Eine Regel, deren Geltungsbereich verschwunden ist oder deren Inhalt inzwischen eine Nachbar-Regel trägt, wird gelöscht oder dorthin verschmolzen. Ein Regelwerk, das nur wächst, wird selbst zu der unübersichtlichen Datei, die es ablösen sollte.

Regeln ohne Inventur, die still veralteten. Die frühen Dateien bestanden aus Regel und Begründung, ohne Bestands-Teil. Einige davon beschrieben nach zwei Monaten einen Stand, den der Code längst verlassen hatte, und niemand hatte es gemerkt. Erst die Inventur-Abschnitte machten das Veralten sichtbar. Rückblickend hätte jede Regel mit Verwendungsstellen von Anfang an eine führen sollen.

paths: zu spät entdeckt. Das Scoping kam erst, als die Kontextkosten schon spürbar waren, und der Umbau bestehender Dateien auf saubere Pfad-Scopes war mühsamer als es ein früher Zuschnitt gewesen wäre. Wer heute anfängt, sollte bei jeder neuen Regel-Datei einmal kurz fragen: Gilt das überall oder in einem Teilbaum? Diese Frage zu beantworten kostet beim Anlegen zehn Sekunden. Sie nicht zu stellen kostet später einen Refactor.

FAQ

Wann sollte ich meine CLAUDE.md aufteilen?

Spätestens dann, wenn beim Hineinschreiben einer neuen Konvention die Frage auftaucht, wohin sie eigentlich gehört. Das ist das Signal, dass die Datei mehrere Themen trägt. Ein zweites Signal ist wiederholtes Ignorieren einer Regel, die nachweislich in der Datei steht — die Regel ertrinkt dann in ihrem Umfeld.

Wie viele Regel-Dateien sind zu viele?

Die Zahl selbst ist nicht das Limit, die Kontextkosten sind es. 27 Dateien funktionieren, weil die großen pfad-gebunden laden und die ungescopeten klein sind. Wie sich diese Kosten zusammensetzen und wo die Grenze verläuft, behandelt Skills vs. Rules in Claude Code.

Warum wirken Negativbeispiele besser als Vorschriften?

Weil sie die Übersetzungs-Lücke schließen. Eine Vorschrift muss das Modell erst auf den konkreten Fall anwenden, ein Don’t enthält die falsche Schreibweise bereits wörtlich — genau die Zeichenkette, die das Trainings-Prior vorschlagen würde, markiert mit dem Grund und der Ziel-Schreibweise. Wiedererkennen ist zuverlässiger als Ableiten.

Was mache ich, wenn zwei Regeln sich widersprechen?

Den Konflikt in beide Dateien schreiben, als expliziten Carve-out mit Verweis aufeinander. Welche Regel im Überschneidungsfall gewinnt, muss in den Dateien stehen, nicht im Kopf des Autors. Ein unentschiedener Konflikt wird sonst vom Zufall entschieden, je nachdem, welche Regel gerade prominenter im Kontext steht.

Muss der Code immer der Doku entsprechen?

Nein — und das ist die vielleicht kontraintuitivste Lektion. Eine neue Konvention gilt ab sofort für neuen Code, der Bestand wird als getrackter Retrofit-Backlog schrittweise nachgezogen. Entscheidend ist das Tracking: Ein dokumentierter Rückstand ist eine bewusste Entscheidung, ein undokumentierter ist eine Doku, die lügt.

Verwandte Artikel

Weiterführend:

Vorgelagert:

Starter-Kit: