Claude Code in monorepos kan wegdrijven wanneer de repo groot is. Leer grenzen, lokale samenvattingen en herhaalbare workflows om antwoorden precies te houden.

Claude Code in monorepos kan onvoorspelbaar aanvoelen om een eenvoudige reden: de repo is groter dan wat het model tegelijk in het werkgeheugen kan houden.
"Context" is de set bestanden, codefragmenten, aantekeningen en instructies die Claude voor deze taak te zien heeft, plus wat het daaruit kan afleiden. Als cruciale details ontbreken, vult Claude de gaten met aannames. In een grote repo gebeurt dat vaker.
Drie faalmodi komen steeds terug:
Ten eerste: gemiste bestanden. Een wijziging die in één map veilig lijkt, hangt soms af van een gedeeld type, een configregel of een buildstap die ergens anders staat. Als die afhankelijkheid niet in de context zit, kan Claude vol vertrouwen het verkeerde bestand aanpassen of vroegtijdig stoppen omdat het de echte bron van waarheid niet ziet.
Ten tweede: valse gelijkenis. Monorepos bevatten vaak meerdere pakketten die op elkaar lijken: twee auth-modules, drie API-clients, of meerdere React-apps met vergelijkbare mappenstructuren. Claude kan patronen mengen tussen deze, een helper in het verkeerde pakket updaten, of importeren uit de “bijna juiste” modulenaam.
Ten derde: tijdsdrift. Grote codebases hebben meestal oude en nieuwe manieren om hetzelfde te doen. Als Claude alleen oudere bestanden ziet, kan hij verouderde patronen kopiëren (deprecated configopties, legacy-API's) terwijl het team al verder is gegaan.
Een veelvoorkomend reëel voorbeeld: je vraagt om een kleine verandering in een billing-UI, en Claude past een gedeelde payments-component aan die door andere apps wordt gebruikt, omdat hij nooit de app-specifieke wrapper zag die aangepast had moeten worden.
Het doel is niet om Claude de hele monorepo te laten zien. Het doel is om kleinere, doelbewuste inputs te geven die toch het antwoord bevatten: het pakket dat je verandert, de directe afhankelijkheden en één of twee "sources of truth" voor types en config. Geef ook aan wat "niet aanraken" is (andere apps, infra, gegenereerde code) en bevestig welk pakket eigenaar is van het gedrag.
Nauwkeurigheid hangt minder af van hoeveel code je plakt en meer van hoe duidelijk je de klus beschrijft.
Begin met het gewenste resultaat: een specifieke fix, refactor of antwoord. Een "vraag over de code" kan hoog niveau blijven. Een "maak een wijziging" verzoek heeft grenzen, inputs en succescontroles nodig.
Schrijf voordat je iets deelt één zin die deze frase afmaakt: “Als je klaar bent, moet ik in staat zijn om…”. Bijvoorbeeld: “de unit tests voor package X draaien zonder failures” of “het nieuwe veld in de API-respons voor endpoint Y zien.” Die zin wordt het noordster wanneer de repo omvangrijk is.
Voor wijzigingen: deel de kleinst mogelijke set artefacten die kunnen bewijzen dat de wijziging correct is: de entry point(s), de relevante types/interfaces of schema, één falende test of een repro-stap met het verwachte resultaat, en alle config die dit pad beïnvloedt (routing, feature flags, build of lint regels). Als het helpt, voeg een korte foldermap van het pakket toe zodat Claude begrijpt wat elke directory doet.
Wees expliciet over wat je niet wilt dat hij bekijkt. Zeg: “Ignore generated files, vendor folders, build outputs, snapshots, and lockfiles unless I ask.” Dat voorkomt tijdverspilling en edits op plekken die je niet gaat reviewen.
Stel ook verwachtingen bij onzekerheid. Vraag Claude aannames en onbekenden te markeren in plaats van te gissen. Bijvoorbeeld: “Als je niet kunt zien waar deze functie wordt aangeroepen, zeg het en stel 2 manieren voor om die te vinden.”
In een grote monorepo daalt de nauwkeurigheid wanneer het model "behulpzaam" begint code erbij te trekken die geen deel uitmaakt van de taak. De oplossing is simpel: definieer wat binnen scope is en wat erbuiten valt voordat je om wijzigingen vraagt.
Begin met een grens die overeenkomt met hoe je repo is georganiseerd: een package, een service, een app of een gedeelde library. Als de wijziging bijvoorbeeld “update checkout UI” is, is de boundary waarschijnlijk één app-package, niet elke plek waar het woord "checkout" voorkomt.
Signalen die Claude helpen op zijn plek te blijven zijn folderconventies (apps/, services/, packages/, libs/), package manifests (exports en dependencies), publieke entry points (index-bestanden, geëxporteerde componenten, handlers) en tests (die vaak het beoogde oppervlak laten zien). Een README binnen de map kan de snelste boundary-marker zijn.
Boundaries werken het beste wanneer je de bruggen tussen hen noemt. Geef duidelijk aan welke interfaces Claude mag aanraken en behandel alles anders als off-limits. Typische bruggen zijn HTTP API-contracten, event topics en payloads, gedeelde types, of een kleine set geëxporteerde functies.
Noem ook altijd “do not touch” zones wanneer de wijziging deze niet zou moeten beïnvloeden. Veelvoorkomende zijn infrastructuur- en deploymentconfiguraties, beveiligings- en authlogica, billing en payments, datamigraties en productieschema's, en gedeelde libraries die door veel teams worden gebruikt.
Een concreet promptdetail dat helpt:
“Make changes only inside packages/cart/ and its tests. You may read shared types in packages/types/ but do not modify them. Do not edit infra, auth, or billing.”
Nauwkeurigheid verbetert wanneer je een kleine, stabiele kaart van het gebied geeft dat je wilt veranderen. Een "lokale samenvatting" is die kaart: kort genoeg om snel te lezen, specifiek genoeg om gokken te voorkomen.
Houd elke samenvatting rond de 10–20 regels. Schrijf het alsof je de code aan een nieuwe collega geeft die alleen deze boundary hoeft aan te passen, niet de hele repo. Gebruik gewone taal en echte namen uit de code: mappen, pakketten, geëxporteerde functies.
Een nuttige lokale samenvatting beantwoordt vijf vragen:
Voeg één "gotchas" regel toe. Dit voorkomt dure fouten: verborgen caching, feature flags, migratiestappen en alles dat stil kan breken.
Hier is een compact template dat je kunt kopiëren:
Local summary: <package/service name>
Purpose: <1 sentence>
Scope: <what to touch> | Not: <what not to change>
Entry points: <files/routes/commands>
Public surface: <exports/endpoints/events>
Data sources: <tables/collections/queues/caches>
Conventions: errors=<how>, logging=<how>, tests=<where/how>
Gotchas: <flags/caching/migrations/edge cases>
Voorbeeld: als je een billing-pakket bewerkt, noteer de exacte functie die facturen aanmaakt, de tabelnamen waarnaar wordt geschreven, en de regel voor retryable errors. Dan kan Claude zich op die boundary concentreren in plaats van in gedeelde auth, config of ongewenste pakketten te dwalen.
De beste samenvatting is degene die Claude ziet op het moment dat hij die nodig heeft. Zet het naast de code die het beschrijft zodat het moeilijk te negeren en makkelijk te updaten is. Bijvoorbeeld: houd een korte SUMMARY.md (of een README.md-sectie) in elk package, service of app in plaats van één gigantisch document in de repo-root.
Een eenvoudige, herhaalbare structuur helpt. Houd het kort genoeg zodat mensen het bijwerken:
YYYY-MM-DD - <wat veranderde in één zin>Samenvattingen verouderen om voorspelbare redenen. Behandel updates alsof je een type-definitie bijwerkt: onderdeel van het werk afronden, geen apart taakje.
Werk de samenvatting bij wanneer een refactor structuur of namen verandert, een nieuwe module de hoofdmanier wordt om iets te doen, een API/event/schema verandert (zelfs als tests nog slagen), boundaries tussen pakketten verschuiven, of een dependency wordt verwijderd of vervangen.
Een praktische gewoonte: wanneer je een change merged, voeg één "Last updated" regel toe die kort beschrijft wat er veranderde. Tools zoals Koder.ai kunnen je helpen sneller te werken aan de code change, maar de samenvatting is wat toekomstige wijzigingen nauwkeurig houdt.
Nauwkeurigheid hangt vaak af van hoe je het gesprek tempo geeft. Laat Claude context in kleine stappen verdienen in plaats van te gokken op basis van een enorme snapshot.
Voordat je iets editeert, vraag Claude te beschrijven wat hij ziet en wat hij nodig heeft. Een goede kaart is kort: sleutelpackages, de entry point voor de flow en waar tests of types leven.
Prompt:
“Create a map of this change: packages involved, main flow, and likely touch points. Do not propose code yet.”
Kies een smalle slice: één feature, één package, één user flow. Geef de boundary duidelijk aan (bijvoorbeeld: “Only change packages/billing-api. Do not touch shared-ui or infra.”).
Een workflow die je controle houdt:
Als Claude iets mist, moet hij dat zeggen. Laat hem opschrijven: (1) aannames die hij maakt, (2) wat die aannames zou falsifiëren, en (3) de volgende bestanden die nodig zijn om dat te bevestigen.
Voorbeeld: je moet een veld toevoegen aan een Invoice-response in één package. Claude vraagt om de handler, de DTO/type-definitie en één test. Jij deelt alleen die bestanden. Als je een chat-gebaseerde builder zoals Koder.ai gebruikt, geldt dezelfde regel: lever de kleinste set bronbestanden en breid alleen uit als het echt nodig is.
Je beste verdediging tegen verkeerde edits is een klein "contract" in de prompt: wat Claude mag aanraken, hoe je succes beoordeelt en welke regels gevolgd moeten worden.
Begin met een boundary die makkelijk te volgen en verifiëren is. Wees expliciet over waar edits zijn toegestaan en noem “do not touch” zones zodat er geen verleiding is om te dwalen.
Contract-template:
packages/payments/.packages/auth/, infra/, or any shared configs.Definieer daarna acceptatiechecks. Zonder die checks kan Claude code produceren die er op het first gezicht goed uitziet maar de echte regels van de repo breekt.
Style-constraints zijn ook belangrijk. Zeg welke patronen gevolgd moeten worden en welke vermeden worden, gebaseerd op wat je codebase al doet. Bijvoorbeeld: “Use existing error helpers in this package; do not add new dependencies; keep function names consistent with camelCase; don’t introduce a new architecture layer.”
Eis tenslotte een kort wijzigingsplan vóórdat er ge-edit wordt:
“Before editing, list the 3-5 files you expect to touch and the exact behavior change. Wait for approval.”
Voorbeeld:
“Fix rounding in invoice totals. Only edit packages/billing/src/ and tests under packages/billing/test/. Acceptance: pnpm -C packages/billing test and typecheck. Follow existing money utils; do not rewrite API types. Provide a 4-step plan first.”
De snelste manier om verkeerde edits te krijgen in een monorepo is Claude te veel ineens geven. Als je een grote stapel code plakt, valt hij vaak terug op generieke patronen in plaats van het specifieke ontwerp dat je repo al gebruikt.
Een andere valkuil is het model het architectuurplaatje te laten raden. Als je geen echte entry points laat zien, kan hij het eerste plausibele bestand kiezen en daar logica in weven. In de praktijk komt nauwkeurigheid van een kleine set "sources of truth" (entry-modules, routers, service-registries, package-boundary docs). Als die niet in de context zitten, vult het model de gaten.
Namen kunnen het ook misleiden. Monorepos hebben vaak pakketten als ui, ui-kit, shared-ui, of gedupliceerde helpers zoals date.ts op twee plekken. Als je fragmenten van beide mixt, kan Claude het ene bestand patchen terwijl hij over het andere redeneert. Voorbeeld: je vraagt een knopstijl te veranderen, hij past packages/ui/Button.tsx aan, maar de app importeert packages/ui-kit/Button.tsx. De diff ziet er prima uit, maar niets verandert in productie.
Config is een andere bron van stille drift. Gedrag kan afhangen van env-vars, feature flags, build-instellingen of workspace tooling. Als je die niet vermeldt, kan Claude een “rare” check weghalen die alleen nodig is wanneer een vlag aanstaat, of code toevoegen die een build stap breekt.
Rode vlaggen dat je dreigt te driften:
Behandel cross-package imports als een bewuste beslissing, niet als standaard. Houd edits lokaal tenzij je scope expres uitbreidt.
De snelste manier om correcte edits te krijgen is beginnen met limits, niet met volume. Een goede prompt voelt een beetje streng: hij zegt waar Claude moet kijken, wat te negeren en wat “klaar” betekent.
Voordat je code plakt, schrijf een korte preface die het werk vastpint op één plaats in de repo. Noem het package, de exacte folder en het specifieke doel. Voeg dan een lokale samenvatting toe (doel, belangrijke dependencies, belangrijke conventies) en het entry-bestand dat de wijziging ankert.
Checklist:
\u003cpackage\u003e/\u003cpath\u003e. Doel: \u003cone sentence\u003e. Ignore alles anders tenzij gevraagd.\u003c5-10 lines\u003e. Entry bestand: \u003cpath/to/file\u003e.\u003c...\u003e. Niet veranderen: \u003cfolders/files or APIs\u003e. Gedrag behouden: \u003cwhat must stay true\u003e.Als Claude wijzigingen buiten je boundary voorstelt, zie dat als een signaal: ofwel verscherp de prompt, ofwel breid de boundary expres uit en formuleer het opnieuw.
Stel: je monorepo heeft apps/web-store (een React-app) en packages/ui-kit (gedeelde buttons, inputs en styles). Je wilt één kleine feature: een “Save for later” knop op de cart-pagina toevoegen, gebruikmakend van een nieuwe SaveIcon uit ui-kit. Niets anders mag veranderen.
Maak eerst twee lokale samenvattingen die als boundaries fungeren. Houd ze kort, specifiek en sturend over wat belangrijk is.
# apps/web-store/LOCAL_SUMMARY.md
Purpose: Customer shopping UI.
Entry points: src/routes.tsx, src/pages/cart/CartPage.tsx
Cart rules: cart state lives in src/cart/useCart.ts
Do not touch: checkout flow (src/pages/checkout), payments, auth.
Tests: npm test -w apps/web-store
# packages/ui-kit/LOCAL_SUMMARY.md
Purpose: shared UI components.
Exports: src/index.ts
Icons: src/icons/*, add new icons by exporting from index.
Do not touch: theming tokens, build config.
Tests: npm test -w packages/ui-kit
Houd de iteratie vervolgens kort:
CartPage and ui-kit icons. No checkout/auth edits.”CartPage, useCart, ui-kit icons, ui-kit index).Na de wijziging, documenteer het zodat toekomstige context klein blijft:
Als het goed werkt voor één persoon maar niet voor de rest van het team, ontbreekt meestal herhaalbaarheid. Maak “goede contexthygiëne” de default, niet een persoonlijke gewoonte.
Bewaar één prompt-skelet die iedereen kan kopiëren en invullen. Houd het kort maar strikt. Neem het doel op (wat “klaar” betekent), toegestane scope, harde boundaries (en waarom), een lokale samenvatting en een output-contract (eerst plan, daarna diff-achtige edits en tests).
Sla grootschalige maandelijkse reviews over die niemand doet. Koppel samenvatting-updates aan normaal werk: wanneer een wijziging gedrag, afhankelijkheden of API's verandert, update dan de lokale samenvatting in dezelfde PR.
Een eenvoudige regel: als een teammate zou vragen “waar woont dit?” of “wat hangt hiervan af?”, dan is de samenvatting verouderd.
Als je een chat-first workflow verkiest, kan Koder.ai je helpen dit iteratiepatroon veiliger te maken. Planning mode helpt bij het overeenkomen over scope en boundaries voordat edits gebeuren, en snapshots met rollback laten je wijzigingen proberen zonder vast te lopen wanneer een aanname fout blijkt te zijn.
Claude wordt minder nauwkeurig wanneer hij de echte bron van waarheid niet "ziet".
In een grote monorepo mist het model vaak een dependencybestand, verwart het twee vergelijkbare pakketten, of kopieert het een ouder patroon omdat dat in de context aanwezig was.
Probeer niet de hele repo mee te geven. Begin met de kleinst mogelijke set die aantoont dat de wijziging correct is.
Een goede vuistregel is:
Deel wat het gedrag verankert, niet alles dat toevallig dezelfde naam heeft.
Een praktische set is:
Kies één boundary die past bij hoe je repo is georganiseerd: een package, app of service.
Zeg het daarna expliciet en geef aan wat buiten scope is. Voorbeelden van constraints:
packages/cart/ and its tests.”Omdat monorepos vaak look-alike modules bevatten (ui, ui-kit, shared-ui) en gedupliceerde helpers (date.ts op meerdere plekken).
Claude kan het juiste idee in het verkeerde package toepassen of importeren uit een “bijna juiste” modulenaam. Voorkom dit door het exacte package en de entry points te noemen.
Een lokale samenvatting is een korte kaart van het exacte gebied dat je wilt veranderen, meestal 10–20 regels.
Neem op:
Zet het naast de code die het beschrijft zodat het makkelijk te vinden en bij te werken is.
Een eenvoudig default:
SUMMARY.md of een klein gedeelte in de package README.mdZeg tegen Claude dat hij veronderstellingen en onbekenden moet markeren in plaats van te gokken.
Een nuttige regel:
Gebruik een strak iteratief proces dat dwingt om context in kleine stukjes te verdienen:
Schrijf een mini-"contract" in je prompt en maak het afdwingbaar:
Dat maakt review makkelijker en verkleint per ongeluk cross-package edits.