W sesji Claude Code odpala się 30 zdarzeń hooków. Tylko 3 mogą odpowiedzieć.
Kompletna lista zdarzeń hooków Claude Code, kiedy każde z nich się odpala, które 15 może blokować i reguła stdout, która po cichu połyka wyjście większości hooków. Referencja z pola walki, zbudowana na hookach działających w produkcji przez tysiące sesji agentów.
Dwie awarie wracają raz za razem, kiedy ludzie podpinają hooki do Claude Code, i nie są do siebie ani trochę podobne.
Pierwsza: dodajesz hooka, nic się nie dzieje. Bez błędu, bez ostrzeżenia, bez linijki w logu. Hook po prostu nigdy się nie uruchamia.
Druga: hook wyraźnie działa, widzisz jego efekty uboczne na dysku, ale wiadomość, którą wypisuje dla agenta, nigdy nie dociera. Agent zachowuje się tak, jakby hook nic nie powiedział.
Obie biorą się z tego samego miejsca. System hooków jest większy i mniej jednolity niż garstka zdarzeń, które opisuje większość artykułów, a reguły mówiące o tym, kto może odezwać się do agenta, nie są tymi, których byś się spodziewał. To jest referencja, której nam brakowało. Budujemy AgentsRoom na tych hookach, a wszystko poniżej jest albo zacytowane z oficjalnej referencji, albo zmierzone w produkcji.
Zdarzeń jest 30, nie sześć
Większość poradników omawia PreToolUse, PostToolUse, UserPromptSubmit, Stop, Notification i SubagentStop. Ta szóstka jest prawdziwa i to na niej opiera się większość użytecznej pracy. Jest też jedną piątą tego, co istnieje.
Pełna lista, pogrupowana według tego, co obserwują:
| Grupa | Zdarzenia |
|---|---|
| Sesja | SessionStart, SessionEnd, Setup |
| Prompt | UserPromptSubmit, UserPromptExpansion |
| Narzędzia | PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch |
| Uprawnienia | PermissionRequest, PermissionDenied |
| Tura | Stop, StopFailure |
| Subagenty i zadania | SubagentStart, SubagentStop, TaskCreated, TaskCompleted, TeammateIdle |
| Kontekst | PreCompact, PostCompact, InstructionsLoaded |
| Środowisko | FileChanged, CwdChanged, ConfigChange |
| Worktrees | WorktreeCreate, WorktreeRemove |
| Interfejs | Notification, MessageDisplay |
| Elicitation MCP | Elicitation, ElicitationResult |

Kolejność odpalania zdarzeń w jednej sesji. Blok narzędziowy powtarza się raz na każde wywołanie narzędzia, a cały blok promptu raz na turę.
Kilka z nich zmienia sposób myślenia o systemie. PostToolUseFailure istnieje, więc gałąź „czy narzędzie zadziałało" jest zdarzeniem, a nie czymś, co wnioskujesz z payloadu. PostToolBatch odpala się raz, po rozwiązaniu paczki równoległych wywołań narzędzi, i to jest właściwe miejsce, żeby uruchomić linter jeden raz zamiast raz na każdą edycję. InstructionsLoaded odpala się przy odczycie CLAUDE.md, co daje punkt zaczepienia do sprawdzenia, czy agent naprawdę załadował reguły, o których myślisz, że je załadował.
Reguła stdout, która połyka wyjście większości hooków
To najbardziej użyteczna rzecz na tej stronie.
Przy kodzie wyjścia 0 Claude Code parsuje stdout w poszukiwaniu pól JSON. Ale to, czy ten stdout kiedykolwiek zostanie pokazany agentowi, zależy od zdarzenia, a wyjątków jest krótka lista. Z referencji:
W przypadku większości zdarzeń stdout jest zapisywany do logu debug, ale nie jest pokazywany w transkrypcji. Wyjątkami są
UserPromptSubmit,UserPromptExpansioniSessionStart, gdzie stdout jest dodawany jako kontekst, który Claude może zobaczyć i wykorzystać.
Trzy zdarzenia na trzydzieści. Jeśli zrobisz echo "uwaga: ta migracja jest destrukcyjna" z hooka PostToolUse i liczysz, że agent to przeczyta, nigdy tego nie zrobi. Twój tekst poszedł do logu debug.
Istnieją dokładnie dwa sposoby, żeby podstawić agentowi tekst z dowolnego innego zdarzenia:
- Zakończ z kodem 2 i pisz na stderr. Przy kodzie wyjścia 2 Claude Code ignoruje stdout i cały JSON w nim zawarty, a stderr podaje agentowi jako komunikat błędu.
- Zakończ z kodem 0 i wypisz obiekt JSON niosący
hookSpecificOutput.additionalContext.
Zwróć uwagę na asymetrię w pierwszym punkcie. Kod wyjścia 0 znaczy, że liczy się stdout, a stderr nie. Kod wyjścia 2 znaczy, że liczy się stderr, a stdout jest wyrzucany w całości. Pomylenie tych dwóch kierunków to powód, dla którego hook może wyglądać całkowicie poprawnie i mimo to być niemy.
Każdy inny kod wyjścia to błąd nieblokujący. W transkrypcji pojawia się komunikat <hook name> hook error z pierwszą linijką stderr, wykonanie trwa dalej, a pełny stderr ląduje w logu debug.

Który kanał dociera do agenta, w zależności od kodu wyjścia. Ścieżka przerywana to ta, o której ludzie zakładają, że istnieje, a której nie ma.
Dokładnie połowa z nich może blokować
Piętnaście zdarzeń zatrzymuje akcję przy kodzie wyjścia 2. Piętnaście ignoruje go i idzie dalej.
Mogą blokować: PreToolUse, PermissionRequest, UserPromptSubmit, UserPromptExpansion, Stop, SubagentStop, TeammateIdle, TaskCreated, TaskCompleted, ConfigChange, PostToolBatch, PreCompact, Elicitation, ElicitationResult, WorktreeCreate.
Nie mogą blokować: PostToolUse, PostToolUseFailure, PermissionDenied, StopFailure, Notification, SubagentStart, SessionStart, Setup, SessionEnd, CwdChanged, FileChanged, PostCompact, WorktreeRemove, InstructionsLoaded, MessageDisplay.
Praktyczna konsekwencja: zabezpieczenie zakłada się na PreToolUse, nigdy na PostToolUse. PostToolUse odpala się po tym, jak narzędzie zakończyło się sukcesem. Zakończenie tam z kodem 2 nie cofa zapisu, tylko wypisuje błąd, podczas gdy szkody już leżą na dysku. Jeśli chcesz zatrzymać rm -rf, masz dokładnie jedno miejsce, żeby to zrobić.
To, że PostToolBatch blokuje, a PostToolUse nie, warte jest drugiego spojrzenia. Znaczy to, że sprawdzenie na poziomie paczki wciąż może zatrzymać turę po wylądowaniu równoległych edycji, a to najbliższa rzecz do weta po zapisie, jaką ten system oferuje.
Matchery są dokładne, dopóki nagle nie przestaną
Pole matcher zmienia strategię ewaluacji w zależności od własnych znaków i nic ci nie mówi, którą ścieżką poszło.
| Matcher | Ewaluowany jako |
|---|---|
"*", "", albo pominięty | dopasowuje wszystko |
Tylko litery, cyfry, _, -, spacje, ,, | | dokładny łańcuch albo lista dokładnych łańcuchów rozdzielona | lub , |
| Cokolwiek innego | niezakotwiczone wyrażenie regularne JavaScript |
Pułapką jest brak zakotwiczenia. Referencja mówi wprost, że wyrażenie jest testowane przez RegExp.prototype.test, który zwraca sukces przy dopasowaniu gdziekolwiek w wartości. Więc Edit.* dopasowuje Edit oraz NotebookEdit. Jeśli chodziło ci o jedno narzędzie, napisz ^Edit$.
Dwa zachowania zależne od wersji, warte poznania, zanim zaczniesz debugować nie to co trzeba:
- Przecinki jako separatory i tolerancja na białe znaki wymagają Claude Code v2.1.191 lub nowszego.
- Myślniki dołączyły do zestawu znaków dokładnego dopasowania w v2.1.195. Wcześniej matcher taki jak
code-reviewerbył traktowany jak niezakotwiczona regex, więc odpalał się także dlasenior-code-reviewer.
W AgentsRoom zawężamy nasz własny hook atrybucji plików przez Write|Edit|MultiEdit|NotebookEdit, co zostaje na ścieżce dokładnego łańcucha i dopasowuje te cztery narzędzia i nic więcej. Hooki cyklu życia, które instalujemy, nie mają żadnego matchera, bo zawsze nas dotyczą.
Hooki może definiować sześć miejsc, i one się łączą
Odruchem jest szukanie kolejności pierwszeństwa. Nie ma jej i to jest właśnie ciekawe.
| Lokalizacja | Zasięg |
|---|---|
~/.claude/settings.json | wszystkie twoje projekty, lokalnie na twojej maszynie |
.claude/settings.json | jeden projekt, do zacommitowania |
.claude/settings.local.json | jeden projekt, gitignorowany przez Claude Code |
| Managed policy settings | cała organizacja, kontrolowane przez admina |
hooks/hooks.json pluginu | dopóki plugin jest włączony |
| Frontmatter skilla albo agenta | dopóki komponent jest aktywny |
Z referencji:
Wpisy hooków łączą się między poziomami ustawień, zamiast się nawzajem zastępować: ustawienia użytkownika, projektu i lokalne dokładają własne hooki, nie usuwając tych zarządzanych, a ustawienie
disableAllHooksnie może wyłączyć hooków zarządzanych spoza ustawień zarządzanych.
Więc hook projektowy nigdy nie nadpisuje globalnego, tylko dokłada się do niego. Sześć źródeł, wszystkie addytywne. Formater PostToolUse zdefiniowany w twoich ustawieniach użytkownika i ponownie w projekcie uruchamia się dwa razy na każdą edycję, a jedynym objawem jest wrażenie, że wszystko chodzi wolno.

Sześć źródeł, jeden połączony zbiór. Nic tutaj niczego nie nadpisuje.
To wyjaśnia też, dlaczego .claude/settings.local.json jest właściwym miejscem, żeby narzędzie zainstalowało hooka w czyimś projekcie. Jest ograniczony do projektu, Claude Code go gitignoruje i ładuje się bez żadnej flagi CLI. To tam AgentsRoom zapisuje swoje wpisy, dzięki czemu zacommitowany przez użytkownika .claude/settings.json nigdy nie jest ruszany, a jego koledzy z zespołu nigdy nie dziedziczą ścieżki związanej z konkretną maszyną.
Czego nauczyło nas uruchamianie hooków w produkcji
AgentsRoom instaluje hooki w każdym otwieranym projekcie, żeby deterministycznie śledzić status agentów i przypisywać edytowane pliki do właściwego agenta. Kilka rzeczy widać dopiero w tej skali.
Nieznane nazwy zdarzeń są po cichu ignorowane. Nie ma tego w dokumentacji, a my na tym polegamy. Kiedy dodajemy nowe zdarzenie cyklu życia do naszego instalatora, użytkownicy na starszym CLI dostają settings.local.json zawierający nazwę zdarzenia, o której ich binarka nigdy nie słyszała. Nic się nie psuje, nic nie ostrzega, wpis jest pomijany. To właśnie sprawia, że instalator można bezpiecznie wydać przed wydaniem CLI. To także, nieuchronnie, powód, dla którego literówka daje kompletną ciszę zamiast błędu.
agent_id to sposób, żeby wiedzieć, że jesteś wewnątrz subagenta. Pole jest obecne tylko wtedy, gdy hook odpala się wewnątrz wywołania subagenta. Znaczy to więcej, niż brzmi: Stop odpala się, gdy subagent kończy swoją turę, nie tylko agent główny. Naiwna reguła „oznacz sesję jako zakończoną przy Stop" oznacza całą sesję jako skończoną przy pierwszym powrocie dowolnego subagenta. Dokładnie z tego powodu pomijamy zdarzenia tury niosące agent_id.
Nie czytaj transcript_path dla bieżącej tury. Referencja ostrzega, że transkrypcja jest zapisywana asynchronicznie i może być opóźniona względem rozmowy w pamięci, więc najnowszych wiadomości może tam jeszcze nie być, kiedy twój hook się odpala. Stop i SubagentStop dostają last_assistant_message właśnie po to, żebyś nigdy nie musiał ścigać się z plikiem.
Hooki są jedynym wiarygodnym sygnałem statusu. Zanim pojawiły się hooki, skrobaliśmy PTY, żeby ustalić, czy agent myśli, czeka, czy skończył. To przestaje działać w chwili, w której CLI renderuje przez alternatywny bufor ekranu terminala, a to właśnie robi /tui fullscreen. Hooki odpalają się identycznie pod każdym rendererem. Jeśli budujesz cokolwiek, co obserwuje agenta z zewnątrz, to jest warstwa, na której należy budować, a skrobanie zostaje w najlepszym razie jako rozwiązanie awaryjne.
async: true nic nie kosztuje. Komenda hooka może zadeklarować async: true i agent na nią nie czeka. Nasz hook wysyła POST na lokalny endpoint z limitem 2 sekund i wraca; opóźnienie tury agenta pozostaje bez zmian, nawet gdy aplikacja odbierająca jest zamknięta. Jeśli twój hook tylko obserwuje i nigdy nie decyduje, zrób go asynchronicznym i przestań za niego płacić.
Nigdy nie pozwól hookowi wypisać śmieci do terminala. Nasz skrypt połyka każdy wyjątek, również na najwyższym poziomie. Nieobsłużony traceback z hooka nie zawodzi po cichu: wypisuje pythonowy stos wywołań do sesji terminala użytkownika, w środku jego pracy.
Limity czasu
Wartości domyślne są hojne, z trzema wyjątkami, które hojne nie są:
| Typ hooka | Domyślny limit czasu |
|---|---|
command, http, mcp_tool | 600 s |
prompt | 30 s |
agent | 60 s |
UserPromptSubmit (command, http, mcp_tool) | 30 s |
MessageDisplay (command, http, mcp_tool) | 10 s |
SessionEnd | 1,5 s dzielone między wszystkie hooki, podnoszone do dłuższego timeout ustawionego dla pojedynczego hooka, maksymalnie do 60 s |
Budżet SessionEnd to ten, który ludzi zaskakuje. To budżet dzielony, a nie przydział na hooka, więc trzy hooki sprzątające dzielą między siebie 1,5 sekundy, o ile nie podniesiesz go jawnie.
Wersja skrócona
- Istnieje 30 zdarzeń. Sześć jest znanych.
- stdout dociera do agenta wyłącznie przy
UserPromptSubmit,UserPromptExpansioniSessionStart. Wszędzie indziej użyj kodu wyjścia 2 ze stderr alboadditionalContextw JSON. - 15 zdarzeń blokuje przy kodzie wyjścia 2, 15 go ignoruje. Zabezpieczenia idą na
PreToolUse. - Matchery są dokładnymi łańcuchami, dopóki znak specjalny nie zamieni ich w niezakotwiczoną regex.
- Sześć źródeł ustawień łączy się addytywnie. Nic niczego nie nadpisuje.
- Literówka w nazwie zdarzenia zawodzi w kompletnej ciszy.
Jeśli wolisz oglądać, jak te zdarzenia się odpalają, zamiast o nich rozmyślać, właśnie to zbudowaliśmy: AgentsRoom pokazuje każde odpalenie hooka dla każdego agenta, projektu i uruchomienia, w dziesiątkach równoległych agentów i sesjach subagentów. Hooki, które konfigurujesz we własnych ustawieniach, działają dokładnie tak, jak je napisałeś, bo pod spodem chodzi prawdziwe CLI.
Czytaj dalej
Vibe coding a RODO: dlaczego strona zbudowana przez AI łamie prawo
Agenty kodujące w stylu Claude Code czy Codex potrafią postawić działającą stronę w kilka godzin, ale po cichu wprowadzają naruszenia RODO, o które nikt nie prosił: pliki cookie ustawiane przed zgodą, dane osobowe trzymane w nieskończoność, brak możliwości ich usunięcia. Oto dlaczego dzieje się to przy każdym agencie kodującym, ile może cię to kosztować i darmowy skill do Claude Code, który skanuje projekt pod kątem problemów z RODO i je naprawia.
Czytaj artykułKonwersja PDF na Markdown, aby oszczędzać tokeny LLM: poradnik MarkItDown
Podanie PDF prosto do Claude lub dowolnego LLM po cichu pożera tokeny: każda strona jest też zamieniana w obraz. Najpierw przekonwertuj plik na Markdown za pomocą MarkItDown, darmowego narzędzia open source od Microsoftu, i obetnij rachunek za tokeny nawet o 80%. Pełny poradnik: CLI, Python i serwer MCP.
Czytaj artykułJak skalować agentów AI do kodowania w zespole deweloperskim
Jeden deweloper z agentem kodującym to historia o produktywności. Pięciu deweloperów z dwudziestoma agentami to problem koordynacji. Oto co psuje się jako pierwsze, gdy zespół się rozrasta, oraz konfiguracja, która działa: zobowiązane pliki kontekstowe, jasna własność plików, przegląd według promienia eksplozji i koszty, które naprawdę widać.
Czytaj artykuł
Pobierz AgentsRoom
Uruchamiaj swoich agentów AI (Claude, Codex, Antigravity CLI, OpenCode, Aider, Grok Build, Mistral Vibe, Kimi Code) na wszystkich projektach z jednego okna.
Aplikacja towarzyszaca: monitoruj agentów w podrozy
Użyj Claude, Codex, Antigravity CLI lub innego dostawcy AI.
Wysyłaj bugi i prośby bezpośrednio do swojego publicznego backlogu.
Spojrzenie na AgentsRoom w akcji.