Hooki Claude Code nie działają w systemie Windows: przyczyny i rozwiązania

Ten sam hook, który na Macu działa bez zarzutu, w systemie Windows nie robi nic, albo co gorsza blokuje każde polecenie. Prawie zawsze winna jest powłoka. Oto jak Claude Code uruchamia hooki w systemie Windows i jak sprawić, żeby twoje działały niezawodnie.

Autor: Aslan, zespół Pet Island · Zaktualizowano 26 paź 2026 · 5 min czytania

KRÓTKA ODPOWIEDŹ

W systemie Windows Claude Code uruchamia command hooka za pomocą Git Bash, a gdy Git Bash nie jest zainstalowany, za pomocą PowerShell. Określ, o którą chodzi, przez "shell": "powershell" lub "shell": "bash", ogranicz stdout do jednego obiektu JSON (żadnych echo z profilu), używaj kodu wyjścia 2 do blokowania i zaktualizuj Claude Code (w wersjach do 2.1.310 naprawiono kilka błędów hooków w Windows). Debuguj za pomocą /hooks i claude --debug.

Która powłoka uruchamia twój hook

Claude Code przekazuje ciąg command do powłoki: sh -c w systemach macOS i Linux, Git Bash w systemie Windows lub PowerShell, gdy Git Bash nie jest zainstalowany. To jedno zdanie z dokumentacji hooków wyjaśnia większość zgłoszeń typu „na moim Macu działa”. Polecenie napisane dla PowerShell zawodzi w Git Bash, skrypt bash zawodzi w PowerShell, a to, którą powłokę dostaniesz, zależy od tego, czy akurat masz zainstalowany Git for Windows.

Wyeliminuj zgadywanie za pomocą pola shell. Przyjmuje ono "bash" lub "powershell":

%USERPROFILE%\.claude\settings.jsonKopiuj
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"shell": "powershell",
"command": "[Console]::Beep(880, 200)"
}
]
}
]
}
}

Jeśli chcesz używać Git Bash, a Claude Code nie może go znaleźć, zainstaluj Git for Windows lub ustaw CLAUDE_CODE_GIT_BASH_PATH na jego lokalizację, a potem rozpocznij nową sesję.

Objawy i ich przyczyny

Co widziszPrawdopodobna przyczynaRozwiązanie
Wygląda na to, że hook nigdy się nie uruchamiaStara wersja Claude Code, złe zdarzenie lub matcher, nieprawidłowy JSON w ustawieniachZaktualizuj; sprawdź /hooks; usuń komentarze i przecinki na końcu
ParserError lub „unexpected token”Składnia PowerShell trafia do Git Bash albo odwrotnieUstaw shell jawnie
Dane wyjściowe hooka „does not start with {”Coś zostało wypisane przed JSON, często przez profil powłokiWycisz dane wypisywane przez profil; logi kieruj do stderr
Nie można znaleźć ścieżki z mieszanymi \ i /Windowsowa zmienna ścieżki połączona z sufiksem w stylu UnixUżyj formy exec: program w command, każdy argument w args
powershell: Permission denied z Git BashZgłaszane sporadycznie w 2.1.283 i 2.1.304–2.1.305 (#103910, otwarte)Użyj "shell": "powershell", żeby Git Bash nie pośredniczył
Hook strażnik przepuszcza wszystkoKod wyjścia 1 zamiast 2 albo błąd fail-open w starszych wersjachKończ z kodem 2, żeby blokować; zaktualizuj do 2.1.310 lub nowszej
Hook kończy się natychmiast bez danych wyjściowychProgram z podsystemu GUI, na który powłoka nie czekaUżyj programu konsolowego albo poczekaj na proces

Tylko JSON na stdout

Claude Code odczytuje standardowe wyjście hooka jako jego odpowiedź. Zasada w dokumentacji jest krótka: nie wypisuj na stdout niczego poza obiektem JSON. W systemie Windows łatwo ją złamać w podstępny sposób: Git Bash i niektóre konfiguracje nadal wczytują profil powłoki, a bezwarunkowe echo w tym profilu zostaje doklejone przed twoim JSON. Hook „działa” wtedy w terminalu, ale zawodzi w Claude Code.

Zamiast tego loguj do pliku lub do stderr, a dane wypisywane przez profil uzależnij od tego, czy powłoka jest interaktywna.

Kody wyjścia: 2 blokuje, 1 nie

Kod wyjścia 0 oznacza sukces. Kod wyjścia 2 to błąd blokujący: przy zdarzeniach, które mogą blokować, Claude Code zatrzymuje akcję i pokazuje twoje stderr. Kod wyjścia 1 bez prawidłowego JSON to błąd nieblokujący i akcja zostaje wykonana. Jeśli twój hook egzekwuje zasady, używaj kodu wyjścia 2.

Nie każde zdarzenie można zablokować w ten sposób. Kod wyjścia hooka Notification jest ignorowany. Hook Stop, który kończy się kodem 2, sprawia, że Claude pracuje dalej. Hook PermissionRequest całkowicie ignoruje kod 2. Decyduje za pomocą obiektu decision w swoim JSON.

Claude Code 2.1.309 naprawił błąd, przez który hooki PowerShell nie blokowały, gdy program hooka kończył się kodem 2. Jeśli twój strażnik w PowerShell wydaje się ignorowany, najpierw sprawdź wersję.

Poprawki dla Windows, dla których warto zrobić aktualizację

Lista zmian Anthropic zawiera długą serię poprawek hooków w Windows. Te wyjaśniają stare wątki na forach:

WersjaPoprawka
2.1.47Hooki PreToolUse i PostToolUse po cichu zawodziły w systemie Windows; teraz działają z Git Bash zamiast cmd.exe
2.1.161Hooki, które jawnie wywołują bash (/usr/bin/bash script.sh), kończyły się błędem „command not found”
2.1.299Hooki PreToolUse i PermissionRequest bez ustawionej powłoki działały w trybie fail-open bez Git for Windows; nieudany strażnik teraz blokuje
2.1.309Hooki PowerShell nie blokowały przy kodzie wyjścia 2; strażnicy z "shell": "powershell" działali w trybie fail-open bez Git for Windows
2.1.310Strażnicy, których polecenie składało się wyłącznie z ciągów w cudzysłowie (na przykład ścieżki w cudzysłowie), działali w trybie fail-open bez Git Bash

Starsze zgłoszenie zatytułowane „No hook is working on Windows” (#10450) dotyczyło wersji 2.0.27; jeden z komentujących ustalił, że stdin nie docierał do poleceń hooków. Jeśli używasz tak starej wersji, zaktualizuj ją, zanim zaczniesz debugować cokolwiek innego.

Bezpośrednie wywoływanie programu

Jeśli twój hook jest skompilowanym programem, możesz pominąć powłokę, używając formy exec (pole args; shell jest ignorowane, gdy ustawiono args). W systemie Windows forma exec wymaga, żeby command wskazywało prawdziwy plik wykonywalny, taki jak .exe; nakładek .cmd i .bat (w tym większości tego, co instaluje npm) nie da się uruchomić bez powłoki. Wskaż plik .exe albo użyj formy shell.

Jedna lekcja z budowy naszego własnego pomocnika do hooków: w systemie Windows powłoka nie czeka na program zbudowany dla podsystemu GUI, który uruchamia. Powłoka natychmiast wraca, agent odczytuje puste dane wyjściowe, a hook wygląda na martwy. Programy hooków muszą być programami konsolowymi.

Hooki pluginów i ścieżki

Hooki pluginów, które budują ścieżki takie jak ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh, nie działały w systemie Windows między v2.1.2 a v2.1.12 (#18610): zmienna rozwija się do ścieżki z ukośnikami odwrotnymi, a dodanie sufiksu ze zwykłym ukośnikiem daje mieszaną ścieżkę, której bash nie potrafi rozwiązać. Obecna dokumentacja podaje czyste rozwiązanie: używaj formy exec zawsze, gdy hook odwołuje się do symbolu zastępczego ścieżki. Umieść program w command, a każdy argument w args, na przykład "command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/scripts/format.js"]. Każdy element jest przekazywany jako jeden argument, bez powłoki, która mogłaby go zniekształcić.

Lista kontrolna debugowania

  1. /hooks otwiera listę tylko do odczytu wszystkich skonfigurowanych hooków i ich źródeł.
  2. claude --debug (lub /debug w trakcie sesji) pokazuje każde uruchomienie hooka, jego dane wyjściowe i kod wyjścia. claude --debug-file <path> zapisuje to do pliku.
  3. Zweryfikuj JSON. Pliki ustawień to ścisły JSON; jeden przecinek na końcu wyłącza cały plik.
  4. Sprawdź matcher. W matcherach wielkość liter ma znaczenie; "*", "" lub brak matchera dopasowuje wszystko.
  5. Uruchom polecenie samodzielnie w tej samej powłoce, której użyje Claude Code, przekazując przez potok przykładowy JSON.
  6. Sprawdź limit czasu. Hooki poleceń mają domyślnie 600 sekund; hook, który czeka na człowieka, potrzebuje tego zapasu.

Żeby wyłączyć wszystkie hooki na czas szukania przyczyny, ustaw "disableAllHooks": true.

Jeśli chodziło ci tylko o powiadomienia i zatwierdzenia

Wiele konfiguracji hooków w Windows powstaje z jednego powodu: żeby wiedzieć, kiedy Claude Code cię potrzebuje, i móc mu odpowiedzieć. Pet Island robi to bez żadnych skryptów. Łączy się z Claude Code jednym kliknięciem, załatwia za ciebie szczegóły związane z Windows i umieszcza każdą prośbę o zgodę, pytanie i plan na małej wyspie u góry ekranu, razem z poleceniem lub diffem, gdzie je zatwierdzasz lub odrzucasz. Działa też wtedy, gdy Claude Code jest uruchomiony w WSL.

CZĘSTE PYTANIA

Która powłoka uruchamia hooki Claude Code w systemie Windows?

Git Bash, a gdy Git Bash nie jest zainstalowany, PowerShell. Ustaw "shell": "powershell" lub "shell": "bash" w hooku, żeby wybrać jawnie.

Dlaczego mój hook Claude Code działa w terminalu, ale nie w Claude Code?

Zwykle przez dodatkowe dane wyjściowe: profil powłoki, który wypisuje tekst przez echo, zostaje doklejony przed JSON hooka. Wypisuj na stdout tylko obiekt JSON.

Jak sprawić, żeby hook zablokował wywołanie narzędzia?

Zakończ go kodem 2 (lub zwróć decyzję deny w JSON). Kod wyjścia 1 to błąd nieblokujący i akcja zostaje wykonana. Hooki PermissionRequest ignorują kod 2 i zamiast tego używają obiektu decision.

Czy polecenie hooka może być plikiem .cmd lub .bat?

Nie w formie exec. W systemie Windows musi ono wskazywać prawdziwy plik wykonywalny, taki jak .exe. Do uruchamiania plików .cmd lub .bat użyj formy shell.

Jak sprawdzić, dlaczego hook zawiódł?

Uruchom claude --debug lub wpisz /debug, a za pomocą /hooks sprawdź, które hooki są wczytane.

Źródła

Każde ustawienie i zachowanie opisane na tej stronie zostało sprawdzone z tymi stronami 26 października 2026. Agenci szybko się zmieniają; jeśli coś przestało się zgadzać, obowiązuje strona oficjalna.

CZYTAJ DALEJ

Odpowiadaj każdemu agentowi z górnej części ekranu.

Windows i Mac · 7 dni za darmo, potem jednorazowo 8,99 USD · 1 USD z każdej sprzedaży idzie na karmę dla bezdomnych zwierząt

Wypróbuj Pet Island za darmo