Hooki w Claude Code to polecenia, które program uruchamia w stałych momentach pracy: na starcie sesji, po wysłaniu polecenia, przed użyciem narzędzia, na końcu odpowiedzi. Różnica wobec instrukcji w CLAUDE.md jest jedna, ale zasadnicza. Instrukcja działa tylko wtedy, gdy model ją zastosuje. Hook wywołuje Claude Code, gdy wystąpi ustawione zdarzenie, niezależnie od tego, czy model o nim pamięta. Sprawdziłem, co ludzie naprawdę ustawiają: przejrzałem 414 publicznych projektów na GitHubie, które mają hooki, i policzyłem zdarzenia i rodzaje poleceń. Na końcu pokazuję dwa hooki, których używam codziennie.

Z tego artykułu dowiesz się:

  • Czym jest hook i czym różni się od reguły w CLAUDE.md
  • W których momentach pracy może się uruchomić i który potrafi zatrzymać Claude'a
  • Co ustawia 414 projektów na GitHubie: najczęstsze zdarzenia i do czego ludzie ich używają
  • Mój hook nr 1: dźwięk i powiadomienie, gdy Claude skończył, gotowy do skopiowania
  • Mój hook nr 2: blokada godziny, której nie ma na zegarze, z uproszczonym skryptem
  • Jak ustawić pierwszy hook i na co uważać
0zdarzenia, w których może zadziałać hook (dokumentacja Claude Code, stan 20.10.2026)
0 z 33zdarzeń, w których hook może zatrzymać akcję kodem wyjścia 2
0%z 414 projektów na GitHubie ma hook przed użyciem narzędzia (PreToolUse), mój pomiar 20.10
0zapisów zatrzymanych w 7 dni przez mój hook pilnujący godziny (14–20.10)

Czym są hooki w Claude Code

Claude Code pracuje w pętli. Dostaje Twoje polecenie, myśli, sięga po narzędzie (uruchamia komendę w terminalu, edytuje plik, czyta stronę), patrzy na wynik i znowu myśli, aż skończy odpowiedź. Hook to bramka postawiona w jednym ze stałych miejsc tej pętli. Gdy Claude przez nią przechodzi i spełnione są ustawione warunki, program uruchamia Twoje polecenie: skrypt, adres HTTP albo zapytanie do innego modelu. W 1154 z 1166 hooków, które przejrzałem (99%), to zwykłe polecenie powłoki.

Pętla pracy Claude Code jako tor z pięcioma bramkami: start sesji (SessionStart), Twoje polecenie (UserPromptSubmit), przed narzędziem (PreToolUse), po narzędziu (PostToolUse) i koniec odpowiedzi (Stop).
Pętla pracy Claude Code jako tor z pięcioma bramkami: start sesji (SessionStart), Twoje polecenie (UserPromptSubmit), przed narzędziem (PreToolUse), po narzędziu (PostToolUse) i koniec odpowiedzi (Stop).

Dokumentacja Anthropic ujmuje to tak: hooki dają „deterministic control: certain actions always happen rather than relying on the LLM to choose to run them”, czyli pewne rzeczy dzieją się bez względu na to, czy model zdecyduje się je zrobić. W oficjalnym filmie o hookach pada przykład: możesz napisać w CLAUDE.md, żeby po każdej edycji formatować plik, i zwykle Claude to zrobi, ale czasem nie. Hook ustawiony na edycję pliku uruchomi formatowanie przy każdej edycji.

Film z YouTube. Klikając „Odtwórz”, zgadzasz się na połączenie z serwerami Google i zapisanie przez nie danych w Twojej przeglądarce (polityka prywatności). Obejrzyj na YouTube ↗

Jedno zastrzeżenie, zanim pójdziemy dalej. Hook przenosi uruchomienie reguły z decyzji modelu do programu, ale nie gwarantuje, że sama reguła jest dobra. Skrypt może mieć błąd, może sprawdzać nie to, co trzeba, a hook typu „prompt” albo „agent” nadal opiera się na ocenie modelu.

Hooki są w Claude Code od wersji 1.0.38 z 30 czerwca 2025. Słowo „hook” znaczy dziś w Claude Code dwie rzeczy: hook w pliku ustawień (o nim jest ten tekst) i funkcję w modzie. Jak działają mody i czym różnią się od hooków, pokazałem w tekście o modach w Claude Code.

Kiedy hook się uruchamia, a kiedy może zatrzymać Claude'a

Dokumentacja wymienia dziś 33 zdarzenia. Na co dzień liczy się pięć, bo wyznaczają szkielet każdej sesji:

ZdarzenieKiedy się uruchamiaCzy może zatrzymać?
SessionStartna starcie albo przy wznowieniu sesjinie, ale może dodać Claude'owi kontekst
UserPromptSubmitpo wysłaniu Twojego polecenia, zanim Claude je przeczytatak, odrzuca polecenie
PreToolUseprzed każdym użyciem narzędziatak, blokuje narzędzie
PostToolUsepo udanym użyciu narzędzianie, narzędzie już zadziałało; może przekazać Claude'owi uwagi
Stopgdy Claude kończy odpowiedźtak, każe mu pracować dalej

Opisuję tu najprostszy wariant: hook typu command, który steruje pracą samym kodem wyjścia. Kod 0 znaczy, że hook nie ma zastrzeżeń i akcja idzie dalej. Kod 2 blokuje akcję, a tekst błędu wraca do Claude'a jako wyjaśnienie. Co dokładnie znaczy „blokuje”, zależy od zdarzenia, co widać w tabeli: przed narzędziem to blokada narzędzia, na końcu odpowiedzi polecenie dalszej pracy. Inny kod to błąd hooka, po którym akcja zwykle idzie dalej. Dokumentacja opisuje też warianty bardziej rozbudowane: hook może zakończyć się kodem 0 i zwrócić decyzję w JSON, która blokuje akcję, a hook z ustawieniem "onFailure": "block" zatrzymuje akcję także wtedy, gdy sam zawiedzie. Zatrzymać akcję kodem 2 potrafi 16 z 33 zdarzeń.

Stop uruchamia się po każdej odpowiedzi Claude'a, nie tylko na koniec dużego zadania. Nie uruchamia się, gdy sam przerwiesz pracę.

Co ustawia 414 projektów na GitHubie

Zamiast zgadywać, które hooki są popularne, policzyłem je 20 października 2026. Wyszukiwarka kodu GitHuba zwróciła 500 publicznych plików .claude/settings.json ze słowem „hooks”. Odrzuciłem pliki o innej ścieżce (na przykład kopie zapasowe) i kolejne pliki z tego samego repozytorium. Zostało 430 plików z 430 projektów, w 414 z nich był co najmniej jeden hook. Każdy plik przeczytałem programem i policzyłem zdarzenia, dopasowania i rodzaje poleceń. Projekt liczy się raz przy każdym zdarzeniu, nawet jeśli ma na nie kilka hooków.

#ZdarzenieProjekty z tym hookiem (z 414)
1PreToolUse, przed narzędziem216 (52%)
2PostToolUse, po narzędziu191 (46%)
3SessionStart, start sesji124 (30%)
4Stop, koniec odpowiedzi104 (25%)
5UserPromptSubmit, po Twoim poleceniu57 (14%)

Dalej jest przepaść: koniec pracy subagenta ma 5% projektów, powiadomienie 4%, reszta po kilka procent albo mniej. Wyszukiwarka GitHuba, licząc wszystkie pliki, pokazuje tę samą kolejność pierwszej czwórki.

Dwa miejsca, w które ludzie wpinają się najczęściej, to moment przed komendą w terminalu (148 projektów, 36%, ma hook PreToolUse z dopasowaniem do narzędzia Bash) i moment po edycji pliku (156 projektów, 38%, ma hook PostToolUse przy narzędziach Edit, Write albo MultiEdit). Do czego? Podzieliłem polecenia po słowach kluczowych w ich treści. Jeden projekt mógł trafić do kilku grup, więc odsetki nie sumują się do 100%:

  • blokada i ochrona (zakazane komendy, chronione pliki, sekrety): ok. 39% projektów,
  • kontekst na start (stan repozytorium, notatki, przypomnienia): ok. 29%,
  • sprawdzenie pracy (przegląd, weryfikacja przed końcem): ok. 29%,
  • formatowanie i sprawdzanie kodu po edycji: ok. 22%.

To przybliżenie: w ok. 31% projektów co najmniej jednego hooka nie dało się przypisać po treści, bo wywołuje skrypt o nic niemówiącej nazwie. I najważniejsze zastrzeżenie: to analiza publicznych konfiguracji, które znalazła wyszukiwarka GitHuba, a nie reprezentatywna próba użytkowników Claude Code. Obecność hooka w pliku nie potwierdza też, że był uruchamiany.

Powiadomienie albo dźwięk prawie nie występuje w plikach projektów (5%). Takie hooki trzyma się raczej w ustawieniach osobistych, a nie w repozytorium zespołu. W 99 publicznych plikach osobistych z hookami (settings.local.json), które znalazłem tą samą metodą, Stop jest na drugim miejscu (36%), a powiadomienia mają 12%. To też tylko znaleziona próba, ale kierunek jest wyraźny. Moje pięć hooków siedzi w pliku osobistym, więc w takim pomiarze w ogóle by się nie pojawiło.

Podobnie wyglądają przykłady z Reddita, które znalazłem. Wysoko w wynikach wyszukiwania są sygnały dla człowieka: lampka na biurku, która świeci na niebiesko, gdy Claude pracuje, i na różowo, gdy czeka, albo drukarka paragonów z kosztem sesji. W poradach wraca myśl, którą jeden z autorów ujął tak: „A rule that holds 95 percent of the time is not a rule. It is a default.” Reguła, która działa w 95% przypadków, nie jest regułą, tylko ustawieniem domyślnym (wątek na r/ClaudeAI).

Mój hook nr 1: dźwięk, gdy Claude skończył

Najprostszy hook, jaki mam, i ten, bez którego nie wyobrażam sobie pracy. Po każdej odpowiedzi Claude'a dostaję powiadomienie na pulpicie i krótki dźwięk. Mogę zlecić zadanie, odejść od terminala i wrócić, gdy usłyszę, że skończył.

Oficjalny poradnik Anthropic pokazuje bliski przykład na zdarzeniu Notification, czyli wtedy, gdy Claude czeka na Ciebie, na przykład o zgodę. Ja ustawiłem go na Stop, czyli wtedy, gdy Claude skończył odpowiedź. Oba mają sens i można mieć oba naraz.

Wersja z mojego pliku (Linux):

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'Claude Code' 'Skończył pisać' 2>/dev/null; paplay /usr/share/sounds/freedesktop/stereo/complete.oga 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}

Na Linuksie potrzebujesz pulpitu z powiadomieniami oraz poleceń notify-send i paplay (zwykle są w systemie, jeśli działa dźwięk i powiadomienia). Na macOS zamień wewnętrzny obiekt z poleceniem na ten (cudzysłowy wewnątrz polecenia muszą mieć ukośnik, inaczej JSON się zepsuje; samo afplay dałoby dźwięk bez powiadomienia):

{
  "type": "command",
  "command": "osascript -e 'display notification \"Skończył pisać\" with title \"Claude Code\"'; afplay /System/Library/Sounds/Glass.aiff || true"
}

Końcówka || true sprawia, że hook nie zgłosi błędu, nawet gdy dźwięk się nie odtworzy.

Mój hook nr 2: godzina z zegara

Model nie ma pewnej informacji o aktualnej godzinie, dopóki nie odczyta jej narzędziem, a w długiej sesji jego poczucie czasu rośnie z liczbą kroków, nie z minutami. Prowadzę w plikach dzienniki pracy i listy zadań z godzinami, więc to dla mnie realny problem: godzina w zapisie jest potem adresem dla ludzi i dla narzędzi. Reguła „godzinę bierz z polecenia date” stoi w moim CLAUDE.md. Hook pilnuje jej w jednym, konkretnym miejscu.

Działa na zdarzeniu PreToolUse, przed edycją i zapisem pliku, i sprawdza tylko pliki z dziennikiem i zadaniami. Jeśli w zapisie stoi dzisiejsza data i godzina późniejsza niż zegar o więcej niż 2 minuty, kończy się kodem 2. Godzinę zaplanowaną na później przepuszcza, jeśli w wierszu stoi znacznik godzina-planowana. Gdy sam skrypt zawiedzie, przepuszcza zapis, bo hook nie może zablokować pracy własną awarią.

Granice warto nazwać wprost. Hook nie sprawdza, czy godzina pochodzi z polecenia date. Nie złapie godziny za wczesnej ani złej daty, tylko dzisiejszą godzinę z przyszłości w wybranych plikach.

Przykład: Claude chce dopisać do dziennika wiersz 2026-10-20 23:40 wdrożenie zakończone, a zegar pokazuje 20:49. Zapis nie powstaje, a Claude dostaje komunikat:

PreToolUse:Write hook error: [python3 ~/.claude/hooks/godzina.py]: Godzina 23:40 wyprzedza zegar (20:49). Odczytaj godzinę poleceniem date i przepisz ją z wyniku.

Uruchamia date, dostaje 20:49 i zapisuje wiersz z właściwą godziną. Uproszczony szkic takiego skryptu (mój ma jeszcze obsługę wielu plików i testy):

#!/usr/bin/env python3
# Uproszczony szkic: blokuje zapis dzisiejszej godziny późniejszej niż zegar + 2 min.
import json, re, sys, datetime as dt

dane = json.load(sys.stdin)
wejscie = dane.get("tool_input", {})
sciezka = wejscie.get("file_path", "")
tekst = wejscie.get("content") or wejscie.get("new_string") or ""

if not sciezka.endswith("dziennik.md"):   # pilnuj tylko wybranych plików
    sys.exit(0)

teraz = dt.datetime.now()
granica = teraz + dt.timedelta(minutes=2)
for linia in tekst.splitlines():
    if teraz.strftime("%Y-%m-%d") not in linia or "godzina-planowana" in linia:
        continue
    for g, m in re.findall(r"\b([01]\d|2[0-3]):([0-5]\d)\b", linia):
        if teraz.replace(hour=int(g), minute=int(m)) > granica:
            print(f"Godzina {g}:{m} wyprzedza zegar ({teraz:%H:%M}). "
                  "Odczytaj godzinę poleceniem date i przepisz ją z wyniku.", file=sys.stderr)
            sys.exit(2)
sys.exit(0)

W ustawieniach podpinasz go pod PreToolUse z dopasowaniem Edit|Write. Od 14 do 20 października mój hook zatrzymał 25 zapisów w 7 projektach. Policzyłem to z zapisów sesji na moim komputerze. Ta liczba mówi, ile razy zadziałał, a nie ile razy miał rację: zdarzają mu się fałszywe alarmy, na przykład gdy liczba w tekście tylko wygląda jak godzina. Wtedy zapisuję ją inaczej i idę dalej.

Bonus. Trzeci hook, który polecam, działa na SessionStart: na starcie każdej sesji wkleja Claude'owi do kontekstu dziesięć ostatnich lekcji z poprawek w danym repozytorium. Zajmuje to 0,31 sekundy i ok. 3,4 KB tekstu.

Pierwszy hook w kilka minut

  1. Otwórz plik ustawień

    Hook dla wszystkich projektów wpisujesz do ~/.claude/settings.json. Hook dla jednego projektu, którym dzielisz się z zespołem, do .claude/settings.json w repozytorium, a osobisty dla jednego projektu do .claude/settings.local.json. Jeśli pliku nie ma, utwórz go.

  2. Wklej blok hooks

    Jeśli w pliku nie ma klucza hooks, wklej blok z dźwiękiem obok pozostałych ustawień. Jeśli hooks już jest, nie dodawaj drugiego: dopisz Stop do istniejącego obiektu, a jeśli Stop też już jest, dodaj nową pozycję do jego listy.

  3. Sprawdź polecenie w terminalu

    Zanim zaufasz hookowi, uruchom jego polecenie ręcznie. Jeśli nie zadziała w terminalu, nie zadziała też jako hook.

  4. Zajrzyj do /hooks

    W Claude Code wpisz /hooks. Zobaczysz listę ustawionych hooków. To tylko podgląd, zmiany robisz w pliku.

Dopasowanie (matcher) zawęża hook do wybranych narzędzi. Edit|Write znaczy „tylko przy edycji i zapisie pliku”, Bash „tylko przy komendach w terminalu”. Puste albo pominięte dopasowanie znaczy „przy każdym wystąpieniu danego zdarzenia”, a przy zdarzeniach narzędzi: przy każdym użyciu narzędzia.

Na co uważać

  • Hook działa z Twoimi uprawnieniami. Dokumentacja mówi wprost, że polecenia hooków „execute shell commands with your full user permissions”, czyli mogą zmienić albo usunąć każdy plik, do którego masz dostęp. Hook z cudzego repozytorium przeczytaj, zanim go uruchomisz.
  • Każdy hook kosztuje czas. Hook na UserPromptSubmit działa przy każdym poleceniu, a formatowanie po każdym zapisie może zmusić Claude'a do ponownego czytania pliku. Stawiaj hooki tam, gdzie naprawdę chronią albo oszczędzają pracę.
  • Twarde zakazy ustawiaj w uprawnieniach. Pole if, które zawęża hook do wybranych poleceń, dokumentacja nazywa „best-effort” i do twardego zezwalania albo zakazywania odsyła do systemu uprawnień.
  • Claude potrafi próbować obejść hook. Na Reddicie są opisy, w których po blokadzie Claude szukał innej drogi do tego samego pliku. Hook, który chroni pliki, powinien chronić też swój plik ustawień.
  • Wyłączasz wszystkie naraz. "disableAllHooks": true w ustawieniach wyłącza hooki bez usuwania ich z pliku. Pojedynczego hooka nie da się tak wyłączyć, trzeba go usunąć. Jeśli firma ustawiła hooki centralnie (ustawienia zarządzane przez administratora), Twoje disableAllHooks ich nie wyłączy.

Podsumowanie

Hooki w Claude Code przenoszą wykonanie reguły z decyzji modelu do mechanizmu programu. Instrukcja w CLAUDE.md jest prośbą do modelu, hook jest poleceniem, które program uruchamia w stałym miejscu pętli. W publicznych projektach na GitHubie, które przejrzałem, hooki służą głównie do zatrzymania czegoś przed komendą w terminalu i do uporządkowania pliku po edycji. Hooki dla siebie, jak dźwięk po skończonej pracy, ludzie trzymają raczej w ustawieniach osobistych.

Jeśli masz ustawić jeden, zacznij od dźwięku. Drugi ustaw wtedy, gdy przyłapiesz Claude'a na pominięciu tej samej reguły po raz drugi. Ile wysiłku Claude wkłada w odpowiedź i jak to ustawić, opisałem w tekście o effort w Claude.

Nowe funkcje Claude Code zbieram też w newsletterze: co dwa tygodnie, zawsze z cytatem i źródłem. Zapis jest na dole strony.

Czym hook różni się od instrukcji w CLAUDE.md?

Instrukcję w CLAUDE.md czyta model i zwykle się do niej stosuje, ale nie zawsze. Hook wywołuje program Claude Code, gdy wystąpi ustawione zdarzenie i spełnione są warunki, niezależnie od tego, co model postanowi. Sama kontrola w hooku jest tak dobra, jak skrypt, który ją robi.

Czy hook może zatrzymać Claude'a?

Tak, w 16 z 33 zdarzeń. W najprostszym wariancie polecenie hooka kończy się kodem wyjścia 2, akcja zostaje zablokowana, a tekst błędu wraca do Claude'a jako wyjaśnienie. Najczęściej używa się do tego zdarzenia PreToolUse, przed użyciem narzędzia.

Gdzie wpisać hook?

Do pliku ustawień: ~/.claude/settings.json dla wszystkich projektów, .claude/settings.json w repozytorium dla projektu i zespołu albo .claude/settings.local.json dla siebie w jednym projekcie. Polecenie /hooks w Claude Code tylko pokazuje ustawione hooki.

Czy hook Stop uruchamia się tylko na koniec całego zadania?

Nie. Stop uruchamia się po każdej odpowiedzi Claude'a. Nie uruchamia się, gdy sam przerwiesz pracę.

Jak wyłączyć hooki?

Wpisz "disableAllHooks": true w pliku ustawień. Wyłącza to hooki z Twoich ustawień naraz, ale nie te, które ustawił administrator w ustawieniach zarządzanych. Pojedynczy hook trzeba usunąć z pliku.

Czy hooki są bezpieczne?

Są tak bezpieczne jak polecenia, które w nie wpiszesz. Działają z Twoimi uprawnieniami, więc hook z cudzego repozytorium przeczytaj przed uruchomieniem.