CLAUDE.md best practices (met geannoteerd voorbeeld)

CLAUDE.md best practices (met geannoteerd voorbeeld)

CLAUDE.md is het duurste bestand in je repository. Niet in bytes. In herhaling. Alles wat je erin zet wordt aan het begin van elke sessie in Claudes context geladen en reist daarna mee met elk bericht dat je stuurt. Een opgeblazen CLAUDE.md is een belasting die je honderden keren per dag betaalt zonder het te merken.

Wij testen Claude-setups voor de kost bij SkillProof, en we hebben inmiddels meer CLAUDE.md-bestanden gelezen dan we willen toegeven. De meeste doen het op dezelfde manier fout: ze behandelen het bestand als stortplaats voor alles wat de auteur Claude ooit wilde vertellen. Codeerfilosofie, toonvoorkeuren, een complete stijlgids, drie alinea's over voorzichtig zijn. Alles geladen, altijd, voor elk verzoek, inclusief dat ene waarin je Claude vroeg een variabele te hernoemen.

Deze gids is onze poging dat recht te zetten. Waar CLAUDE.md echt voor is, een compleet geannoteerd voorbeeld dat je kunt overnemen, wat je verhuist naar skills, en het rekensommetje dat verklaart waarom dit alles ertoe doet.

Wat CLAUDE.md is en wanneer het laadt

CLAUDE.md is het projectgeheugenbestand van Claude Code. Start je een sessie in een directory, dan loopt Claude Code vanaf je werkdirectory omhoog op zoek naar CLAUDE.md-bestanden en laadt wat het vindt in de systeemcontext. Je globale bestand op ~/.claude/CLAUDE.md laadt ook, in elk project. Bestanden in submappen laden wanneer Claude met bestanden in die submappen werkt.

Het deel dat mensen missen: dit is geen eenmalige leesactie. Taalmodellen zijn stateless, dus de volledige context, inclusief je CLAUDE.md, gaat mee met elk verzoek in het gesprek. Stel veertig vragen in een sessie en het bestand wordt veertig keer verstuurd. Prompt caching verzacht de kosten in dollars, en we komen zo bij de echte cijfers, maar niets verzacht de aandachtskosten. Elke token in CLAUDE.md is een token die met je eigenlijke code concurreert om de focus van het model.

Dat is de prijs. Je krijgt er iets echts voor terug: Claude begint elke sessie met kennis van je buildcommando's, je architectuureigenaardigheden en de landmijnen in je codebase. Niemand hoeft voor de negende keer "we gebruiken pnpm, niet npm" te plakken. De vraag is nooit óf je een CLAUDE.md moet hebben. De vraag is wat een plek erin verdient.

De gouden regel: feiten in CLAUDE.md, gedrag in skills

Hier is de stelling van dit hele artikel, en het ene filter dat de meeste slechte bestanden fixt:

CLAUDE.md is voor feiten over dit project. Skills zijn voor herbruikbaar gedrag.

Een feit over dit project: "prijzen worden opgeslagen als integer centen." Dat kan Claude niet raden. Geen enkele hoeveelheid algemene intelligentie haalt het uit de lucht, en het fout hebben corrumpeert data. Het hoort in CLAUDE.md, permanent geladen, omdat het relevant is voor vrijwel elke wijziging die geld raakt.

Herbruikbaar gedrag: "check bij een codereview eerst error handling, dan security, dan naamgeving." Dat is geen feit over jouw project. Het is een procedure, die geldt voor elk project dat je ooit aanraakt, en die alleen relevant is wanneer je daadwerkelijk code reviewt. Zet het in CLAUDE.md en je betaalt ervoor tijdens elk commitbericht, elke CSS-tweak, elke "wat doet deze functie". Zet het in een skill en het kost je één regel metadata tot het moment dat er echt een review plaatsvindt, waarna de volledige instructies on demand laden.

De meeste mensen proppen alles in CLAUDE.md omdat het het bestand is dat ze kennen. Het staat er, het werkt aantoonbaar, en de kosten zijn onzichtbaar omdat geen factuur ooit zegt "je hebt deze maand 4.000 keer voor je stijlgids betaald." Maar de kosten zijn echt, en de splitsing wordt bijna mechanisch zodra je twee vragen stelt bij elke instructie. Geldt dit alleen voor dit project? Is het relevant voor de meeste verzoeken? Twee keer ja: CLAUDE.md. Al het andere: een skill, of de prullenbak.

Er is een tweede reden voor de splitsing die niets met tokens te maken heeft. Instructies in een altijd-geladen bestand concurreren met elkaar. We hebben een CLAUDE.md van 2.000 woorden gezien waarin de werkelijk belangrijke regel ("draai nooit db:push tegen staging") in alinea elf stond, onder een preek over clean code. Claude volgt lange instructielijsten zoals mensen dat doen: de scherpe punten verwateren door de vulling eromheen. Korte bestanden worden gehoorzaamd. Lange bestanden worden gescand.

Een geannoteerd CLAUDE.md-voorbeeld voor een middelgrote webapp

Hier een compleet voorbeeld voor een fictieve maar realistische Next.js-webshop. De annotaties leggen uit waarom elke sectie zijn permanente plek in de context verdient. Het komt neer op zo'n 350 woorden, ruwweg 500 tokens, en wij zouden zeggen dat er niets in te schrappen valt.

# Acme Storefront

Next.js 14 (App Router) + TypeScript. Postgres via Prisma. Deployed on Vercel.
<!-- One line of stack. Claude infers most of this from package.json anyway;
     this just saves it the lookup. Do not write paragraphs here. -->

## Commands
- `pnpm dev` — local server on :3000 (needs `docker compose up db` first)
- `pnpm test` — unit tests (Vitest). Integration: `pnpm test:int` (slow, needs db)
- `pnpm lint && pnpm typecheck` — run both before calling any task done
- Migrations go through `pnpm db:migrate`. NEVER `db:push` outside local.
<!-- Commands earn their place because Claude runs them dozens of times per
     session, and a wrong guess (npm vs pnpm) wastes a round-trip every time.
     The db:push line is here because the failure is irreversible. -->

## Architecture facts you can't guess
- `src/app` is routes only. All logic lives in `src/modules/<domain>`.
- API routes are thin wrappers over `src/modules/*/service.ts`. No logic in routes.
- Auth is Clerk, but `userId` in services is OUR internal id, not Clerk's.
  Map with `getInternalUser()`.
- Prices are integer cents everywhere. Formatting lives in `lib/money.ts`.
- Feature flags come from `flags.ts`, not env vars.
<!-- The test for this section: would a skilled new hire get it wrong on
     day one? The Clerk id mismatch has caused real bugs; that is exactly
     the kind of fact worth paying for on every request. -->

## Conventions that differ from defaults
- Named exports only. Legacy violations exist in `src/legacy`; don't add new ones.
- Server components by default. `"use client"` needs a comment saying why.
- Zod schemas live next to services; infer types from them, never hand-write both.
<!-- Only conventions that DIFFER from what Claude would do anyway.
     "Use TypeScript strict mode" when tsconfig already says so is a wasted line. -->

## Gotchas
- `src/legacy/*` is frozen. Don't refactor it or import from it in new code.
- CI runs Node 20. `pnpm test:int` fails on 22; use `nvm use` first.
<!-- Each line here represents an hour someone actually lost. -->

## Definition of done
Lint, typecheck, and unit tests pass, and you state which of them you ran.
<!-- One sentence. Not a philosophy of quality. -->

Let op wat er ontbreekt. Geen "schrijf schone, onderhoudbare code". Geen tooninstructies. Geen uitleg over wat Next.js is. Geen lintregels die de linter al mechanisch afdwingt. Elke regel is óf een commando dat Claude gaat uitvoeren, óf een feit dat het niet kan afleiden, óf een grens waarvan overschrijding echt geld of echte uren kost.

Wat je verhuist naar skills

Is je huidige CLAUDE.md 1.500 woorden, dan valt het overschot meestal in een paar herkenbare emmers, en elke emmer heeft een skillvormig thuis. Een paar voorbeelden uit onze eigen catalogus, allemaal geïnstalleerd en getest op schone machines voordat we ze opnamen:

Git-ceremonieel. Branchnaamgeving, commitberichtformaat, PR-beschrijvingstemplates, wanneer je squasht. Dit is gedrag, het is identiek in al je projecten, en het is alleen relevant wanneer je daadwerkelijk commit. De git-workflow-skill die we testten dekt precies deze scope, en hem uit CLAUDE.md halen bespaart doorgaans 200 tot 400 woorden altijd-geladen tekst.

Reviewchecklists. "Als ik om een review vraag, check dan X en daarna Y"-instructies zijn de klassieke kraker in CLAUDE.md. Ze zijn lang, procedureel en 95% van de tijd slapend. code-review-checklist laadt zijn checklist alleen wanneer er een review plaatsvindt, en dat is precies het punt van het skillformaat.

Debugdiscipline. Instructies als "reproduceer voordat je fixt, benoem je hypothese, verifieer achteraf" beschrijven een methodologie, niet jouw project. systematic-debugging verpakt die methodologie en blijft buiten de context zolang je met iets anders bezig bent dan een bug najagen.

De algemene regel: kun je de alinea zonder aanpassing in de CLAUDE.md van een ander project plakken, dan is het geen feit over jouw project en hoort hij er niet. Extraheer hem. Je eigen skill schrijven kost ongeveer twintig minuten met onze gids, en het zijn de twintig minuten met de hoogste hefboom voor iedereen wiens CLAUDE.md langer is dan één scherm.

GRATIS STARTERSPACK

We bundelden vijf geteste skills die de meest voorkomende CLAUDE.md-bloat absorberen: git-workflow, reviewchecklists, debugdiscipline en meer. Installeer ze en verwijder daarna de bijbehorende alinea's uit je bestand.

Download het gratis starterspack

Antipatronen die we blijven zien

We reviewen veel setups, en dezelfde vijf missers duiken telkens op.

De roman. Een CLAUDE.md van 3.000 woorden die leest als een engineeringhandboek. Iemand had een slechte ervaring, voegde een alinea toe, had er nog een, voegde weer een toe, en verwijderde nooit iets. Het bestand groeit alleen maar. Naast de tokenkosten begraven zulke bestanden de twee regels die er echt toe doen onder twintig die dat niet doen, en Claudes naleving van allemaal daalt tegelijk.

Verouderde commando's. Het bestand zegt npm run test:unit, het script is acht maanden geleden hernoemd naar pnpm test, en nu draait Claude vol vertrouwen een commando dat faalt, leest de fout, snuffelt in package.json en herstelt. Elke sessie. Je betaalt voor de verkeerde documentatie en betaalt daarna nog eens zodat Claude eromheen kan werken. Een foute CLAUDE.md is erger dan geen CLAUDE.md, want Claude vertrouwt hem.

Gedupliceerde lintregels. "Gebruik enkele aanhalingstekens. Geen ongebruikte variabelen. Maximale regellengte 100." Je ESLint-config dwingt dit al mechanisch af, met betere dekking dan de aandacht van een LLM ooit zal hebben. Machinaal afgedwongen regels in proza herhalen is pure verspilling. De ene uitzondering: regels die de tooling niet kan vangen, zoals "importeer niet uit src/legacy"; die moeten juist wél op papier.

De "wees behulpzaam"-sectie. "Schrijf schone code. Denk goed na voordat je iets wijzigt. Wees grondig maar beknopt." We zien een variant hiervan in misschien de helft van de bestanden die we reviewen, en het doet niets. Claude doet al zijn best. Instructies op gevoel zonder toetsbare inhoud zijn het eerste wat je schrapt, en hun enige meetbare effect is de tokens die ze verbranden.

Autobiografie. Lange beschrijvingen van wat het product doet, wie de gebruikers zijn, de bedrijfsmissie. Af en toe doet één productfeit ertoe voor codebeslissingen ("onze gebruikers zitten op trage plattelandsverbindingen, bundlegrootte is een echte beperking"). Houd die ene zin. Schrap het pitchdeck.

De tokenberekening

Laten we het sommetje maken dat mensen overslaan, want de cijfers zijn wat ons tot minimalisten maakte.

Een CLAUDE.md van 3.000 woorden is ruwweg 4.000 tokens. Hij reist mee met elk verzoek, dus een werksessie van 40 berichten verstuurt hem 40 keer: 160.000 tokens input in één sessie die je geheugenbestand zijn, niet je code of je gesprek. Werk vijf sessies per dag en je verplaatst dagelijks 800.000 CLAUDE.md-tokens. Over een maand van 22 werkdagen: zo'n 17,6 miljoen.

Prompt caching redt het grootste deel van de dollarkosten, en daar moeten we eerlijk over zijn. Gecachete input op Sonnet kost een tiende van de basisprijs, dus die 17,6M tokens kosten een paar dollar per maand als de cache warm blijft, eerder $50 als dat niet zo is. Vervelend, niet ruïneus.

De kosten die caching níét redt, zijn context. Het contextvenster van Claude Code is eindig, en lange sessies eindigen nu al in compaction, waarbij het gesprek wordt samengevat en detail verloren gaat. Een permanente bewoner van 4.000 tokens betekent dat je eerder tegen compaction aanloopt, elke sessie, voor altijd. Het tast bovendien de aandacht aan voordat je enige harde limiet raakt: modellen volgen instructies aantoonbaar beter naarmate er minder van concurreren. Het verschil tussen een bestand van 500 tokens en een van 4.000 tokens is niet 3.500 tokens. Het is of het model bij bericht 35 nog steeds geeft om je regel "raak staging nooit aan".

Draai dezelfde berekening voor het uitgeklede voorbeeld hierboven: 500 tokens, 40 berichten, vijf sessies, 22 dagen. Ongeveer 2,2M tokens per maand, een achtste van de opgeblazen versie, met de belangrijke regels in een lege kamer. Het bredere kostenbesparingsdraaiboek staat in onze gids over tokenkosten, en CLAUDE.md afslanken is daarin steevast de goedkoopste winst.

Project vs. globaal: de ~/.claude/CLAUDE.md-splitsing

Je hebt twee bestanden, en het gaat mis wanneer inhoud in het verkeerde belandt.

~/.claude/CLAUDE.md is globaal. Het laadt in elk project, dus er mag alleen in staan wat overal waar is: "ik gebruik pnpm in al mijn persoonlijke projecten", "antwoord in het Engels, ook al zijn mijn prompts soms Russisch", "commit nooit zonder dat erom gevraagd is". Houd het onder de tien regels. Elke regel hier wordt vermenigvuldigd over al je werk, dus dit budget hoort het strakst te zijn.

<project>/CLAUDE.md is het projectbestand, ingecheckt in git, gedeeld met teamgenoten en CI. Feiten over deze codebase, in de vorm van het voorbeeld hierboven. Omdat het gedeeld is, horen persoonlijke voorkeuren er niet in; daar zijn CLAUDE.local.md of het globale bestand voor.

CLAUDE.md-bestanden in submappen zijn de onderbenutte middenlaag. Een packages/api/CLAUDE.md met API-specifieke feiten laadt alleen wanneer Claude dat package aanraakt. Heeft het rootbestand van je monorepo secties die maar voor één workspace gelden, dan is ze een niveau naar beneden duwen gratis tokenwinst zonder informatieverlies.

Eén misvatting die de wereld uit moet: iets in meer dan één van deze bestanden zetten laat Claude het niet harder volgen. Het maakt het bestand langer. Kies één thuis per feit.

Vers houden

CLAUDE.md rot sneller dan gewone documentatie, omdat er niets zichtbaar breekt als hij fout is. Tests falen luidkeels. Een verouderd geheugenbestand stuurt het model stilletjes de verkeerde kant op, dat stilletjes herstelt, en jij betaalt stilletjes voor allebei.

Ons ritueel is saai en kost tien minuten per maand. Open het bestand. Draai elk commando echt. Vraag je bij elk genoemd feit af of het nog waar is en of Claude deze maand ergens de fout in ging vanwege dit bestand. Verwijder minstens één regel; er is altijd een regel, en vind je hem niet, dan zijn je normen voor "een plek verdienen" verslapt. Check daarna de lengte: één scherm is het doel, twee schermen het plafond, en daarboven ben je niet meer aan het redigeren maar aan het extraheren naar skills.

De beste trigger voor updates is trouwens niet de kalender. Het is het moment dat Claude iets fout doet omdat het bestand hem misleidde. Fix het bestand in dezelfde adem als de code. Behandel CLAUDE.md-bugs als bugs, want ze hebben hetzelfde terugkeergedrag: onopgelost gebeuren ze volgende sessie opnieuw.

SKILLPROOF-PACK

Het Optimizer Pack is onze geteste bundel voor precies dit probleem: skills die je contextverbruik auditen, je setup afslanken en je sessies snel houden. Elke skill erin doorstond onze tests op een schone machine, en het pack verdient zichzelf terug in de eerste maand bespaarde tokens.

Koop het Optimizer Pack — $10

FAQ

Hoe lang mag een CLAUDE.md zijn?

Onder de 500 woorden voor de meeste projecten, onder de 1.000 voor een echt ingewikkelde monorepo. Onze werktest: past het niet op één scherm, dan zit er iets in dat gedrag is vermomd als feit, en dat iets hoort in een skill. Het voorbeeld in dit artikel is zo'n 350 woorden en dekt een echte middelgrote app.

Wat is het verschil tussen CLAUDE.md en een skill?

Laadgedrag. CLAUDE.md wordt volledig geladen, altijd, voor elk verzoek. Een skill toont alleen een beschrijving van één regel totdat een taak matcht, en laadt dan on demand. CLAUDE.md moet dus feiten bevatten die je constant nodig hebt, en skills de procedures die je af en toe nodig hebt. Onze skillsgids behandelt de mechaniek.

Moet ik CLAUDE.md in git committen?

Ja. Het is gedeelde documentatie, en de Claude-sessies van je teamgenoten profiteren van dezelfde feiten als de jouwe. Houd persoonlijke voorkeuren in CLAUDE.local.md (in .gitignore) of in je globale bestand in plaats van ze aan het team op te dringen.

Kan ik geneste CLAUDE.md-bestanden in submappen gebruiken?

Ja, en in monorepo's moet je dat ook doen. Claude Code laadt het bestand van een submap wanneer het met bestanden daar werkt. Het rootbestand krijgt repo-brede feiten, packages/api/CLAUDE.md krijgt API-feiten, en projecten met één package kunnen nesting helemaal overslaan.

Verandert CLAUDE.md afslanken echt Claudes gedrag, of alleen de kosten?

Allebei, en gedrag is de grotere winst. Instructienaleving verslechtert naarmate het aantal instructies groeit; een kort bestand met vijf scherpe regels wordt betrouwbaarder gevolgd dan een lang bestand met dertig. De tokenbesparing is het meetbare deel, en onze efficiency-ranglijst houdt bij welke skills daar het meest helpen, maar de verbeterde naleving is wat je het eerst merkt.

Nog één mening tot slot: de beste CLAUDE.md-bestanden die we zagen, zijn allemaal geredigeerd door te schrappen. Niemand schrijft op dag één een geweldige. Je schrijft een middelmatige, kijkt waar Claude struikelt, voegt het feit toe dat dat had voorkomen, en schrapt een regel vulling om ervoor te betalen. Zes weken daarvan verslaat elke template, ook de onze.

★ 9.6/10 × 3

Het gratis starterspakket

De 3 skills met onze hoogste testscores plus de installatiechecklist — de setup die wij op een verse machine zouden zetten. Gratis, per e-mail.

Eén e-mail met het pakket + een korte wekelijkse digest met nieuwe testresultaten. Uitschrijven kan altijd.