Claude Code hooks, Claude Code’un oturumun belli anlarında kendiliğinden çalıştırdığı komutlardır: bir araç çağrısından önce, dosya düzenlendikten sonra, prompt gönderildiğinde, Claude durduğunda ya da senden yanıt beklediğinde. Hepsini settings.json içindeki hooks anahtarına yazarsın. Bir hook bağlam ekleyebilir, dosyayı biçimleyebilir ya da 2 koduyla çıkarak veya JSON kararı dönerek bir işlemi engelleyebilir. CLAUDE.md’deki talimatlardan farkı şu: hook’u model değil, Claude Code’un kendisi çalıştırır, yani her seferinde çalışır.
Bu rehberde işe yarayan olayları, ayar biçimini, matcher’ları, çıkış kodlarını ve JSON çıktısını, hemen kopyalayabileceğin üç hook’u ve eklemeden önce bilmen gereken güvenlik notlarını bulacaksın. Bilgiler resmi hooks referansından ve hooks rehberinden geliyor. Kısa tanım için sözlükteki Claude Code hooks maddesine bakabilirsin.
Neden talimat değil de hook?
CLAUDE.md’ye “her düzenlemeden sonra Prettier çalıştır” yazabilirsin, Claude da çoğu zaman bunu yapar. Sorun “çoğu zaman” kısmında. Talimat, modelin bağlamdaki her şeyle birlikte tarttığı bir öneridir. Hook ise olay her tetiklendiğinde çalışan koddur.
Bu yüzden hook’lar üç tür kural için doğru araç:
- Her zaman olması gerekenler: biçimleme, lint, loglama.
- Asla olmaması gerekenler:
.envdosyasını düzenlemek ya da yanlış klasörderm -rfçalıştırmak. - Haberdar olmak istediklerin: sen başka penceredeyken Claude’un izin yanıtı beklemesi gibi.
Üslup tercihlerini ve proje bilgisini CLAUDE.md dosyasında tut, kesin kuralları hook’a taşı.
Gerçekten kullanacağın hook olayları
Referansta otuzdan fazla olay var ve her sürümle liste uzuyor. Çoğu kurulumda birkaçı yeter:
| Olay | Ne zaman çalışır | Engelleyebilir mi? |
|---|---|---|
PreToolUse | Araç çağrısı çalışmadan önce | Evet, çağrıyı engeller |
PostToolUse | Araç çağrısı başarıyla bittikten sonra | Hayır, araç zaten çalıştı; stderr Claude’a gider |
UserPromptSubmit | Prompt gönderdiğinde | Evet, prompt Claude’a hiç ulaşmaz |
Notification | Claude Code bildirim gönderdiğinde (izin sorusu, boşta bekleme) | Hayır |
Stop | Claude yanıtını bitirdiğinde | Evet, Claude çalışmaya devam eder |
SubagentStart / SubagentStop | Bir alt ajan başladığında veya bittiğinde | Sadece SubagentStop |
SessionStart | Açılışta, devam ederken, /clear veya sıkıştırma sonrası | Hayır, ama stdout bağlama eklenir |
PreCompact | Bağlam sıkıştırılmadan önce | Evet, sıkıştırmayı engeller |
PermissionRequest | İzin penceresi açılmak üzereyken | Sadece JSON ile, 2 koduyla değil |
SessionEnd | Oturum bittiğinde | Hayır |
İhtiyaçların çoğunu PreToolUse ve PostToolUse karşılar. “İş bitince ya da takılınca bana haber ver” için Notification ve Stop var.
settings.json’da hook ayarı
Hook’lar izinlerle aynı ayar dosyalarında durur:
| Dosya | Kapsam | Git ile paylaşılır mı? |
|---|---|---|
~/.claude/settings.json | Tüm projelerin | Hayır |
.claude/settings.json | Tek proje | Evet |
.claude/settings.local.json | Tek proje, sadece sen | Hayır (gitignore’da) |
| Yönetilen politika ayarları | Tüm kurum | Yöneticiler belirler |
Plugin’ler hook’ları hooks/hooks.json içinde getirebilir; skill’ler ve alt ajanlar da frontmatter’larında hook tanımlayabilir.
Yapı üç katmanlı: olay, bir matcher grubu ve handler listesi.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write",
"timeout": 30
}
]
}
]
}
}
Handler’ın type alanı command (kabuk komutu), http (bir adrese POST), mcp_tool (bağlı bir MCP sunucusundaki araç), prompt (bir modelin hızlı evet/hayır kontrolü) veya agent (deneysel alt ajan kontrolü) olabilir. Varsayılan zaman aşımı command, HTTP ve MCP aracı için 600 saniye, prompt hook’ları için 30, agent hook’ları için 60 saniye.
Her hook stdin’den JSON alır. Ortak alanlar session_id, transcript_path, cwd, permission_mode ve hook_event_name. Araç olaylarında tool_name, tool_input ve tool_use_id da gelir. Script’in bu JSON’u genelde jq ile okuyup karar verir. CLAUDE_PROJECT_DIR ortam değişkeni proje kökünü gösterir, depodaki script’leri çağırırken çok işe yarar.
Claude Code içinde /hooks yazarak yüklü hook’ları ve her birinin hangi dosyadan geldiğini görebilirsin. Bu ekran sadece okunur; değiştirmek için JSON’u düzenlersin.
Matcher: hook hangi çağrıları görür
matcher, hangi çağrıların hook’u tetikleyeceğini belirler. Araç olaylarında araç adıyla eşleşir:
| Matcher | Anlamı |
|---|---|
"*", "" veya hiç yok | Tüm çağrılar |
"Bash" | Sadece Bash aracı |
"Edit|Write" | Edit veya Write (liste) |
"mcp__memory__.*" | memory MCP sunucusunun tüm araçları |
"mcp__.*__write.*" | Adı write ile başlayan her MCP aracı |
Kural basit: matcher’da sadece harf, rakam, _, -, boşluk, virgül veya | varsa birebir ad ya da ad listesi sayılır. Başka herhangi bir karakter onu JavaScript düzenli ifadesine çevirir. MCP araçlarının adı mcp__<sunucu>__<araç> biçimindedir.
UserPromptSubmit ve Stop gibi bazı olaylar matcher’ı yok sayar, çünkü eşleşecek bir şey yoktur. Bazıları da araç adı yerine başka bir şeye bakar. SessionStart oturumun nasıl başladığıyla (startup, resume, clear, compact), Notification ise bildirim türüyle (permission_prompt, idle_prompt gibi) eşleşir.
Araç olayları izin kuralı sözdizimiyle bir if alanı da alır; örneğin Bash hook’u sadece "Bash(git *)" için çalışabilir. Dokümanlar bunu “elden geldiğince” çalışan bir filtre olarak tanımlıyor, asıl kontrolü script’inde tut.
Çıkış kodları ve JSON çıktısı
Komut hook’u Claude Code’a iki yolla yanıt verir: çıkış kodu ve isteğe bağlı stdout JSON’u.
| Çıkış kodu | Ne olur |
|---|---|
0 | Başarılı. stdout tek bir JSON nesnesiyse JSON olarak okunur. UserPromptSubmit ve SessionStart’ta düz metin Claude’un bağlamına eklenir. |
2 | Engelleyen hata. Neden stderr’dir. PreToolUse’ta çağrı iptal olur, UserPromptSubmit’te prompt reddedilir, Stop’ta Claude devam eder. |
Diğerleri, 1 dahil | Engellemeyen hata. Claude Code not alır ve devam eder. |
Asıl tuzak 1 kodu. Çoğu script hata olunca 1 ile çıkar ve bu hiçbir şeyi engellemez. “Dur” demek istiyorsan 2 ile çık.
Daha ince kontrol için 0 ile çık ve JSON bas. PreToolUse hook’u izin verebilir, reddedebilir ya da sorabilir:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Use rg instead of grep for better performance"
}
}
permissionDecision alanı allow, deny, ask veya defer alır. Hook, updatedInput ile çağrıyı değiştirebilir ya da additionalContext ile Claude’a ek metin verebilir. Her olayda çalışan alanlar da var: continue: false Claude’u tamamen durdurur (stopReason ile birlikte), systemMessage sana bir uyarı gösterir.
Birden fazla hook eşleşirse paralel çalışırlar ve en kısıtlayıcı yanıt kazanır: deny, defer’i; defer, ask’i; ask da allow’u geçer. Hook’tan gelen allow, izinlerindeki bir deny kuralını aşmaz.
Örnek 1: her düzenlemeden sonra dosyayı biçimle
Çoğu kişinin ilk hook’u budur. Claude’un yazdığı ya da düzenlediği her dosyada Prettier çalıştırır:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
Başka diller için ruff format, gofmt -w veya rustfmt koyabilirsin. Biçimleyici düzenlemeden sonra çalıştığı için Claude dosyayı bir sonraki okuyuşunda biçimli hâlini görür, sen de incelemede sadece boşluk değişen diff’lerden kurtulursun.
Örnek 2: tehlikeli komutları ve korumalı dosyaları engelle
Kesin sınırların yeri PreToolUse. Resmi rehberden uyarlanan bu script hassas dosyaların düzenlenmesini engeller. .claude/hooks/protect-files.sh olarak kaydet:
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")
for pattern in "${PROTECTED_PATTERNS[@]}"; do
if [[ "$FILE_PATH" == *"$pattern"* ]]; then
echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
exit 2
fi
done
exit 0
chmod +x .claude/hooks/protect-files.sh ile çalıştırılabilir yap, sonra kaydet:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
}
]
}
]
}
}
Aynı yöntem kabuk komutlarında da işler. Bash ile eşleştir, .tool_input.command alanını oku ve içinde rm -rf /, git push --force ya da DROP TABLE gibi asla istemediğin bir şey varsa 2 ile çık. Metin kontrolünün kolayca atlatılabileceğini unutma; bunu kilit değil, emniyet kemeri olarak düşün.
Örnek 3: masaüstü bildirimi al
Uzun işler sandığından sık durup seni bekler. Notification hook’u bunu hemen haber verir. macOS’ta:
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}
Linux’ta bunun yerine notify-send 'Claude Code' 'Claude Code needs your attention' kullan. Sadece izin soruları ilgilendiriyorsa matcher’ı permission_prompt yap; Claude işi bitirdiğinde de haber almak istersen aynı komutla bir Stop hook’u ekle.
İşe yarayan başka kalıplar
- Sıkıştırmadan sonra bağlamı geri yükle.
compactmatcher’lı birSessionStarthook’u kurallarını kısacaechoile basabilir; stdout yeni bağlama eklenir. - Ayar değişikliklerini kaydet.
ConfigChangehook’u her ayar değişikliğini bir log dosyasına yazabilir. - Stop’ta kalite kapısı.
Stophook’u testleri çalıştırıp hataları stderr’e yazarak 2 ile çıkabilir, Claude da düzeltmeye devam eder. Sonsuz döngüye girmemek için girdidekistop_hook_activealanına bak. Claude Code da arka arkaya birkaç engellemeden sonra Stop hook’unu geçersiz kılar. - Tek bir güvenli soruyu otomatik onayla.
PermissionRequesthook’u belirli bir pencereyi karar nesnesinde{"behavior": "allow"}ile yanıtlayabilir. Matcher’ı dar tut.
Hook eklemeden önce güvenlik notları
Hook’lar senin kullanıcı yetkilerinle, sormadan çalışan kabuk komutlarıdır. Bütün mesele bu, risk de burada.
- Bir depoya güvenmeden önce hook’larını oku. Projenin
.claude/settings.jsondosyası hook getirebilir. Bunu birpostinstallscript’i gibi incele. - Değişkenleri tırnakla. Hook girdisi modelden gelir; model de prompt enjeksiyonu içerebilecek dosya ve web sayfalarını okur.
"$VAR"kullan, girdiyi asla eval etme, elle ayrıştırmak yerinejqtercih et. - Mutlak ya da projeye göreli yol kullan.
$CLAUDE_PROJECT_DIRile hook’un o anki klasöre bağlı kalmasını önle. - Hook’ları hızlı tut. Yavaş bir
PreToolUsehook’u her araç çağrısını yavaşlatır.timeoutbelirle. - Hook sandbox değildir. deny hook’u
--dangerously-skip-permissionsaltında bile çağrıyı engeller, bu iyi; ama kararlı ya da kafası karışmış bir ajan aynı sonuca başka yoldan ulaşabilir. Hook’ları deny kurallarıyla ve yalıtımla birlikte kullan. Ayrıntılar yapay zeka kodlama ajanı güvenliği ve izinleri güvenle atlamak yazılarında. - Kapatma düğmelerini bil.
"disableAllHooks": truehook’ları kapatır; yöneticiler yönetilen ayarlardaallowManagedHooksOnlyile kullanıcı ve proje hook’larını engelleyebilir.
Bir hook tuhaf davranıyorsa Claude Code’u claude --debug ile başlat ya da logu --debug-file /tmp/claude.log ile dosyaya yaz; her hook’un matcher’ını, çıkış kodunu ve çıktısını görürsün.
AgentVera hook’ları nasıl kullanıyor
AgentVera; Claude Code, Codex, Gemini CLI ve diğer kodlama CLI’larını yan yana çalıştıran bir masaüstü uygulaması. Claude Code ile çalışırken hook’lar işin önemli bir parçası.
- Senin hook’ların sana kalır. AgentVera kendi hook’larını her Claude Code sürecine
--settingsbayrağıyla verir. Claude Code bunları ayar dosyalarındaki hook’larınla birleştirir,settings.jsondosyana dokunulmaz. - Ajan durumu hook’lardan gelir. Uygulamada her ajanın gösterdiği durum, terminal metninden tahmin edilmez; CLI’ın kendi hook olaylarından okunur.
- Akıllı araçlar birer hook. Akıllı araçlar özelliği yerel Claude Code ajanlarına dört hook ekler: aynı dosyanın tekrar tekrar okunmasını engeller, sadece düzenlemenin etkilediği testleri çalıştırır, düzenlemeden hemen sonra hata kontrolü yapar ve sonuçları ajanlar arasında paylaştırır. Varsayılan olarak açıktır; Ayarlar → “Token tasarrufu” altından kapatabilirsin.
- Bildirim script’ine gerek yok. Bildirimler ve onaylar onay bekleyen tüm ajanları tek kuyrukta toplar, uygulama arka plandayken masaüstü bildirimi gönderir ve Telegram üzerinden telefonuna da haber verebilir.
Qwen Code da AgentVera’nın hook’larını alır, çünkü onun hook sistemi Claude Code’un olaylarını ve JSON biçimini izler.
Toparlarsak
Bir PostToolUse biçimleyici ve bir PreToolUse korumasıyla başla, /hooks ve --debug ile kontrol et, bir kural sürekli çiğneniyorsa yenisini ekle. Engellemek için 2 ile çık, daha fazla kontrol gerekiyorsa JSON bas ve her hook’u senin yetkilerinle çalışan kod olarak gör.
Devamını oku:
AgentVera’yı denemek için ana sayfadan başlayabilirsin.