ai-machine-learning

Claude Code Hooks: Den komplette utviklerguiden med produksjonsklare eksempler

Skrevet av Mert Batur
Apr 5, 2026
15 lesing
Claude Code Hooks: Den komplette utviklerguiden med produksjonsklare eksempler

Claude Code Hooks: Den komplette utviklerguiden med produksjonsklare eksempler

Claude Code er utmerket til å skrive kode, men det er fortsatt et probabilistisk system. Du kan be det kjøre Prettier etter hver filediting. Du kan legge den instruksjonen i CLAUDE.md. Og noen ganger vil det bare... glemme det. Claude Code-hooks løser dette ved å gi deg deterministisk, garantert kontroll over hva som skjer før, under og etter hver handling Claude tar.

Jeg har konfigurert hooks på tvers av dusinvis av prosjekter de siste månedene, og de har stille blitt den viktigste delen av Claude Code-oppsettet mitt. Denne guiden dekker alt fra grunnleggende til en produksjonsklar startpakke du kan slippe inn i ethvert prosjekt i dag. Har du brukt Claude Code sammen med verktøy som Cursor eller Copilot, vet du allerede verdien av tilpasning -- hooks tar det et steg videre.

Hva er Claude Code-hooks (og hvorfor bør du bry deg)?

Claude Code-hooks er brukerdefinerte shell-kommandoer, HTTP-endepunkter eller LLM-prompter som kjøres automatisk på bestemte punkter i Claude Codes livssyklus. I henhold til Anthropics offisielle dokumentasjon utløses hooks deterministisk hver gang -- i motsetning til promptinstruksjoner som Claude kan ignorere -- og gir deg garantert kontroll over formatering, sikkerhet, varsler og arbeidsflytautomatisering.

Det probabilistiske problemet

Her er saken med CLAUDE.md-instruksjoner: de er forslag, ikke kontrakter. Du kan skrive "kjør alltid npx prettier --write etter redigering av TypeScript-filer" i prosjektkonteksten din, og Claude vil følge det det meste av tiden. Men "det meste av tiden" er ikke godt nok når du håndhever kodeformatering på tvers av et team, blokkerer push til produksjon, eller logger hver shell-kommando for en sikkerhetsrevisjon.

Dette er den grunnleggende spenningen i ethvert AI-kodeverktøy. Claude er en språkmodell -- den opererer på sannsynligheter. Kontekstteknikk kan justere atferd, men kan ikke garantere den.

Hvordan hooks løser dette

Hooks omgår LLM-en helt. De er shell-skript, HTTP-kall eller AI-evalueringer som utløses ved bestemte livssyklushendelser -- før et verktøy kjører (PreToolUse), etter at det er ferdig (PostToolUse), når et varsel vises, når en økt starter, eller når Claude stopper. Tenk på dem som Git-hooks, men for AI-kodingsassistenten din.

Fire hook-typer finnes: command (shell-skript), HTTP (webhook POST-forespørsler), prompt (enkelt-turn Claude ja/nei-evalueringer) og agent (starter en underagent med verktøytilgang). Vi bryter ned hver enkelt senere -- command-hooks håndterer omtrent 90 % av det du trenger.

Slik fungerer Claude Code-hooks: Livssyklusflyten

Claude Code-hooks kjører i en definert livssyklus: en hendelse utløses (f.eks. PreToolUse), matcheren sjekker om hooken gjelder, hook-skriptet kjører og mottar JSON på stdin, og exit-koden avgjør hva som skjer. Exit-kode 0 betyr fortsett, exit-kode 2 betyr blokker handlingen. Denne flyten er den samme uansett hvilken hook-type du bruker.

Hendelse -> Matcher -> Hook -> Exit-kode (4-trinns flyten)

Slik fungerer enhver hook-kjøring:

text
1. HENDELSE UTLØSES     f.eks. PreToolUse(Write)
       |
2. MATCHER SJEKKER      Samsvarer "Write" med hookens matchermønster?
       |
3. HOOK KJØRES          Shell-skript kjøres, mottar JSON via stdin
       |
4. EXIT-KODE AVGJØR     0 = fortsett | 2 = blokker | annen = feil

JSON-en som ankommer på stdin inneholder alt om hendelsen: tool_name, tool_input (filsti, innhold, kommando) og øktmetadata. Skriptet ditt leser denne JSON-en, utfører logikken sin og avslutter med riktig kode.

For PreToolUse-hooks er exit-kode 2 den kraftige -- den blokkerer handlingen fullstendig og sender stdout-meldingen din tilbake til Claude som tilbakemelding. Claude ser meldingen din og kan justere tilnærmingen sin.

Konfigurasjonsomfang: Bruker, prosjekt og lokal

Hooks bor i settings.json på tre nivåer:

OmfangFilCommitted til Git?Brukstilfelle
Bruker~/.claude/settings.jsonNeiPersonlige standardinnstillinger (varsler, formateringspreferanser)
Prosjekt.claude/settings.jsonJaTeam-delte hooks (filbeskyttelse, testløpere, linting)
Lokal.claude/settings.local.jsonNei (gitignorert)Personlige overstyringer for dette prosjektet

Prosjektinnstillinger er mest nyttige for team. Legg hooks inn i .claude/settings.json, commit det, og alle utviklere på teamet får de samme sikkerhetstiltakene automatisk.

if-feltet: Finkornet filtrering

Siden Claude Code v2.1.85 støtter hooks et if-felt som lar deg filtrere etter verktøyargumenter -- ikke bare verktøynavn. Som dokumentert i Anthropics hooks-referanse betyr dette at du kan skrive en hook som bare utløses på Bash-kommandoer som matcher git push, i stedet for å utløses på hvert eneste Bash-kall.

json
{
  "matcher": "Bash",
  "if": "tool_input.command matches 'git push'",
  "hooks": [{ "type": "command", "command": "./scripts/check-branch.sh" }]
}

Dette var en spillveksler. Før if måtte du enten matche for bredt (alle Bash-kommandoer) eller gjøre filtreringen inne i skriptet ditt (rotete).

Alle Claude Code hook-hendelser: Hurtigreferansetabell

Claude Code tilbyr over 20 hook-hendelser på tvers av livssyklusen, som dokumentert i den offisielle hooks-referansen og Claude Code-endringsloggen. De mest brukte er PreToolUse, PostToolUse, Notification og Stop -- men nyere hendelser som ConfigChange og FileChanged åpner avanserte automatiseringsmønstre.

Her er den komplette referansen:

HendelseNår den utløsesKan blokkere?Vanlig brukstilfelle
PreToolUseFør et verktøy kjøresJa (exit 2)Blokker farlige kommandoer, beskytt filer
PostToolUseEtter at et verktøy er ferdigNeiAutoformatering, kjør tester, logg handlinger
NotificationNår Claude sender et varselNeiSkrivebordsvarsel, Slack-meldinger
StopNår Claude avslutter en responsNeiOpprydding, oppsummeringsgenerering
SessionStartVed øktinitialiseringNeiInjiser kontekst, sett miljø
UserPromptSubmitNår bruker sender en promptJa (exit 2)Inndatavalidering, innholdsfiltrering
PreCompactFør kontekstkomprimeringNeiLagre tilstand før minnet trimmes
PostCompactEtter kontekstkomprimeringNeiRe-injiser kritisk kontekst
ConfigChangeNår innstillinger endresNeiReload miljøvariabler
FileChangedNår en overvåket fil endresNeiUtløs rebuilds, ugyldiggjør cacher
TaskCreatedNår en ny oppgave opprettesNeiOppgavesporing, ressursallokering
PermissionDeniedNår en tillatelsessjekk mislykkesNeiRevisjonslogging, varsle om blokkerte handlinger
WorktreeCreateNår et nytt Git worktree opprettesNeiInitialiser worktree-spesifikke innstillinger
SubagentStartNår en underagent starterNeiOvervåk underagentaktivitet
SubagentStopNår en underagent er ferdigNeiValider underagentutdata

Protips: Du vil bruke PreToolUse og PostToolUse for 80 % av hookene dine. SessionStart er den nest mest nyttige -- den er perfekt for å injisere prosjektkontekst som Claude trenger ved starten av hver økt.

De 4 Claude Code hook-typene forklart

Claude Code støtter fire hook-handlertypes: command-hooks kjører shell-skript, HTTP-hooks sender POST til URL-er, prompt-hooks spør Claude om et ja/nei-spørsmål, og agent-hooks starter en underagent med verktøytilgang. Etter vår erfaring håndterer command-hooks 90 % av brukstilfellene. Bruk HTTP for eksterne integrasjoner, prompt og agent for nyanserte beslutninger som trenger AI-vurdering.

TypeHastighetKompleksitetBest forEksempel
CommandRaskLavFormatering, blokkering, loggingKjør Prettier etter filredigering
HTTPMiddelsMiddelsEksterne tjenester, webhooksPOST til Slack ved fullføring
PromptTregMiddelsSubjektive beslutninger"Er denne koden trygg å kjøre?"
AgentTregestHøyKompleks fil-bevisst verifiseringSjekk om ny kode følger prosjektmønstre

Command-hooks (arbeidshesten)

Command-hooks kjører en shell-kommando og bruker exit-koden til å bestemme utfallet. De mottar hendelsens JSON-data på stdin.

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "jq -r '.tool_input.command' | grep -q 'rm -rf /' && exit 2 || exit 0"
      }]
    }]
  }
}

Dette er det du vil bruke for formatering, filbeskyttelse, varsler og det meste av automatisering. Raskt, enkelt og forutsigbart.

HTTP-hooks (eksterne integrasjoner)

HTTP-hooks sender en POST-forespørsel til en URL med hendelses-JSON som body. Responsstatuskoden bestemmer utfallet (200 = fortsett, 403 = blokker).

json
{
  "hooks": {
    "Stop": [{
      "matcher": "",
      "hooks": [{
        "type": "http",
        "url": "https://your-api.com/claude-webhook"
      }]
    }]
  }
}

Flott for å sende hendelser til Slack, Discord, PagerDuty eller et egendefinert dashbord. Du kan også bruke dette til å spørre en ekstern policy-motor før du tillater en verktøykjøring.

Prompt-hooks (AI-drevne beslutninger)

Prompt-hooks sender hendelsesdataene til Claude selv for en enkelt-turn ja/nei-evaluering. Claude returnerer en JSON-respons med "decision": "allow" eller "decision": "block" pluss begrunnelse.

json
{
  "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?"
      }]
    }]
  }
}

Bruk disse med måte. De legger til ventetid (et fullt LLM-kall per hook-kjøring) og koster. Men for genuint subjektive sikkerhetskontroller -- som "ser denne databasemigreringen destruktiv ut?" -- er de vanskelige å slå. Hvis du er nysgjerrig på å bytte Claude Code-modeller, følger modellen som brukes for prompt-hooks din nåværende øktmodell.

Agent-hooks (verktøystøttet verifisering)

Agent-hooks starter en underagent med tilgang til Read-, Grep- og Glob-verktøy. Underagenten kan inspisere filer før den tar sin beslutning.

json
{
  "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-typen, men også den tregeste. Reserver den for høyrisikokontroller der du trenger filkontekst for å ta en god beslutning.

7 produksjonsklare Claude Code hook-eksempler (klar til copy-paste)

De mest nyttige Claude Code-hookene inkluderer autoformatering med Prettier eller Black etter filredigering, blokkering av skriving til beskyttede filer, sending av skrivebordsvarsel ved fullføring av oppgave, injisering av prosjektkontekst ved øktstart, kjøring av tester etter kodeendringer, håndhevelse av grensbeskyttelse og revisjon av all verktøybruk. Jeg har kjørt varianter av disse på tvers av alle prosjekter de siste tre månedene.

Hvert eksempel nedenfor er et komplett settings.json-utdrag du kan legge inn i .claude/settings.json. Fellesskapssamlinger som awesome-claude-code har enda flere mønstre.

1. Autoformater ved lagring

json
{
  "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"
      }]
    }]
  }
}

Dette utløses etter hver Write eller Edit, henter filstien fra stdin JSON og kjører riktig formater. exit 0 på slutten sikrer at hooken aldri blokkerer -- formateringsfeil bør ikke stoppe Claude.

Protips: Legg til *.go med gofmt og *.rs med rustfmt hvis du jobber på tvers av språk.

2. Blokker skriving til beskyttede filer

json
{
  "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"
      }]
    }]
  }
}

Exit-kode 2 blokkerer handlingen og sender JSON-meldingen tilbake til Claude. Claude ser tilbakemeldingen og justerer -- vanligvis vil den fortelle deg at den ønsket å endre filen og be deg gjøre det manuelt. if-feltet hindrer dette fra å utløses på hvert eneste Write.

3. Skrivebordsvarsel ved fullføring

json
{
  "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 matcheren betyr at den utløses på alle varsler. Dette er genuint nyttig når du setter i gang en lang oppgave og bytter til et annet vindu.

4. Kontekstinjeksjon ved øktstart

json
{
  "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 injiserer gjeldende prosjektnavn, Git-gren og siste commit i hver økt. Claude mottar denne konteksten automatisk -- du trenger ikke fortelle den hvilken gren du er på.

5. Autokjør tester etter kodeendringer

json
{
  "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 matchende testfil finnes, kjøres den automatisk etter at Claude redigerer kilden. tail -5 holder utdataene kortfattet, og tidsavbruddet forhindrer ukontrollerte testsett. Dette passer godt med en AI-drevet kodegjennomgang-arbeidsflyt.

6. Grensbeskyttelseshåndhevelse (avansert)

json
{
  "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 blokkerer enhver git push som er rettet mot main-, master- eller production-grener. Claude får tilbakemeldingen og vil foreslå å opprette en feature-gren i stedet.

7. Sikkerhetsrevisjonslogging (avansert)

json
{
  "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 Claude kjører til en revisjonsfil med UTC-tidsstempel. Uvurderlig for sikkerhetsgjennomganger og forståelse av hva Claude faktisk gjorde i løpet av en økt. Hold .claude/audit.log i .gitignore.

Hooks vs MCP vs Skills vs CLAUDE.md: Når bruker du hva?

Bruk hooks for deterministisk automatisering som alltid må kjøre (formatering, blokkering, varsler). Bruk MCP for å gi Claude tilgang til eksterne verktøy og data. Bruk Skills for gjenbrukbare promptpakker. Bruk CLAUDE.md for atferdsveiledning og prosjektkontekst. Hooks er garanterte; alt annet er probabilistisk. Dette er det viktigste skillet, og jeg kommer tilbake til det igjen og igjen når jeg rådgir team.

Beslutningsmatrisen

MekanismeDeterministisk?Når den kjørerBest forEksempel
HooksJaAutomatisk på livssyklushendelserHåndhevelse, automatisering, varslerAutoformat, blokker filskriving
MCPNei (Claude bestemmer)Når Claude kaller MCP-verktøyetNye funksjoner, tilgang til eksterne dataSpørr en database, søk i Notion
SkillsNei (bruker utløser)Når bruker starter en slash-kommandoGjenbrukbare instruksjonssett/review for kodegjennomgang
CLAUDE.mdNei (veiledning)Leses ved øktstartProsjektkontekst, kodestandarder"Bruk Tailwind, skriv tester for all ny kode"

For en dybdedykk på MCP, se vår MCP-guide. Kommer du fra Cursor, er Cursors regelsystem omtrent analogt med CLAUDE.md -- men Cursor har ingenting som tilsvarer hooks.

Når de overlapper (og hvordan du velger)

Her er flyten jeg bruker:

  • "Må dette skje hver eneste gang, uten unntak?" -- Hook. Formater kode, blokker beskyttede filer, send varsler. Null tvetydighet.
  • "Trenger Claude en ny FUNKSJON den ikke har?" -- MCP-server. Tilgang til en database, kall et API, søk i ekstern dokumentasjon.
  • "Vil jeg ha gjenbrukbare INSTRUKSJONER for en bestemt arbeidsflyt?" -- Skill (slash-kommando). Kodegjennomgangsmaler, distribusjonsjekklister.
  • "Vil jeg forme Claudes ATFERD i dette prosjektet?" -- CLAUDE.md. Kodestandarder, arkitekturbeslutninger, foretrukne biblioteker.

Eksempler som tydeliggjør grensen:

  • "Formater alltid med Prettier" = Hook (det må skje hver gang)
  • "Bruk Prettier for formatering" i CLAUDE.md = Veiledning (Claude kan glemme det)
  • "Søk i selskapsdokumentasjonen vår" = MCP (ny funksjon)
  • "Følg stilguiden vår ved kodegjennomgang" = Skill eller CLAUDE.md

Som beskrevet i Anthropics kunngjøring om plugins er hooks én del av et bredere plugin-økosystem som også inkluderer MCP og Skills. De er designet for å utfylle hverandre, ikke konkurrere.

Startpakken: Drop-in Claude Code hooks-konfig for ethvert prosjekt

En startpakke for hooks i Claude Code bør inkludere autoformat ved filredigering, varsel ved oppgavefullføring, filbeskyttelse for sensitive filer, økt-kontekstinjeksjon og en stop-hook for opprydding. Dette er den eksakte konfigurasjonen jeg legger inn i hvert nye prosjekt -- tilpasset stacken, men strukturen forblir den samme.

Konfigurasjonen

json
{
  "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"
      }]
    }]
  }
}

Slik tilpasser du til din stack

StackFormaterkommandoTestkommandoOvervåk utvidelser
Node/TypeScriptnpx prettier --writenpx jest --no-coverage.ts, .tsx, .js, .jsx
Pythonblackpytest -x.py
Gogofmt -wgo test ./....go
Rustrustfmtcargo test.rs

Bytt ut format- og testkommandoene i konfigurasjonen ovenfor for å matche stacken din. Strukturen forblir identisk.

Verifisering av at hookene fungerer

Tre måter å bekrefte at hooks er aktive:

  1. /hooks-kommandoen -- Skriv /hooks i Claude Code for å se alle registrerte hooks, matcherne deres og statusen.
  2. Transkriptinspeksjon -- Etter at en hook utløses, sjekk økttranskriptet. Hook-kjøringer vises med utdata og exit-kode.
  3. Rask veksling -- Legg til "disableAllHooks": true i settings.json for midlertidig å deaktivere alle hooks uten å slette konfigurasjonen. Fjern det (eller sett til false) for å reaktivere.

CI/CD-integrasjon: Claude Code-hooks i headless-modus

Claude Code-hooks fungerer i headless-modus (claude -p) med noen forskjeller: Notification-hooks utløses fortsatt, men du bør omdirigere til logging i stedet for skrivebordsvarsel. PreToolUse-hooks med exit-kode 2 kan pause headless-sesjoner for menneskelig gjennomgang. GitHub Actions bruker anthropics/claude-code-action@v1 ved siden av hooks for automatiserte arbeidsflyter.

Headless-modus-atferd

Hook-hendelseInteraktiv modusHeadless-modus (-p)CI-anbefaling
PreToolUse (exit 2)Blokkerer, viser meldingPauserer for --resumeBruk for obligatoriske menneskelige godkjenninger
PostToolUseKjører normaltKjører normaltBehold formatere og loggere
NotificationSkrivebordsvarselUtløses fortsatt (ingen UI)Omdiriger til loggfil eller Slack-webhook
StopKjører oppryddingKjører oppryddingGod for CI-artefaktinnsamling
SessionStartInjiserer kontekstInjiserer kontekstInjiser CI-miljøvariabler

Den store overraskelsen i headless-modus: PreToolUse-hooks som avslutter med kode 2 mislykkes ikke stille. De pauser sesjonen og lar deg gjenoppta med --resume, noe som gir deg et menneske-i-loopen-mønster for CI/CD-pipelines.

GitHub Actions-integrasjon

Her er en minimal GitHub Actions-arbeidsflyt som bruker Claude Code med hooks. Som dokumentert i den offisielle GitHub Actions-guiden:

yaml
- 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 }}

.claude/settings.json-hookene dine følger med repoet, så de utløses i CI akkurat som de gjør lokalt. Bare sørg for at hooks som er avhengige av skrivebordsspesifikke verktøy (som osascript) har reserveløsninger eller betingede uttrykk.

Team-hook-administrasjon

Et mønster som fungerer bra for team:

  • .claude/settings.json (committed) -- Team-delte hooks: filbeskyttelse, formatere, grensbeskyttelse. Alle får disse.
  • .claude/settings.local.json (gitignorert) -- Personlige hooks: varslingspreferanser, egendefinert logging, eksperimentelle hooks.
  • ~/.claude/settings.json (bruker-global) -- Dine standardinnstillinger på tvers av alle prosjekter: varslingstype, personlige formateringspreferanser.

Dette speiler hvordan .editorconfig (committed) og lokale IDE-innstillinger (personlige) fungerer. Som nevnt i Angelo Limas CI/CD-guide ser team som standardiserer på delte hooks færre "fungerer på min maskin"-problemer med Claude Code.

Feilsøking av Claude Code-hooks og vanlige feil

Vanlige problemer med Claude Code-hooks inkluderer hooks som ikke utløses (sjekk stavemåte på matcher og plassering av settings.json), hooks som kjører men ikke blokkerer (feil exit-kode -- bruk 2 ikke 1), uendelige løkker (Stop-hook som utløser seg selv) og treg oppstart (for mange synkrone hooks). Den vanligste feilen jeg ser er forvirring om exit-kode -- utviklere bruker exit 1 når de mener exit 2.

Hook utløses ikke

Symptomer: Du la til en hook, men ingenting skjer når hendelsen inntreffer.

Løsninger:

  • Skrivefeil i matcher -- Matchere er store og små bokstaver-sensitive. "write" vil ikke matche Write-verktøyet. Sjekk eksakte verktøynavn med /hooks.
  • Feil innstillingsfil -- Hooks i ~/.claude/settings.json vil ikke vises i /hooks-utdataene for prosjektomfanget. Prøv .claude/settings.json i prosjektets rotmappe.
  • JSON-syntaksfeil -- Et feilplassert komma eller manglende parentes deaktiverer hele hooks-konfigurasjonen stille. Kjør settings.json gjennom jq . for å validere.
  • disableAllHooks: true -- Sjekk om noen (eller en tidligere feilsøkingsøkt) har satt dette flagget.

Hook kjører, men blokkerer ikke

Symptomer: PreToolUse-hooken din kjøres, men handlingen fortsetter likevel.

Løsninger:

  • Feil exit-kode -- Exit-kode 1 betyr "feil" (hook mislyktes), ikke "blokker". Bruk exit 2 for å blokkere en handling. Dette snubler nesten alle, som nevnt i den offisielle dokumentasjonen.
  • Manglende stdout JSON -- For blokkerende hooks, skriv ut en JSON-melding slik at Claude vet hvorfor handlingen ble blokkert: echo '{"message": "Blocked: reason"}'

Uendelige løkker

Symptomer: Claude fortsetter å prøve den samme handlingen på nytt, eller maskinen din varmes opp mistenkelig.

Løsninger:

  • Stop-hook som utløser handlinger -- Hvis Stop-hooken skriver en fil eller kjører en kommando som får Claude til å svare, har du skapt en løkke. Stop-hooks bør bare gjøre passive ting: logge, varsle, rydde opp.
  • PostToolUse-hook som forårsaker redigeringer -- En PostToolUse-hook som endrer en fil utløser en annen PostToolUse-hendelse. Beskytt mot dette med spesifikke matchere eller if-feltet.

Ytelsesproblemer

Symptomer: Claude tar merkbart lengre tid å starte eller kjøre verktøy.

Løsninger:

  • For mange SessionStart-hooks -- Hver kjører synkront ved oppstart. Hold disse lette (under 1 sekund hver).
  • Tunge skript i hyppige stier -- Hooks på PreToolUse og PostToolUse utløses ofte. Hvis skriptet ditt gjør nettverksforespørsler eller tung beregning, legg til et timeout-felt (millisekunder) og vurder om det heller bør være en HTTP-hook.
  • Ingen bufring -- Hvis du sjekker det samme gjentatte ganger (som "er dette en beskyttet gren?"), cache resultatet i en temp-fil i stedet for å kjøre Git-kommandoer ved hvert hook-kall.

Ofte stilte spørsmål

Hva er Claude Code-hooks, og hvordan fungerer de?

Claude Code-hooks er brukerdefinerte automatiseringsskript som kjøres ved bestemte livssyklushendelser under en Claude Code-økt. Du konfigurerer dem i settings.json med et matchermønster og en handler (shell-kommando, HTTP-endepunkt, prompt eller agent). Når den matchende hendelsen utløses, kjøres hooken automatisk og bruker exit-koder til å kontrollere utfallet.

Hvordan konfigurerer jeg hooks i Claude Code settings.json?

Legg til et "hooks"-objekt i et av de tre konfigurasjonslokasjonene: ~/.claude/settings.json (bruker-global), .claude/settings.json (prosjektdelt), eller .claude/settings.local.json (prosjektpersonlig). Hver hendelsestype tilordnes en rekke hook-definisjoner med matcher, valgfritt if-felt og et hooks-array som inneholder handlerobjekter med type og command eller url.

Hva er forskjellen mellom PreToolUse- og PostToolUse-hooks?

PreToolUse utløses før et verktøy kjøres, og gir deg muligheten til å blokkere det med exit-kode 2. PostToolUse utløses etter at kjøringen er fullført, nyttig for formatering, testing eller logging. PreToolUse er for forebygging og portvakt. PostToolUse er for validering og opprydding. Begge mottar verktøynavn og inndata som JSON på stdin.

Kan Claude Code-hooks blokkere farlige kommandoer?

Ja. PreToolUse-hooks med exit-kode 2 blokkerer enhver verktøykjøring. Du kan beskytte sensitive filer fra å bli skrevet, blokkere shell-kommandoer som matcher farlige mønstre som rm -rf eller git push main, og forhindre tilgang til produksjonsdatabaser. Blokkeringsmeldingen sendes tilbake til Claude som tilbakemelding, slik at den kan justere tilnærmingen sin.

Hvilke hook-hendelser er tilgjengelige i Claude Code?

Claude Code tilbyr 15+ hendelser: PreToolUse og PostToolUse for verktøykjøring, Notification for varsler, Stop for øktavslutning, SessionStart for initialisering, UserPromptSubmit for inngangsfiltrering, PreCompact og PostCompact for kontekststyring, og nyere hendelser som ConfigChange, FileChanged, TaskCreated og PermissionDenied. Se den fullstendige referansetabellen i hook-hendelsesseksjonen ovenfor.

Hvordan skiller hooks seg fra MCP-verktøy og Skills?

Hooks er deterministiske -- de utløses alltid på matchende hendelser uavhengig av hva Claude bestemmer. MCP-verktøy utvider Claudes funksjoner (databasetilgang, API-kall), men Claude velger når de skal brukes. Skills er gjenbrukbare instruksjonspakker som aktiveres med slash-kommandoer. CLAUDE.md gir atferdsveiledning. Bruk hooks når noe alltid må skje, MCP når Claude trenger nye evner.

Fungerer Claude Code-hooks i headless-modus?

Ja, med forbehold. Hooks utløses normalt i headless-modus (claude -p), men skrivebordsspesifikke hooks som macOS-varsler trenger reserveløsninger. Viktig: PreToolUse-hooks som avslutter med kode 2 kan pause headless-sesjoner for menneskelig godkjenning via --resume. Dette muliggjør menneske-i-loopen CI/CD-pipelines der visse handlinger krever manuell godkjenning.

Hvor mange hooks er for mange? Gjør hooks Claude Code tregere?

Det er ingen hard grense, men hver synkron hook legger til ventetid. SessionStart-hooks kjøres ved oppstart, så hold dem raske (under 1 sekund hver). PreToolUse- og PostToolUse-hooks utløses ved hvert matchende verktøykall -- tunge skript her akkumuleres raskt. Jeg anbefaler å holde totalt antall hooks under 10-15, bruke if-feltet for å innsnevre omfanget, og legge til timeout-verdier for å forhindre ukontrollerte skript.

Kan jeg bruke hooks til å autoformatere kode med Prettier eller Black?

Ja -- det er det mest populære hook-brukstilfellet. Opprett en PostToolUse-hook som matcher Write|Edit, hent filstien fra stdin JSON og kjør riktig formater basert på filutvidelse. Se eksempel nummer én i seksjonen for produksjonseksempler for en komplett, kopy-paste-klar konfigurasjon som håndterer TypeScript-, JavaScript- og Python-filer.

Er Claude Code-hooks trygge? Hva er sikkerhetsrisikoene?

Hooks kjøres med dine fulle brukertillatelser -- det er ingen sandkasse. En ondsinnet hook kan lese SSH-nøklene dine, slette filer eller eksfiltrere data. Bruk bare hooks fra pålitelige kilder, gjennomgå delte .claude/settings.json-filer før du aksepterer dem i prosjektet ditt, og bruk .claude/settings.local.json for personlige hooks som ikke bør deles. For bredere AI-sikkerhetsmønstre, se vår LLM guardrails-guide.

Emneord

claude code hooksclaude codeutviklerverktøyAI-automatiseringarbeidsflytautomatiseringsettings.jsonPreToolUsePostToolUse

Del denne artikkelen

Kom i gang

Klar til å bygge noe ekstraordinært?

La oss gjøre visjonen din til virkelighet. Teamet vårt er klart til å hjelpe deg med å lage programvare som utgjør en forskjell.