Claude Code hooks nasıl kullanılır: örneklerle rehber

Claude Code hooks nasıl kullanılır? Olaylar, settings.json, matcher, çıkış kodları ve JSON çıktısı; dosya biçimleyen, riskli komutu engelleyen ve haber veren örnekler.

Solviera Teknoloji 9 dk okuma

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: .env dosyasını düzenlemek ya da yanlış klasörde rm -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:

OlayNe zaman çalışırEngelleyebilir mi?
PreToolUseAraç çağrısı çalışmadan önceEvet, çağrıyı engeller
PostToolUseAraç çağrısı başarıyla bittikten sonraHayır, araç zaten çalıştı; stderr Claude’a gider
UserPromptSubmitPrompt gönderdiğindeEvet, prompt Claude’a hiç ulaşmaz
NotificationClaude Code bildirim gönderdiğinde (izin sorusu, boşta bekleme)Hayır
StopClaude yanıtını bitirdiğindeEvet, Claude çalışmaya devam eder
SubagentStart / SubagentStopBir alt ajan başladığında veya bittiğindeSadece SubagentStop
SessionStartAçılışta, devam ederken, /clear veya sıkıştırma sonrasıHayır, ama stdout bağlama eklenir
PreCompactBağlam sıkıştırılmadan önceEvet, sıkıştırmayı engeller
PermissionRequestİzin penceresi açılmak üzereykenSadece JSON ile, 2 koduyla değil
SessionEndOturum bittiğindeHayı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:

DosyaKapsamGit ile paylaşılır mı?
~/.claude/settings.jsonTüm projelerinHayır
.claude/settings.jsonTek projeEvet
.claude/settings.local.jsonTek proje, sadece senHayır (gitignore’da)
Yönetilen politika ayarlarıTüm kurumYö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:

MatcherAnlamı
"*", "" veya hiç yokTü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ış koduNe olur
0Başarılı. stdout tek bir JSON nesnesiyse JSON olarak okunur. UserPromptSubmit ve SessionStart’ta düz metin Claude’un bağlamına eklenir.
2Engelleyen hata. Neden stderr’dir. PreToolUse’ta çağrı iptal olur, UserPromptSubmit’te prompt reddedilir, Stop’ta Claude devam eder.
Diğerleri, 1 dahilEngellemeyen 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. compact matcher’lı bir SessionStart hook’u kurallarını kısaca echo ile basabilir; stdout yeni bağlama eklenir.
  • Ayar değişikliklerini kaydet. ConfigChange hook’u her ayar değişikliğini bir log dosyasına yazabilir.
  • Stop’ta kalite kapısı. Stop hook’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 girdideki stop_hook_active alanına bak. Claude Code da arka arkaya birkaç engellemeden sonra Stop hook’unu geçersiz kılar.
  • Tek bir güvenli soruyu otomatik onayla. PermissionRequest hook’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.json dosyası hook getirebilir. Bunu bir postinstall script’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 yerine jq tercih et.
  • Mutlak ya da projeye göreli yol kullan. $CLAUDE_PROJECT_DIR ile hook’un o anki klasöre bağlı kalmasını önle.
  • Hook’ları hızlı tut. Yavaş bir PreToolUse hook’u her araç çağrısını yavaşlatır. timeout belirle.
  • Hook sandbox değildir. deny hook’u --dangerously-skip-permissions altı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": true hook’ları kapatır; yöneticiler yönetilen ayarlarda allowManagedHooksOnly ile 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 --settings bayrağıyla verir. Claude Code bunları ayar dosyalarındaki hook’larınla birleştirir, settings.json dosyana 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.

Sık sorulanlar

Claude Code hooks nedir?

Hook’lar, Claude Code’un oturumun belli anlarında kendiliğinden çalıştırdığı kabuk komutları, HTTP çağrıları, MCP araçları veya prompt’lardır. Örneğin bir araç çağrısından önce, dosya düzenlendikten sonra ya da Claude senden yanıt beklediğinde çalışırlar. settings.json içinde tanımlanırlar.

Claude Code hook’larını nereye yazarım?

Bir ayar dosyasının hooks anahtarına. Tüm projeler için ~/.claude/settings.json, git ile paylaşılan proje ayarı için .claude/settings.json, sadece senin makinendeki proje ayarı için .claude/settings.local.json. Plugin’ler, skill’ler ve alt ajanlar da hook tanımlayabilir.

Bir hook araç çağrısını nasıl engeller?

PreToolUse hook’u ya 2 koduyla çıkıp nedeni stderr’e yazar ya da 0 ile çıkıp permissionDecision alanı deny olan bir JSON basar. Claude Code çağrıyı iptal eder ve nedeni Claude’a gösterir. 1 koduyla çıkmak engellemez.

--dangerously-skip-permissions açıkken hook’lar çalışır mı?

Evet. deny dönen bir hook, bypassPermissions modunda bile araç çağrısını engeller. Bu yüzden PreToolUse hook’u asla istemediğin komutlar için iyi bir son kontroldür, ama bir sandbox yerine geçmez.

Çalışmayan bir hook’u nasıl ayıklarım?

/hooks ile hangi hook’ların yüklendiğine ve nereden geldiğine bak, matcher’ın araç adıyla birebir eşleştiğini kontrol et, sonra Claude Code’u --debug veya --debug-file ile başlatıp her hook’un çıkış kodunu ve çıktısını gör.

Ajanlarını bir masaya topla.

AgentVera’yı ücretsiz indir; kurulu CLI’ların hazır.

Diğer yazılar