Claude Code-config delen met je team: wat de repo wel en niet afdwingt
10m leestijd

Claude Code-config delen met je team: wat de repo wel en niet afdwingt

Hoe je Claude Code-config deelt met je team: wat er in .claude/settings.json hoort en wat in CLAUDE.md, wat een collega stilletjes op zijn eigen machine overrulet, en welke gecommitte regels pas werken als iedereen een dialoog goedkeurt.

De repo waar dit blog in staat, heeft acht skills in git staan onder .claude/. In diezelfde repo ligt een .claude/settings.local.json van dertig kilobyte met 354 permissieregels, en dat bestand staat nergens onder versiebeheer.

Die scheiding is nooit een besluit geweest. De helft van mijn setup die de agent iets leert, is gedeeld. De helft die de agent iets toestaat, bleef op één machine staan en groeide daar verder, één "ja, niet meer vragen" tegelijk.

Die scheiding blijkt niet aan mijn slordigheid te liggen. Zo zit het systeem in elkaar. Een repo kan alles delen wat de agent beperkt. Alles wat de agent iets toestaat, kan een repo hooguit voorstellen. Zodra je die grens ziet, ben je in een minuut of tien klaar met beslissen wat je voor vijf ontwikkelaars commit.

Wat je in de repo kwijt kunt

Vier dingen gaan mee in versiebeheer, en ze gedragen zich verschillend zodra ze op een andere machine terechtkomen:

WatWaar het staatWat het doet na een clone
InstructiesCLAUDE.md, .claude/rules/*.mdLaadt in de context
Permissieregels, hooks, pluginkeuzes.claude/settings.jsonWacht deels op een dialoog
Skills.claude/skills/<naam>/SKILL.mdInstructies laden, grants wachten
MCP-servers.mcp.jsonWacht op goedkeuring per persoon

Skills zijn de makkelijke winst, en meteen de reden dat mijn repo zo scheefgegroeid is. Zet een SKILL.md in .claude/skills/, commit hem, en elke collega heeft jouw /consolidation-pass de volgende sessie tot zijn beschikking, zonder ook maar één installatiestap. Wil je hem kunnen versioneren en in meerdere repo's hergebruiken, dan bouw je hem later om tot plugin, en ruil je die installatie zonder gedoe in voor een marketplace-entry en een installatiecommando per ontwikkelaar. Begin standalone.

Die scheiding loopt dwars door één enkel skill-bestand heen, en daar staat de regel het duidelijkst in de documentatie. De instructies van een gecommitte skill laden bij iedereen. De allowed-tools-regel in de frontmatter, die de skill git laat draaien zonder tussendoor te vragen, werkt pas nadat die ontwikkelaar de map vertrouwt, net als de permissieregels in .claude/settings.json. Het advies van Anthropic op diezelfde pagina is om de skills van een project te lezen voordat je een repo vertrouwt, want een skill kan zichzelf brede toegang toekennen. Wat de agent leert, reist mee. Wat hij mag, wacht.

Bij de andere drie rijen in die tabel lopen teams tegen verrassingen aan.

De volgorde staat precies verkeerd om

Claude Code bepaalt zijn settings in deze volgorde, hoogste eerst:

  1. Managed settings (/etc/claude-code/managed-settings.json op Linux en WSL)
  2. Argumenten op de commandoregel
  3. .claude/settings.local.json
  4. .claude/settings.json
  5. ~/.claude/settings.json

Lees drie en vier nog eens. Bij elke instelling met één waarde wint het persoonlijke bestand dat je niet kunt inzien van het teambestand dat jullie in een PR hebben doorgenomen. defaultMode is degene waar je het merkt: commit plan voor het team, en de lokale acceptEdits van je collega wint stilletjes op zijn machine, zonder dat de repo daar iets van laat zien.

Permissieregels zijn de uitzondering, en die uitzondering pakt goed voor je uit. Ze worden over de scopes heen samengevoegd in plaats van vervangen, en daarna loopt de deny-eerst-volgorde over die samengevoegde set. Een lokale Bash(*) van je collega haalt dus geen deny weg die jij hebt gecommit, hij verruimt alleen wat die collega zelf mag. Toestemmingen stapelen zich per persoon op. Beperkingen overleven het samenvoegen.

Er is één laag die boven de discussie staat, en die zit met opzet niet in je repo: managed settings, een bestand dat root beheert op een vast systeempad, uitgerold via MDM of Ansible. Daar houdt disableBypassPermissionsMode op een voorkeur te zijn waar iemand zichzelf omheen praat. Al het andere wat je in .claude/settings.json zet, is een stevige standaardwaarde, en een standaardwaarde houdt het precies zo lang vol als de minst geduldige collega toelaat.

Toestaan wacht, verbieden niet

Dit is de asymmetrie die de handleidingen overslaan. permissions.allow-regels en additionalDirectories in de .claude/settings.json van een project geven de agent iets extra's, en daarom past Claude Code ze pas toe nadat die ontwikkelaar de workspace trust-dialoog voor die map heeft geaccepteerd. Tot die tijd leest hij ze in en doet er niets mee. Bij deny en ask speelt dat niet, want die perken alleen in.

De allowlist die je hebt gecommit om je team van promptmoeheid te redden, doet in een net gekloonde repo dus niets tot iedereen ja zegt tegen een dialoog die precies opsomt wat de map wil toestaan. De denylist die je hebt gecommit om .env-bestanden uit de context te houden, werkt vanaf de eerste sessie, bij iedereen, geruisloos en correct.

Die ene regel verklaart de rest van de verrassingen:

  • Een gekloonde repo kan zijn eigen MCP-servers niet goedkeuren. Zet enableAllProjectMcpServers in je projectsettings en hij wordt genegeerd zolang de map niet vertrouwd is. De server blijft op ⏸ Pending approval staan tot iemand daar claude draait en ja zegt.
  • Teamplugins vragen ook. Met extraKnownMarketplaces en enabledPlugins in .claude/settings.json krijgen je collega's de marketplace aangeboden zodra ze de map vertrouwen. Zet alleen het project een plugin uit een externe bron aan, dan laadt die pas als ze hem zelf installeren.
  • Een gecommitte externe import krijgt één kans. Importeert je CLAUDE.md iets van buiten de werkmap, bijvoorbeeld @~/.claude/standards.md, dan verschijnt de eerste sessie een goedkeuringsdialoog. Wijs je die af, dan blijven de imports uit staan en komt de dialoog nooit meer terug. Geen waarschuwing, geen tweede kans, en de collega die afwees leest sindsdien een kortere CLAUDE.md dan jij.

En dan het echte addertje: in -p-modus, dus zonder interactie, verschijnt er geen dialoog en blijven de regels genegeerd. Je zorgvuldig beoordeelde allowlist doet in CI helemaal niets, permanent, zonder één regel output die dat verraadt. Wat je pipeline mag doen, moet uit managed settings komen, uit --settings, of uit de flags op het commando zelf.

De gitignore die in je home-directory staat

Als Claude Code een instelling wegschrijft naar .claude/settings.local.json in een repo die dat bestand nog niet negeert, zet hij **/.claude/settings.local.json in je globale git excludes. Ik heb het tijdens het schrijven even bij mezelf nagekeken: die regel staat in ~/.config/git/ignore, en de .gitignore van dit project heeft nog nooit van dat bestand gehoord.

Daar volgen twee dingen uit. Een collega die het bestand met de hand aanmaakt, of het door de agent met de Write-tool laat schrijven, heeft die uitzondering helemaal niet, en zo belandt een persoonlijke allowlist van 354 regels in een PR. En als het bestand ooit toch gecommit wordt, zijn de allow-regels niet langer privé: het bestand kan dan uit de repo zijn gekomen, dus vallen ze onder dezelfde trust-controle als gewone projectsettings.

Zet .claude/settings.local.json in de .gitignore van de repo zelf. Het kost één regel, en dan hangt het niet langer af van wat elke ontwikkelaar toevallig in zijn home-directory heeft staan.

Het geheugen dat niemand deelt

"Eén CLAUDE.md, vijf ontwikkelaars" heeft een verborgen tweede helft, want Claude Code heeft twee geheugensystemen en je kunt er maar één van committen.

CLAUDE.md schrijf jij zelf, hij laadt elke sessie en gaat mee in git. Het automatische geheugen schrijft Claude, het staat in ~/.claude/projects/<project>/memory/, hangt aan de git-repo en blijft op die ene machine. Het wordt nooit tussen machines gedeeld, dus vijf ontwikkelaars op één repo hebben vijf privé-geheugens die maandenlang stilletjes uit elkaar groeien.

Dat is het echte antwoord op de vraag waarom de agent van je collega dat ene rare buildprobleem kent dat de jouwe elke week opnieuw ontdekt. Die kennis is in een bestand terechtgekomen dat jou nooit zou bereiken. Blijkt zoiets algemeen te gelden, dan moet je het met de hand doorschuiven naar CLAUDE.md, en dat is meteen de enige versie die iemand kan beoordelen. Verouderde regels zijn erger dan geen regels zodra vijf mensen erop varen.

CLAUDE.md is context, geen configuratie

Anthropic zegt het zelf onomwonden in de documentatie: CLAUDE.md wordt als gebruikersbericht aangeleverd, Claude leest het en probeert het te volgen, en er is geen garantie dat hij het doet. Het stuurt gedrag, en het afdwingen gebeurt in de andere lagen.

Een gedeelde CLAUDE.md faalt daarmee op de gewone manier waarop gedeelde documenten falen: hij wordt lang. Houd hem onder de 200 regels, want langere bestanden vreten context en de naleving zakt. In een repo met vijf mensen zit je zo tegen dat plafond aan, want iedereen wil zijn eigen onderwerp terugzien in het bestand dat elke sessie meelaadt.

.claude/rules/ is de oplossing die je beter vroeg dan laat invoert. Eén onderwerp per bestand, en met een paths:-blok in de frontmatter beperk je een regel tot de bestanden waar hij echt over gaat:

markdown
---
paths:
  - 'src/api/**/*.ts'
---

# API rules

- Every endpoint validates its input
- Use the standard error response shape

De backendregels laden nu pas als iemand aan de backend werkt, en je frontender betaalt er geen context meer voor. Regels zonder paths laden bij het opstarten, met hetzelfde gewicht als .claude/CLAUDE.md, dus daar houd je alleen wat echt voor iedereen geldt.

Nog twee dingen die specifiek in een team spelen. Een collega kan claudeMdExcludes in zijn lokale settings zetten en jouw CLAUDE.md met een glob compleet uit zijn sessies weren, wat in een monorepo vol andermans bestanden precies de bedoeling is en daarbuiten een verrassing. En Claude Code leest CLAUDE.md en nooit AGENTS.md, dus in een repo waar de helft van het team een andere agent draait, wil je bovenaan een @AGENTS.md-import in plaats van twee bestanden die uit elkaar lopen.

Wat je dus wel commit

DoelWaar het hoort
Conventies, buildcommando's, structuurCLAUDE.md, onder de 200 regels
Regels voor één deel van de codebase.claude/rules/*.md met paths
Herhaalbare workflows.claude/skills/<naam>/SKILL.md
Wat niemand magdeny in .claude/settings.json
Wat iedereen zonder vragen magallow, en reken op de dialoog
Wat elke keer moet gebeurenEen hook
Wat tegen iedereen moet standhoudenManaged settings, buiten de repo
Je eigen goedkeuringen en experimenten.claude/settings.local.json, in .gitignore

De rij die het meeste werk verzet, is de hook. Een PreToolUse-hook draait als shellcommando op een vast moment in de levenscyclus en doet zijn werk ongeacht wat het model besloot, en een blokkerende hook gaat vóór je allow-regels. Met dezelfde kanttekening als de rest van dit stuk, want een hook uit andermans repo is uitvoerbare code en zit achter dezelfde trust-drempel. Als een conventie er echt toe doet, is "we hebben het in CLAUDE.md gezet" een verzoek en is "de hook eindigt met exit 2" een antwoord. Alles wat ik schreef over het stapelen van regels, hooks en de sandbox geldt hier onverkort, met één extra beperking: in een team gaan de lagen waar een mens ja tegen moet zeggen later werken dan je denkt.

Anthropic komt van de andere kant bij hetzelfde gat uit. Hun handleiding voor grote codebases beantwoordt de uitrolvraag met een persoon in plaats van met een bestand: iemand die eigenaar is van de configuratie en de knopen mag doorhakken over het permissiebeleid en de plugin-marketplace, want zonder dat werk blijft de kennis bij een handjevol mensen hangen en loopt de adoptie vast. Ze zien er een agent manager-rol voor ontstaan. Dat is de eerlijke lezing van alles hierboven. Er zijn zo weinig lagen die zichzelf overeind houden, dat iemand zich om de rest moet blijven bekommeren.

Dit gaat eigenlijk niet over Claude Code. Een team dat het in een code review niet eens wordt over zijn conventies, wordt het ook niet eens in een CLAUDE.md, en gedeelde agent-config erbij halen om die knoop door te hakken is de bekende reflex om het gereedschap de schuld te geven van het proces. Wat de repo je wel geeft, is één plek om de afspraak op te schrijven, en een veel kortere weg van "dit hebben we besloten" naar "de agent doet dit standaard op ieders machine".

Verwar een standaardwaarde alleen niet met een regel. Van alles wat je commit houden twee dingen zichzelf overeind: de denylist en de hook. De rest is advies, en advies is het opschrijven nog steeds waard. Kies met zorg welke twee of drie conventies het afdwingen verdienen.

(31 van 31)
01Het beste uit Claude Code halen02Superpowers: hoe je Claude Code leert eerst te denken03Claude Code-hooks: deterministische controle over AI-workflows04Het CLAUDE.md-bestand: geef je AI permanent geheugen05Stop met vriendelijk vragen aan je agent06Wat er nieuw is in Claude Code: notities van het Londen-event07Het beste cijfer in Opus 4.8 is geen benchmark08Verouderd geheugen is erger dan geen geheugen09De agent is gewoon een loop10Bouw een MCP-server, en vraag je dan af of die moet bestaan11Skill, subagent, hook of slash command? Kies de juiste12Inloggen op MCP-servers vanuit je shell13De dag dat 'default' ineens 'Manual' heette14Hoe je een goede Claude Code-skill schrijft15Een goede Claude Code-subagent schrijven16Claude Code permissions instellen: de gids die ik miste17Claude Code sandboxen: toestemming is geen muur18Prompt injection voorkomen: verdediging voor wie agents bouwt19Welk Claude-model voor welke programmeertaak20Legacy code refactoren met AI: begin met characterization tests21Je MCP-server beveiligen: authenticatie, scopes en rate limits22Opus 5 is er, en je effort-instellingen kloppen niet meer23Incident response voor AI-agents: wat je doet als je coding agent de fout in gaat24Claude Code /doctor: van installatiecheck naar contextaudit25Context beheren in Claude Code: wanneer /clear en wanneer /compact26Git worktrees uitgelegd: parallel werken met AI-agents zonder botsingen27Claude Code plan mode: beslissen voordat de agent schrijft28Debuggen met een coding agent: geef hem het zoekwerk, de hypothese houd je zelf29Claude Code checkpoints en /rewind: wijzigingen van je agent terugdraaien30Claude Code cross-session messaging: sessies die elkaar berichten sturen31Claude Code-config delen met je team: wat de repo wel en niet afdwingt