Claude Code-hooks werken niet op Windows: oorzaken en oplossingen

Dezelfde hook die op een Mac prima draait, doet op Windows niets, of erger nog, blokkeert elk commando. Bijna altijd ligt het aan de shell. Zo voert Claude Code hooks uit op Windows en zo maak je de jouwe betrouwbaar.

Door Aslan, Pet Island-team · Bijgewerkt op 26 okt. 2026 · 5 min lezen

KORT ANTWOORD

Op Windows voert Claude Code de command van een hook uit met Git Bash, of met PowerShell als Git Bash niet is geïnstalleerd. Geef aan welke je bedoelt met "shell": "powershell" of "shell": "bash", houd stdout beperkt tot één JSON-object (geen echo’s uit je profiel), gebruik afsluitcode 2 om te blokkeren en werk Claude Code bij (in versies tot en met 2.1.310 zijn meerdere Windows-bugs in hooks opgelost). Debug met /hooks en claude --debug.

Welke shell je hook uitvoert

Claude Code geeft de command-string door aan een shell: sh -c op macOS en Linux, Git Bash op Windows, of PowerShell als Git Bash niet is geïnstalleerd. Die ene zin uit de hooksreferentie verklaart de meeste meldingen van het type “werkt op mijn Mac”. Een commando dat voor PowerShell is geschreven, mislukt in Git Bash, een bash-script mislukt in PowerShell, en welke je krijgt, hangt ervan af of Git for Windows toevallig is geïnstalleerd.

Haal het giswerk weg met het veld shell. Dat accepteert "bash" of "powershell":

%USERPROFILE%\.claude\settings.jsonKopiëren
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"shell": "powershell",
"command": "[Console]::Beep(880, 200)"
}
]
}
]
}
}

Wil je Git Bash en kan Claude Code het niet vinden, installeer dan Git for Windows of zet CLAUDE_CODE_GIT_BASH_PATH op de locatie ervan, en start daarna een nieuwe sessie.

Symptomen en hun oorzaken

Wat je zietWaarschijnlijke oorzaakOplossing
De hook lijkt nooit te draaienOude versie van Claude Code, verkeerde event of matcher, ongeldige JSON in de instellingenBijwerken; /hooks controleren; opmerkingen en komma’s aan het eind verwijderen
ParserError of “unexpected token”PowerShell-syntaxis die in Git Bash terechtkomt, of andersomStel shell expliciet in
Hookuitvoer “does not start with {”Er is iets afgedrukt vóór de JSON, vaak door een shellprofielZet de uitvoer van je profiel stil; stuur logs naar stderr
Een pad met zowel \ als / wordt niet gevondenEen Windows-padvariabele samengevoegd met een achtervoegsel in Unix-stijlGebruik de exec-vorm: het programma in command, elk argument in args
powershell: Permission denied vanuit Git BashAf en toe gemeld in 2.1.283 en 2.1.304–2.1.305 (#103910, open)Gebruik "shell": "powershell" zodat Git Bash er niet tussen zit
Een bewakingshook laat alles doorAfsluitcode 1 in plaats van 2, of een fail-open-bug in oudere versiesSluit af met 2 om te blokkeren; werk bij naar 2.1.310 of later
De hook keert direct terug zonder uitvoerEen programma uit het GUI-subsysteem waar de shell niet op wachtGebruik een consoleprogramma, of wacht op het proces

Alleen JSON op stdout

Claude Code leest de standaarduitvoer van je hook als zijn antwoord. De regel in de documentatie is kort: druk niets anders dan het JSON-object af op stdout. Op Windows gaat dit op een verraderlijke manier mis: Git Bash en sommige configuraties laden nog steeds je shellprofiel, en een onvoorwaardelijke echo in dat profiel komt vóór je JSON te staan. De hook “werkt” dan in een terminal en mislukt in Claude Code.

Log in plaats daarvan naar een bestand of naar stderr, en laat de uitvoer van je profiel afhangen van een interactieve shell.

Afsluitcodes: 2 blokkeert, 1 niet

Afsluitcode 0 betekent succes. Afsluitcode 2 is een blokkerende fout: bij events die kunnen blokkeren, stopt Claude Code de actie en toont het je stderr. Afsluitcode 1 zonder geldige JSON is een niet-blokkerende fout, en de actie gaat door. Als je hook een beleid afdwingt, gebruik dan afsluitcode 2.

Niet elk event kan op deze manier worden geblokkeerd. De afsluitcode van een Notification-hook wordt genegeerd. Een Stop-hook die met 2 afsluit, laat Claude doorwerken. Een PermissionRequest-hook negeert afsluitcode 2 volledig. Die beslist via een decision-object in zijn JSON.

Claude Code 2.1.309 loste op dat PowerShell-hooks niet blokkeerden als het programma van de hook met code 2 afsloot. Lijkt je PowerShell-bewaking genegeerd te worden, controleer dan eerst je versie.

Windows-oplossingen die een update waard zijn

De changelog van Anthropic bevat een lange reeks Windows-oplossingen voor hooks. Deze verklaren oude forumdiscussies:

VersieOplossing
2.1.47PreToolUse- en PostToolUse-hooks mislukten stilletjes op Windows; ze draaien nu met Git Bash in plaats van cmd.exe
2.1.161Hooks die bash expliciet aanroepen (/usr/bin/bash script.sh) mislukten met “command not found”
2.1.299PreToolUse- en PermissionRequest-hooks zonder ingestelde shell lieten bij een fout alles door (fail-open) zonder Git for Windows; een falende bewaking blokkeert nu
2.1.309PowerShell-hooks blokkeerden niet bij afsluitcode 2; bewakingen met "shell": "powershell" lieten bij een fout alles door (fail-open) zonder Git for Windows
2.1.310Bewakingen waarvan het commando alleen uit strings tussen aanhalingstekens bestond (zoals een pad tussen aanhalingstekens), lieten bij een fout alles door (fail-open) zonder Git Bash

Het oudere issue met de titel “No hook is working on Windows” (#10450) werd gemeld op 2.0.27; iemand in de reacties ontdekte dat stdin de hookcommando’s niet bereikte. Zit je op zo’n oude versie, werk dan eerst bij voordat je iets anders gaat debuggen.

Een programma rechtstreeks aanroepen

Is je hook een gecompileerd programma, dan kun je de shell overslaan met de exec-vorm (het veld args; shell wordt genegeerd als args is ingesteld). Op Windows moet command bij de exec-vorm verwijzen naar een echt uitvoerbaar bestand, zoals een .exe; shims van het type .cmd en .bat (waaronder de meeste dingen die npm installeert) kunnen niet zonder shell worden gestart. Verwijs naar de .exe, of gebruik de shell-vorm.

Eén les uit het bouwen van onze eigen hookhelper: op Windows wordt niet gewacht op een programma dat voor het GUI-subsysteem is gebouwd als een shell het start. De shell keert meteen terug, de agent leest lege uitvoer en de hook lijkt dood. Hookprogramma’s moeten consoleprogramma’s zijn.

Plugin-hooks en paden

Plugin-hooks die paden opbouwen zoals ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh werkten niet op Windows tussen v2.1.2 en v2.1.12 (#18610): de variabele wordt uitgebreid tot een pad met backslashes, en een achtervoegsel met een forward slash erachter geeft een gemengd pad dat bash niet kan vinden. De huidige documentatie geeft de nette oplossing: gebruik de exec-vorm zodra een hook naar een padplaceholder verwijst. Zet het programma in command en elk argument in args, bijvoorbeeld "command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/scripts/format.js"]. Elk element wordt als één argument doorgegeven, zonder shell die het kan verminken.

Checklist voor debuggen

  1. /hooks opent een alleen-lezen lijst van elke geconfigureerde hook en waar die vandaan komt.
  2. claude --debug (of /debug midden in een sessie) toont elke hookuitvoering, de uitvoer en de afsluitcode. claude --debug-file <path> schrijft dat naar een bestand.
  3. Valideer de JSON. Instellingenbestanden zijn strikte JSON; één komma aan het eind schakelt het hele bestand uit.
  4. Controleer de matcher. Matchers zijn hoofdlettergevoelig; "*", "" of geen matcher matcht alles.
  5. Voer het commando zelf uit in dezelfde shell die Claude Code gebruikt, met voorbeeld-JSON als invoer via een pipe.
  6. Kijk naar de time-out. Commandohooks hebben standaard 600 seconden; een hook die op een persoon wacht, heeft die ruimte nodig.

Om alle hooks uit te schakelen terwijl je onderzoekt, zet je "disableAllHooks": true.

Als je alleen meldingen en goedkeuringen wilde

Veel Windows-configuraties met hooks bestaan om één reden: weten wanneer Claude Code je nodig heeft en daarop antwoorden. Pet Island doet dat zonder enig script. Het koppelt met één klik aan Claude Code, regelt de Windows-details voor je en zet elk toestemmingsverzoek, elke vraag en elk plan op een klein eiland bovenaan het scherm, met het commando of de diff, waar je het toestaat of weigert. Het werkt ook als Claude Code in WSL draait.

VEELGESTELDE VRAGEN

Welke shell voert Claude Code-hooks uit op Windows?

Git Bash, of PowerShell als Git Bash niet is geïnstalleerd. Zet "shell": "powershell" of "shell": "bash" in de hook om expliciet te kiezen.

Waarom werkt mijn Claude Code-hook in de terminal maar niet in Claude Code?

Meestal door extra uitvoer: een shellprofiel dat tekst echoot, komt vóór de JSON van de hook te staan. Druk alleen het JSON-object af op stdout.

Hoe laat ik een hook een toolaanroep blokkeren?

Sluit af met code 2 (of geef een deny-beslissing terug in JSON). Afsluitcode 1 is een niet-blokkerende fout en de actie gaat door. PermissionRequest-hooks negeren afsluitcode 2 en gebruiken in plaats daarvan een decision-object.

Kan een hookcommando een .cmd- of .bat-bestand zijn?

Niet in de exec-vorm. Op Windows moet het verwijzen naar een echt uitvoerbaar bestand, zoals een .exe. Gebruik de shell-vorm om .cmd- of .bat-bestanden uit te voeren.

Hoe zie ik waarom een hook is mislukt?

Voer claude --debug uit of typ /debug, en gebruik /hooks om te zien welke hooks zijn geladen.

Bronnen

Elke instelling en elk gedrag op deze pagina is op 26 oktober 2026 gecontroleerd aan de hand van deze pagina’s. Agents veranderen snel; klopt er iets niet meer, dan geldt de officiële pagina.

VERDER LEZEN

Beantwoord elke agent vanaf de bovenkant van je scherm.

Windows en Mac · 7 dagen gratis, daarna eenmalig $8.99 · $1 van elke verkoop gaat naar voer voor zwerfdieren

Probeer Pet Island gratis