
Claude Code Hooks: Den kompletta utvecklarguiden med produktionsklara exempel
Claude Code är utmärkt på att skriva kod, men det är ändå ett probabilistiskt system. Du kan be det köra Prettier efter varje filredigering. Du kan lägga in den instruktionen i din CLAUDE.md. Och ibland glömmer det... ändå. Claude Code hooks löser det här genom att ge dig deterministisk, garanterad kontroll över vad som händer före, under och efter varje åtgärd som Claude utför.
Jag har konfigurerat hooks i dussintals projekt under de senaste månaderna, och de har tyst blivit den viktigaste delen av min Claude Code-konfiguration. Den här guiden täcker allt från grunderna till ett produktionsklart startpaket som du kan använda i vilket projekt som helst idag. Om du har använt Claude Code tillsammans med verktyg som Cursor eller Copilot vet du redan värdet av anpassning -- hooks tar det ett steg längre.
Vad är Claude Code Hooks (och varför ska du bry dig)?
Claude Code hooks är användardefinierade skalkommandon, HTTP-endpoints eller LLM-prompter som körs automatiskt vid specifika punkter i Claude Codes livscykel. Enligt Anthropics officiella dokumentation aktiveras hooks deterministiskt varje gång -- till skillnad från promptinstruktioner som Claude kan ignorera -- och ger dig garanterad kontroll över formattering, säkerhet, notiser och arbetsflödesautomatisering.
Det probabilistiska problemet
Här är det knepiga med CLAUDE.md-instruktioner: de är förslag, inte kontrakt. Du kan skriva "kör alltid npx prettier --write efter redigering av TypeScript-filer" i din projektkonfiguration, och Claude följer det för det mesta. Men "för det mesta" räcker inte när du tillämpar kodformattering i ett team, eller blockerar pushar till produktion, eller loggar varje skalkommando för en säkerhetsrevision.
Det här är den grundläggande spänningen i alla AI-kodverktyg. Claude är en språkmodell -- den arbetar med sannolikheter. Din context engineering kan styra beteendet, men kan inte garantera det.
Hur hooks löser det här
Hooks kringgår LLM:en helt. De är skalskript, HTTP-anrop eller AI-utvärderingar som aktiveras vid specifika livscykelhändelser -- innan ett verktyg körs (PreToolUse), efter att det är klart (PostToolUse), när ett meddelande visas, när en session startar, eller när Claude slutar. Tänk på dem som Git-hooks, men för din AI-kodassistent.
Det finns fyra hook-typer: command (skalskript), HTTP (webhook POST-förfrågningar), prompt (enstaka Claude ja/nej-utvärderingar) och agent (skapar en underagent med verktygsåtkomst). Vi går igenom varje typ senare -- command-hooks hanterar ungefär 90 % av vad du behöver.
Hur Claude Code Hooks fungerar: Livscykelflödet
Claude Code hooks körs i ett definierat livscykelflöde: en händelse aktiveras (t.ex. PreToolUse), matcharen kontrollerar om hooken gäller, hook-skriptet körs och tar emot JSON via stdin, och exit-koden avgör vad som händer härnäst. Exit-kod 0 innebär att fortsätta, exit-kod 2 innebär att blockera åtgärden. Det här flödet är detsamma oavsett vilken hook-typ du använder.
Händelse -> Matchare -> Hook -> Exit-kod (det 4-stegsflödet)
Så här fungerar varje hook-körning:
1. HÄNDELSE AKTIVERAS t.ex. PreToolUse(Write)
|
2. MATCHARE KONTROLLERAR Matchar "Write" hookens matcharmönster?
|
3. HOOK KÖRS Skalskript körs, tar emot JSON via stdin
|
4. EXIT-KOD BESTÄMMER 0 = fortsätt | 2 = blockera | annat = felJSON:en som kommer via stdin innehåller allt om händelsen: tool_name, tool_input (filsökväg, innehåll, kommando) och sessionsmetadata. Ditt skript läser denna JSON, utför den logik det behöver och avslutar med lämplig kod.
För PreToolUse-hooks är exit-kod 2 den kraftfulla -- den blockerar åtgärden helt och skickar ditt stdout-meddelande tillbaka till Claude som feedback. Claude ser ditt meddelande och kan justera sitt tillvägagångssätt.
Konfigurationsomfång: Användare, projekt och lokalt
Hooks finns i settings.json på tre nivåer:
| Omfång | Fil | Committed till Git? | Användningsfall |
|---|---|---|---|
| Användare | ~/.claude/settings.json | Nej | Personliga standardinställningar (notiser, formatteringsinställningar) |
| Projekt | .claude/settings.json | Ja | Team-delade hooks (filskydd, testkörnare, linting) |
| Lokalt | .claude/settings.local.json | Nej (gitignorerad) | Personliga overrides för det här projektet |
Projektinställningar är mest användbara för team. Lägg in dina hooks i .claude/settings.json, commita det, och varje utvecklare i teamet får samma skyddsräcken automatiskt.
Fältet if: Detaljerad filtrering
Sedan Claude Code v2.1.85 stöder hooks ett if-fält som låter dig filtrera på verktygsargument -- inte bara verktygsnamn. Som dokumenterat i Anthropics hooks-referens innebär det att du kan skriva en hook som bara aktiveras på Bash-kommandon som matchar git push, istället för att aktiveras vid varje enskilt Bash-anrop.
{
"matcher": "Bash",
"if": "tool_input.command matches 'git push'",
"hooks": [{ "type": "command", "command": "./scripts/check-branch.sh" }]
}Det här var en game-changer. Innan if var du tvungen att antingen matcha för brett (varje Bash-kommando) eller göra filtreringen inuti ditt skript (rörigt).
Alla Claude Code Hook-händelser: Snabbreferenstabell
Claude Code tillhandahåller över 20 hook-händelser i sin livscykel, dokumenterade i den officiella hooks-referensen och Claude Code-ändringsloggen. De vanligast använda är PreToolUse, PostToolUse, Notification och Stop -- men nyare händelser som ConfigChange och FileChanged öppnar upp avancerade automatiseringsmönster.
Här är den kompletta referensen:
| Händelse | När den aktiveras | Kan blockera? | Vanligt användningsfall |
|---|---|---|---|
| PreToolUse | Innan ett verktyg körs | Ja (exit 2) | Blockera farliga kommandon, skydda filer |
| PostToolUse | Efter att ett verktyg är klart | Nej | Autoformattera, kör tester, logga åtgärder |
| Notification | När Claude skickar ett meddelande | Nej | Skrivbordsvarningar, Slack-meddelanden |
| Stop | När Claude avslutar ett svar | Nej | Städning, sammanfattningsgenerering |
| SessionStart | Vid sessionsinitialisering | Nej | Injicera kontext, ställ in miljö |
| UserPromptSubmit | När användaren skickar en prompt | Ja (exit 2) | Inmatningsvalidering, innehållsfiltrering |
| PreCompact | Innan kontextkomprimering | Nej | Spara tillstånd innan minnet trimmas |
| PostCompact | Efter kontextkomprimering | Nej | Injicera om kritisk kontext |
| ConfigChange | När inställningar ändras | Nej | Heta omladdning av miljövariabler |
| FileChanged | När en bevakad fil ändras | Nej | Utlösa byggen, invalidera cacher |
| TaskCreated | När en ny uppgift skapas | Nej | Uppgiftsspårning, resursallokering |
| PermissionDenied | När en behörighetskontroll misslyckas | Nej | Revisionsloggning, avisering om blockerade åtgärder |
| WorktreeCreate | När ett nytt Git-arbetstree skapas | Nej | Initiera arbetstreespecifika inställningar |
| SubagentStart | När en underagent skapas | Nej | Övervaka underagentaktivitet |
| SubagentStop | När en underagent är klar | Nej | Validera underagentens utdata |
Proffstips: Du kommer att använda PreToolUse och PostToolUse för 80 % av dina hooks. SessionStart är näst mest användbar -- den är perfekt för att injicera projektkontexten som Claude behöver i början av varje session.
De 4 Claude Code Hook-typerna förklarade
Claude Code stöder fyra hook-hanteringstyper: command-hooks kör skalskript, HTTP-hooks POSTar till URL:er, prompt-hooks ställer Claude en ja/nej-fråga, och agent-hooks skapar en underagent med verktygsåtkomst. I vår erfarenhet hanterar command-hooks 90 % av användningsfallen. Använd HTTP för externa integrationer, prompt- och agent-hooks för nyanserade beslut som kräver AI-omdöme.
| Typ | Hastighet | Komplexitet | Bäst för | Exempel |
|---|---|---|---|---|
| Command | Snabb | Låg | Formattering, blockering, loggning | Kör Prettier efter filredigering |
| HTTP | Medel | Medel | Externa tjänster, webhooks | POST till Slack vid avslut |
| Prompt | Långsam | Medel | Subjektiva beslut | "Är den här koden säker att köra?" |
| Agent | Långsammast | Hög | Komplex filmedveten verifiering | Kontrollera om ny kod följer projektmönster |
Command-hooks (arbetshästen)
Command-hooks kör ett skalkommando och använder exit-koden för att avgöra utfallet. De tar emot händelsens JSON-data via stdin.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.command' | grep -q 'rm -rf /' && exit 2 || exit 0"
}]
}]
}
}Det här är vad du använder för formattering, filskydd, notiser och de flesta automatiseringar. Snabbt, enkelt och förutsägbart.
HTTP-hooks (externa integrationer)
HTTP-hooks skickar en POST-förfrågan till en URL med händelsens JSON som body. Svarsstatuskoden avgör utfallet (200 = fortsätt, 403 = blockera).
{
"hooks": {
"Stop": [{
"matcher": "",
"hooks": [{
"type": "http",
"url": "https://your-api.com/claude-webhook"
}]
}]
}
}Utmärkt för att skicka händelser till Slack, Discord, PagerDuty eller en anpassad instrumentpanel. Du kan också använda det här för att fråga en extern policymotor innan du tillåter en verktygskörning.
Prompt-hooks (AI-drivna beslut)
Prompt-hooks skickar händelsedata till Claude självt för en enstaka ja/nej-utvärdering. Claude returnerar ett JSON-svar med "decision": "allow" eller "decision": "block" plus motivering.
{
"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?"
}]
}]
}
}Använd dessa sparsamt. De lägger till latens (ett helt LLM-anrop per hook-körning) och kostar pengar. Men för genuint subjektiva säkerhetskontroller -- som "verkar den här databasmigrationen destruktiv?" -- är de svåra att slå. Om du är nyfiken på att byta Claude Code-modeller följer modellen som används för prompt-hooks din aktuella sessionsmodell.
Agent-hooks (verktygsassisterad verifiering)
Agent-hooks skapar en underagent med tillgång till Read-, Grep- och Glob-verktyg. Underagenten kan inspektera filer innan den fattar sitt beslut.
{
"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."
}]
}]
}
}Det här är den kraftfullaste hook-typen, men också den långsammaste. Reservera den för högrisk-kontroller där du behöver filkontext för att fatta ett bra beslut.
7 produktionsklara Claude Code Hook-exempel (klara att kopiera)
De mest användbara Claude Code-hooks inkluderar autoformattering med Prettier eller Black efter filredigering, blockering av skrivningar till skyddade filer, skrivbordsnotiser vid uppgiftsavslut, injicering av projektkontexten vid sessionsstart, körning av tester efter kodändringar, tillämpa grenskydd och granskning av all verktygsamvändning. Jag har kört varianter av dessa i varje projekt under de senaste tre månaderna.
Varje exempel nedan är ett komplett settings.json-utdrag som du kan lägga in i din .claude/settings.json. Community-samlingar som awesome-claude-code har ännu fler mönster.
1. Autoformattera vid sparande
{
"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"
}]
}]
}
}Den här aktiveras efter varje Write eller Edit, extraherar filsökvägen från stdin JSON och kör lämplig formatterare. exit 0 i slutet säkerställer att hooken aldrig blockerar -- formatteringsfel bör inte stoppa Claude.
Proffstips: Lägg till *.go med gofmt och *.rs med rustfmt om du jobbar med flera språk.
2. Blockera skrivningar till skyddade 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"
}]
}]
}
}Exit-kod 2 blockerar åtgärden och skickar JSON-meddelandet tillbaka till Claude. Claude ser feedbacken och justerar -- vanligtvis meddelar den dig att den ville ändra filen och ber dig göra det manuellt. if-fältet förhindrar att detta aktiveras vid varje enskilt Write.
3. Skrivbordsnotis vid avslut
{
"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"
}]
}]
}
}Fungerar på macOS (osascript) och Linux (notify-send). Den tomma matcharen innebär att den aktiveras vid alla notiser. Det här är genuint användbart när du startar en lång uppgift och byter till ett annat fönster.
4. Kontextinjicering vid 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"
}]
}]
}
}Det här injicerar aktuellt projektnamn, Git-gren och senaste commit i varje session. Claude tar emot den här kontexten automatiskt -- du behöver inte berätta för den vilken gren du är på.
5. Kör tester automatiskt efter kodändringar
{
"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
}]
}]
}
}Om en matchande testfil finns körs den automatiskt efter att Claude redigerat källkoden. tail -5 håller utdatan koncis och timeout förhindrar uppsvällda testsviter. Det här passar bra med ett AI-drivet kodgranskningsarbetsflöde.
6. Grensskydd (avancerat)
{
"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"
}]
}]
}
}Det här blockerar alla git push som riktar sig mot grenarna main, master eller production. Claude får feedbacken och föreslår att skapa en feature-gren istället.
7. Säkerhetsrevisionsloggning (avancerat)
{
"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"
}]
}]
}
}Loggar varje Bash-kommando som Claude kör till en revisionsfil med en UTC-tidsstämpel. Ovärderligt för säkerhetsgranskningar och för att förstå vad Claude faktiskt gjorde under en session. Håll .claude/audit.log i din .gitignore.
Hooks vs MCP vs Skills vs CLAUDE.md: När ska du använda vad?
Använd hooks för deterministisk automatisering som alltid måste köras (formattering, blockering, notiser). Använd MCP för att ge Claude tillgång till externa verktyg och data. Använd Skills för återanvändbara promptpaket. Använd CLAUDE.md för beteendestyrning och projektkontexten. Hooks är garanterade; allt annat är probabilistiskt. Det är den enstaka viktigaste distinktionen, och jag återkommer ständigt till den när jag rådger team.
Beslutsmatrisen
| Mekanism | Deterministisk? | När den körs | Bäst för | Exempel |
|---|---|---|---|---|
| Hooks | Ja | Automatiskt vid livscykelhändelser | Tillämpning, automatisering, notiser | Autoformattera, blockera filskrivningar |
| MCP | Nej (Claude bestämmer) | När Claude anropar MCP-verktyget | Nya funktioner, extern dataåtkomst | Fråga en databas, sök i Notion |
| Skills | Nej (användaren utlöser) | När användaren anropar ett snedstreck-kommando | Återanvändbara instruktionsuppsättningar | /review för kodgranskningsarbetsflöde |
| CLAUDE.md | Nej (vägledning) | Läses vid sessionsstart | Projektkontexten, kodningsstandarder | "Använd Tailwind, skriv tester för all ny kod" |
För en djupdykning i MCP, kolla vår MCP-guide. Om du kommer från Cursor är Cursors regelssystem ungefär analogt med CLAUDE.md -- men Cursor har inget som liknar hooks.
När de överlappar (och hur du väljer)
Här är flödesschemat jag använder:
- "Måste det här hända varje enskild gång, utan undantag?" -- Hook. Formattera kod, blockera skyddade filer, skicka notiser. Noll tvetydighet.
- "Behöver Claude en ny FÖRMÅGA som den inte har?" -- MCP-server. Kom åt en databas, anropa ett API, sök externa dokument.
- "Vill jag ha återanvändbara INSTRUKTIONER för ett specifikt arbetsflöde?" -- Skill (snedstreck-kommando). Kodgranskningsmallar, driftsättningscheck-listor.
- "Vill jag forma Claudes BETEENDE i det här projektet?" -- CLAUDE.md. Kodningsstandarder, arkitekturbeslut, föredragna bibliotek.
Verkliga exempel som klargör gränsen:
- "Formattera alltid med Prettier" = Hook (det måste hända varje gång)
- "Använd Prettier för formattering" i CLAUDE.md = Vägledning (Claude kan glömma det)
- "Sök i våra företagsdokument" = MCP (ny förmåga)
- "Följ vår stilguide vid kodgranskning" = Skill eller CLAUDE.md
Som beskrivs i Anthropics pluginannouncement är hooks en del av ett bredare plugin-ekosystem som även inkluderar MCP och Skills. De är designade för att komplettera varandra, inte konkurrera.
Startpaketet: Färdig Claude Code Hooks-konfiguration för vilket projekt som helst
En startkonfiguration för Claude Code-hooks bör inkludera autoformattering vid filredigering, notis vid uppgiftsavslut, filskydd för känsliga filer, kontextinjicering vid sessionsstart och en stop-hook för städning. Det här är exakt den konfiguration jag lägger in i varje nytt projekt -- anpassad för stacken, men strukturen är densamma.
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"
}]
}]
}
}Hur du anpassar för din stack
| Stack | Formatteringskommando | Testkommando | Bevakade filändelser |
|---|---|---|---|
| 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 |
Byt ut format- och testkommandona i konfigurationen ovan för att matcha din stack. Strukturen är identisk.
Verifiera att dina hooks fungerar
Tre sätt att bekräfta att hooks är aktiva:
/hooks-kommandot -- Skriv/hooksi Claude Code för att se alla registrerade hooks, deras matchare och deras status.- Transkriptinspektion -- Efter att en hook aktiveras, kontrollera sessionstranskriptet. Hook-körningar visas med deras utdata och exit-kod.
- Snabb av/på-knapp -- Lägg till
"disableAllHooks": truei din settings.json för att tillfälligt inaktivera alla hooks utan att radera konfigurationen. Ta bort det (eller sätt det tillfalse) för att återaktivera.
CI/CD-integration: Claude Code Hooks i headless-läge
Claude Code hooks fungerar i headless-läge (claude -p) med vissa skillnader: Notification-hooks aktiveras fortfarande men du bör omdirigera till loggning istället för skrivbordsvarningar. PreToolUse-hooks med exit-kod 2 kan pausa headless-sessioner för mänsklig granskning. GitHub Actions använder anthropics/claude-code-action@v1 tillsammans med hooks för automatiserade arbetsflöden.
Beteende i headless-läge
| Hook-händelse | Interaktivt läge | Headless-läge (-p) | CI-rekommendation |
|---|---|---|---|
| PreToolUse (exit 2) | Blockerar, visar meddelande | Pausar för --resume | Använd för obligatoriska mänskliga godkännanden |
| PostToolUse | Körs normalt | Körs normalt | Behåll formatterare och loggare |
| Notification | Skrivbordsvarning | Aktiveras fortfarande (inget UI) | Omdirigera till loggfil eller Slack-webhook |
| Stop | Kör städning | Kör städning | Bra för CI-artefaktinsamling |
| SessionStart | Injicerar kontext | Injicerar kontext | Injicera CI-miljövariabler |
Den stora överraskningen i headless-läge: PreToolUse-hooks som avslutar med kod 2 misslyckas inte tyst. De pausar sessionen och låter dig återuppta med --resume, vilket ger dig ett mänskligt-i-loopen-mönster för CI-pipelines.
GitHub Actions-integration
Här är ett minimalt GitHub Actions-arbetsflöde som använder Claude Code med hooks. Som dokumenterat i den officiella GitHub Actions-guiden:
- 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 }}Dina .claude/settings.json-hooks följer med repot, så de aktiveras i CI precis som lokalt. Se bara till att hooks som förlitar sig på skrivbordsspecifika verktyg (som osascript) har fallbacks eller villkor.
Team-hookhantering
Ett mönster som fungerar bra för team:
.claude/settings.json(committat) -- Team-delade hooks: filskydd, formatterare, grensskydd. Alla i teamet får dessa..claude/settings.local.json(gitignorerad) -- Personliga hooks: notiseringsinställningar, anpassad loggning, experimentella hooks.~/.claude/settings.json(användareglobal) -- Dina standardinställningar för alla projekt: notiseringsstil, personliga formatteringsinställningar.
Det här speglar hur .editorconfig (committat) och lokala IDE-inställningar (personliga) fungerar. Som noterat av Angelo Limas CI/CD-guide ser team som standardiserar på delade hooks färre "fungerar på min maskin"-problem med Claude Code.
Felsökning av Claude Code Hooks och vanliga misstag
Vanliga Claude Code hooks-problem inkluderar hooks som inte aktiveras (kontrollera matcharstav och settings.json-plats), hooks som körs men inte blockerar (fel exit-kod -- använd 2, inte 1), oändliga loopar (Stop-hook utlöser sig själv) och långsam start (för många synkrona hooks). Det vanligaste misstaget jag ser är exit-kodsförvirring -- utvecklare använder exit 1 när de menar exit 2.
Hook aktiveras inte
Symptom: Du lade till en hook men ingenting händer när händelsen inträffar.
Åtgärder:
- Matcharstavfel -- Matchare är skiftlägeskänsliga.
"write"matchar inteWrite-verktyget. Kontrollera exakta verktygsnamn med/hooks. - Fel inställningsfil -- Hooks i
~/.claude/settings.jsonvisas inte i/hooks-utdatan för projektomfånget. Prova.claude/settings.jsoni projektroten. - JSON-syntaxfel -- Ett extra komma eller en saknad klammer inaktiverar tyst hela hooks-konfigurationen. Kör din settings.json genom
jq .för att validera. disableAllHooks: true-- Kontrollera om någon (eller en tidigare felsökningssession) lämnade den här flaggan på.
Hook körs men blockerar inte
Symptom: Din PreToolUse-hook körs, men åtgärden fortsätter ändå.
Åtgärder:
- Fel exit-kod -- Exit-kod 1 betyder "fel" (hook misslyckades), inte "blockera." Använd
exit 2för att blockera en åtgärd. Det här snubblar nästan alla, som noterat i de officiella dokumenten. - Saknad stdout JSON -- För blockerande hooks, skicka ett JSON-meddelande så att Claude vet varför åtgärden blockerades:
echo '{"message": "Blocked: reason"}'
Oändliga loopar
Symptom: Claude fortsätter att försöka med samma åtgärd, eller din maskin värms upp misstänkt.
Åtgärder:
- Stop-hook utlöser åtgärder -- Om din Stop-hook skriver en fil eller kör ett kommando som får Claude att svara har du skapat en loop. Stop-hooks bör bara göra passiva saker: logga, notifiera, städa.
- PostToolUse-hook orsakar redigeringar -- En PostToolUse-hook som modifierar en fil utlöser en ny PostToolUse-händelse. Skydda mot detta med specifika matchare eller
if-fältet.
Prestandaproblem
Symptom: Claude tar märkbart längre tid att starta eller köra verktyg.
Åtgärder:
- För många SessionStart-hooks -- Var och en körs synkront vid start. Håll dessa lätta (under 1 sekund var).
- Tunga skript i heta sökvägar -- Hooks på PreToolUse och PostToolUse aktiveras ofta. Om ditt skript gör nätverksförfrågningar eller tung beräkning, lägg till ett
timeout-fält (millisekunder) och överväg om det borde vara en HTTP-hook istället. - Ingen caching -- Om du kontrollerar samma sak upprepade gånger (som "är det här en skyddad gren?"), cacha resultatet i en tempfil istället för att köra Git-kommandon vid varje hook-anrop.
Vanliga frågor
Vad är Claude Code hooks och hur fungerar de?
Claude Code hooks är användardefinierade automatiseringsskript som körs vid specifika livscykelhändelser under en Claude Code-session. Du konfigurerar dem i settings.json med ett matcharmönster och en hanterare (skalkommando, HTTP-endpoint, prompt eller agent). När den matchande händelsen aktiveras körs hooken automatiskt och använder exit-koder för att kontrollera utfallet.
Hur konfigurerar jag hooks i Claude Code settings.json?
Lägg till ett "hooks"-objekt i någon av de tre konfigurationsplatserna: ~/.claude/settings.json (användareglobal), .claude/settings.json (projektdelad) eller .claude/settings.local.json (projektpersonlig). Varje händelsetyp mappar till en array av hook-definitioner med matcher, valfritt if-fält och en hooks-array som innehåller handlerobjekt med type och command eller url.
Vad är skillnaden mellan PreToolUse- och PostToolUse-hooks?
PreToolUse aktiveras innan ett verktyg körs, vilket ger dig möjligheten att blockera det med exit-kod 2. PostToolUse aktiveras efter att körningen är klar, användbart för formattering, testning eller loggning. PreToolUse är för förebyggande och grindvakter. PostToolUse är för validering och städning. Båda tar emot verktygets namn och indata som JSON via stdin.
Kan Claude Code hooks blockera farliga kommandon?
Ja. PreToolUse-hooks med exit-kod 2 blockerar vilken verktygskörning som helst. Du kan skydda känsliga filer från att skrivas, blockera skalkommandon som matchar farliga mönster som rm -rf eller git push main, och förhindra åtkomst till produktionsdatabaser. Blockeringsmeddelandet skickas tillbaka till Claude som feedback, så det kan justera sitt tillvägagångssätt.
Vilka hook-händelser finns tillgängliga i Claude Code?
Claude Code tillhandahåller 15+ händelser: PreToolUse och PostToolUse för verktygskörning, Notification för varningar, Stop för sessionsavslut, SessionStart för initialisering, UserPromptSubmit för inmatningsfiltrering, PreCompact och PostCompact för kontexthantering, och nyare händelser som ConfigChange, FileChanged, TaskCreated och PermissionDenied. Se den fullständiga referenstabellen i hook-händelsesektionen ovan.
Hur skiljer sig hooks från MCP-verktyg och Skills?
Hooks är deterministiska -- de aktiveras alltid vid matchande händelser oavsett vad Claude beslutar. MCP-verktyg utökar Claudes förmågor (databasåtkomst, API-anrop) men Claude väljer när de ska användas. Skills är återanvändbara instruktionspaket som anropas av snedstreck-kommandon. CLAUDE.md ger beteendevägledning. Använd hooks när något måste hända varje gång, MCP när Claude behöver nya förmågor.
Fungerar Claude Code hooks i headless-läge?
Ja, med förbehåll. Hooks aktiveras normalt i headless-läge (claude -p), men skrivbordsspecifika hooks som macOS-notiser behöver fallbacks. Viktigt: PreToolUse-hooks som avslutar med kod 2 kan pausa headless-sessioner för mänskligt godkännande via --resume. Det möjliggör mänskliga-i-loopen CI/CD-pipelines där vissa åtgärder kräver manuellt godkännande.
Hur många hooks är för många? Saktar hooks ner Claude Code?
Det finns ingen hård gräns, men varje synkron hook lägger till latens. SessionStart-hooks körs vid start, så håll dem snabba (under 1 sekund var). PreToolUse- och PostToolUse-hooks aktiveras vid varje matchande verktygsanrop -- tunga skript här ackumuleras snabbt. Jag rekommenderar att hålla det totala antalet hooks under 10-15, använda if-fältet för att begränsa omfånget och lägga till timeout-värden för att förhindra uppsvällda skript.
Kan jag använda hooks för att autoformattera kod med Prettier eller Black?
Ja -- det är det mest populära hook-användningsfallet. Skapa en PostToolUse-hook som matchar Write|Edit, extrahera filsökvägen från stdin JSON och kör lämplig formatterare baserat på filändelsen. Se exempel nummer ett i produktionsexemplen ovan för en komplett, klar-att-kopiera-konfiguration som hanterar TypeScript-, JavaScript- och Python-filer.
Är Claude Code hooks säkra? Vilka är säkerhetsriskerna?
Hooks körs med dina fulla användarbehörigheter -- det finns ingen sandlåda. En skadlig hook kan läsa dina SSH-nycklar, radera filer eller exfiltrera data. Använd bara hooks från betrodda källor, granska alla delade .claude/settings.json innan du accepterar dem i ditt projekt, och använd .claude/settings.local.json för personliga hooks som inte bör delas. För bredare AI-säkerhetsmönster, se vår LLM guardrails-guide.