İçeriğe geç

Reklam

Claude Code Hooks Nedir? Pahalı Hataları Önleme Rehberi

Claude Code hooks nedir sorusunu görselleştiren kapak: terminalde bir PreToolUse hook ana dala doğrudan commit girişimini BLOCKED uyarısıyla engelliyor

Silinmemesi gereken bir klasörün terminalde bir anda yok olduğunu görmek, yapay zekâ destekli kodlamanın en pahalı dersidir. Peki Claude Code hooks nedir ve bu tür kazaları gerçekten önleyebilir mi? Bu yazımızda, Anthropic’in terminal ajanı Claude Code’a kalıcı güvenlik refleksleri kazandıran hook (kanca) sistemini sizler için adım adım inceledik.

Aşağıda önce hook kavramını tanımlıyor, ardından hangi olayların mevcut olduğunu, bir Claude Code hook’unun nasıl kurulduğunu ve yanlışlıkla dosya silme, gizli anahtar sızdırma ya da yıkıcı Git komutu çalıştırma gibi pahalı hataları engelleyen beş hazır tarifi paylaşıyoruz. Claude Code’a yeni başlıyorsanız, önce Claude Code nasıl kullanılır başlangıç rehberimize göz atmanızı öneririz.

Reklam

Claude Code Hooks Nedir?

Claude Code hooks, aracın yaşam döngüsündeki belirli anlarda otomatik olarak çalışan kullanıcı tanımlı komutlardır. Bir araç çağrısı yürütülmeden hemen önce, bir dosya düzenlendikten sonra ya da oturum başlarken devreye girerler. Kısaca: Git hook’larının yapay zekâ ajanı için uyarlanmış hâli.

Buradaki kritik ayrım determinizmdir. Bir hook, modele “şunu yapmayı düşün” demez; koşul sağlandığında her seferinde çalışır. Anthropic’in resmi hook rehberinde de bu özellik “deterministik kontrol” olarak tanımlanıyor.

Bir hook yalnızca kabuk (shell) komutu olmak zorunda değil. Ağustos 2026 itibarıyla resmi referans; komut hook’ları, HTTP uç noktaları, MCP araç çağrıları ve hatta bir modele soru soran istem (prompt) tabanlı hook’ları destekliyor. Yine de günlük kullanımda en yaygın tip, küçük bir Bash betiğini çağıran komut hook’udur.

Konuyu resmi ağızdan dinlemek isterseniz, Claude’un kendi kanalındaki tanıtım videosu iyi bir başlangıç:

Claude Code terminalinde PreToolUse hook tarafından engellenen git push --force komutu: BLOCKED hata mesajı ekranda görünüyor
Bir PreToolUse hook, riskli git push –force komutunu araç çağrısı başlamadan BLOCKED mesajıyla durduruyor.

Hook’lar Kural Dosyalarından Neden Daha Güvenilir?

Pek çok geliştirici güvenlik kurallarını proje talimat dosyasına yazar. Bu yaklaşım işe yarar, ancak bir sınırı vardır: talimat dosyası modele verilen bir öneridir. Bağlam penceresi dolduğunda ya da görev karmaşıklaştığında model o öneriyi gözden kaçırabilir.

Hook ise model katmanının dışında, uygulama katmanında çalışır. Betik “hayır” dediğinde araç çağrısı hiç başlamaz. Bu yüzden ikisini birbirinin alternatifi değil, tamamlayıcısı olarak düşünmek gerekir: üslup ve mimari tercihlerini CLAUDE.md dosyasına yazın, geri dönüşü olmayan işlemleri ise hook’la kilitleyin.

  • Talimat dosyası: esnek, bağlama duyarlı, ama ihlal edilebilir.
  • İzin (permission) kuralları: güçlü, fakat çoğunlukla “sor / izin ver” ikilisiyle sınırlı.
  • Hook: koşullu, betikle programlanabilir ve pazarlığa kapalı.

Claude Code’da Hangi Hook Olayları Bulunuyor?

Resmi belgelerde otuza yakın hook olayı listeleniyor; oturum, istem, araç kullanımı, alt ajan, dosya değişikliği ve bağlam sıkıştırması gibi kategorilere ayrılmış durumdalar. Hata önleme açısından işinize yarayacak olanlar ise küçük bir avuç. Aşağıdaki tabloda en çok kullanılanları özetledik.

Hook olayıNe zaman çalışırİşlemi engelleyebilir mi?
SessionStartOturum başladığında veya devam ettirildiğindeHayır
UserPromptSubmitSiz istemi gönderdiğinizde, model işlemeden önceEvet
PreToolUseBir araç çağrısı çalıştırılmadan hemen önceEvet
PostToolUseAraç çağrısı başarıyla tamamlandıktan sonraHayır
PostToolUseFailureAraç çağrısı hata verdikten sonraHayır
StopClaude yanıtını bitirdiğindeEvet
SubagentStopBir alt ajan (subagent) işini bitirdiğindeEvet
PreCompactBağlam sıkıştırmasından önceEvet
SessionEndOturum sonlandığındaHayır

Tablodaki ayrım basit ama hayati: PreToolUse hook ile tehlikeli komutları engelleme mümkündür, çünkü bu olay araç çağrısından önce tetiklenir. PostToolUse hook ile araç çağrısı sonrası kontrol de yapabilirsiniz; formatlama, test koşturma veya uyarı üretme gibi işler buna uygundur. Ne var ki bu olay iş bittikten sonra çalışır ve çalışmış bir komutu geri alamaz. Yıkıcı işlemleri PostToolUse ile durdurmaya çalışmak, kaza olduktan sonra fren pedalına basmaya benzer.

Claude Code hook yaşam döngüsü diyagramı: SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop ve SessionEnd olaylarının sıralı akışı
Claude Code hook yaşam döngüsü: SessionStart’tan SessionEnd’e kadar tetiklenen olaylar ve PreToolUse’un engelleme noktası. (Kaynak: Anthropic Claude Code Docs)

Claude Code Hook Nasıl Kurulur?

Kurulum üç adımdan ibaret: yapılandırma dosyasını seçmek, hook bloğunu tanımlamak ve çalıştığını doğrulamak. Tek satır JSON’la başlayıp ihtiyaç büyüdükçe ayrı betik dosyalarına geçebilirsiniz.

Hook Yapılandırması Nereye Yazılır?

Hook tanımları ayar dosyalarındaki hooks anahtarı altında yaşar. Bir Claude Code settings.json hook yapılandırması tek bir dosyaya sıkışmak zorunda değildir; üç yaygın konum vardır ve bunlar birbirini ezmez, birleşerek çalışır:

  • ~/.claude/settings.json — tüm projeleriniz için kişisel kurallar.
  • .claude/settings.json — proje içi, sürüm kontrolüne eklenir ve ekiple paylaşılır.
  • .claude/settings.local.json — yalnızca size özel, genellikle Git dışında bırakılır.

Ekip güvenliğini ilgilendiren kuralları proje dosyasına koymanızı öneririz; böylece hook’lar depoyla birlikte dolaşır ve kod incelemesinde görünür olur.

Yapılandırma Bloğu Nasıl Görünür?

Yapı üç katmanlıdır: olay adı, eşleştirici (matcher) grubu ve çalışacak komutlar. Aşağıdaki örnek, her Edit veya Write çağrısından önce bir betik çalıştırır:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

Eşleştirici, olayın türüne göre farklı şeylerle karşılaştırılır. Araç olaylarında araç adına bakar: Bash, Edit|Write gibi düz listeler doğrudan eşleşir; içinde başka karakter geçen ifadeler ise düzenli ifade (regex) olarak değerlendirilir. Eşleştiricilerin büyük-küçük harfe duyarlı olduğunu unutmayın.

MCP (Model Context Protocol) araçları mcp__sunucu__arac kalıbını izler. Tek bir sunucunun tüm araçlarını kapsamak isterseniz sunucu adına .* ekleyin: mcp__memory__.* yalnızca memory sunucusunu yakalar. Buna karşılık mcp__.* çok daha geniştir; bağlı bütün MCP sunucularının bütün araçlarını kapsar. Sondaki .* zorunludur: mcp__memory gibi bir yazım tam eşleşme olarak değerlendirilir ve hiçbir araçla eşleşmez.

Hook’un Çalıştığını Nasıl Doğrularsınız?

Claude Code içinde /hooks komutunu çalıştırdığınızda, tüm ayar katmanlarından yüklenen hook’ları, eşleştiricileriyle birlikte tek ekranda görebilirsiniz. Bir hook listede görünmüyorsa sorun genellikle JSON söz diziminde ya da eşleştirici yazımındadır. macOS ve Linux’ta betik dosyalarına chmod +x vermeyi de atlamayın; çalıştırma izni olmayan bir betik sessizce başarısız olur.

PreToolUse hook eşleştirme (matcher) şeması: Bash rm komutu çalıştırıldığında matcher ve if koşulu kontrol edilip hook komutu çalışıyor ve permissionDecision deny dönüyor
Matcher eşleşince hook komutu çalışır ve permissionDecision alanı deny/allow/ask/defer kararını belirler. (Kaynak: Anthropic Claude Code Docs)

Pahalı Hataları Önleyen 5 PreToolUse Hook Tarifi

Aşağıdaki tarifler, geliştiricilerin en sık canını yakan senaryolara odaklanıyor. Hepsi aynı iskeleti kullanıyor: standart girdiden gelen JSON’u jq aracıyla okuyun, riskli kalıbı arayın ve bulursanız exit 2 ile çıkın.

Listeyi kendi ölçütümüzle sıraladık: hasarın geri döndürülebilirliği. En üstte veri kurtarma yazılımı bile gerektirebilecek işlemler var; aşağı indikçe telafisi mümkün ama pahalı, en sonda ise günler sonra fark edilen sessiz hatalar geliyor. Bu sıra aynı zamanda hangi hook’u önce yazmanız gerektiğini de gösteriyor.

1. Yıkıcı Kabuk Komutlarını Durdurun

Listenin başında olmalarının nedeni basit: özyinelemeli silme, disk üzerine yazma ve dosya sistemi biçimlendirme yanlış dizinde çalıştığında geri dönüşü yoktur. Yedeğiniz yoksa telafi de yoktur.

#!/bin/bash
# .claude/hooks/block-destructive-bash.sh
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

# Bayrak sirasindan ve buyuk/kucuk harften bagimsiz yakalama:
# rm -rf, rm -fr, rm -Rf, rm -r -f, rm --recursive --force
RM_KALIBI='rm[[:space:]]+(-[a-z]*[rf][a-z]*[rf]|-[a-z]*[rf][a-z]*[[:space:]]+-[a-z]*[rf]|--recursive|--force)'

if echo "$CMD" | grep -Eiq "$RM_KALIBI|dd[[:space:]]+if=|mkfs"; then
  echo "Engellendi: yikici komut kalibi tespit edildi -> $CMD" >&2
  exit 2
fi
exit 0

Buradaki ayrıntı önemli. Yalnızca -rf yazımını arayan dar bir kalıp, rm -fr, rm -Rf ve rm --recursive --force gibi eşdeğer komutları kaçırır; siz korunduğunuzu sanırsınız, hook sessizce yan yatar. grep çağrısındaki -i bayrağı büyük harfli yazımları, alternatifli kalıp ise ayrı yazılmış bayrakları yakalar. Betiği "matcher": "Bash" ile PreToolUse altına kaydettiğinizde, Claude bu komutlardan birini denediği anda çağrı başlamadan reddedilir ve gerekçe modele geri bildirim olarak iletilir.

2. Riskli Git Komutlarına Fren Koyun

Sıralamada ikinci basamak, kurtarılabilir ama pahalı hasar. Zorlamalı gönderim (force push) ve sert sıfırlama, ekip deposunda saatlerce emeği silebilir. Ana dala yapılan bir --force, tek kişilik bir hata olmaktan çıkıp herkesin sorunu hâline gelir.

#!/bin/bash
# .claude/hooks/git-guard.sh
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if echo "$CMD" | grep -Eq 'git[[:space:]]+push.*(--force|-f)|git[[:space:]]+reset[[:space:]]+--hard'; then
  echo "Engellendi: yikici Git komutu. Once yedek dal olusturun." >&2
  exit 2
fi
exit 0

Yine de kaza olduysa her şey bitmiş sayılmaz; Git reflog ile kayıp commit kurtarma rehberimiz çoğu durumda imdadınıza yetişir. Ama en iyi kurtarma, hiç yaşanmayan kazadır.

3. Veritabanında DROP ve TRUNCATE’i Engelleyin

Üretim veritabanında çalışan bir DROP TABLE, son yedeğinizin yaşı kadar veri kaybı demektir; bu yüzden listenin üst sıralarında yer alıyor. Ajan bir göç (migration) betiği yazarken ya da test verisi temizlerken şema komutlarına uzanabilir. Bu tarifte çıkış kodu yerine yapılandırılmış JSON kararı kullanıyoruz; böylece reddetme gerekçesi modele daha temiz bir biçimde iletilir.

#!/bin/bash
# .claude/hooks/sql-guard.sh
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if echo "$CMD" | grep -Eiq 'drop[[:space:]]+table|truncate[[:space:]]+table|drop[[:space:]]+database'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Yikici SQL komutu hook tarafindan engellendi."
    }
  }'
  exit 0
fi
exit 0

4. .env ve Kimlik Bilgisi Dosyalarını Kilitleyin

Buradaki hasar diskte değil, güvendedir: sızan bir anahtar geri alınamaz, yalnızca iptal edilip yenilenebilir. Üstelik sızıntıların çoğu kötü niyetten değil dikkatsizlikten doğar. Ajan hata ayıklarken .env dosyasını açar, içerik bağlama girer, oradan bir günlük kaydına ya da commit’e taşınır. Yol tabanlı bir kara liste bu zinciri en başta koparır.

Aşağıdaki betik, en sade hâliyle bir Claude Code .env dosyasını koruma hook’u örneğidir:

#!/bin/bash
# .claude/hooks/protect-files.sh
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

for pattern in ".env" "secrets" "credentials" ".git/" "id_rsa"; do
  if [[ "$FILE_PATH" == *"$pattern"* ]]; then
    echo "Engellendi: $FILE_PATH korumali kalipla eslesti ($pattern)" >&2
    exit 2
  fi
done
exit 0

Aynı mantığı Read aracına da uygularsanız, dosyanın yalnızca değiştirilmesini değil okunmasını da engellemiş olursunuz. Windows kullanıyorsanız yol ayıracını normalleştirmeyi unutmayın; ters bölü işaretleri yukarıdaki kalıplarla eşleşmez.

5. Paket Yöneticisi Tutarlılığını Zorunlu Kılın

Listenin sonundaki bu tarif, “pahalı hata”nın sessiz versiyonudur: projede pnpm-lock.yaml varken çalıştırılan bir npm install, ikinci bir kilit dosyası üretir ve bağımlılık ağacını bozar. Hata anında görünmez, birkaç gün sonra derleme çöktüğünde ortaya çıkar.

#!/bin/bash
# .claude/hooks/enforce-pnpm.sh
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if [[ -f "pnpm-lock.yaml" ]] && echo "$CMD" | grep -Eq '^[[:space:]]*npm[[:space:]]+(install|i|add|ci)'; then
  echo "Engellendi: bu proje pnpm kullaniyor. 'pnpm install' deneyin." >&2
  exit 2
fi
exit 0

Aynı kalıbı Python projelerinde pip yerine uv, Node tarafında yarn yerine bun gibi tercihleriniz için de çoğaltabilirsiniz.

Claude Code terminalinde rm -rf scratch komutunun PreToolUse hook tarafından destructive-operation pattern gerekçesiyle engellendiği gerçek terminal çıktısı
Gerçek bir terminal oturumunda rm -rf scratch komutu, yıkıcı komut kalıbını yakalayan hook tarafından engelleniyor.

Çıkış Kodları ve JSON Kararları Nasıl Çalışır?

Hook’ların en çok karıştırılan tarafı burasıdır. Bir güvenlik hook’u yanlış çıkış koduyla biterse hiçbir şeyi engellemez; sadece günlüğe uyarı düşer ve komut çalışmaya devam eder. Kısacası exit 1 ile yazılmış bir koruma, koruma değildir.

Çıkış koduAnlamıPreToolUse’daki etkisi
0BaşarıKarar üretilmez, normal izin akışı işler; stdout geçerli JSON ise karar olarak okunur
2Bloklayıcı hataAraç çağrısı engellenir; stderr metni gerekçe olarak modele iletilir
Diğer (1, 3…)Bloklamayan hataİşlem devam eder; geçerli JSON basıldıysa karar yine dikkate alınır

Daha ayrıntılı denetim isterseniz, çıkış kodu yerine hookSpecificOutput nesnesiyle permissionDecision alanını kullanabilirsiniz. Bu alan dört değer alır:

  • allow — izin istemini atlar, araç doğrudan çalışır.
  • deny — çağrıyı engeller; gerekçe modele iletilir.
  • ask — kararı kullanıcıya yükseltir, onay istemi gösterilir.
  • defer — çağrıyı çalıştırmadan erteler; oturum daha sonra kaldığı yerden sürdürülür.

Bu dörtlüyü karıştırmamak önemlidir. Resmi belgenin düzyazısında geçen “kullanıcıya yükseltme” ifadesi bir değer adı değil, ask kararının karşılığıdır. Alana geçersiz bir metin yazarsanız çıktı geçerli bir karar sayılmaz ve araç çağrısı çalışmaya devam eder; yani koruma sessizce devre dışı kalır. Birden fazla hook aynı anda farklı karar döndürürse öncelik sırası deny > defer > ask > allow biçimindedir. Üçüncü tarifte deny kullanımının örneğini gördünüz; alanların tam listesi resmi hook referansında yer alıyor.

Bir ayrıntıyı da not edelim: PostToolUse olayında çıkış kodu 2 işlemi geri almaz, yalnızca hata metnini modele gösterir. Engelleme kararı vermek istiyorsanız doğru yer daima PreToolUse’dur.

Hook Yazarken Nelere Dikkat Etmelisiniz?

Hook’lar sizin kullanıcı yetkilerinizle, onay istemeden çalışır. Bu güç, dikkatsiz yazılmış bir betiği doğrudan bir risk hâline getirir. Kurulumdan önce şu maddeleri gözden geçirmenizi tavsiye ederiz:

  • Kabuk değişkenlerini tırnak içine alın. Tırnaksız bir $FILE_PATH, boşluklu yollarda beklenmedik davranır.
  • Mutlak yol kullanın. Betikleri $CLAUDE_PROJECT_DIR gibi değişkenlerle çağırın; göreli yollar çalışma dizini değiştiğinde kopar.
  • Girdiyi doğrulayın. JSON’dan gelen değeri doğrudan bir kabuk komutuna geçirmeyin; yol geçişi (..) denemelerini eleyin.
  • Önce kuru çalıştırın. Yeni hook’u engelleme yerine yalnızca günlüğe yazacak şekilde deneyin, kalıbın doğru eşleştiğinden emin olun.
  • Zaman aşımını ayarlayın. Uzun süren denetimler için timeout ve async alanlarını kullanın; her araç çağrısında saniyeler beklemek iş akışını yorar.
  • Kalıpları dar tutun. Aşırı geniş bir regex, meşru komutları da engelleyerek ajanı kullanılmaz hâle getirir.

Yapay zekâ araçlarının yetkilerini sınırlama fikrini daha geniş bir çerçevede okumak isterseniz, yapay zeka tarayıcılarını güvenli kullanma rehberimiz benzer bir mantığı tarayıcı tarafında ele alıyor.

Sonuç

Hook’lar, güvenliği “hatırlanması gereken bir kural” olmaktan çıkarıp projenin altyapısına taşır. Bu yüzden bir hook’un asıl değeri, engellediği komut sayısı değil; yazdıktan sonra o riski bir daha düşünmek zorunda kalmamanızdır. Yıkıcı kabuk komutlarını, riskli Git ve SQL işlemlerini, gizli anahtar dosyalarını birkaç küçük betikle kapattığınızda dikkatiniz asıl işe kalır.

Küçük başlamanızı öneririz: önce hasarı en geri döndürülemez olan tek bir PreToolUse hook’u yazın, /hooks ile göründüğünü doğrulayın, birkaç gün gerçek işte deneyin ve ancak ondan sonra listeyi büyütün. Baştan altı kural birden yazmak, çoğu zaman meşru komutların da engellenmesiyle ve hook’ların tümden kapatılmasıyla sonuçlanır.

Eğer bu tarz içerikler ilginizi çekiyorsa, sitemizde yer alan “Claude Code Skill’leri İçin En Popüler 8 GitHub Reposu (2026)” adlı yazımıza da göz atabilirsiniz.

Reklam

Abone ol
Bildir
guest
0 Yorum
Eskiler
En Yeniler Beğenilenler

Reklam

Reklam