Lekcja 5 · Deterministyczne kontra "model zdecyduje"

Hooki: automatyzacja, która nie pyta modelu o zdanie

CLAUDE.md, skille i subagenty mają jedną wspólną cechę: to Claude czyta ich treść i decyduje, czy i jak z niej skorzystać. Hook łamie tę zasadę — to zwykła komenda shellowa, która wykonuje się zawsze w konkretnym momencie cyklu życia sesji, niezależnie od tego, co model "myśli".

Polecane źródło Automate actions with hooks — Claude Code Docs — wprowadzenie z gotowymi przykładami konfiguracji.

Czego Ty pilnujesz, a czego pilnuje hook

CLAUDE.md / Skill / SubagentHook
Kto decyduje, czy coś się wykonaModel, na podstawie treści instrukcjiNikt nie decyduje — wykonuje się zawsze
FormaTekst, który model interpretujeKomenda shellowa
Ryzyko pominięciaModel może zapomnieć albo zignorowaćBrak — to nie jest sugestia

Dlatego hook jest właściwym narzędziem dla reguł, których złamanie kosztuje realnie: formatowanie kodu, blokada edycji plików chronionych, walidacja komend przed wykonaniem.

Kluczowy wniosek: hook SessionStart z matcherem compact może po każdym /compact (Lekcja 1) automatycznie dopisać do kontekstu rzeczy, które nie są na tyle stałe, żeby trzymać je w CLAUDE.md, ale na tyle ważne, żeby nie zgubić ich w podsumowaniu — np. nad czym akurat pracujesz w tej sesji.

Gdzie mieszkają hooki

LokalizacjaZasięgWspółdzielony?
~/.claude/settings.jsonwszystkie Twoje projektynie, tylko lokalnie
.claude/settings.jsonten projekttak, przez git
.claude/settings.local.jsonten projektnie, gitignorowane

Hook to blok hooks w pliku ustawień: nazwa eventu jako klucz, matcher filtrujący kiedy się odpali, i lista komend do uruchomienia.

Kilka najważniejszych eventów

EventKiedy się odpala
PreToolUseprzed wywołaniem narzędzia — może je zablokować
PostToolUsepo udanym wywołaniu narzędzia — np. auto-format po edycji
Notificationgdy Claude czeka na Twoją odpowiedź albo zgodę
SessionStartna starcie sesji albo po /compact (matcher compact)
Stopgdy Claude kończy odpowiedź

Jak hook odpowiada: kod wyjścia

Kod wyjściaCo się dzieje
0brak sprzeciwu — normalny przepływ toczy się dalej (dla PreToolUse to nie jest automatyczna zgoda, tylko brak blokady)
2akcja zablokowana — tekst z stderr wraca do Claude jako informacja zwrotna
innytraktowane jak błąd hooka — akcja i tak przechodzi dalej

Zadanie praktyczne — dostań powiadomienie, gdy czekam na Ciebie

Dodaj do ~/.claude/settings.json hook typu Notification, który pokaże okienko Windows, gdy skończę odpowiadać i czekam na Twój ruch:

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code czeka na Ciebie', 'Claude Code')\""
          }
        ]
      }
    ]
  }
}
  1. Zapisz plik (jeśli już masz tam hooks, dopisz Notification jako kolejny klucz, nie nadpisuj reszty).
  2. Wpisz /hooks w Claude Code i sprawdź, czy Notification pojawia się na liście.
  3. Poproś mnie o coś, co wymaga Twojej zgody, i przełącz się na inne okno — powinno wyskoczyć powiadomienie.

Sprawdź się

1. Co fundamentalnie odróżnia hook od CLAUDE.md, skilla czy subagenta?

CLAUDE.md, skille i subagenty to tekst, który model interpretuje i o którym decyduje. Hook to komenda shellowa, która uruchamia się deterministycznie, niezależnie od decyzji modelu.

2. Twój hook PreToolUse ma zablokować komendę i przekazać Claude powód. Jaki kod wyjścia zwrócisz?

Kod 2 blokuje akcję, a treść wypisana na stderr wraca do Claude jako informacja zwrotna, więc model może dostosować podejście. Kod 0 oznacza brak sprzeciwu, inne kody to błąd hooka.

3. Chcesz automatycznie odpalać Prettier po każdej edycji pliku przez Claude. Jaki event i matcher wybierzesz?

PostToolUse fires po udanym wywołaniu narzędzia, a matcher Edit|Write ogranicza go wyłącznie do edycji i zapisu plików — dokładnie moment, w którym warto przepuścić plik przez formatter.

4. Gdzie umieścisz hook, żeby cały zespół dostał go automatycznie przez git, tak jak skill w Lekcji 3?

Podobnie jak przy skillach i subagentach, wersja projektowa (.claude/settings.json) trafia do gita i dociera do całego zespołu. Wersje user i local zostają tylko na Twoim komputerze.

5. Twój hook PreToolUse zwraca kod wyjścia 0. Co to oznacza dla wywołania narzędzia?

Kod 0 to brak sprzeciwu ze strony hooka, ale to nie to samo, co zgoda — dla PreToolUse nadal obowiązuje zwykły mechanizm uprawnień, chyba że hook jawnie zwróci strukturalne "allow".
Coś niejasne? Zapytaj mnie wprost — mogę pomóc dobrać matcher albo napisać skrypt hooka pod konkretną regułę tego repo.
← Lekcja 4: Subagenci Następna lekcja: Ustawienia i uprawnienia — hierarchia settings.json →