Claude Code wijzigde bestanden zonder te vragen: wat git diff je niet laat zien
6m leestijd

Claude Code wijzigde bestanden zonder te vragen: wat git diff je niet laat zien

Sinds auto mode de standaard is, vraagt een agent maar zelden eerst of hij iets mag aanpassen, en dat is zo bedoeld. De uiteindelijke diff laat zien waar de sessie eindigde. Welke wijzigingen je voorgelegd kreeg, welke in een subagent gebeurden en welk werk al was teruggedraaid voordat je keek, zie je er niet in.

Vijf prompts, twee minuten, één kleine checkout-module. Aan het eind ziet git diff er zo uit:

text
 src/cart.ts     | 8 ++++++--
 src/checkout.ts | 3 +++
 2 files changed, 9 insertions(+), 2 deletions(-)

Negen regels. Een e-mailcheck en een kortingscode. Dat review je bij een kop koffie.

Het is ook maar een deel van wat er gebeurde. Claude Code bracht in die sessie acht wijzigingen aan, en geen enkele kreeg ik als beslissing voorgelegd. Twee kwamen van een subagent: ik zag alleen zijn samenvatting, de edits zelf kwamen nooit in mijn gesprek terecht. En drie wijzigingen werden geschreven en daarna overschreven of teruggedraaid voordat de sessie afliep, dus in de diff is er helemaal niets meer van te zien.

Dit is een sessie die ik voor deze post in een wegwerprepository heb opgezet. Wat je hierna ziet, doet een gewone sessie ook al vanzelf.

Vijf prompts op een tijdlijn: acht edits, waarvan drie ongedaan gemaakt en twee door een subagent, en een diff van +9 -2

Waarom het prima is dat hij niet vraagt ​

Auto mode is sinds Claude Code 2.1.283 de mode waarin een interactieve sessie standaard start. Een tweede model, de classifier, beoordeelt de acties in jouw plaats. Daarvoor draaiden veel mensen al de hele dag acceptEdits, omdat je van een prompt bij elke edit vooral leert om zonder te lezen op Enter te drukken.

Dat is een goede ruil. Veertig keer per uur een vraag maakt elke vraag waardeloos, en de classifier houdt de acties tegen die echt schade kunnen aanrichten. Ik draai zelf auto mode en ga niet terug.

Wat de ruil kost, zie je minder snel. De permission prompt was ook je logboek. Elke edit die je goedkeurde, had je in elk geval kunnen zien. Haal de prompt weg en dat logboek verdwijnt mee. Ongemerkt wordt de uiteindelijke diff dan het enige verslag van de sessie dat je ooit leest.

Drie routes naar je werkmap ​

Elke wijziging die Claude Code met zijn edit-tools aanbrengt, komt via een van drie routes binnen:

  • Decided: de prompt erachter werd verstuurd in een mode waarin Claude Code eerst stopt en vraagt: Manual (in de config nog steeds default) of plan.
  • Auto: verstuurd onder acceptEdits, auto of bypassPermissions. Doorgevoerd zonder te vragen.
  • Subagent: doorgevoerd binnen een subagent. Die werkt in zijn eigen context en geeft volgens de documentatie over subagents alleen een samenvatting terug ("returns only the summary"). De diff blijft in zijn eigen transcript.

Aan de subagent-route zit nog een haakje. Volgens de documentatie over checkpoints legt Claude Code die edits "usually" niet vast in de checkpoints van je sessie. Terugspoelen zet de bestanden terug die Claude al in je eigen gesprek had aangepast. Wat een subagent aan andere bestanden veranderde, blijft gewoon staan.

Voor git zijn alle drie de routes hetzelfde: regels die veranderd zijn.

Wat er tussen twee prompts verdwijnt ​

De uiteindelijke diff is een snapshot. Hij laat de laatste stand van elk bestand zien en niets over hoe het bestand daar kwam. Bij code die je zelf schreef is dat geen probleem, want de omwegen ken je nog. Bij een sessie die je niet volgde wel, want juist in die omwegen zitten de verrassingen.

In de opgezette sessie vroeg prompt 1 om e-mailvalidatie en kreeg een strenge check. Prompt 4 vroeg om een soepelere, en de strenge versie werd overschreven. Prompt 3 voegde een bevestigingsmail toe, prompt 5 vroeg om dat ongedaan te maken, en die edit werd teruggedraaid. Dat was allemaal gevraagd, dus hier kan het geen kwaad.

Stel je nu hetzelfde patroon voor zonder dat iemand erom vroeg. Een fix van 19:02 wordt om 19:41 overschreven door een latere beurt die met iets heel anders bezig was. De bug is terug, de diff ziet er netjes uit, en het enige wat weet wat er gebeurde, is een JSONL-bestand in ~/.claude/projects dat niemand opent.

Minos: de sessie lezen in plaats van de werkmap ​

Minos is een tool die ik precies voor deze vraag heb gebouwd. Hij leest de transcripts van Claude Code die al op je schijf staan en reconstrueert wat een sessie veranderde, via welke route, en wat het niet overleefde. Zelf legt hij niets vast terwijl je werkt, want alles staat al in het transcript. Daardoor kan hij ook iets zeggen over sessies van vóór de installatie, zolang Claude Code hun transcripts nog bewaart.

Voor de opgezette sessie geeft minos report dit (ingekort):

text
CHANGED  2 files, 8 changes, +25 / -18

  decided       0 changes  +   0  -   0   you were asked before it was applied
  auto          6 changes  +  15  -  12   acceptEdits or auto, no prompt
  subagent      2 changes  +  10  -   6   applied inside a subagent, never rendered

UNDONE  3 changes did not survive the session

  src/checkout.ts   overwritten  22:50  prompt 1  to 22:51  prompt 4
  src/checkout.ts   reverted     22:51  prompt 3  to 22:52  prompt 5
  src/checkout.ts   overwritten  22:51  prompt 3  to 22:52  prompt 5

De diff zei negen regels in twee bestanden. De sessie zegt acht wijzigingen, en de kortingscode in src/cart.ts kwam van een subagent. Dat lees ik als eerste, want dat deel heb ik nooit gezien. Bij een onbekende code gooit hij een error, en over dat gedrag van checkout heeft niemand besloten.

minos file src/checkout.ts zet alle bewerkingen op één bestand op volgorde, met de prompt erachter. minos undone geeft je alleen de verloren wijzigingen. minos sessions --all zet alle projecten op de machine in één tabel, voor een periode die je zelf kiest.

Minos is nog pre-release en installeer je vanuit de repository of de plugin-marketplace. Binnen Claude Code geeft /minos:report het rapport van de sessie waarin je zit, en /minos opent naast de chat een paneel dat datzelfde overzicht bijhoudt terwijl je werkt.

Wat hij niet ziet ​

Een tool die doet alsof hij meer weet dan hij weet, is erger dan geen tool. De grenzen horen daarom bij het ontwerp.

  • decided volgt uit de permission mode, niet uit een goedkeuring. Niets op je machine legt vast dat je een prompt hebt gelezen. Met een vaste allow-regel kan een beurt in default voorbijgaan zonder dat er iets op je scherm verschijnt, en dat meldt Minos onder zijn eigen cijfers.
  • Alleen Edit, Write en NotebookEdit tellen mee. Een bestand dat via sed -i, een redirect of een MCP-server is herschreven, laat geen edit achter om te lezen. Shell-commando's die op een schrijfactie lijken, telt Minos apart als losse heuristiek, buiten de drie klassen.
  • Teruggedraaide wijzigingen herkent hij aan de tekst van de wijzigingen. Zie een melding als een sterke aanwijzing en controleer in het bestand of hij klopt.
  • De geschiedenis is eindig. Claude Code verwijdert transcripts na cleanupPeriodDays, standaard 30 dagen.

Wat je ermee doet ​

De routes vragen elk om een eigen aanpak, omdat ze elk op hun eigen manier misgaan.

  • Lees de wijzigingen van subagents apart. Die kwamen nooit in je gesprek terecht, en terugspoelen laat ze mogelijk staan. Moet een subagent code schrijven, dan kun je een fork met isolation: "worktree" in een eigen git-worktree laten werken. Zijn edits komen dan binnen als een branch die je reviewt, in plaats van als wijzigingen in je eigen checkout.
  • Kijk voordat je commit wat er is teruggedraaid. Een overschreven fix is de goedkoopste bug die je ooit vindt, zolang je hem vindt voordat het transcript de enige plek is waar hij nog bestaat.
  • Blijf de diff reviewen. Minos vertelt je waar je moet kijken. Of de code klopt, merk je pas als je de code van een agent beoordeelt, en dat blijft gewoon je werk.

De diff van negen regels bovenaan gaf precies weer waar de sessie eindigde. Wat er onderweg gebeurde, staat in het transcript.