Claude Code hook'ları Windows'ta çalışmıyor: sebepleri ve çözümleri

Mac'te sorunsuz çalışan aynı hook Windows'ta hiçbir şey yapmıyor ya da daha kötüsü, her komutu engelliyor. Neredeyse her zaman sebep shell'dir. Claude Code'un Windows'ta hook'ları nasıl çalıştırdığını ve kendi hook'larını nasıl güvenilir hâle getireceğini burada bulabilirsin.

Aslan, Pet Island ekibi · Güncellendi: 26 Eki 2026 · 5 dk okuma

KISA CEVAP

Windows'ta Claude Code bir hook'un command değerini Git Bash ile, Git Bash kurulu değilse PowerShell ile çalıştırır. Hangisini kastettiğini "shell": "powershell" veya "shell": "bash" ile belirt, stdout'ta tek bir JSON nesnesi bırak (profil echo'ları olmasın), engellemek için çıkış kodu 2 kullan ve Claude Code'u güncelle (2.1.310'a kadarki sürümlerde Windows'a özgü birkaç hook hatası düzeltildi). Hata ayıklamak için /hooks ve claude --debug kullan.

Hook'unu hangi shell çalıştırır

Claude Code command metnini bir shell'e verir: macOS ve Linux'ta sh -c, Windows'ta Git Bash, Git Bash kurulu değilse PowerShell. Hooks referansındaki bu tek cümle, “benim Mac'imde çalışıyor” şikayetlerinin çoğunu açıklar. PowerShell için yazılmış bir komut Git Bash'te başarısız olur, bir bash script'i PowerShell'de başarısız olur ve hangisine denk geleceğin, Git for Windows'un kurulu olup olmamasına bağlıdır.

Tahmini shell alanıyla ortadan kaldır. "bash" veya "powershell" değerlerini kabul eder:

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

Git Bash istiyorsan ve Claude Code onu bulamıyorsa Git for Windows'u kur veya CLAUDE_CODE_GIT_BASH_PATH değişkenini onun konumuna ayarla, sonra yeni bir oturum başlat.

Belirtiler ve sebepleri

BelirtiOlası sebepÇözüm
Hook hiç çalışmıyor gibi görünüyorEski Claude Code sürümü, yanlış event veya matcher, ayarlarda geçersiz JSONGüncelle; /hooks ile kontrol et; yorumları ve sondaki virgülleri kaldır
ParserError veya “unexpected token”PowerShell söz dizimi Git Bash'e ulaşıyor ya da tam tersishell alanını açıkça ayarla
Hook çıktısı “does not start with {”JSON'dan önce bir şey yazdırılmış, çoğu zaman bir shell profiliProfil çıktısını sustur; logları stderr'e gönder
\ ve / karışık bir yol bulunamıyorWindows yol değişkeni Unix tarzı bir son ekle birleştirilmişExec biçimini kullan: program command içinde, her argüman args içinde
Git Bash'ten powershell: Permission denied2.1.283 ve 2.1.304–2.1.305 sürümlerinde aralıklı olarak bildirildi (#103910, açık)Araya Git Bash girmesin diye "shell": "powershell" kullan
Bir koruma hook'u her şeyi geçiriyor2 yerine çıkış kodu 1 ya da eski sürümlerde fail-open hatasıEngellemek için 2 ile çık; 2.1.310 veya sonrasına güncelle
Hook çıktı vermeden anında dönüyorShell'in beklemediği GUI alt sistemi programıBir konsol programı kullan veya sürecin bitmesini bekle

Stdout'ta sadece JSON

Claude Code, hook'unun standart çıktısını onun cevabı olarak okur. Dokümanlardaki kural kısa: stdout'a JSON nesnesi dışında hiçbir şey yazdırma. Windows'ta bu sinsi bir şekilde bozulur: Git Bash ve bazı kurulumlar shell profilini yine de yükler ve o profildeki koşulsuz bir echo JSON'unun başına eklenir. Hook bu durumda terminalde “çalışır” ama Claude Code içinde başarısız olur.

Bunun yerine bir dosyaya veya stderr'e logla ve profilinin çıktısını etkileşimli shell koşuluna bağla.

Çıkış kodları: 2 engeller, 1 engellemez

0 ile çıkmak başarı demektir. 2 ile çıkmak engelleyen bir hatadır: engellenebilen event'lerde Claude Code işlemi durdurur ve stderr çıktını gösterir. Geçerli JSON olmadan 1 ile çıkmak engellemeyen bir hatadır ve işlem devam eder. Hook'un bir politika uyguluyorsa 2 ile çık.

Her event bu şekilde engellenemez. Bir Notification hook'unun çıkış kodu yok sayılır. 2 ile çıkan bir Stop hook'u Claude'un çalışmaya devam etmesini sağlar. Bir PermissionRequest hook'u çıkış kodu 2'yi tamamen yok sayar; kararını JSON'undaki bir decision nesnesiyle verir.

Claude Code 2.1.309, hook'un programı 2 koduyla çıktığında PowerShell hook'larının engellememesi sorununu düzeltti. PowerShell koruman yok sayılıyor gibi görünüyorsa önce sürümünü kontrol et.

Güncellemeye değer Windows düzeltmeleri

Anthropic'in değişiklik günlüğünde uzun bir Windows hook düzeltmeleri listesi var. Eski forum konularını açıklayanlar şunlar:

SürümDüzeltme
2.1.47PreToolUse ve PostToolUse hook'ları Windows'ta sessizce başarısız oluyordu; artık cmd.exe yerine Git Bash ile çalışıyorlar
2.1.161Bash'i açıkça çağıran hook'lar (/usr/bin/bash script.sh) “command not found” hatasıyla başarısız oluyordu
2.1.299Shell ayarlanmamış PreToolUse ve PermissionRequest hook'ları Git for Windows olmadan fail-open davranıyordu; başarısız olan bir koruma artık engelliyor
2.1.309PowerShell hook'ları çıkış kodu 2'de engellemiyordu; "shell": "powershell" korumaları Git for Windows olmadan fail-open davranıyordu
2.1.310Komutu sadece tırnak içindeki metinlerden oluşan korumalar (tırnak içinde bir yol gibi) Git Bash olmadan fail-open davranıyordu

“No hook is working on Windows” başlıklı eski issue (#10450) 2.0.27 sürümünde bildirilmişti; bir yorumcu sorunu stdin'in hook komutlarına ulaşmamasına bağladı. O kadar eski bir sürümdeysen başka bir şeyle uğraşmadan önce güncelle.

Bir programı doğrudan çağırmak

Hook'un derlenmiş bir programsa exec biçimiyle shell'i atlayabilirsin (args alanı; args ayarlıysa shell yok sayılır). Windows'ta exec biçimi, command değerinin .exe gibi gerçek bir çalıştırılabilir dosyaya çözülmesini gerektirir; .cmd ve .bat shim'leri (npm'in kurduğu çoğu şey dahil) shell olmadan başlatılamaz. .exe dosyasını hedefle veya shell biçimini kullan.

Kendi hook yardımcımızı geliştirirken öğrendiğimiz bir ders: Windows'ta GUI alt sistemi için derlenmiş bir program, bir shell tarafından başlatıldığında beklenmez. Shell hemen döner, ajan boş çıktı okur ve hook ölü gibi görünür. Hook programları konsol programı olmak zorundadır.

Plugin hook'ları ve yollar

${CLAUDE_PLUGIN_ROOT}/hooks/run.sh gibi yollar oluşturan plugin hook'ları Windows'ta v2.1.2 ile v2.1.12 arasında bozuldu (#18610): değişken ters eğik çizgili bir yola genişler ve sonuna eğik çizgili bir ek koymak, bash'in çözemediği karışık bir yol üretir. Güncel dokümanlar temiz çözümü veriyor: bir hook bir yol yer tutucusuna başvurduğunda her zaman exec biçimini kullan. Programı command içine, her argümanı args içine koy, örneğin "command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/scripts/format.js"]. Her öğe tek bir argüman olarak iletilir ve onu bozacak bir shell yoktur.

Hata ayıklama kontrol listesi

  1. /hooks yapılandırılmış her hook'un ve nereden geldiğinin salt okunur bir listesini açar.
  2. claude --debug (veya oturum ortasında /debug) her hook çalışmasını, çıktısını ve çıkış kodunu gösterir. claude --debug-file <path> bunu bir dosyaya yazar.
  3. JSON'u doğrula. Ayar dosyaları katı JSON'dur; sondaki tek bir virgül tüm dosyayı devre dışı bırakır.
  4. Matcher'ı kontrol et. Matcher'lar büyük/küçük harfe duyarlıdır; "*", "" veya matcher olmaması her şeyle eşleşir.
  5. Komutu kendin çalıştır: Claude Code'un kullanacağı shell'de, örnek bir JSON'u pipe ile vererek.
  6. Zaman aşımına bak. Komut hook'larının varsayılan süresi 600 saniyedir; bir insanı bekleyen hook'un bu paya ihtiyacı vardır.

İncelerken tüm hook'ları kapatmak için "disableAllHooks": true ayarla.

Sadece bildirim ve onay istediysen

Windows'taki birçok hook kurulumu tek bir sebeple var: Claude Code'un sana ne zaman ihtiyaç duyduğunu bilmek ve ona cevap vermek. Pet Island bunu hiç script yazmadan yapar. Claude Code'a tek tıkla bağlanır, Windows ayrıntılarını senin yerine halleder ve her izin isteğini, soruyu ve planı komut veya diff ile birlikte ekranın üstündeki küçük bir adaya koyar; orada izin verir veya reddedersin. Claude Code WSL içinde çalışırken de çalışır.

SSS

Windows'ta Claude Code hook'larını hangi shell çalıştırır?

Git Bash, Git Bash kurulu değilse PowerShell. Açıkça seçmek için hook'ta "shell": "powershell" veya "shell": "bash" ayarla.

Claude Code hook'um neden terminalde çalışıyor da Claude Code'da çalışmıyor?

Genellikle fazladan çıktı yüzünden: metin yazdıran bir shell profili, hook'un JSON'unun başına eklenir. Stdout'a sadece JSON nesnesini yazdır.

Bir hook'un bir araç çağrısını engellemesini nasıl sağlarım?

2 koduyla çık (veya JSON içinde bir deny kararı döndür). Çıkış kodu 1 engellemeyen bir hatadır ve işlem devam eder. PermissionRequest hook'ları çıkış kodu 2'yi yok sayar ve bunun yerine bir decision nesnesi kullanır.

Bir hook komutu .cmd veya .bat dosyası olabilir mi?

Exec biçiminde olamaz. Windows'ta .exe gibi gerçek bir çalıştırılabilir dosyaya çözülmesi gerekir. .cmd veya .bat dosyalarını çalıştırmak için shell biçimini kullan.

Bir hook'un neden başarısız olduğunu nasıl görürüm?

claude --debug çalıştır veya /debug yaz ve hangi hook'ların yüklendiğini görmek için /hooks kullan.

Kaynaklar

Bu sayfadaki her ayar ve davranış 26 Ekim 2026 tarihinde bu sayfalarla karşılaştırılarak kontrol edildi. Ajanlar hızlı değişir; bir şey artık uyuşmuyorsa geçerli olan resmi sayfadır.

OKUMAYA DEVAM ET

Tüm ajanlarına ekranının üstünden cevap ver.

Windows ve Mac · 7 gün ücretsiz, sonra tek seferlik $8.99 · Her satıştan $1 sokak hayvanlarını besler

Pet Island'ı ücretsiz dene