Modül 4 · Hooks and the SDK · ⏱ 10 dakika

Hook tanımlamak

Defining hooks

Bu derste neler öğreneceksin

  • settings.json içinde hook bloğunu doğru yazmak
  • matcher pattern'leriyle hangi tool'a uygulanacağını sınırlamak
  • Hook script'inin stdin/stdout/exit code protokolünü anlamak

Bu derste kuru kuruya hook formatı: JSON şeması, matcher, exit code ve JSON çıktı protokolü.

1. settings.json yapısı

{
  "hooks": {
    "<EventName>": [
      {
        "matcher": "<opsiyonel regex>",
        "hooks": [
          {
            "type": "command",
            "command": "<komut çalıştırılacak>"
          }
        ]
      }
    ]
  }
}

İç içe hooks görmek kafa karıştırır ama yapısı şu:

  • Dış hooks: tüm event tanımlarının kökü
  • <EventName>: PreToolUse / PostToolUse / vs.
  • Liste: aynı event için birden çok grup
  • İç hooks: aynı matcher için sıralı komutlar

2. Matcher pattern’leri

Tool-bağlı event’lerde (PreToolUse, PostToolUse) matcher hangi tool’a uygulanacağını sınırlar.

MatcherTetiklenir
"Edit"Sadece Edit tool
"Edit|Write"Edit veya Write
"Edit|MultiEdit|Write"Üçü de
".*" veya boşTüm tool’lar
"Bash"Sadece shell komutları

Regex destekli — daha karmaşık şablonlar mümkün, ama basit tut, debug kolay olur.

3. Komut nasıl çalıştırılır?

Komut shell’de çalışır. İçinde $CLAUDE_PROJECT_DIR env variable kullanırsan repo köküne mutlak yol verirsin:

{
  "type": "command",
  "command": "$CLAUDE_PROJECT_DIR/.claude/scripts/format.sh"
}

Tek satır komut da kabul:

{ "type": "command", "command": "npx prettier --write" }

4. Hook’a giren input

Komuda stdin üzerinden JSON verilir. Yapı:

{
  "session_id": "abc-123",
  "tool_name": "Edit",
  "tool_input": {
    "file_path": "src/index.ts",
    "old_string": "...",
    "new_string": "..."
  }
}

Script bunu okuyabilir:

#!/usr/bin/env bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path')
# ...

5. Exit code anlamları

Exit codeAnlamı
0Başarılı, akış devam eder
2Aksiyonu bloklaPreToolUse’da tool çağrısı iptal olur; stderr Claude’a feedback olarak geri verilir
DiğerNon-blocking error — sana gösterilir ama akış durmaz

6. JSON çıktı protokolü (gelişmiş)

Komut stdout’a JSON yazarsa Claude Code’un davranışını programatik kontrol edebilirsin:

{
  "decision": "block",
  "reason": "Production config dosyasına yazma denemesi"
}

Veya context enjekte etme:

{
  "additionalContext": "Son commit: feat: add pagination (yusuf, 2 saat önce)"
}

Tüm field listesi resmi docs’ta. Tipik üç field:

Fieldİşi
decision"block" / "allow"
reasonEngelleme/onay nedeni
additionalContextKonuşmaya enjekte edilecek metin

7. Birden çok hook

Aynı event için birden çok grup ekleyebilirsin; sırayla çalışırlar:

"PostToolUse": [
  { "matcher": "Edit", "hooks": [{ "type": "command", "command": "format.sh" }] },
  { "matcher": "Edit", "hooks": [{ "type": "command", "command": "lint.sh" }] }
]

Bir hook exit 2 verirse sonrakiler çalışmaz (bloklama durumunda).

Özet

  • Event + matcher + komut üçlüsü
  • stdin’den JSON al, stdout/exit code ile yanıtla
  • Exit 2 → blokla, stderr → feedback
  • JSON çıktı protokolü ile gelişmiş kontrol

Sırada ne var?

Bir sonraki derste gerçek bir hook’u baştan sona yazıp deneyeceğiz.