
Claude Code Hooks: Den komplette udviklerguide med produktionsklare eksempler
Claude Code er fremragende til at skrive kode, men det er stadig et probabilistisk system. Du kan bede den om at køre Prettier efter hver filredigering. Du kan lægge den instruktion i din CLAUDE.md. Og nogle gange vil den bare... glemme det. Claude Code hooks løser dette ved at give dig deterministisk, garanteret kontrol over, hvad der sker før, under og efter hver handling, Claude udfører.
Jeg har konfigureret hooks på tværs af snesevis af projekter i løbet af de seneste par måneder, og de er stille og roligt blevet den vigtigste del af min Claude Code-opsætning. Denne guide dækker alt fra det grundlæggende til et produktionsklart startkit, du kan smide ind i ethvert projekt i dag. Hvis du har brugt Claude Code sammen med værktøjer som Cursor eller Copilot, kender du allerede værdien af tilpasning, hooks tager det et skridt videre.
Hvad er Claude Code Hooks (og hvorfor er det vigtigt for dig)?
Claude Code-hooks er brugerdefinerede shell-kommandoer, HTTP-endpoints eller LLM-prompts, der udføres automatisk på bestemte punkter i Claude Codes livscyklus. Ifølge Anthropics officielle dokumentation udløses hooks, i modsætning til promptinstruktioner, som Claude kan ignorere, deterministisk hver gang, hvilket giver dig garanteret kontrol over formatering, sikkerhed, notifikationer og workflowautomatisering.
Det probabilistiske problem
Sagen er den med CLAUDE.md-instruktioner: de er forslag, ikke kontrakter. Du kan skrive "kør altid npx prettier --write efter redigering af TypeScript-filer" i din projektkontekst, og Claude vil følge det det meste af tiden. Men "det meste af tiden" er ikke godt nok, når du håndhæver kodeformatering på tværs af et team, blokerer pushes til produktion eller logger hver eneste shell-kommando til en sikkerhedsrevision.
Dette er kernespændingen i ethvert AI-kodeværktøj. Claude er en sprogmodel, den opererer ud fra sandsynligheder. Din kontekst-engineering kan påvirke adfærden, men den kan ikke garantere den.
Hvordan hooks løser dette
Hooks omgår LLM'en fuldstændigt. De er shell-scripts, HTTP-kald eller AI-evalueringer, der udløses ved bestemte livscyklusbegivenheder – før et værktøj kører (PreToolUse), efter det er færdigt (PostToolUse), når en notifikation vises, når en session starter, eller når Claude stopper. Tænk på dem som Git hooks, men for din AI-kodeassistent.
Der findes fire hook-typer: command (shell-scripts), HTTP (webhook POST-forespørgsler), prompt (single-turn Claude ja/nej-evalueringer) og agent (starter en subagent med værktøjsadgang). Vi gennemgår hver enkelt senere – command-hooks dækker cirka 90 % af det, du får brug for.
Sådan fungerer Claude Code-hooks: Livscyklusforløbet
Claude Code-hooks afvikles i en defineret livscyklus: en hændelse udløses (f.eks. PreToolUse), matcheren kontrollerer, om hooket er relevant, hook-scripten køres og modtager JSON via stdin, og afslutningskoden bestemmer, hvad der sker derefter. Afslutningskode 0 betyder fortsæt, afslutningskode 2 betyder blokér handlingen. Dette forløb er det samme, uanset hvilken hook-type du bruger.
Hændelse -> Matcher -> Hook -> Exitkode (4-trins-flowet)
Sådan fungerer hver hook-eksekvering:
1. EVENT FIRES e.g., PreToolUse(Write)
|
2. MATCHER CHECKS Does "Write" match the hook's matcher pattern?
|
3. HOOK EXECUTES Shell script runs, receives JSON via stdin
|
4. EXIT CODE DECIDES 0 = proceed | 2 = block | other = errorDen JSON, der ankommer på stdin, indeholder alt om hændelsen: tool_name, tool_input (filsti, indhold, kommando) og sessionsmetadata. Dit script læser denne JSON, udfører den nødvendige logik og afslutter med den relevante kode.
For PreToolUse-hooks er exitkode 2 den kraftfulde — den blokerer handlingen fuldstændigt og sender din stdout-besked tilbage til Claude som feedback. Claude ser din besked og kan justere sin tilgang.
Konfigurationsscope: Bruger, projekt og lokalt
Hooks findes i settings.json på tre niveauer:
| Scope | Fil | Committes til Git? | Anvendelsestilfælde |
|---|---|---|---|
| Bruger | ~/.claude/settings.json | Nej | Personlige standardindstillinger (notifikationer, formateringspræferencer) |
| Projekt | .claude/settings.json | Ja | Teamdelte hooks (filbeskyttelse, testkørsel, linting) |
| Lokalt | .claude/settings.local.json | Nej (gitignored) | Personlige tilsidesættelser for dette projekt |
Projektindstillinger er de mest nyttige for teams. Læg dine hooks i .claude/settings.json, commit det, så får alle udviklere på teamet automatisk de samme sikkerhedsrammer.
if-feltet: Finkornet filtrering
Siden Claude Code v2.1.85 har hooks understøttet et if-felt, der lader dig filtrere efter værktøjsargumenter og ikke kun efter værktøjsnavne. Som dokumenteret i Anthropic hooks-referencen betyder det, at du kan skrive et hook, der kun udløses ved Bash-kommandoer, der matcher git push, i stedet for at fyre ved hver eneste Bash-kørsel.
{
"matcher": "Bash",
"if": "tool_input.command matches 'git push'",
"hooks": [{ "type": "command", "command": "./scripts/check-branch.sh" }]
}Dette var en stor forbedring. Før if matchede du enten for bredt (alle Bash-kommandoer) eller foretog filtreringen inde i dit script (rodet).
Alle Claude Code Hook-begivenheder: Hurtig oversigtstabel
Claude Code tilbyder over 20 hook-begivenheder på tværs af sin livscyklus, som dokumenteret i den officielle hooks-reference og Claude Code-ændringsloggen. De mest anvendte er PreToolUse, PostToolUse, Notification og Stop, men nyere begivenheder som ConfigChange og FileChanged åbner op for avancerede automatiseringsmønstre.
Her er den komplette reference:
| Begivenhed | Hvornår den udløses | Kan blokere? | Almindeligt anvendelsestilfælde |
|---|---|---|---|
| PreToolUse | Før et værktøj udføres | Ja (exit 2) | Bloker farlige kommandoer, beskyt filer |
| PostToolUse | Efter et værktøj er færdigt | Nej | Auto-formatering, kør tests, log handlinger |
| Notification | Når Claude sender en notifikation | Nej | Skrivebordsadvarsler, Slack-beskeder |
| Stop | Når Claude afslutter et svar | Nej | Oprydning, generering af opsummering |
| SessionStart | Ved sessionsinitialisering | Nej | Injicer kontekst, opsæt miljø |
| UserPromptSubmit | Når brugeren indsender en prompt | Ja (exit 2) | Inputvalidering, indholdsfiltrering |
| PreCompact | Før kontekstkomprimering | Nej | Gem tilstand, før hukommelsen beskæres |
| PostCompact | Efter kontekstkomprimering | Nej | Geninjicer kritisk kontekst |
| ConfigChange | Når indstillinger ændres | Nej | Genindlæs miljøvariabler i realtid |
| FileChanged | Når en overvåget fil ændres | Nej | Udløs genopbygninger, ugyldiggør caches |
| TaskCreated | Når en ny opgave oprettes | Nej | Opgavesporing, ressourcetildeling |
| PermissionDenied | Når en tilladelseskontrol fejler | Nej | Revisionslogføring, advar ved blokerede handlinger |
| WorktreeCreate | Når et nyt Git worktree oprettes | Nej | Initialiser worktree-specifikke indstillinger |
| SubagentStart | Når en subagent startes | Nej | Overvåg subagentaktivitet |
| SubagentStop | Når en subagent er færdig | Nej | Valider subagentoutput |
Pro tip: Du vil bruge PreToolUse og PostToolUse til 80 % af dine hooks. SessionStart er den næstmest nyttige — den er perfekt til at injicere projekt kontekst, som Claude har brug for ved starten af hver session.
De 4 Claude Code Hook-typer forklaret
Claude Code understøtter fire hook-handler-typer: command-hooks kører shell-scripts, HTTP-hooks POSTer til URL'er, prompt-hooks stiller Claude et ja/nej-spørgsmål, og agent-hooks starter en subagent med adgang til værktøjer. Vores erfaring er, at command-hooks dækker 90 % af alle use cases. Brug HTTP til eksterne integrationer, og prompt- og agent-hooks til nuancerede beslutninger, der kræver AI-vurdering.
| Type | Hastighed | Kompleksitet | Bedst til | Eksempel |
|---|---|---|---|---|
| Command | Hurtig | Lav | Formatering, blokering, logning | Kør Prettier efter filredigering |
| HTTP | Medium | Medium | Eksterne tjenester, webhooks | POST til Slack ved færdiggørelse |
| Prompt | Langsom | Medium | Subjektive beslutninger | "Er denne kode sikker at køre?" |
| Agent | Langsomst | Høj | Kompleks filbevidst verifikation | Tjek om ny kode følger projektets mønstre |
Kommando-hooks (Arbejdshesten)
Kommando-hooks kører en shell-kommando og bruger exitkoden til at bestemme resultatet. De modtager begivenhedens JSON-data på stdin.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.command' | grep -q 'rm -rf /' && exit 2 || exit 0"
}]
}]
}
}Det er denne, du vil bruge til formatering, filbeskyttelse, notifikationer og det meste automatisering. Hurtig, enkel og forudsigelig.
HTTP Hooks (eksterne integrationer)
HTTP-hooks sender en POST-forespørgsel til en URL med event-JSON'en som body. Statuskoden i svaret afgør udfaldet (200 = fortsæt, 403 = blokér).
{
"hooks": {
"Stop": [{
"matcher": "",
"hooks": [{
"type": "http",
"url": "https://your-api.com/claude-webhook"
}]
}]
}
}Perfekt til at sende events til Slack, Discord, PagerDuty eller et brugerdefineret dashboard. Du kan også bruge det til at forespørge en ekstern policy-engine, før du tillader udførelse af et værktøj.
Prompt-hooks (AI-drevne beslutninger)
Prompt-hooks sender eventdataene til selve Claude til en ja/nej-vurdering i én runde. Claude returnerer et JSON-svar med "decision": "allow" eller "decision": "block" samt en begrundelse.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "prompt",
"prompt": "Is this bash command safe to run in a production environment? Consider: does it modify system files, delete data, or access sensitive credentials?"
}]
}]
}
}Brug dem sparsomt. De tilføjer latenstid (et fuldt LLM-kald pr. hook-eksekvering) og omkostninger. Men til reelt subjektive sikkerhedstjek, som "ser denne databasemigrering destruktiv ud?", er de svære at overgå. Hvis du er nysgerrig efter at skifte Claude Code-model, følger den model, der bruges til prompt-hooks, din nuværende sessionsmodel.
Agent Hooks (værktøjsassisteret verifikation)
Agent hooks spawner en underagent med adgang til værktøjerne Read, Grep og Glob. Underagenten kan inspicere filer, før den træffer sin beslutning.
{
"hooks": {
"PreToolUse": [{
"matcher": "Write",
"hooks": [{
"type": "agent",
"prompt": "Check if the file being written follows the project's naming conventions and import patterns. Read .claude/CONVENTIONS.md for the rules."
}]
}]
}
}Dette er den kraftigste hook-type, men også den langsomste. Forbehold den til kritiske kontroller, hvor du har brug for filkontekst for at træffe en god beslutning.
7 produktionsklare Claude Code Hook-eksempler (klar til at kopiere og indsætte)
De mest nyttige Claude Code hooks omfatter automatisk formatering med Prettier eller Black efter filredigeringer, blokering af skrivning til beskyttede filer, afsendelse af skrivebordsnotifikationer ved opgaveafslutning, injicering af projektkontekst ved sessionsstart, kørsel af tests efter kodeændringer, håndhævelse af branch-beskyttelse og revision af al værktøjsbrug. Jeg har kørt variationer af disse på tværs af alle projekter i de seneste tre måneder.
Hvert eksempel nedenfor er et komplet settings.json-uddrag, som du kan indsætte i din .claude/settings.json. Community-samlinger som awesome-claude-code har endnu flere mønstre.
1. Automatisk formatering ved gemning
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "FILE=$(jq -r '.tool_input.file_path // .tool_input.file' /dev/stdin); case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) black \"$FILE\" 2>/dev/null;; esac; exit 0"
}]
}]
}
}Denne udløses efter hver Write eller Edit, udtrækker filstien fra stdin-JSON'en og kører det relevante formateringsprogram. exit 0 i slutningen sikrer, at hooken aldrig blokerer — formateringsfejl bør ikke stoppe Claude.
Proftip: Tilføj *.go med gofmt og *.rs med rustfmt, hvis du arbejder på tværs af sprog.
2. Bloker skrivning til beskyttede filer
{
"hooks": {
"PreToolUse": [{
"matcher": "Write|Edit",
"if": "tool_input.file_path matches '(\\.env|\\.env\\.local|package-lock\\.json|yarn\\.lock|pnpm-lock\\.yaml)'",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"BLOCKED: This file is protected. Edit it manually.\"}' && exit 2"
}]
}]
}
}Exitkode 2 blokerer handlingen og sender JSON-beskeden tilbage til Claude. Claude ser feedbacken og justerer sig — typisk fortæller den dig, at den ville ændre filen, og beder dig om at gøre det manuelt. if-feltet forhindrer, at dette udløses ved hver eneste Write.
3. Skrivebordsnotifikation ved fuldførelse
{
"hooks": {
"Notification": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "MSG=$(jq -r '.message // \"Claude Code task finished\"' /dev/stdin); if [ \"$(uname)\" = 'Darwin' ]; then osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\"; else notify-send 'Claude Code' \"$MSG\"; fi; exit 0"
}]
}]
}
}Fungerer på macOS (osascript) og Linux (notify-send). Den tomme matcher betyder, at den udløses ved alle notifikationer. Dette er virkelig nyttigt, når du sætter en lang opgave i gang og skifter til et andet vindue.
4. Kontekstindsprøjtning ved sessionsstart
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"Project: '\"$(basename $(pwd))\"' | Branch: '\"$(git branch --show-current 2>/dev/null || echo none)\"' | Last commit: '\"$(git log --oneline -1 2>/dev/null || echo none)\"'\"}'; exit 0"
}]
}]
}
}Dette indsætter det aktuelle projektnavn, Git-grenen og det seneste commit i hver session. Claude modtager denne kontekst automatisk – du behøver ikke at fortælle den, hvilken gren du befinder dig på.
5. Kør automatisk tests efter kodeændringer
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"if": "tool_input.file_path matches '\\.(ts|tsx|js|jsx|py)$'",
"hooks": [{
"type": "command",
"command": "FILE=$(jq -r '.tool_input.file_path' /dev/stdin); TEST_FILE=$(echo \"$FILE\" | sed 's/\\.[^.]*$/.test&/'); if [ -f \"$TEST_FILE\" ]; then npx jest \"$TEST_FILE\" --no-coverage 2>&1 | tail -5; fi; exit 0",
"timeout": 30000
}]
}]
}
}Hvis en tilsvarende testfil findes, køres den automatisk, efter at Claude har redigeret kildekoden. tail -5 holder outputtet kortfattet, og timeouten forhindrer løbske testsuiter. Dette fungerer godt sammen med en AI-drevet kodegennemgang-workflow.
6. Håndhævelse af branch-beskyttelse (avanceret)
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"if": "tool_input.command matches 'git push.*(main|master|production)'",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"BLOCKED: Direct push to protected branch. Use a feature branch and open a PR.\"}' && exit 2"
}]
}]
}
}Dette blokerer enhver git push, der har main, master eller production-brancher som mål. Claude modtager feedbacken og vil foreslå at oprette en feature-branch i stedet.
7. Logning af sikkerhedsrevision (avanceret)
{
"hooks": {
"PostToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "INPUT=$(cat /dev/stdin); CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command'); echo \"[$(date -u +%Y-%m-%dT%H:%M:%SZ)] BASH: $CMD\" >> .claude/audit.log; exit 0"
}]
}]
}
}Logger hver Bash-kommando, som Claude udfører, til en revisionsfil med et UTC-tidsstempel. Uundværlig til sikkerhedsgennemgange og til at forstå, hvad Claude faktisk foretog sig under en session. Sørg for, at .claude/audit.log står i din .gitignore.
Hooks vs. MCP vs. Skills vs. CLAUDE.md: Hvornår bruger man hvad
Brug hooks til deterministisk automatisering, der altid skal køre (formatering, blokering, notifikationer). Brug MCP til at give Claude adgang til eksterne værktøjer og data. Brug Skills til genanvendelige prompt-pakker. Brug CLAUDE.md til adfærdsvejledning og projektkontekst. Hooks er garanterede; alt andet er probabilistisk. Det er den absolut vigtigste skelnen, og jeg vender tilbage til den igen og igen, når jeg rådgiver teams.
Beslutningsmatricen
| Mekanisme | Deterministisk? | Hvornår den kører | Bedst til | Eksempel |
|---|---|---|---|---|
| Hooks | Ja | Automatisk ved livscyklushændelser | Håndhævelse, automatisering, notifikationer | Auto-formatér, blokér filskrivninger |
| MCP | Nej (Claude beslutter) | Når Claude kalder MCP-værktøjet | Nye funktioner, adgang til eksterne data | Forespørg i en database, søg i Notion |
| Skills | Nej (brugeren udløser) | Når brugeren kalder en slash-kommando | Genanvendelige instruktionssæt | /review til kodegennemgangsworkflow |
| CLAUDE.md | Nej (vejledning) | Læses ved sessionens start | Projektkontekst, kodestandarder | "Brug Tailwind, skriv tests til al ny kode" |
For en dybdegående gennemgang af MCP, se vores MCP-guide. Hvis du kommer fra Cursor, minder Cursors regelsystem nogenlunde om CLAUDE.md, men Cursor har ikke noget, der ligner hooks.
Når de overlapper (og hvordan du vælger)
Her er det flowdiagram, jeg bruger:
- "Skal det her ske hver eneste gang, uden undtagelser?", Hook. Formatér kode, blokér beskyttede filer, send notifikationer. Nul tvetydighed.
- "Har Claude brug for en ny KAPACITET, den ikke har?", MCP-server. Tilgå en database, kald en API, søg i eksterne dokumenter.
- "Vil jeg have genanvendelige INSTRUKTIONER til et bestemt workflow?", Skill (slash-kommando). Kodegennemgangs-skabeloner, deployment-tjeklister.
- "Vil jeg forme Claudes ADFÆRD i dette projekt?", CLAUDE.md. Kodestandarder, arkitekturbeslutninger, foretrukne biblioteker.
Rigtige eksempler, der tydeliggør grænsen:
- "Formatér altid med Prettier" = Hook (det skal ske hver gang)
- "Brug Prettier til formatering" i CLAUDE.md = Vejledning (Claude kan glemme det)
- "Søg i vores virksomhedsdokumenter" = MCP (ny kapacitet)
- "Følg vores style guide ved kodegennemgang" = Skill eller CLAUDE.md
Som beskrevet i Anthropics plugins-annoncering er hooks én del af et bredere plugin-økosystem, der også omfatter MCP og Skills. De er designet til at supplere hinanden, ikke konkurrere.
Startpakken: Drop-in Claude Code Hooks-konfiguration til ethvert projekt
En startkonfiguration af hooks til Claude Code bør omfatte automatisk formatering ved filredigering, notifikation ved opgaveafslutning, filbeskyttelse af følsomme filer, injicering af sessionskontekst samt et stop-hook til oprydning. Det er præcis den konfiguration, jeg smider ind i hvert nyt projekt, tilpasset stakken, men strukturen forbliver den samme.
Konfigurationen
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"Project: '\"$(basename $(pwd))\"' | Branch: '\"$(git branch --show-current 2>/dev/null)\"' | Node: '\"$(node -v 2>/dev/null)\"'\"}'; exit 0"
}]
}],
"PreToolUse": [{
"matcher": "Write|Edit",
"if": "tool_input.file_path matches '(\\.env|\\.env\\..+|.*lock\\.json|.*lock\\.yaml)'",
"hooks": [{
"type": "command",
"command": "echo '{\"message\": \"Protected file. Edit manually.\"}' && exit 2"
}]
}],
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "FILE=$(jq -r '.tool_input.file_path // .tool_input.file' /dev/stdin); case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) black \"$FILE\" 2>/dev/null;; *.go) gofmt -w \"$FILE\" 2>/dev/null;; esac; exit 0"
}]
}],
"Notification": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "MSG=$(jq -r '.message // \"Done\"' /dev/stdin); osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\" 2>/dev/null || notify-send 'Claude Code' \"$MSG\" 2>/dev/null; exit 0"
}]
}],
"Stop": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "echo '[STOP] '\"$(date +%H:%M:%S)\"'' >> .claude/session.log; exit 0"
}]
}]
}
}Sådan tilpasser du til din stak
| Stak | Formateringskommando | Testkommando | Overvågede filendelser |
|---|---|---|---|
| Node/TypeScript | npx prettier --write | npx jest --no-coverage | .ts, .tsx, .js, .jsx |
| Python | black | pytest -x | .py |
| Go | gofmt -w | go test ./... | .go |
| Rust | rustfmt | cargo test | .rs |
Udskift formaterings- og testkommandoerne i konfigurationen ovenfor, så de passer til din stak. Strukturen forbliver identisk.
Bekræftelse af, at dine hooks fungerer
Tre måder at bekræfte, at hooks er aktive:
/hooks-kommandoen, Skriv/hooksi Claude Code for at se alle registrerede hooks, deres matchers og deres status.- Inspektion af transskriptet, Når et hook udløses, skal du tjekke sessionens transskript. Hook-kørsler vises med deres output og exit code.
- Hurtig til/fra-kontakt, Tilføj
"disableAllHooks": truetil din settings.json for midlertidigt at deaktivere alle hooks uden at slette konfigurationen. Fjern den (eller sæt den tilfalse) for at genaktivere.
CI/CD-integration: Claude Code Hooks i headless-tilstand
Claude Code hooks fungerer i headless-tilstand (claude -p) med nogle forskelle: Notifikations-hooks udløses stadig, men du bør omdirigere til logning i stedet for skrivebordsadvarsler. PreToolUse-hooks med afslutningskode 2 kan sætte headless-sessioner på pause til menneskelig gennemgang. GitHub Actions bruger anthropics/claude-code-action@v1 sammen med hooks til automatiserede workflows.
Headless-tilstandsadfærd
| Hook-hændelse | Interaktiv tilstand | Headless-tilstand (-p) | CI-anbefaling |
|---|---|---|---|
| PreToolUse (exit 2) | Blokerer, viser besked | Pauser og venter på --resume | Brug til obligatoriske menneskelige godkendelser |
| PostToolUse | Kører normalt | Kører normalt | Behold formatters og loggers |
| Notification | Skrivebordsnotifikation | Udløses stadig (ingen UI) | Omdiriger til logfil eller Slack-webhook |
| Stop | Kører oprydning | Kører oprydning | God til CI-artefaktindsamling |
| SessionStart | Injicerer kontekst | Injicerer kontekst | Injicer CI-miljøvariabler |
Den store overraskelse i headless-tilstand: PreToolUse-hooks, der afsluttes med kode 2, fejler ikke bare lydløst. De pauser sessionen og lader dig genoptage med --resume, hvilket giver dig et human-in-the-loop-mønster til CI-pipelines.
GitHub Actions-integration
Her er et minimalt GitHub Actions-workflow, der bruger Claude Code med hooks. Som dokumenteret i den officielle GitHub Actions-guide:
- name: Run Claude Code
uses: anthropics/claude-code-action@v1
with:
prompt: "Review this PR and suggest improvements"
allowed_tools: "Read,Grep,Glob"
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}Dine .claude/settings.json-hooks følger med repoet, så de udløses i CI præcis som lokalt. Sørg blot for, at hooks, der afhænger af skrivebordsspecifikke værktøjer (som osascript), har fallbacks eller betingelser.
Hook-håndtering for teams
Et mønster, der fungerer godt for teams:
.claude/settings.json(committed), delte team-hooks: filbeskyttelse, formatters, branch-beskyttelse. Alle får disse..claude/settings.local.json(gitignored), personlige hooks: notifikationspræferencer, tilpasset logning, eksperimentelle hooks.~/.claude/settings.json(user-global), dine standardindstillinger på tværs af alle projekter: notifikationsstil, personlige formateringspræferencer.
Dette afspejler, hvordan .editorconfig (committed) og lokale IDE-indstillinger (personlige) fungerer. Som bemærket i Angelo Limas CI/CD-guide oplever teams, der standardiserer på delte hooks, færre "det virker på min maskine"-problemer med Claude Code.
Fejlfinding af Claude Code-hooks og almindelige fejl
Almindelige problemer med Claude Code-hooks omfatter hooks, der ikke udløses (tjek stavningen af matcher og placeringen af settings.json), hooks, der kører men ikke blokerer (forkert exit-kode – brug 2, ikke 1), uendelige loops (Stop-hook, der udløser sig selv) og langsom opstart (for mange synkrone hooks). Den mest almindelige fejl, jeg ser, er forvirring om exit-koder: udviklere bruger exit 1, når de mener exit 2.
Hook udløses ikke
Symptomer: Du har tilføjet en hook, men der sker intet, når begivenheden indtræffer.
Løsninger:
- Matcher-stavefejl, Matchere skelner mellem store og små bogstaver.
"write"matcher ikkeWrite-værktøjet. Kontroller de præcise værktøjsnavne med/hooks. - Forkert indstillingsfil, Hooks i
~/.claude/settings.jsonvises ikke i/hooks-outputtet for projektets scope. Prøv.claude/settings.jsoni projektets rod. - JSON-syntaksfejl, Et overskydende komma eller en manglende parentes deaktiverer lydløst hele hooks-konfigurationen. Kør din settings.json gennem
jq .for at validere den. disableAllHooks: true, Kontroller, om nogen (eller en tidligere fejlfindingssession) har efterladt dette flag slået til.
Hook kører, men blokerer ikke
Symptomer: Din PreToolUse-hook kører, men handlingen fortsætter alligevel.
Løsninger:
- Forkert exit-kode, Exit-kode 1 betyder "fejl" (hooken fejlede), ikke "blokering." Brug
exit 2til at blokere en handling. Det snubler næsten alle over, som det også bemærkes i den officielle dokumentation. - Manglende stdout-JSON, For blokerende hooks skal du udskrive en JSON-besked, så Claude ved, hvorfor handlingen blev blokeret:
echo '{"message": "Blocked: reason"}'
Uendelige loops
Symptomer: Claude bliver ved med at gentage den samme handling, eller din maskine bliver mistænkeligt varm.
Løsninger:
- Stop-hook udløser handlinger – Hvis din Stop-hook skriver en fil eller kører en kommando, der får Claude til at svare, har du skabt et loop. Stop-hooks bør kun udføre passive handlinger: logge, underrette, rydde op.
- PostToolUse-hook forårsager redigeringer – En PostToolUse-hook, der ændrer en fil, udløser endnu en PostToolUse-hændelse. Beskyt mod dette med specifikke matchers eller
if-feltet.
Ydelsesproblemer
Symptomer: Claude er mærkbart længere tid om at starte eller udføre værktøjer.
Løsninger:
- For mange SessionStart-hooks, Hver enkelt kører synkront ved opstart. Hold dem lette (under 1 sekund hver).
- Tunge scripts i hyppigt eksekverede stier, Hooks ved PreToolUse og PostToolUse udløses ofte. Hvis dit script udfører netværksanmodninger eller tung beregning, så tilføj et
timeout-felt (millisekunder) og overvej, om det i stedet bør være en HTTP-hook. - Ingen caching, Hvis du kontrollerer det samme gentagne gange (som "er dette en beskyttet branch?"), så cache resultatet i en midlertidig fil i stedet for at køre Git-kommandoer ved hver hook-aktivering.
Ofte stillede spørgsmål
Hvad er Claude Code hooks, og hvordan fungerer de?
Claude Code hooks er brugerdefinerede automatiseringsscripts, der udføres ved bestemte livscyklusbegivenheder i løbet af en Claude Code-session. Du konfigurerer dem i settings.json med et matcher-mønster og en handler (shell-kommando, HTTP-endpoint, prompt eller agent). Når den matchende begivenhed udløses, kører hooket automatisk og bruger afslutningskoder (exit codes) til at styre resultatet.
Hvordan konfigurerer jeg hooks i Claude Code settings.json?
Tilføj et \"hooks\"-objekt til en af de tre konfigurationsplaceringer: ~/.claude/settings.json (brugerglobale), .claude/settings.json (projektdelte) eller .claude/settings.local.json (projektpersonlige). Hver begivenhedstype knyttes til et array af hook-definitioner med en matcher, et valgfrit if-felt samt et hooks-array, der indeholder handler-objekter med type og command eller url.
Hvad er forskellen mellem PreToolUse- og PostToolUse-hooks?
PreToolUse udløses, før et værktøj udføres, og giver dig mulighed for at blokere det med exitkode 2. PostToolUse udløses, når udførelsen er fuldført, og er nyttig til formatering, test eller logning. PreToolUse bruges til forebyggelse og adgangskontrol. PostToolUse bruges til validering og oprydning. Begge modtager værktøjets navn og input som JSON via stdin.
Kan Claude Code-hooks blokere farlige kommandoer?
Ja. PreToolUse-hooks med afslutningskode 2 blokerer enhver udførelse af værktøjer. Du kan beskytte følsomme filer mod at blive overskrevet, blokere shell-kommandoer, der matcher farlige mønstre som rm -rf eller git push main, og forhindre adgang til produktionsdatabaser. Blokeringsbeskeden sendes tilbage til Claude som feedback, så den kan justere sin tilgang.
Hvilke hook-hændelser er tilgængelige i Claude Code?
Claude Code tilbyder 15+ hændelser: PreToolUse og PostToolUse til værktøjskørsel, Notification til advarsler, Stop til sessionsafslutning, SessionStart til initialisering, UserPromptSubmit til inputfiltrering, PreCompact og PostCompact til kontekststyring samt nyere hændelser som ConfigChange, FileChanged, TaskCreated og PermissionDenied. Se den fulde referencetabel i afsnittet om hook-hændelser ovenfor.
Hvordan adskiller hooks sig fra MCP-værktøjer og Skills?
Hooks er deterministiske – de udløses altid ved matchende begivenheder, uanset hvad Claude beslutter. MCP-værktøjer udvider Claudes muligheder (databaseadgang, API-kald), men Claude vælger selv, hvornår de skal bruges. Skills er genanvendelige instruktionspakker, der aktiveres via skråstregskommandoer. CLAUDE.md giver adfærdsmæssig vejledning. Brug hooks, når noget skal ske hver gang, og MCP, når Claude har brug for nye evner.
Virker Claude Code-hooks i headless-tilstand?
Ja, men med visse forbehold. Hooks udløses normalt i headless-tilstand (claude -p), men skrivebordsspecifikke hooks som macOS-notifikationer kræver fallbacks. Det er værd at bemærke, at PreToolUse-hooks, der afsluttes med kode 2, kan sætte headless-sessioner på pause for at afvente menneskelig godkendelse via --resume. Dette muliggør human-in-the-loop CI/CD-pipelines, hvor bestemte handlinger kræver manuel godkendelse.
Hvor mange hooks er for mange? Gør hooks Claude Code langsommere?
Der er ingen hård grænse, men hvert synkront hook tilføjer latenstid. SessionStart-hooks køres ved opstart, så hold dem hurtige (under 1 sekund hver). PreToolUse- og PostToolUse-hooks udløses ved hvert matchende værktøjskald, og tunge scripts her hober sig hurtigt op. Jeg vil anbefale at holde det samlede antal hooks under 10-15, bruge if-feltet til at indsnævre omfanget og tilføje timeout-værdier for at forhindre løbske scripts.
Kan jeg bruge hooks til automatisk at formatere kode med Prettier eller Black?
Ja, det er det mest populære brugstilfælde for hooks. Opret en PostToolUse-hook, der matcher Write|Edit, udtræk filstien fra stdin-JSON'en, og kør den relevante formatering baseret på filtypenavnet. Se eksempel nummer ét i sektionen med produktionseksempler for en komplet, kopier-og-indsæt-klar konfiguration, der håndterer TypeScript-, JavaScript- og Python-filer.
Er Claude Codes hooks sikre? Hvilke sikkerhedsrisici er der?
Hooks afvikles med dine fulde brugerrettigheder — der er ingen sandbox. En ondsindet hook kunne læse dine SSH-nøgler, slette filer eller eksfiltrere data. Brug kun hooks fra betroede kilder, gennemgå enhver delt .claude/settings.json, før du accepterer den i dit projekt, og brug .claude/settings.local.json til personlige hooks, som ikke bør deles. For bredere AI-sikkerhedsmønstre, se vores LLM-guardrails-vejledning.