Claude Code hooks zijn commando's (of HTTP-calls, prompts en nog een paar andere handlertypes) die Claude Code automatisch uitvoert op vaste momenten in een sessie, bijvoorbeeld voordat een tool draait, wanneer er toestemming nodig is of wanneer Claude klaar is met antwoorden. Je definieert ze onder een hooks-key in een settingsbestand zoals ~/.claude/settings.json. Elke hook krijgt JSON over het event binnen via stdin en kan reageren met zijn exitcode of een JSON-object op stdout. Zo kan een hook loggen, een notificatie sturen, een actie blokkeren of namens jou antwoorden.
01Hoe een hook is opgebouwd
Een hookconfiguratie heeft drie niveaus:
- Het hook-event, zoals
PreToolUseofStop. - Een matchergroep, die bepaalt wanneer de hook afgaat, bijvoorbeeld "alleen voor de Bash-tool".
- Een of meer hook-handlers: het onderdeel dat daadwerkelijk wordt uitgevoerd.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "/path/to/lint-check.sh"
}
]
}
]
}
}
Dit voert een lintscript uit nadat Claude een bestand heeft geschreven of bewerkt. Wil je een tweede event toevoegen, zet dan een extra key naast de bestaande in hetzelfde hooks-object.
02Waar hooks staan
~/.claude/settings.jsonAl je projectenNee, alleen op jouw machine.claude/settings.jsonEén projectJa, kan gecommit worden.claude/settings.local.jsonEén projectNeehooks/hooks.json van een pluginZolang de plugin aanstaatJaHooks uit verschillende bestanden worden bij elkaar opgeteld en vervangen elkaar niet. Typ /hooks in Claude Code om alle actieve hooks te zien en waar ze vandaan komen.
In een interactieve sessie houdt Claude Code hooks tegen, ook je eigen, totdat je de workspace trust-dialoog voor de map hebt geaccepteerd.
03Handlertypes
De meeste hooks zijn "type": "command", wat een shellcommando uitvoert. Er zijn nog vier andere:
http: POST de event-JSON naar een URL en leest de response body.mcp_tool: roept een tool aan op een MCP-server die je hebt geconfigureerd.prompt: stelt een Claude-model één vraag en leest een JSON-beslissing uit.agent: start een subagent die eerst bestanden kan lezen voordat hij beslist (experimenteel).
Command hooks draaien met al je gebruikersrechten, via sh -c op macOS en Linux en via Git Bash (of PowerShell) op Windows. Voeg "async": true toe om een hook op de achtergrond te draaien; hij kan dan geen beslissingen meer nemen.
04Matchers
De matcher bepaalt bij welke keren dat een event optreedt de hook draait. Waarop gematcht wordt hangt af van het event: de toolnaam bij tool-events, het notificatietype bij Notification, de manier waarop de sessie is gestart bij SessionStart, enzovoort.
"*",""of helemaal geen matcher matcht alles.- Letters, cijfers,
_,-, spaties,|en,worden als exacte namen behandeld.Edit|Writematcht beide tools. - Al het andere is een JavaScript-regex, dus
mcp__memory__.*matcht elke tool van één MCP-server.
Matchers zijn hoofdlettergevoelig. Sommige events, waaronder Stop en UserPromptSubmit, negeren matchers. Bij tool-events kun je één handler verder afbakenen met een if-veld met een permissieregel zoals "Bash(git *)".
05Input: wat je hook binnenkrijgt
Elke hook krijgt JSON via stdin met een paar algemene velden, waaronder session_id, transcript_path, cwd en hook_event_name, plus velden die specifiek zijn voor het event. Een PreToolUse-hook voor een Bash-call krijgt bijvoorbeeld ook tool_name en tool_input.command. Lees het uit met jq of een andere JSON-parser:
#!/bin/bash
input=$(cat)
cmd=$(jq -r '.tool_input.command // empty' <<<"$input")
echo "Claude wants to run: $cmd" >> ~/claude-commands.log
exit 0
06Output: exitcodes en JSON
Een hook kan op twee manieren iets teruggeven.
Exitcodes. 0 betekent succes. 2 is een blokkerende fout: bij events die kunnen blokkeren stopt de actie en wordt je stderr de reden. Elke andere code, ook de gebruikelijke 1, is een niet-blokkerende fout: de actie gaat gewoon door en je ziet een melding over een hook-fout. Moet een hook een regel afdwingen, exit dan met 2, niet met 1.
JSON op stdout. Exit met 0 en print één JSON-object voor meer controle. Sommige velden werken overal, zoals continue: false om Claude helemaal te stoppen. Andere zijn per event: Stop gebruikt decision: "block" met een reason, terwijl PreToolUse en PermissionRequest hun beslissing in hookSpecificOutput zetten. Print verder niets op stdout: één verdwaalde regel uit je shellprofiel en Claude Code kan de JSON niet meer lezen.
07Alle hook-events
SessionStartEen sessie start of wordt hervatNee (voegt context toe)SetupGestart met --init-only, of --init / --maintenance met -pNeeInstructionsLoadedEen CLAUDE.md- of .claude/rules/*.md-bestand wordt geladenNeeUserPromptSubmitJe verstuurt een prompt, voordat Claude die zietJaUserPromptExpansionEen getypt command wordt uitgeklapt tot een promptJaPreToolUseVóór elke tool-callJaPermissionRequestEen tool-call heeft een permissiebeslissing nodigStaat toe of weigert via JSONPermissionDeniedAuto mode weigert een tool-callNeePostToolUseNadat een tool-call is geslaagdNee (tool is al uitgevoerd)PostToolUseFailureNadat een tool-call is misluktNeePostToolBatchNa een batch parallelle tool-calls, vóór de volgende model-callJaNotificationClaude Code stuurt een notificatieNeeMessageDisplayTerwijl de antwoordtekst van Claude wordt getoondNee (kan aanpassen wat er getoond wordt)SubagentStart / SubagentStopEen subagent start of is klaarAlleen SubagentStopTaskCreated / TaskCompletedEen taak wordt aangemaakt of als voltooid gemarkeerdJaStopClaude is klaar met antwoordenJa (laat Claude doorgaan)StopFailureDe beurt eindigt met een API-foutNeeTeammateIdleEen teammate in een agent team staat op het punt idle te wordenJaConfigChangeEen settingsbestand verandert tijdens een sessieJaCwdChangedDe werkmap verandertNeeDirectoryAddedEr wordt een map toegevoegd met /add-dirNeeFileChangedEen gevolgd bestand verandert op schijfNeeWorktreeCreate / WorktreeRemoveEen worktree wordt aangemaakt of verwijderdJaPreCompact / PostCompactVoor en na het compacten van de contextAlleen PreCompactPreModelSwitch / PostModelSwitchVoor en na het wisselen van modelAlleen PreModelSwitchElicitation / ElicitationResultEen MCP-server vraagt om input, en nadat je hebt geantwoordJaSessionEndEen sessie eindigtNeeAnthropic voegt af en toe events toe, dus kijk in de hooks-referentie voor de actuele lijst en de inputvelden van elk event.
08Welke events relevant zijn voor notificaties
Vier events dekken bijna alles waarover je een melding wilt krijgen:
Stopvoor "Claude is klaar". Zie de handleiding over de Stop hook.Notificationvoor "Claude wacht op je", met types alspermission_promptenidle_prompt. Zie de handleiding over de Notification hook.PermissionRequestom direct een melding te krijgen, of te antwoorden, zodra er toestemming nodig is. Zie de handleiding over PermissionRequest.PreToolUseop de toolAskUserQuestion, om de meerkeuzevragen van Claude te zien of te beantwoorden. Zie vragen beantwoorden vanaf je telefoon.
Wil je een desktopsetup die je zo kunt plakken? Begin dan met een notificatie krijgen als Claude Code klaar is.
09Waar Claude Code Notifier in past
Claude Code Notifier is volledig op deze hooks gebouwd. De gratis command line tool, ccn, draait op Mac, Windows en Linux. Bij de installatie worden zeven hook-entries toegevoegd aan ~/.claude/settings.json, die elk ccn hook uitvoeren, en wordt eenmalig een backup van het bestand gemaakt. ccn draait per event een paar milliseconden en stopt dan weer, dus er blijft niets op de achtergrond draaien.
Op zichzelf toont het desktopnotificaties. Koppel je de iPhone- of Android-app, dan sturen dezelfde hooks je antwoorden terug: een permissie toestaan of weigeren, een vraag beantwoorden of de volgende instructie sturen nadat Claude is gestopt. Het is onafhankelijk en niet gemaakt door Anthropic. Heb je alleen een log of een lint-stap nodig, dan zijn een paar eigen regels simpeler. Meer details vind je op de ccn-pagina.
10FAQ
Hoe test ik een hook zonder op Claude te wachten?
Pipe voorbeeld-JSON naar het script en controleer de exitcode: echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh; echo $?. Voer daarna /hooks uit in Claude Code om te checken of hij onder het juiste event is geregistreerd.
Waarom draait mijn hook niet?
Meestal komt het door ongeldige JSON in settings.json (komma's aan het eind, commentaar), een matcher die niet exact overeenkomt (ze zijn hoofdlettergevoelig), een script dat niet uitvoerbaar is, of een map die je nog niet vertrouwd hebt. Start Claude Code met claude --debug en lees de debuglog om te zien wat er is uitgevoerd. De volledige lijst staat in de troubleshooting-checklist.
Hoe zet ik alle hooks tijdelijk uit?
Zet "disableAllHooks": true in een settings-bestand. Wil je ze voor één run overslaan, start Claude Code dan met --settings '{"disableAllHooks": true}'. Er is geen schakelaar voor één losse hook; dan verwijder je de entry. Geen van beide kan hooks uitschakelen die je organisatie in managed settings heeft ingesteld.
Wat is de standaard timeout van een hook?
Tien minuten (600 seconden) voor command-, HTTP- en MCP-tool-hooks, 30 seconden voor prompt-hooks en 60 voor agent-hooks. Een paar events hebben kortere standaardwaarden, en je kunt op elke handler timeout in seconden instellen.