
Hooki Claude Code: Kompletny przewodnik dla programistów z gotowymi przykładami produkcyjnymi
Claude Code świetnie radzi sobie z pisaniem kodu, ale nadal jest systemem probabilistycznym. Możesz poprosić go o uruchamianie Prettiera po każdej edycji pliku. Możesz umieścić tę instrukcję w swoim CLAUDE.md. A mimo to czasem on po prostu... zapomni. Hooki Claude Code rozwiązują ten problem, dając Ci deterministyczną, gwarantowaną kontrolę nad tym, co dzieje się przed, w trakcie i po każdej akcji podejmowanej przez Claude.
Przez ostatnie kilka miesięcy konfigurowałem hooki w dziesiątkach projektów i po cichu stały się one najważniejszą częścią mojej konfiguracji Claude Code. Ten przewodnik obejmuje wszystko — od podstaw po gotowy do wdrożenia zestaw startowy, który możesz już dziś wrzucić do dowolnego projektu. Jeśli korzystałeś z Claude Code obok narzędzi takich jak Cursor czy Copilot, znasz już wartość dostosowywania — hooki idą o krok dalej.
Czym są hooki Claude Code (i dlaczego powinny Cię zainteresować)?
Hooki Claude Code to zdefiniowane przez użytkownika polecenia powłoki, endpointy HTTP lub prompty LLM, które wykonują się automatycznie w określonych momentach cyklu życia Claude Code. Zgodnie z oficjalną dokumentacją Anthropic, w przeciwieństwie do instrukcji w prompcie, które Claude może zignorować, hooki uruchamiają się deterministycznie za każdym razem, dając Ci gwarantowaną kontrolę nad formatowaniem, bezpieczeństwem, powiadomieniami i automatyzacją przepływu pracy.
Problem probabilistyczny
Rzecz w tym, że instrukcje w CLAUDE.md to sugestie, nie kontrakty. Możesz wpisać „zawsze uruchamiaj npx prettier --write po edycji plików TypeScript" w kontekście swojego projektu, a Claude będzie się tego trzymać przez większość czasu. Ale „przez większość czasu" to za mało, gdy egzekwujesz formatowanie kodu w całym zespole, blokujesz push na produkcję albo logujesz każde polecenie powłoki na potrzeby audytu bezpieczeństwa.
To fundamentalne napięcie w każdym narzędziu do kodowania opartym na AI. Claude jest modelem językowym — operuje na prawdopodobieństwach. Inżynieria kontekstu może nakierowywać zachowanie, ale nie może go zagwarantować.
Jak hooki rozwiązują ten problem
Hooki całkowicie omijają LLM. To skrypty powłoki, wywołania HTTP lub ewaluacje AI, które uruchamiają się w określonych zdarzeniach cyklu życia — przed wykonaniem narzędzia (PreToolUse), po jego zakończeniu (PostToolUse), gdy pojawia się powiadomienie, gdy rozpoczyna się sesja lub gdy Claude się zatrzymuje. Możesz myśleć o nich jak o hookach Gita, ale dla Twojego asystenta AI do programowania.
Istnieją cztery typy hooków: command (skrypty powłoki), HTTP (żądania POST webhooka), prompt (jednoturowe ewaluacje Claude tak/nie) oraz agent (uruchamia subagenta z dostępem do narzędzi). Każdy z nich omówimy później — hooki command pokrywają około 90% tego, czego będziesz potrzebować.
Jak działają hooki Claude Code: cykl życia
Hooki Claude Code są wykonywane w ściśle określonym cyklu życia: wyzwalane jest zdarzenie (np. PreToolUse), mechanizm dopasowujący sprawdza, czy hook ma zastosowanie, skrypt hooka zostaje uruchomiony i otrzymuje dane JSON na stdin, a kod zakończenia decyduje o dalszym przebiegu. Kod zakończenia 0 oznacza kontynuację, natomiast kod 2 oznacza zablokowanie akcji. Przebieg ten jest identyczny niezależnie od używanego typu hooka.
Wydarzenie -> Matcher -> Hook -> Kod zakończenia (4-etapowy przepływ)
Oto jak działa każde wykonanie hooka:
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 = errorJSON, który dociera na stdin, zawiera wszystko o wydarzeniu: tool_name, tool_input (ścieżkę pliku, zawartość, polecenie) oraz metadane sesji. Twój skrypt odczytuje ten JSON, wykonuje potrzebną logikę i kończy działanie z odpowiednim kodem.
W przypadku hooków PreToolUse kod zakończenia 2 jest tym najpotężniejszym — całkowicie blokuje akcję i odsyła Twój komunikat ze stdout z powrotem do Claude'a jako informację zwrotną. Claude widzi Twój komunikat i może dostosować swoje podejście.
Zakresy konfiguracji: użytkownika, projektu i lokalny
Hooki znajdują się w pliku settings.json na trzech poziomach:
| Zakres | Plik | Commitowany do Gita? | Zastosowanie |
|---|---|---|---|
| Użytkownika | ~/.claude/settings.json | Nie | Osobiste ustawienia domyślne (powiadomienia, preferencje formatowania) |
| Projektu | .claude/settings.json | Tak | Hooki współdzielone przez zespół (ochrona plików, uruchamianie testów, lintowanie) |
| Lokalny | .claude/settings.local.json | Nie (ignorowany przez git) | Osobiste nadpisania dla tego projektu |
Ustawienia projektu są najbardziej przydatne dla zespołów. Umieść swoje hooki w pliku .claude/settings.json, zrób commit, a każdy programista w zespole automatycznie otrzyma te same zabezpieczenia.
Pole if: filtrowanie szczegółowe
Od wersji Claude Code 2.1.85 hooki obsługują pole if, które pozwala filtrować po argumentach narzędzia, a nie tylko po jego nazwie. Jak opisano w dokumentacji hooków Anthropic, oznacza to, że możesz napisać hook uruchamiany wyłącznie dla poleceń Bash pasujących do git push, zamiast wyzwalać go przy każdym wywołaniu Bash.
{
"matcher": "Bash",
"if": "tool_input.command matches 'git push'",
"hooks": [{ "type": "command", "command": "./scripts/check-branch.sh" }]
}Było to duże usprawnienie. Przed wprowadzeniem if albo dopasowywałeś zbyt szeroko (każde polecenie Bash), albo filtrowałeś wewnątrz swojego skryptu (co było nieeleganckie).
Wszystkie zdarzenia hooków Claude Code: tabela szybkiego odniesienia
Claude Code udostępnia ponad 20 zdarzeń hooków w całym swoim cyklu życia, zgodnie z dokumentacją w oficjalnym przewodniku po hookach i dzienniku zmian Claude Code. Najczęściej używane to PreToolUse, PostToolUse, Notification i Stop, ale nowsze zdarzenia, takie jak ConfigChange i FileChanged, otwierają zaawansowane wzorce automatyzacji.
Oto pełne zestawienie:
| Zdarzenie | Kiedy się uruchamia | Czy może blokować? | Typowy przypadek użycia |
|---|---|---|---|
| PreToolUse | Przed wykonaniem narzędzia | Tak (exit 2) | Blokowanie niebezpiecznych poleceń, ochrona plików |
| PostToolUse | Po zakończeniu działania narzędzia | Nie | Automatyczne formatowanie, uruchamianie testów, logowanie akcji |
| Notification | Gdy Claude wysyła powiadomienie | Nie | Alerty na pulpicie, wiadomości na Slacku |
| Stop | Gdy Claude kończy odpowiedź | Nie | Sprzątanie, generowanie podsumowania |
| SessionStart | Przy inicjalizacji sesji | Nie | Wstrzykiwanie kontekstu, ustawianie środowiska |
| UserPromptSubmit | Gdy użytkownik przesyła prompt | Tak (exit 2) | Walidacja danych wejściowych, filtrowanie treści |
| PreCompact | Przed kompaktowaniem kontekstu | Nie | Zapisywanie stanu przed przycięciem pamięci |
| PostCompact | Po kompaktowaniu kontekstu | Nie | Ponowne wstrzykiwanie krytycznego kontekstu |
| ConfigChange | Gdy zmieniają się ustawienia | Nie | Przeładowywanie zmiennych środowiskowych w locie |
| FileChanged | Gdy zmienia się obserwowany plik | Nie | Wyzwalanie przebudowy, unieważnianie pamięci podręcznych |
| TaskCreated | Gdy tworzone jest nowe zadanie | Nie | Śledzenie zadań, przydzielanie zasobów |
| PermissionDenied | Gdy kontrola uprawnień nie powiedzie się | Nie | Logowanie audytowe, alerty o zablokowanych akcjach |
| WorktreeCreate | Gdy tworzony jest nowy worktree Gita | Nie | Inicjalizowanie ustawień specyficznych dla worktree |
| SubagentStart | Gdy uruchamia się subagent | Nie | Monitorowanie aktywności subagenta |
| SubagentStop | Gdy subagent kończy działanie | Nie | Walidowanie wyników subagenta |
Wskazówka: PreToolUse i PostToolUse wykorzystasz w 80% swoich hooków. SessionStart jest kolejnym najbardziej przydatnym — idealnie nadaje się do wstrzykiwania kontekstu projektu, którego Claude potrzebuje na początku każdej sesji.
Cztery typy hooków Claude Code – wyjaśnienie
Claude Code obsługuje cztery typy handlerów hooków: hooki typu command uruchamiają skrypty powłoki, hooki HTTP wysyłają żądania POST na adresy URL, hooki typu prompt zadają Claude pytanie typu tak/nie, a hooki typu agent uruchamiają subagenta z dostępem do narzędzi. Z naszego doświadczenia wynika, że hooki typu command pokrywają 90% przypadków użycia. HTTP stosuj do integracji zewnętrznych, a hooki typu prompt i agent – do niuansowych decyzji wymagających oceny AI.
| Typ | Szybkość | Złożoność | Najlepsze zastosowanie | Przykład |
|---|---|---|---|---|
| Command | Szybki | Niska | Formatowanie, blokowanie, logowanie | Uruchom Prettier po edycji pliku |
| HTTP | Średnia | Średnia | Usługi zewnętrzne, webhooki | Wyślij POST do Slacka po zakończeniu |
| Prompt | Wolny | Średnia | Subiektywne decyzje | „Czy ten kod jest bezpieczny do uruchomienia?" |
| Agent | Najwolniejszy | Wysoka | Złożona weryfikacja uwzględniająca pliki | Sprawdź, czy nowy kod jest zgodny z wzorcami projektu |
Haki poleceń (koń roboczy)
Haki poleceń uruchamiają polecenie powłoki i na podstawie kodu wyjścia określają rezultat. Dane JSON zdarzenia otrzymują przez stdin.
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.command' | grep -q 'rm -rf /' && exit 2 || exit 0"
}]
}]
}
}Tego będziesz używać do formatowania, ochrony plików, powiadomień i większości automatyzacji. Szybkie, proste i przewidywalne.
Hooki HTTP (integracje zewnętrzne)
Hooki HTTP wysyłają żądanie POST na adres URL, przekazując JSON zdarzenia jako treść żądania. Kod statusu odpowiedzi decyduje o rezultacie (200 = kontynuuj, 403 = zablokuj).
{
"hooks": {
"Stop": [{
"matcher": "",
"hooks": [{
"type": "http",
"url": "https://your-api.com/claude-webhook"
}]
}]
}
}Świetnie nadają się do wysyłania zdarzeń do Slacka, Discorda, PagerDuty lub własnego dashboardu. Można ich również użyć do odpytania zewnętrznego silnika polityk przed zezwoleniem na wykonanie narzędzia.
Hooki promptów (decyzje wspierane przez AI)
Hooki promptów przekazują dane zdarzenia bezpośrednio do Claude w celu jednokrotnej oceny tak/nie. Claude zwraca odpowiedź JSON zawierającą "decision": "allow" lub "decision": "block" wraz z uzasadnieniem.
{
"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?"
}]
}]
}
}Używaj ich oszczędnie. Zwiększają opóźnienie (pełne wywołanie LLM przy każdym wykonaniu hooka) i koszty. Ale w przypadku naprawdę subiektywnych kontroli bezpieczeństwa, takich jak „czy ta migracja bazy danych wygląda na destrukcyjną?", trudno o lepsze rozwiązanie. Jeśli ciekawi Cię przełączanie modeli w Claude Code, model używany przez hooki promptów jest zgodny z modelem bieżącej sesji.
Hooki agenta (weryfikacja wspomagana narzędziami)
Hooki agenta tworzą subagenta z dostępem do narzędzi Read, Grep i Glob. Subagent może analizować pliki przed podjęciem decyzji.
{
"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."
}]
}]
}
}To najpotężniejszy typ hooka, ale jednocześnie najwolniejszy. Zarezerwuj go na sprawdzenia o dużej wadze, gdzie do podjęcia trafnej decyzji potrzebny jest kontekst plików.
7 Gotowych do użycia w produkcji przykładów hooków Claude Code (gotowe do skopiowania i wklejenia)
Do najbardziej przydatnych hooków Claude Code należą: automatyczne formatowanie za pomocą Prettier lub Black po edycji plików, blokowanie zapisu do chronionych plików, wysyłanie powiadomień systemowych po zakończeniu zadania, wstrzykiwanie kontekstu projektu na początku sesji, uruchamianie testów po zmianach w kodzie, egzekwowanie ochrony gałęzi oraz audytowanie wszelkiego użycia narzędzi. Od ostatnich trzech miesięcy używam różnych wariantów tych hooków w każdym projekcie.
Każdy z poniższych przykładów to kompletny fragment settings.json, który możesz wkleić do swojego .claude/settings.json. W kolekcjach społeczności, takich jak awesome-claude-code, znajdziesz jeszcze więcej wzorców.
1. Automatyczne formatowanie przy zapisie
{
"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"
}]
}]
}
}To uruchamia się po każdym zapisie (Write) lub edycji (Edit), wyodrębnia ścieżkę pliku z JSON-a na stdin i uruchamia odpowiedni formater. exit 0 na końcu gwarantuje, że hook nigdy nie blokuje — błędy formatowania nie powinny zatrzymywać Claude'a.
Wskazówka: Jeśli pracujesz w wielu językach, dodaj *.go z gofmt oraz *.rs z rustfmt.
2. Blokowanie zapisu do chronionych plików
{
"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"
}]
}]
}
}Kod wyjścia 2 blokuje akcję i odsyła komunikat JSON z powrotem do Claude. Claude widzi informację zwrotną i dostosowuje swoje działanie — zazwyczaj poinformuje Cię, że chciał zmodyfikować plik, i poprosi o zrobienie tego ręcznie. Pole if zapobiega uruchamianiu tej reguły przy każdym pojedynczym Write.
3. Powiadomienie na pulpicie po zakończeniu
{
"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"
}]
}]
}
}Działa na macOS (osascript) i Linuksie (notify-send). Pusty matcher oznacza, że jest wyzwalane dla wszystkich powiadomień. To naprawdę przydatne, gdy uruchamiasz długie zadanie i przełączasz się na inne okno.
4. Wstrzykiwanie kontekstu na początku sesji
{
"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"
}]
}]
}
}Wstrzykuje to nazwę bieżącego projektu, gałąź Git oraz ostatni commit do każdej sesji. Claude otrzymuje ten kontekst automatycznie — nie musisz informować go, na której gałęzi pracujesz.
5. Automatyczne uruchamianie testów po zmianach w kodzie
{
"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
}]
}]
}
}Jeśli istnieje pasujący plik testowy, jest on automatycznie uruchamiany po edycji kodu źródłowego przez Claude. tail -5 zapewnia zwięzłość danych wyjściowych, a limit czasu zapobiega niekontrolowanemu wykonywaniu się pakietów testów. Doskonale współgra to z procesem przeglądu kodu wspomaganego przez AI.
6. Wymuszanie ochrony gałęzi (zaawansowane)
{
"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"
}]
}]
}
}Blokuje to każde polecenie git push skierowane do gałęzi main, master lub production. Claude otrzyma informację zwrotną i zamiast tego zasugeruje utworzenie gałęzi funkcyjnej.
7. Rejestrowanie audytu bezpieczeństwa (zaawansowane)
{
"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"
}]
}]
}
}Rejestruje każde polecenie Bash wykonywane przez Claude w pliku audytu, opatrując je znacznikiem czasu UTC. Nieocenione podczas przeglądów bezpieczeństwa i przy ustalaniu, co Claude faktycznie zrobił w trakcie sesji. Dodaj .claude/audit.log do pliku .gitignore.
Hooks vs MCP vs Skills vs CLAUDE.md: kiedy czego używać
Używaj hooks do deterministycznej automatyzacji, która musi działać zawsze (formatowanie, blokowanie, powiadomienia). Używaj MCP, aby dać Claude dostęp do zewnętrznych narzędzi i danych. Używaj Skills dla pakietów promptów wielokrotnego użytku. Używaj CLAUDE.md do wskazówek dotyczących zachowania i kontekstu projektu. Hooks są gwarantowane; wszystko pozostałe jest probabilistyczne. To najważniejsze rozróżnienie i nieustannie do niego wracam, doradzając zespołom.
Macierz decyzyjna
| Mechanizm | Deterministyczny? | Kiedy działa | Najlepsze do | Przykład |
|---|---|---|---|---|
| Hooki | Tak | Automatycznie przy zdarzeniach cyklu życia | Egzekwowanie, automatyzacja, powiadomienia | Automatyczne formatowanie, blokowanie zapisu plików |
| MCP | Nie (decyduje Claude) | Gdy Claude wywołuje narzędzie MCP | Nowe możliwości, dostęp do danych zewnętrznych | Odpytywanie bazy danych, wyszukiwanie w Notion |
| Umiejętności | Nie (uruchamia użytkownik) | Gdy użytkownik wywołuje polecenie z ukośnikiem | Zestawy instrukcji wielokrotnego użytku | /review dla procesu przeglądu kodu |
| CLAUDE.md | Nie (wskazówki) | Odczytywany na początku sesji | Kontekst projektu, standardy kodowania | „Używaj Tailwind, pisz testy dla każdego nowego kodu" |
Aby zgłębić temat MCP, zapoznaj się z naszym przewodnikiem po MCP. Jeśli przechodzisz z Cursora, system reguł Cursora jest w przybliżeniu odpowiednikiem CLAUDE.md, ale Cursor nie ma niczego podobnego do hooków.
Kiedy się pokrywają (i jak wybrać)
Oto schemat blokowy, którego używam:
- „Czy to MUSI wydarzyć się za każdym razem, bez wyjątków?", Hook. Formatowanie kodu, blokowanie chronionych plików, wysyłanie powiadomień. Zero niejasności.
- „Czy Claude potrzebuje nowej MOŻLIWOŚCI, której nie ma?", serwer MCP. Dostęp do bazy danych, wywoływanie API, przeszukiwanie zewnętrznych dokumentów.
- „Czy chcę mieć wielokrotnego użytku INSTRUKCJE dla konkretnego przepływu pracy?", Skill (polecenie z ukośnikiem). Szablony przeglądu kodu, listy kontrolne wdrożenia.
- „Czy chcę kształtować ZACHOWANIE Claude w tym projekcie?", CLAUDE.md. Standardy kodowania, decyzje architektoniczne, preferowane biblioteki.
Prawdziwe przykłady, które wyjaśniają granicę:
- „Zawsze formatuj za pomocą Prettier" = Hook (musi wydarzyć się za każdym razem)
- „Używaj Prettier do formatowania" w CLAUDE.md = Wskazówka (Claude może zapomnieć)
- „Przeszukaj dokumentację naszej firmy" = MCP (nowa możliwość)
- „Przestrzegaj naszego przewodnika stylu podczas przeglądu kodu" = Skill lub CLAUDE.md
Jak opisano w ogłoszeniu Anthropic o wtyczkach, hooki stanowią jeden z elementów szerszego ekosystemu wtyczek, który obejmuje również MCP i Skills. Zostały zaprojektowane tak, aby się wzajemnie uzupełniać, a nie ze sobą konkurować.
Zestaw startowy: gotowa do wrzucenia konfiguracja hooków Claude Code dla dowolnego projektu
Początkowa konfiguracja hooków dla Claude Code powinna zawierać automatyczne formatowanie przy edycji plików, powiadomienia o ukończeniu zadania, ochronę wrażliwych plików, wstrzykiwanie kontekstu sesji oraz hook stop do sprzątania. To dokładnie ta konfiguracja, którą wrzucam do każdego nowego projektu, dostosowana do stosu technologicznego, ale struktura pozostaje taka sama.
Konfiguracja
{
"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"
}]
}]
}
}Jak dostosować do swojego stosu technologicznego
| Stos technologiczny | Polecenie formatowania | Polecenie testowania | Rozszerzenia do śledzenia |
|---|---|---|---|
| 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 |
Podmień polecenia formatowania i testowania w powyższej konfiguracji, aby dopasować je do swojego stosu technologicznego. Struktura pozostaje identyczna.
Weryfikacja działania hooków
Trzy sposoby na potwierdzenie, że hooki są aktywne:
- Komenda
/hooks— wpisz/hooksw Claude Code, aby zobaczyć wszystkie zarejestrowane hooki, ich dopasowania i status. - Inspekcja transkrypcji — po uruchomieniu hooka sprawdź transkrypcję sesji. Wykonania hooków pojawiają się wraz z ich wynikiem i kodem zakończenia.
- Szybkie przełączanie — dodaj
"disableAllHooks": truedo pliku settings.json, aby tymczasowo wyłączyć wszystkie hooki bez usuwania konfiguracji. Usuń ten wpis (lub ustaw nafalse), aby ponownie je włączyć.
Integracja CI/CD: hooki Claude Code w trybie headless
Hooki Claude Code działają w trybie headless (claude -p) z pewnymi różnicami: hooki powiadomień nadal się uruchamiają, ale należy przekierować je do logowania zamiast alertów pulpitu. Hooki PreToolUse z kodem wyjścia 2 mogą wstrzymywać sesje headless w celu weryfikacji przez człowieka. GitHub Actions używa anthropics/claude-code-action@v1 wraz z hookami do zautomatyzowanych przepływów pracy.
Zachowanie trybu headless
| Zdarzenie hooka | Tryb interaktywny | Tryb headless (-p) | Rekomendacja dla CI |
|---|---|---|---|
| PreToolUse (exit 2) | Blokuje, wyświetla komunikat | Wstrzymuje do --resume | Używaj do obowiązkowych zatwierdzeń przez człowieka |
| PostToolUse | Działa normalnie | Działa normalnie | Zachowaj formatery i loggery |
| Notification | Alert na pulpicie | Wciąż wyzwalany (bez UI) | Przekieruj do pliku logu lub webhooke'a Slacka |
| Stop | Uruchamia czyszczenie | Uruchamia czyszczenie | Dobre do zbierania artefaktów CI |
| SessionStart | Wstrzykuje kontekst | Wstrzykuje kontekst | Wstrzykuj zmienne środowiskowe CI |
Duża niespodzianka w trybie headless: hooki PreToolUse, które zwracają kod wyjścia 2, nie kończą się po cichu niepowodzeniem. Wstrzymują sesję i pozwalają wznowić ją za pomocą --resume, co daje wzorzec human-in-the-loop dla potoków CI.
Integracja z GitHub Actions
Oto minimalny przepływ pracy GitHub Actions wykorzystujący Claude Code z hookami. Jak opisano w oficjalnym przewodniku GitHub Actions:
- 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 }}Twoje hooki w pliku .claude/settings.json przemieszczają się wraz z repozytorium, więc będą uruchamiać się w CI dokładnie tak samo, jak lokalnie. Upewnij się tylko, że wszelkie hooki korzystające z narzędzi specyficznych dla pulpitu (takich jak osascript) mają mechanizmy zapasowe lub instrukcje warunkowe.
Zarządzanie hookami w zespole
Wzorzec, który dobrze sprawdza się w zespołach:
.claude/settings.json(commitowany), Hooki współdzielone przez zespół: ochrona plików, formatery, ochrona gałęzi. Każdy je otrzymuje..claude/settings.local.json(ignorowany przez git), Hooki osobiste: preferencje powiadomień, niestandardowe logowanie, eksperymentalne hooki.~/.claude/settings.json(globalny dla użytkownika), Twoje domyślne ustawienia we wszystkich projektach: styl powiadomień, osobiste preferencje formatowania.
Odzwierciedla to sposób działania .editorconfig (commitowany) i lokalnych ustawień IDE (osobiste). Jak zauważa Angelo Lima w swoim przewodniku po CI/CD, zespoły, które standaryzują współdzielone hooki, napotykają mniej problemów typu „u mnie działa" w Claude Code.
Rozwiązywanie problemów z hookami Claude Code i najczęstsze błędy
Do najczęstszych problemów z hookami Claude Code należą: hooki, które się nie uruchamiają (sprawdź pisownię matchera i lokalizację pliku settings.json), hooki, które działają, ale nie blokują (błędny kod wyjścia — użyj 2 zamiast 1), nieskończone pętle (hook Stop wywołujący sam siebie) oraz wolne uruchamianie (zbyt wiele hooków synchronicznych). Najczęstszym błędem, jaki spotykam, jest mylenie kodów wyjścia — programiści używają exit 1, gdy w rzeczywistości chodzi im o exit 2.
Hook się nie uruchamia
Objawy: Dodałeś hook, ale gdy zdarzenie występuje, nic się nie dzieje.
Rozwiązania:
- Literówka w matcherze – Matchery rozróżniają wielkość liter.
\"write\"nie dopasuje się do narzędziaWrite. Sprawdź dokładne nazwy narzędzi za pomocą/hooks. - Niewłaściwy plik ustawień – Hooki w
~/.claude/settings.jsonnie pojawią się w wynikach/hooksdla zakresu projektu. Spróbuj użyć.claude/settings.jsonw katalogu głównym projektu. - Błąd składni JSON – Zbędny przecinek lub brakujący nawias po cichu wyłącza całą konfigurację hooków. Przepuść swój settings.json przez
jq ., aby zweryfikować składnię. disableAllHooks: true– Sprawdź, czy ktoś (lub poprzednia sesja debugowania) nie zostawił tej flagi włączonej.
Hook się uruchamia, ale nie blokuje
Objawy: Twój hook PreToolUse się wykonuje, ale akcja i tak jest kontynuowana.
Rozwiązania:
- Niewłaściwy kod wyjścia, Kod wyjścia 1 oznacza „błąd" (hook nie powiódł się), a nie „blokuj". Aby zablokować akcję, użyj
exit 2. Potyka się o to niemal każdy, o czym wspominają oficjalne dokumenty. - Brak JSON-a na stdout, W przypadku hooków blokujących wypisz komunikat JSON, aby Claude wiedział, dlaczego akcja została zablokowana:
echo '{"message": "Blocked: reason"}'
Nieskończone pętle
Objawy: Claude bez końca ponawia tę samą akcję lub Twój komputer podejrzanie się nagrzewa.
Rozwiązania:
- Hook Stop wywołujący akcje, jeśli Twój hook Stop zapisuje plik lub uruchamia polecenie, które powoduje odpowiedź Claude, tworzysz pętlę. Hooki Stop powinny wykonywać wyłącznie bierne czynności: logować, powiadamiać, sprzątać.
- Hook PostToolUse powodujący edycje, hook PostToolUse, który modyfikuje plik, wyzwala kolejne zdarzenie PostToolUse. Zabezpiecz się przed tym za pomocą precyzyjnych matcherów lub pola
if.
Problemy z wydajnością
Objawy: Uruchamianie Claude lub wykonywanie narzędzi trwa zauważalnie dłużej.
Rozwiązania:
- Zbyt wiele hooków SessionStart – każdy z nich wykonuje się synchronicznie przy starcie. Zadbaj, aby były lekkie (poniżej 1 sekundy każdy).
- Ciężkie skrypty w często wykonywanych ścieżkach – hooki PreToolUse i PostToolUse są wywoływane bardzo często. Jeśli Twój skrypt wykonuje żądania sieciowe lub złożone obliczenia, dodaj pole
timeout(w milisekundach) i rozważ, czy zamiast tego nie powinien być to hook HTTP. - Brak cache'owania – jeśli wielokrotnie sprawdzasz to samo (np. „czy to jest chroniony branch?"), zapisuj wynik w pliku tymczasowym zamiast uruchamiać polecenia Git przy każdym wywołaniu hooka.
Często zadawane pytania
Czym są hooki Claude Code i jak działają?
Hooki Claude Code to zdefiniowane przez użytkownika skrypty automatyzujące, które wykonują się w określonych zdarzeniach cyklu życia podczas sesji Claude Code. Konfiguruje się je w pliku settings.json, podając wzorzec dopasowania i procedurę obsługi (polecenie powłoki, endpoint HTTP, prompt lub agenta). Gdy wystąpi pasujące zdarzenie, hook uruchamia się automatycznie i wykorzystuje kody wyjścia do sterowania wynikiem.
Jak skonfigurować hooki w pliku settings.json programu Claude Code?
Dodaj obiekt "hooks" do dowolnej z trzech lokalizacji konfiguracji: ~/.claude/settings.json (globalna dla użytkownika), .claude/settings.json (współdzielona dla projektu) lub .claude/settings.local.json (osobista dla projektu). Każdy typ zdarzenia mapuje na tablicę definicji hooków zawierających matcher, opcjonalne pole if oraz tablicę hooks z obiektami handlerów posiadającymi type i command lub url.
Jaka jest różnica między hookami PreToolUse a PostToolUse?
PreToolUse uruchamia się przed wykonaniem narzędzia, dając Ci możliwość zablokowania go za pomocą kodu wyjścia 2. PostToolUse uruchamia się po zakończeniu wykonania i przydaje się do formatowania, testowania lub logowania. PreToolUse służy do zapobiegania i kontrolowania dostępu. PostToolUse służy do walidacji i sprzątania. Oba otrzymują nazwę narzędzia oraz dane wejściowe w formacie JSON na stdin.
Czy hooki Claude Code mogą blokować niebezpieczne polecenia?
Tak. Hooki PreToolUse z kodem wyjścia 2 blokują wykonanie dowolnego narzędzia. Możesz chronić wrażliwe pliki przed zapisem, blokować polecenia powłoki pasujące do niebezpiecznych wzorców, takich jak rm -rf czy git push main, oraz uniemożliwiać dostęp do produkcyjnych baz danych. Komunikat blokujący jest odsyłany z powrotem do Claude jako informacja zwrotna, dzięki czemu może on dostosować swoje podejście.
Jakie zdarzenia hooków są dostępne w Claude Code?
Claude Code udostępnia ponad 15 zdarzeń: PreToolUse i PostToolUse do wykonywania narzędzi, Notification do powiadomień, Stop do zakończenia sesji, SessionStart do inicjalizacji, UserPromptSubmit do filtrowania danych wejściowych, PreCompact i PostCompact do zarządzania kontekstem oraz nowsze zdarzenia, takie jak ConfigChange, FileChanged, TaskCreated i PermissionDenied. Pełną tabelę referencyjną znajdziesz w sekcji dotyczącej zdarzeń hooków powyżej.
Czym hooki różnią się od narzędzi MCP i Skills?
Hooki są deterministyczne — zawsze uruchamiają się przy pasujących zdarzeniach, niezależnie od decyzji Claude. Narzędzia MCP rozszerzają możliwości Claude (dostęp do bazy danych, wywołania API), ale to Claude decyduje, kiedy z nich skorzystać. Skills to wielokrotnego użytku pakiety instrukcji wywoływane poleceniami z ukośnikiem. CLAUDE.md zawiera wskazówki dotyczące zachowania. Używaj hooków, gdy coś musi wydarzyć się za każdym razem, a MCP — gdy Claude potrzebuje nowych zdolności.
Czy hooki Claude Code działają w trybie headless?
Tak, ale z pewnymi zastrzeżeniami. Hooki uruchamiają się normalnie w trybie headless (claude -p), jednak hooki specyficzne dla środowiska desktopowego, takie jak powiadomienia macOS, wymagają mechanizmów zapasowych. Co istotne, hooki PreToolUse kończące działanie z kodem 2 mogą wstrzymywać sesje headless w celu uzyskania zatwierdzenia przez człowieka za pośrednictwem --resume. Umożliwia to tworzenie potoków CI/CD z udziałem człowieka (human-in-the-loop), w których określone działania wymagają ręcznej akceptacji.
Ile hooków to za dużo? Czy hooki spowalniają Claude Code?
Nie ma sztywnego limitu, ale każdy synchroniczny hook zwiększa opóźnienie. Hooki SessionStart uruchamiają się przy starcie, więc zadbaj, by były szybkie (poniżej 1 sekundy każdy). Hooki PreToolUse i PostToolUse są wyzwalane przy każdym pasującym wywołaniu narzędzia — ciężkie skrypty w tym miejscu szybko się kumulują. Zalecam utrzymywanie łącznej liczby hooków poniżej 10–15, używanie pola if do zawężania zakresu oraz dodawanie wartości timeout, aby skrypty nie wymykały się spod kontroli.
Czy mogę używać hooków do automatycznego formatowania kodu za pomocą Prettier lub Black?
Tak, to najpopularniejszy przypadek użycia hooków. Utwórz hook PostToolUse pasujący do Write|Edit, wyodrębnij ścieżkę pliku z JSON-a na stdin i uruchom odpowiedni formater na podstawie rozszerzenia pliku. Zobacz przykład numer jeden w sekcji przykładów produkcyjnych, aby znaleźć gotową do skopiowania konfigurację obsługującą pliki TypeScript, JavaScript i Python.
Czy hooki Claude Code są bezpieczne? Jakie są zagrożenia bezpieczeństwa?
Hooki działają z pełnymi uprawnieniami użytkownika — nie ma żadnej piaskownicy. Złośliwy hook może odczytać Twoje klucze SSH, usunąć pliki lub wykraść dane. Używaj tylko hooków z zaufanych źródeł, sprawdzaj każdy udostępniony plik .claude/settings.json, zanim zaakceptujesz go w swoim projekcie, i używaj .claude/settings.local.json do osobistych hooków, które nie powinny być udostępniane. Więcej informacji o wzorcach bezpieczeństwa AI znajdziesz w naszym przewodniku po zabezpieczeniach LLM.