← Wszystkie wpisy

Hooki Claude Code: dlaczego istnieje każdy z moich 95 hooków

From the guide: Claude Code Comprehensive Guide

Zbudowałem 95 hooków dla Claude Code. Każdy z nich istnieje, ponieważ najpierw coś poszło nie tak. Git-safety-guardian istnieje, ponieważ Claude wymusił push do gałęzi main. Recursion-guard istnieje, ponieważ subagent zrodził nieskończoną liczbę potomków. Blog-quality-gate istnieje, ponieważ opublikowałem wpis z 7 zdaniami w stronie biernej i wiszącym przypisem.1

Hooki Claude Code to polecenia powłoki wykonywane w określonych punktach cyklu życia (start sesji, przed/po użyciu narzędzia, przesłanie promptu, zakończenie odpowiedzi), stanowiące deterministyczne zabezpieczenia nakładane na probabilistyczne zachowanie LLM. Hooki odbierają JSON na stdin i zwracają decyzje (blokuj, zezwól lub modyfikuj) przez stdout. Egzekwują zasady takie jak blokowanie wymuszonych pushów do main, zapobieganie rekurencyjnemu powielaniu agentów, wstrzykiwanie kontekstu w każdej sesji oraz kontrolę jakości wyjścia, której sam LLM nie jest w stanie zagwarantować.

TL;DR

Hooki Claude Code wykonują polecenia powłoki w określonych punktach cyklu życia podczas programowania wspieranego przez AI. Zapewniają deterministyczne gwarancje (blokowanie niebezpiecznych poleceń git, wstrzykiwanie kontekstu, egzekwowanie jakości) na szczycie systemu probabilistycznego (LLM). Po zbudowaniu 95 hooków w ramach mojej infrastruktury stwierdziłem, że najlepsze hooki powstają z incydentów, a nie z planowania. Ten wpis obejmuje architekturę, historie powstania moich najbardziej krytycznych hooków oraz wzorce, których nauczyłem się podczas 9 miesięcy rozwijania hooków.


Architektura

Claude Code udostępnia 26 zdarzeń cyklu życia, w których hooki mogą przechwytywać, modyfikować lub blokować zachowanie (stan na v2.1.116, kwiecień 2026).2 Moje hooki celują w sześć najpowszechniejszych z nich:

Zdarzenia sesji

Zdarzenie Kiedy się uruchamia Moje hooki
SessionStart Rozpoczyna się nowa sesja session-start.sh: wstrzykuje datę, waliduje venv, inicjalizuje stan rekurencji
SessionEnd Sesja kończy się Czyszczenie plików tymczasowych

Zdarzenia wykonania narzędzi

Zdarzenie Kiedy się uruchamia Moje hooki
PreToolUse Przed wykonaniem dowolnego narzędzia git-safety-guardian.sh, recursion-guard.sh, credentials-check.sh
PostToolUse Po zakończeniu narzędzia post-deliberation.sh, log-bash.sh

Zdarzenia odpowiedzi

Zdarzenie Kiedy się uruchamia Moje hooki
UserPromptSubmit Użytkownik wysyła prompt Wstrzykiwacze kontekstu (data, gałąź, informacje o modelu)
Stop Claude kończy odpowiadać deliberation-pride-check.sh, reviewer-stop-gate.sh

Każdy hook odbiera JSON na stdin i komunikuje się przez stdout:

{"decision": "block", "reason": "Force push to main is prohibited"}

Lub po cichu zezwala, wychodząc z kodem 0.3


Historie powstania: hooki, które mają największe znaczenie

Hook 1: git-safety-guardian.sh (PreToolUse:Bash)

Incydent: Podczas jednej z wczesnych sesji Claude Code poprosiłem agenta o „uporządkowanie historii git”. Agent wykonał git push --force origin main. Wymuszony push nadpisał trzy dni commitów na współdzielonej gałęzi. Odzyskałem dane z lokalnej kopii zapasowej, ale 4-godzinny proces odzyskiwania przekonał mnie, że probabilistyczny osąd nigdy nie powinien kontrolować destrukcyjnych operacji git.

Hook:

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

# Only check git commands
echo "$COMMAND" | grep -qE '\bgit\b' || exit 0

# Block force push to main/master
if echo "$COMMAND" | grep -qiE 'git\s+push\s+.*--force.*\b(main|master)\b'; then
    cat << EOF
{"decision": "block", "reason": "Force push to main/master blocked by safety hook"}
EOF
fi

Wniosek: Hook nie próbuje zrozumieć intencji. Dopasowuje wzorzec do ciągu polecenia. Prosty, deterministyczny, niemożliwy do obejścia przez sprytne promptowanie. Agent nadal może wymusić push do gałęzi funkcyjnych (czasem uzasadniony), ale main/master są trwale chronione.4

Uratowane przez cały okres działania: 8 przechwyconych prób wymuszonego pusha w ciągu 9 miesięcy.

Hook 2: recursion-guard.sh (PreToolUse:Task)

Incydent: Podczas budowania systemu deliberacji uruchomiłem sesję, która zrodziła 3 subagenty eksploracyjne. Każdy z subagentów, nie mając limitów powielania, zrodził własne subagenty. Rekurencja pochłonęła API tokenów w tempie 10-krotnie większym niż normalne. Zabiłem sesję ręcznie po zauważeniu przyspieszającego spalania tokenów.

Hook:

#!/bin/bash
CONFIG_FILE="${HOME}/.claude/configs/recursion-limits.json"
STATE_FILE="${HOME}/.claude/state/recursion-depth.json"

MAX_DEPTH=2
MAX_CHILDREN=5
DELIB_SPAWN_BUDGET=2
DELIB_MAX_AGENTS=12

# Validate integers safely (((VAR++)) crashes with set -e when VAR=0)
is_positive_int() {
    [[ "$1" =~ ^[0-9]+$ ]] && [[ "$1" -gt 0 ]]
}

Kluczowa decyzja projektowa: Agenci dziedziczą budżet powielania po rodzicu, zamiast zwiększać głębokość. Agent root z budżetem=12 może rozdzielić ten budżet w ramach dowolnego kształtu drzewa. Limity oparte na głębokości są zbyt sztywne (uniemożliwiają głębokie, ale wąskie łańcuchy, które są całkowicie bezpieczne).5

Blokady przez cały okres działania: 23 próby niekontrolowanego powielania.

Hook 3: blog-quality-gate.sh (Stop)

Incydent: Opublikowałem wpis na blogu z 7 zdaniami w stronie biernej, przypisem odwołanym w tekście, ale brakującym w sekcji odniesień, oraz zdaniem „was implemented by the team” jako linią otwierającą. Wpis wyglądał dopracowanie w moim edytorze, ale nie przeszedł podstawowych kontroli jakości, które wychwyciłby każdy ludzki recenzent.

Hook: Uruchamia mój 12-modułowy linter blogowy na każdym zmodyfikowanym pliku treści bloga. Sprawdza stronę bierną, wiszące przypisy, brakujące meta-opisy, nieotagowane bloki kodu oraz integralność cytowań. Każde znalezisko jest konkretne: „Linia 47: wykryto stronę bierną w ‘was implemented by the team.’ Sugestia: ‘the team implemented.’”

Analogia z ludzkim feedbackiem: Hook krytykuje pracę, a nie operatora. Mówi „linia 47 zawiera stronę bierną”, a nie „piszesz źle”. Ta sama zasada, która czyni ludzki feedback konstruktywnym, czyni zautomatyzowany feedback użytecznym.


Wzorzec stojący za 95 hookami

Architektura oparta na konfiguracji

Moje hooki ewoluowały od zakodowanych na sztywno wartości do zachowań sterowanych konfiguracją:

~/.claude/configs/
├── recursion-limits.json     # Depth, spawn budgets, timeouts
├── deliberation-config.json  # Consensus thresholds per task type
├── consensus-profiles.json   # security=85%, docs=50%
├── circuit-breaker.json      # Failure mode configurations
└── file-scope-rules.json     # Path-scoped hook application

Przeniesienie progów do konfiguracji JSON oznaczało, że mogłem dostrajać zachowanie bez edytowania skryptów bash. Gdy potrzebowałem konsensusu związanego z bezpieczeństwem na poziomie 85%, a dokumentacji na 50%, zmiana konfiguracji zajęła 30 sekund. Zmiana kodu wymagałaby edytowania, testowania i ponownego wdrożenia.6

Wzorzec warstwowania cyklu życia

Moje 95 hooków tworzy siatkę bezpieczeństwa z czterema warstwami:

Warstwa 1: Prewencja (PreToolUse): Powstrzymuj złe rzeczy, zanim się wydarzą. git-safety-guardian, credentials-check, recursion-guard.

Warstwa 2: Kontekst (UserPromptSubmit, SessionStart): Wstrzykuj informacje, których agent potrzebuje. Data, gałąź, kontekst projektu, wpisy pamięci, zasady filozofii.

Warstwa 3: Walidacja (PostToolUse): Weryfikuj, czy zakończone działania spełniają standardy. Sprawdzanie konsensusu po deliberacji, logowanie wyjścia.

Warstwa 4: Jakość (Stop): Bramkowanie końcowego wyjścia. Pride check, quality gate, reviewer stop gate. Ta warstwa realizuje monitorowanie metapoznawcze, w którym agent ocenia jakość własnego rozumowania, a nie tylko wyjścia.

Każda warstwa jest niezależna. Jeśli hook PreToolUse zawiedzie po cichu, hook Stop nadal wychwyci problemy z jakością. Obrona w głąb, zastosowana do zachowania agenta AI.


Konfiguracja

Hooki znajdują się w .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "command": "~/.claude/hooks/git-safety-guardian.sh",
        "timeout": 5000
      }
    ],
    "PreToolUse:Task": [
      {
        "command": "~/.claude/hooks/recursion-guard.sh"
      }
    ]
  }
}

Pole matcher filtruje, które narzędzia wyzwalają hook. PreToolUse:Task to skrót dla matchera, który uruchamia się tylko przy wywołaniach narzędzia Task. Hooki asynchroniczne (async: true) działają w tle bez blokowania.7

Hierarchia zasięgu

  1. Poziom użytkownika (~/.claude/settings.json): ma zastosowanie do wszystkich projektów. Moje 95 hooków znajduje się tutaj.
  2. Poziom projektu (.claude/settings.json): dodaje hooki specyficzne dla projektu.
  3. Frontmatter Skill/Subagent: ograniczony do cyklu życia konkretnego komponentu.8

Co zrobiłbym inaczej

Zacząć od 3 hooków, a nie 25. Mój pierwszy miesiąc dał 25 hooków, z których wiele dodawało kontekst, który agent już posiadał. Narzut związany z ładowaniem 25 hooków przy każdym wywołaniu narzędzia był mierzalny. Ostatecznie przyciąłem zestaw do hooków przynoszących realną wartość (zapobiegających realnym incydentom, wychwytujących realne problemy z jakością).

Oparcie na konfiguracji od pierwszego dnia. Spędziłem dwa tygodnie na refaktoryzacji zakodowanych na sztywno progów do konfiguracji JSON. Ta refaktoryzacja byłaby darmowa, gdybym zaczął od konfiguracji.

Wczesna infrastruktura testowa. Pierwsze 20 hooków nie miało testów. Gdy dodałem zestaw testowy (48 testów integracyjnych bash), znalazłem 3 hooki, które po cichu zawodziły w przypadkach brzegowych. Testy powinny były trafić razem z hookiem #1.


Kluczowe wnioski

Dla deweloperów zaczynających z hookami: - Warto zacząć od trzech hooków: bezpieczeństwo git (PreToolUse:Bash), wstrzykiwanie kontekstu (UserPromptSubmit) oraz bramka jakości (Stop); kolejne należy dodawać dopiero wtedy, gdy pojawią się incydenty, które to uzasadniają - Warto zastosować framework momentu decyzji: architektura hooków jest nieodwracalna (95 hooków od niej zależy), więc należy zainwestować w model cyklu życia przed napisaniem hooków

Dla zespołów standaryzujących hooki: - Należy standaryzować hooki na poziomie użytkownika, aby każdy członek zespołu otrzymał te same zabezpieczenia - Warto śledzić metryki hooków (zablokowane operacje, przechwycone incydenty), aby uzasadnić koszt utrzymania - Należy co miesiąc przeglądać logi hooków, aby zidentyfikować nowe wzorce warte zautomatyzowania


FAQ

Czym są hooki Claude Code?

Hooki to skrypty powłoki wykonywane w określonych punktach cyklu życia podczas sesji Claude Code. Uruchamiają się deterministycznie w konkretnych momentach: przed wykonaniem narzędzia (PreToolUse), po jego zakończeniu (PostToolUse), gdy użytkownik wysyła prompt (UserPromptSubmit), gdy sesja się rozpoczyna (SessionStart) oraz gdy Claude kończy odpowiadać (Stop). Hooki odbierają JSON na stdin z pełnym kontekstem (nazwa narzędzia, dane wejściowe, ID sesji) i mogą blokować operacje, wstrzykiwać kontekst lub egzekwować bramki jakości. Dostarczają deterministyczne gwarancje nakładane na probabilistyczny LLM.

Ile hooków może uruchomić Claude Code i czy wiąże się to z kosztem wydajnościowym?

Nie ma twardego limitu liczby hooków. Uruchamiam 95 hooków w 6 z 26 dostępnych zdarzeń cyklu życia (stan na v2.1.116, kwiecień 2026), z łącznym narzutem około 200 ms na zdarzenie. Praktycznym limitem jest latencja: każdy hook dodaje czas wykonania przed lub po wywołaniach narzędzi. Kluczową optymalizacją jest użycie dispatcherów (jeden na zdarzenie, uruchamiający hooki sekwencyjnie z buforowanego stdin) zamiast niezależnych hooków, z których każdy czyta stdin osobno. Równoczesne zapisy z niezależnych hooków powodowały korupcję JSON w mojej wczesnej konfiguracji; dispatchery całkowicie wyeliminowały ten tryb awarii.

Na jakich zdarzeniach uruchamiają się hooki Claude Code?

Claude Code udostępnia 26 zdarzeń cyklu życia dla hooków według stanu na v2.1.116 (kwiecień 2026). Sześć najpowszechniejszych, w które celują moje hooki, to: SessionStart (rozpoczyna się nowa sesja), SessionEnd (sesja kończy się), PreToolUse (przed wykonaniem dowolnego narzędzia), PostToolUse (po zakończeniu narzędzia), UserPromptSubmit (użytkownik wysyła prompt) oraz Stop (Claude kończy odpowiadać). Inne to SubagentStart, PermissionRequest, PermissionDenied, TaskCreated, CwdChanged, FileChanged, PreCompact i więcej. PreToolUse i PostToolUse można dalej ograniczać matcherami takimi jak PreToolUse:Bash lub PreToolUse:Task, aby uruchamiały się tylko dla określonych typów narzędzi. Każde zdarzenie odbiera JSON na stdin z odpowiednim kontekstem.

Czy hooki Claude Code mogą blokować wywołania narzędzi?

Tak. Hook, który wypisuje {"decision": "block", "reason": "explanation"} na stdout, uniemożliwia wykonanie wywołania narzędzia. To główny mechanizm dla hooków bezpieczeństwa: mój git-safety-guardian blokuje wymuszone pushe do main, mój credentials-check blokuje odczyty plików .env, a mój recursion-guard blokuje nadmierne powielanie agentów. Blokada jest deterministyczna i nie można jej obejść przez promptowanie. Hooki, które kończą się po cichu z kodem 0, pozwalają operacji przejść dalej.

Jaka jest różnica między hookami PreToolUse i PostToolUse?

PreToolUse uruchamia się przed wykonaniem narzędzia i może zablokować operację całkowicie. Stosuje się go do bramek bezpieczeństwa: blokowania niebezpiecznych poleceń, sprawdzania poświadczeń, egzekwowania budżetów powielania. PostToolUse uruchamia się po zakończeniu narzędzia i może zapewnić informację zwrotną lub wyzwolić działania następcze. Stosuje się go do walidacji: sprawdzania jakości wyjścia, logowania aktywności, weryfikowania konsensusu. Razem tworzą pierwszą i trzecią warstwę czterowarstwowej siatki bezpieczeństwa: prewencja (PreToolUse), wstrzykiwanie kontekstu (UserPromptSubmit), walidacja (PostToolUse) oraz bramkowanie jakości (Stop).

Odniesienia


  1. Infrastruktura hooków autora. 95 hooków w 6 z 26 dostępnych zdarzeń cyklu życia (v2.1.116, kwiecień 2026), opracowana przez 9 miesięcy (2025-2026). 

  2. Anthropic, “Claude Code Hooks Reference,” 2026. 26 typów zdarzeń cyklu życia według stanu na v2.1.116 (kwiecień 2026). 

  3. Anthropic, “Claude Code Documentation,” 2025. Format wejścia/wyjścia hooków JSON. 

  4. Skrypt git-safety-guardian.sh autora. 8 przechwyconych prób wymuszonego pusha śledzonych w ~/.claude/state/

  5. Skrypt recursion-guard.sh autora. Model dziedziczenia budżetu udokumentowany w ~/.claude/configs/recursion-limits.json

  6. Architektura autora oparta na konfiguracji. 14 plików konfiguracyjnych JSON kodujących wszystkie progi i reguły hooków. 

  7. Anthropic, “Claude Code Documentation,” 2025. Konfiguracja hooków i wykonywanie asynchroniczne. 

  8. Anthropic, “Claude Code Documentation,” 2025. Hierarchia zasięgu hooków. 

Powiązane artykuły

Tworzenie własnych umiejętności dla Claude Code: Kompletny poradnik

Zbuduj skill przegladu kodu od zera. Struktura katalogow, pola frontmatter, dopasowanie oparte na LLM, budzety kontekstu…

11 min czytania

Zarządzanie oknem kontekstu: czego nauczyło mnie 50 sesji z AI

Zmierzyłem zużycie tokenów w 50 sesjach Claude Code. Wyczerpanie kontekstu pogarsza jakość wyników, zanim to zauważysz. …

5 min czytania

Poradnik Claude Code Hooks: 5 produkcyjnych hooków od podstaw

Zbuduj 5 praktycznych hooków Claude Code od podstaw: automatyczne formatowanie, bramki bezpieczeństwa, uruchamianie test…

7 min czytania