Mistrzostwo w systemie hooków
Twój młodszy programista właśnie poprosił Claude Code o “uporządkowanie plików migracji bazy danych”. Claude zinterpretował to jako usunięcie historii migracji. Skrypt wdrożeniowy produkcyjnego uruchomił się następnego ranka i odtworzył każdą tabelę od podstaw. Twój piątkowy wieczór to teraz operacja odzyskiwania.
Hooki to zapobiegają. To deterministyczne polecenia powłoki, prompty LLM lub wywołania agentów, które uruchamiają się w określonych punktach cyklu życia Claude Code. Nie zależą od tego, czy model postępuje zgodnie z instrukcjami — wykonują się, czy model współpracuje, czy nie.
Co wyniesiesz z tego rozdziału
Dział zatytułowany „Co wyniesiesz z tego rozdziału”- Działający model mentalny 14 zdarzeń hooków i kiedy każde się uruchamia
- Gotowe do produkcji skrypty hooków dla ochrony plików, auto-formatowania i egzekwowania bezpieczeństwa
- Wzorce hooków opartych na promptach i agentach, które wykorzystują osąd AI deterministycznie
- Techniki debugowania, gdy hooki zachowują się nieoczekiwanie
Cykl życia hooków
Dział zatytułowany „Cykl życia hooków”Każda sesja Claude Code przechodzi przez przewidywalny cykl życia. Hooki przechwytują ten cykl w 14 odrębnych punktach:
| Zdarzenie | Kiedy się uruchamia | Może zablokować? |
|---|---|---|
SessionStart | Sesja rozpoczyna się lub wznawia | Tak |
UserPromptSubmit | Po naciśnięciu Enter, przed przetworzeniem przez Claude | Tak |
PreToolUse | Przed wykonaniem jakiegokolwiek wywołania narzędzia | Tak |
PermissionRequest | Gdy pojawi się okno dialogowe uprawnień | Tak |
PostToolUse | Po udanym wywołaniu narzędzia | Nie |
PostToolUseFailure | Po nieudanym wywołaniu narzędzia | Nie |
Notification | Gdy Claude wysyła powiadomienie | Nie |
SubagentStart | Gdy pojawia się subagent | Nie |
SubagentStop | Gdy subagent kończy | Nie |
Stop | Gdy Claude kończy odpowiadać | Tak |
TeammateIdle | Gdy członek zespołu agentów staje się bezczynny | Tak |
TaskCompleted | Gdy zadanie jest oznaczone jako ukończone | Tak |
PreCompact | Przed kompaktowaniem kontekstu | Nie |
SessionEnd | Gdy sesja kończy się | Nie |
Kolumna “Może zablokować?” jest kluczowa. Hooki PreToolUse mogą zapobiec wykonaniu niebezpiecznego polecenia. Hooki Stop mogą zmusić Claude do kontynuowania pracy, gdy próbuje przedwcześnie zakończyć.
Konfiguracja
Dział zatytułowany „Konfiguracja”Hooki znajdują się w plikach JSON ustawień. Konfiguracja ma trzy poziomy:
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": ".claude/hooks/block-dangerous-commands.sh" } ] } ] }}Gdzie umieszczać hooki:
| Lokalizacja | Zakres | Do współdzielenia |
|---|---|---|
~/.claude/settings.json | Wszystkie Twoje projekty | Nie |
.claude/settings.json | Bieżący projekt, wszyscy członkowie zespołu | Tak (commituj) |
.claude/settings.local.json | Bieżący projekt, tylko Ty | Nie (gitignored) |
Wzorce matchera
Dział zatytułowany „Wzorce matchera”Pole matcher to regex, który filtruje, kiedy hook się uruchamia:
"Bash"— tylko wywołania narzędzia Bash"Edit|Write"— narzędzia modyfikacji plików"mcp__.*"— każde narzędzie MCP- Pomiń
matcherlub użyj"*", aby dopasować wszystko
Budowanie hooków produkcyjnych
Dział zatytułowany „Budowanie hooków produkcyjnych”Auto-formatowanie po zmianach plików
Dział zatytułowany „Auto-formatowanie po zmianach plików”Ten hook PostToolUse uruchamia Prettier na każdym pliku, który Claude edytuje lub zapisuje:
#!/bin/bash# Runs after Edit or Write tool calls
FILE_PATH=$(jq -r '.tool_input.file_path // .tool_input.path // empty')
if [ -n "$FILE_PATH" ] && [ -f "$FILE_PATH" ]; then case "$FILE_PATH" in *.ts|*.tsx|*.js|*.jsx|*.json|*.css|*.md) npx prettier --write "$FILE_PATH" 2>/dev/null ;; esacfi
exit 0Konfiguracja hooka:
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": ".claude/hooks/auto-format.sh" } ] } ] }}Dźwięk powiadomienia po zakończeniu
Dział zatytułowany „Dźwięk powiadomienia po zakończeniu”{ "hooks": { "Stop": [ { "matcher": "", "hooks": [ { "type": "command", "command": "afplay /System/Library/Sounds/Glass.aiff" } ] } ], "Notification": [ { "matcher": "", "hooks": [ { "type": "command", "command": "afplay /System/Library/Sounds/Ping.aiff" } ] } ] }}Ochrona krytycznych plików
Dział zatytułowany „Ochrona krytycznych plików”Blokuj Claude przed modyfikowaniem plików, które powinny być zmieniane tylko przez określone procesy:
#!/bin/bashFILE_PATH=$(jq -r '.tool_input.file_path // .tool_input.path // empty')PROTECTED_PATTERNS=( "*/migrations/*" ".env*" "*/secrets/*" "package-lock.json" "yarn.lock")
for pattern in "${PROTECTED_PATTERNS[@]}"; do if [[ "$FILE_PATH" == $pattern ]]; then jq -n "{hookSpecificOutput:{hookEventName:\"PreToolUse\",permissionDecision:\"deny\",permissionDecisionReason:\"Protected file: $FILE_PATH cannot be modified by Claude\"}}" exit 0 fidone
exit 0Hooki oparte na promptach
Dział zatytułowany „Hooki oparte na promptach”Gdy potrzebujesz osądu AI zamiast dopasowywania wzorców, użyj hooków opartych na promptach. Wysyłają one kontekst zdarzenia do LLM i działają na podstawie odpowiedzi:
{ "hooks": { "Stop": [ { "matcher": "", "hooks": [ { "type": "prompt", "prompt": "Review the assistant's final response. Did it actually complete the requested task, or did it stop early with a vague summary? If the task is incomplete, respond with {\"decision\": \"block\", \"reason\": \"Task not complete: [specific missing items]\"}. If complete, respond with {\"decision\": \"allow\"}." } ] } ] }}Ten wzorzec wyłapuje tendencję Claude do ogłaszania zwycięstwa przed faktycznym zakończeniem pracy.
Hooki asynchroniczne
Dział zatytułowany „Hooki asynchroniczne”Niektóre hooki nie powinny blokować głównego przepływu. Wykonywanie testów w tle to klasyczny przykład:
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": ".claude/hooks/run-tests-async.sh", "async": true } ] } ] }}Hooki asynchroniczne uruchamiają się natychmiast, ale nie blokują Claude przed kontynuowaniem. Wynik jest dostarczany, gdy jest dostępny.
Debugowanie hooków
Dział zatytułowany „Debugowanie hooków”Gdy hooki źle się zachowują, użyj flagi debug:
claude --debug "hooks"To pokazuje każde zdarzenie hooka, ocenę matchera i wykonanie handlera. Częste problemy:
- Hook się nie uruchamia: Sprawdź, czy Twój regex matchera faktycznie pasuje do nazwy narzędzia.
"Bash"pasuje do narzędzia Bash, nie"bash"(wielkość liter ma znaczenie). - Hook się uruchamia, ale nie ma efektu: Sprawdź kod wyjścia i output JSON. Kod wyjścia 0 oznacza “zezwól”. Kod wyjścia 2 oznacza “zablokuj”. Wszystko inne to błąd.
- Uprawnienia skryptu hooka: Upewnij się, że pliki
.claude/hooks/*.shsą wykonywalne (chmod +x).
Kiedy to nie działa
Dział zatytułowany „Kiedy to nie działa”Hooki spowalniają każdą operację: Każdy synchroniczny hook dodaje opóźnienie do wywołania narzędzia, które przechwytuje. Jeśli Twój hook PostToolUse uruchamia pełny zestaw testów przy każdej edycji, Claude będzie powolny. Przenieś ciężkie operacje do hooków asynchronicznych.
Hooki konfliktują ze sobą: Gdy wiele hooków uruchamia się na tym samym zdarzeniu, wszystkie działają. Jeśli jeden zezwala, a drugi odmawia, odmowa wygrywa. Użyj /hooks, aby zobaczyć wszystkie skonfigurowane hooki i ich źródła.
Hooki oparte na promptach zużywają dodatkowe tokeny: Hooki oparte na promptach wykonują dodatkowe wywołania API. Każde dodaje koszt. Używaj ich oszczędnie i preferuj hooki poleceń dla zadań dopasowywania wzorców.
Hook nie może odczytać stdin: Hooki poleceń otrzymują JSON na stdin. Jeśli Twój skrypt odczytuje z pliku lub nie przetwarza stdin, nie otrzyma kontekstu zdarzenia. Zawsze używaj jq do parsowania wejścia.
Co dalej
Dział zatytułowany „Co dalej”- Niestandardowe polecenia — Buduj wielokrotnego użytku polecenia uzupełniające Twoje hooki
- System pamięci — Konfiguruj, co Claude wie, aby zmniejszyć potrzebę hooków
- Monitorowanie i koszty — Śledź wykonywanie hooków i ich wpływ na zużycie tokenów