Hooki w Claude Code to polecenia (albo wywołania HTTP, prompty i kilka innych typów handlerów), które Claude Code uruchamia automatycznie w określonych momentach sesji, np. przed uruchomieniem narzędzia, gdy potrzebne jest uprawnienie albo gdy Claude skończy odpowiadać. Definiujesz je pod kluczem hooks w pliku ustawień, np. ~/.claude/settings.json. Każdy hook dostaje na stdin JSON z informacjami o zdarzeniu i może odpowiedzieć kodem wyjścia albo obiektem JSON na stdout. Dzięki temu może logować, wysyłać powiadomienia, blokować akcje albo odpowiadać w twoim imieniu.
01Z czego składa się hook
Konfiguracja hooka ma trzy poziomy:
- Zdarzenie hooka, np.
PreToolUsealboStop. - Grupa matchera, która określa, kiedy hook się odpala, np. „tylko dla narzędzia Bash”.
- Jeden lub więcej handlerów hooka, czyli to, co faktycznie się uruchamia.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "/path/to/lint-check.sh"
}
]
}
]
}
}
Ten przykład uruchamia skrypt lintujący po tym, jak Claude zapisze lub zedytuje plik. Żeby dodać drugie zdarzenie, dodaj kolejny klucz w tym samym obiekcie hooks.
02Gdzie trzymać hooki
~/.claude/settings.jsonWszystkie twoje projektyNie, tylko na twojej maszynie.claude/settings.jsonJeden projektTak, można go commitować.claude/settings.local.jsonJeden projektNiehooks/hooks.json pluginuGdy plugin jest włączonyTakHooki z różnych plików sumują się, a nie nadpisują. Wpisz /hooks w Claude Code, żeby zobaczyć wszystkie aktywne hooki i to, skąd pochodzą.
W sesji interaktywnej Claude Code wstrzymuje hooki, nawet twoje własne, dopóki nie zaakceptujesz okna zaufania dla danego folderu.
03Typy handlerów
Większość hooków to "type": "command", czyli uruchomienie polecenia w shellu. Są jeszcze cztery inne:
http: wysyła JSON zdarzenia POST-em na URL i czyta treść odpowiedzi.mcp_tool: wywołuje narzędzie na skonfigurowanym przez ciebie serwerze MCP.prompt: zadaje modelowi Claude jednorazowe pytanie i odczytuje decyzję w JSON.agent: uruchamia subagenta, który przed decyzją może przeczytać pliki (eksperymentalne).
Hooki typu command działają z pełnymi uprawnieniami twojego użytkownika, przez sh -c na macOS i Linux oraz Git Bash (albo PowerShell) na Windows. Dodaj "async": true, żeby uruchomić hook w tle; wtedy nie może już podejmować decyzji.
04Matchery
matcher decyduje, przy których wystąpieniach zdarzenia hook się uruchomi. To, do czego jest dopasowywany, zależy od zdarzenia: nazwa narzędzia przy zdarzeniach narzędzi, typ powiadomienia przy Notification, sposób rozpoczęcia sesji przy SessionStart itd.
"*",""albo brak matchera pasują do wszystkiego.- Litery, cyfry,
_,-, spacje,|i,są traktowane jako dokładne nazwy.Edit|Writepasuje do obu narzędzi. - Wszystko inne to wyrażenie regularne JavaScript, więc
mcp__memory__.*pasuje do każdego narzędzia z jednego serwera MCP.
Matchery rozróżniają wielkość liter. Niektóre zdarzenia, m.in. Stop i UserPromptSubmit, ignorują matchery. Przy zdarzeniach narzędzi pole if z regułą uprawnień, np. "Bash(git *)", dodatkowo zawęża pojedynczy handler.
05Wejście: co dostaje twój hook
Każdy hook dostaje na stdin JSON z kilkoma wspólnymi polami, m.in. session_id, transcript_path, cwd i hook_event_name, plus polami specyficznymi dla zdarzenia. Na przykład hook PreToolUse dla wywołania Bash dostaje też tool_name i tool_input.command. Odczytasz go za pomocą jq albo dowolnego parsera JSON:
#!/bin/bash
input=$(cat)
cmd=$(jq -r '.tool_input.command // empty' <<<"$input")
echo "Claude wants to run: $cmd" >> ~/claude-commands.log
exit 0
06Wyjście: kody wyjścia i JSON
Hook odpowiada na jeden z dwóch sposobów.
Kody wyjścia. 0 oznacza sukces. 2 to błąd blokujący: przy zdarzeniach, które można zablokować, akcja zostaje zatrzymana, a twój stderr staje się jej powodem. Każdy inny kod, łącznie z typowym 1, to błąd nieblokujący, więc akcja jest wykonywana dalej, a ty widzisz komunikat o błędzie hooka. Jeśli hook ma wymuszać jakąś regułę, zwracaj 2, a nie 1.
JSON na stdout. Zakończ z kodem 0 i wypisz pojedynczy obiekt JSON, jeśli potrzebujesz większej kontroli. Niektóre pola działają wszędzie, np. continue: false, które całkowicie zatrzymuje Claude. Inne zależą od zdarzenia: Stop używa decision: "block" razem z reason, a PreToolUse i PermissionRequest umieszczają decyzję w hookSpecificOutput. Nie wypisuj na stdout nic więcej: jedna przypadkowa linia z profilu shella sprawi, że Claude Code nie odczyta JSON-a.
07Wszystkie zdarzenia hooków
SessionStartSesja się zaczyna lub zostaje wznowionaNie (dodaje kontekst)SetupUruchomienie z --init-only albo --init / --maintenance z -pNieInstructionsLoadedWczytano plik CLAUDE.md lub .claude/rules/*.mdNieUserPromptSubmitWysyłasz prompt, zanim Claude go zobaczyTakUserPromptExpansionWpisana komenda rozwija się w promptTakPreToolUsePrzed każdym wywołaniem narzędziaTakPermissionRequestWywołanie narzędzia wymaga decyzji o uprawnieniachZezwala lub odmawia przez JSONPermissionDeniedTryb auto odrzuca wywołanie narzędziaNiePostToolUsePo udanym wywołaniu narzędziaNie (narzędzie już się wykonało)PostToolUseFailurePo nieudanym wywołaniu narzędziaNiePostToolBatchPo serii równoległych wywołań narzędzi, przed kolejnym wywołaniem modeluTakNotificationClaude Code wysyła powiadomienieNieMessageDisplayPodczas wyświetlania odpowiedzi ClaudeNie (może zmienić to, co jest wyświetlane)SubagentStart / SubagentStopSubagent startuje lub kończy pracęTylko SubagentStopTaskCreated / TaskCompletedZadanie zostaje utworzone lub oznaczone jako ukończoneTakStopClaude kończy odpowiedźTak (Claude pracuje dalej)StopFailureTura kończy się błędem APINieTeammateIdleCzłonek zespołu agentów zaraz przejdzie w stan bezczynnościTakConfigChangePlik ustawień zmienia się w trakcie sesjiTakCwdChangedZmienia się katalog roboczyNieDirectoryAddedDodano katalog przez /add-dirNieFileChangedObserwowany plik zmienia się na dyskuNieWorktreeCreate / WorktreeRemoveWorktree zostaje utworzony lub usuniętyTakPreCompact / PostCompactPrzed kompaktowaniem kontekstu i po nimTylko PreCompactPreModelSwitch / PostModelSwitchPrzed zmianą modelu i po niejTylko PreModelSwitchElicitation / ElicitationResultSerwer MCP prosi o dane i po tym, jak odpowieszTakSessionEndSesja się kończyNieAnthropic co jakiś czas dodaje nowe eventy, więc aktualną listę i pola wejściowe każdego eventu sprawdzisz w dokumentacji hooków.
08Które eventy są ważne dla powiadomień
Cztery eventy pokrywają niemal wszystko, o czym ludzie chcą być informowani:
Stopdla „Claude skończył”. Zobacz poradnik o Stop hook.Notificationdla „Claude na ciebie czeka”, z typami takimi jakpermission_promptiidle_prompt. Zobacz poradnik o Notification hook.PermissionRequest, żeby dostać powiadomienie albo odpowiedzieć w chwili, gdy potrzebne jest uprawnienie. Zobacz poradnik o PermissionRequest.PreToolUsena narzędziuAskUserQuestion, żeby widzieć pytania wielokrotnego wyboru od Claude i na nie odpowiadać. Zobacz odpowiadanie na pytania z telefonu.
Jeśli chcesz gotową konfigurację na desktop do wklejenia, zacznij od tego, jak dostać powiadomienie, gdy Claude Code skończy.
09Gdzie pasuje Claude Code Notifier
Claude Code Notifier jest w całości zbudowany na tych hookach. Jego darmowe narzędzie CLI, ccn, działa na Macu, Windows i Linux. Instalacja dodaje siedem wpisów hooków do ~/.claude/settings.json, każdy uruchamia ccn hook, i jednorazowo robi kopię zapasową pliku. ccn działa kilka milisekund na event i się kończy, więc nic nie zostaje uruchomione w tle.
Samo w sobie pokazuje powiadomienia na desktopie. Po sparowaniu aplikacji na iPhone lub Android te same hooki przekazują z powrotem twoje odpowiedzi: zezwolisz na uprawnienie lub je odrzucisz, odpowiesz na pytanie albo wyślesz kolejne polecenie, gdy Claude się zatrzyma. To niezależny projekt, nie stworzony przez Anthropic. Jeśli potrzebujesz tylko logu albo lintowania, prościej napisać kilka własnych linijek. Szczegóły znajdziesz na stronie ccn.
10FAQ
Jak przetestować hook bez czekania na Claude?
Przekaż przykładowy JSON do skryptu przez pipe i sprawdź kod wyjścia: echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh; echo $?. Potem uruchom /hooks w Claude Code, żeby potwierdzić, że jest zarejestrowany pod właściwym eventem.
Dlaczego mój hook się nie uruchamia?
Najczęstsze przyczyny to niepoprawny JSON w settings.json (końcowe przecinki, komentarze), matcher, który nie pasuje dokładnie (rozróżnia wielkość liter), skrypt bez uprawnień do wykonania albo folder, któremu jeszcze nie zaufałeś. Uruchom Claude Code przez claude --debug i sprawdź w logu debugowania, co się uruchomiło. Pełną listę znajdziesz w checkliście rozwiązywania problemów.
Jak na chwilę wyłączyć wszystkie hooki?
Ustaw "disableAllHooks": true w pliku ustawień. Żeby pominąć je dla jednego uruchomienia, startuj Claude Code z --settings '{"disableAllHooks": true}'. Nie ma przełącznika dla pojedynczego hooka – zamiast tego usuwasz jego wpis. Żaden z tych sposobów nie wyłączy hooków ustawionych przez twoją organizację w managed settings.
Jaki jest domyślny timeout hooka?
Dziesięć minut (600 sekund) dla hooków typu command, HTTP i MCP tool, 30 sekund dla hooków prompt i 60 dla hooków agent. Kilka eventów ma krótsze wartości domyślne, a w każdym handlerze możesz ustawić timeout w sekundach.