# Claude Code Karar Yakalama Hook'u - Otomatik Kurulum

> **Nasıl kullanılır:** Bu dosyayı kendi Claude Code'una ver ve "Bu MD dosyasındaki kurulumu benim projemde yap" de. Claude aşağıdaki adımları sırayla uygulayacak.

---

## Claude için talimatlar (senin için değil, AI için)

Sen Claude Code'sun ve kullanıcının projesinde bu paketi kurmakla görevlisin. Adımları sırayla takip et.

### Ön kontrol

1. `which claude` komutunu çalıştır. Eğer `claude` CLI bulunamazsa kullanıcıya "Claude Code CLI kurulu değil, önce onu kurman gerekiyor" de ve dur.
2. `which python3` komutunu çalıştır. Yoksa kullanıcıya söyle ve dur.
3. Kullanıcının `pwd`'sine bak. Git repo mu, proje kökü mü doğrula. Değilse kullanıcıya "Bu paketi proje kök dizininde kurmak mantıklı, şu anda [X] dizinindesin, devam edeyim mi?" diye sor.
4. Kullanıcıya **bu kurulumun ne yapacağını 3-4 cümleyle özetle:** "İki shell script oluşturacağım, `.claude/settings.json`'a iki hook ekleyeceğim. Bu hook'lar oturum biterken Haiku ile kararları tarar, yeni oturumda sana sorar. Oturum başına ~0.02 USD maliyet. Devam edeyim mi?" Onay bekle.

### Adım 1: Script dizinini oluştur

```bash
mkdir -p scripts/claude-hooks
```

### Adım 2: capture-decisions.sh dosyasını oluştur

`scripts/claude-hooks/capture-decisions.sh` yolunda şu içerikle bir dosya yaz:

```bash
#!/bin/bash
# SessionEnd hook: scan transcript with Haiku for concrete decisions.
# If found, append to pending-decisions.md so the next SessionStart can
# surface them for confirmation.

LOG=/tmp/claude-decision-capture.log
exec 2>>"$LOG"
echo "--- $(date '+%Y-%m-%d %H:%M:%S') capture-decisions invoked ---" >>"$LOG"

INPUT=$(cat 2>/dev/null || echo "{}")

parse() {
  python3 -c "import sys,json; d=json.loads(sys.argv[1] or '{}'); print(d.get('$1',''))" "$INPUT" 2>/dev/null
}

SESSION_ID=$(parse session_id)
TRANSCRIPT=$(parse transcript_path)
CWD=$(parse cwd)

if [ -z "$SESSION_ID" ] || [ -z "$CWD" ]; then
  echo "missing session_id or cwd" >>"$LOG"; exit 0
fi

if [ -z "$TRANSCRIPT" ] || [ ! -f "$TRANSCRIPT" ]; then
  SANITIZED=$(echo "$CWD" | sed 's|/|-|g')
  for candidate in \
    "$HOME/.claude/projects/${SANITIZED}/conversations/${SESSION_ID}.jsonl" \
    "$HOME/.claude/projects/${SANITIZED}/${SESSION_ID}.jsonl"; do
    [ -f "$candidate" ] && TRANSCRIPT="$candidate" && break
  done
fi

if [ ! -f "$TRANSCRIPT" ]; then
  echo "transcript not found" >>"$LOG"; exit 0
fi

LINES=$(wc -l < "$TRANSCRIPT" 2>/dev/null || echo 0)
if [ "$LINES" -lt 6 ]; then
  echo "transcript too short ($LINES lines)" >>"$LOG"; exit 0
fi

CONTENT=$(python3 - "$TRANSCRIPT" <<'PY' 2>/dev/null
import json, sys
out = []
with open(sys.argv[1], 'r', encoding='utf-8', errors='ignore') as f:
    for line in f:
        try:
            rec = json.loads(line)
        except Exception:
            continue
        role = rec.get('type') or rec.get('role') or ''
        msg = rec.get('message') or {}
        content = msg.get('content') if isinstance(msg, dict) else None
        if content is None:
            content = rec.get('content')
        if isinstance(content, list):
            parts = []
            for p in content:
                if isinstance(p, dict) and p.get('type') == 'text':
                    parts.append(p.get('text', ''))
                elif isinstance(p, str):
                    parts.append(p)
            text = '\n'.join(parts)
        elif isinstance(content, str):
            text = content
        else:
            text = ''
        text = text.strip()
        if not text:
            continue
        if role in ('user', 'human'):
            out.append(f"USER: {text}")
        elif role in ('assistant',):
            out.append(f"ASSISTANT: {text}")
body = '\n\n'.join(out)
print(body[-40000:])
PY
)

if [ -z "$CONTENT" ]; then
  echo "no textual content extracted" >>"$LOG"; exit 0
fi

PROMPT=$(cat <<'PROMPT_EOF'
Aşağıdaki Claude Code konuşması bir oturum sonudur. Görev: konuşmada KONKRET KARAR var mı tespit et.

KARAR sayılan:
- Yeni proje/girişim başlatma
- Deadline / tarih komitmanı
- Strateji değişikliği
- Kişi/iş birliği kararları
- Ürün/feature kararları, fiyat değişiklikleri, iptaller
- Tekrarlanacak kural/policy

KARAR DEĞİL:
- Sadece brainstorm, soru, öneri, bilgi alma
- Kod yazma, bug fix, rutin iş
- Kesinleşmemiş fikirler

ÇIKTI FORMATI (başka hiçbir şey yazma):

Karar yoksa: tek satır, sadece: NO

Karar varsa:
YES
DECISION: <1-2 cümle özet>
REASON: <neden karar sayılıyor>
FILES: <hangi MD dosyaları güncellenmeli>
---
(birden fazla karar varsa tekrarla)

Konuşma:
PROMPT_EOF
)

ANALYSIS=$(printf '%s\n\n%s\n' "$PROMPT" "$CONTENT" | timeout 90 claude -p --model haiku --output-format text 2>>"$LOG")

if [ -z "$ANALYSIS" ]; then
  echo "empty analysis" >>"$LOG"; exit 0
fi

FIRST=$(printf '%s' "$ANALYSIS" | head -1 | tr -d '[:space:]' | tr '[:lower:]' '[:upper:]')
echo "first line: $FIRST" >>"$LOG"

if [ "$FIRST" = "NO" ] || [ -z "$FIRST" ]; then
  echo "no decisions detected" >>"$LOG"; exit 0
fi

if [ "$FIRST" != "YES" ]; then
  echo "unexpected first line, treating as no-op" >>"$LOG"; exit 0
fi

SANITIZED=$(echo "$CWD" | sed 's|/|-|g')
PENDING_DIR="$HOME/.claude/projects/${SANITIZED}"
mkdir -p "$PENDING_DIR"
PENDING="$PENDING_DIR/pending-decisions.md"

{
  echo "## $(date '+%Y-%m-%d %H:%M') — session ${SESSION_ID:0:8}"
  echo ""
  printf '%s\n' "$ANALYSIS" | tail -n +2
  echo ""
  echo "---"
  echo ""
} >> "$PENDING"

echo "appended to $PENDING" >>"$LOG"
exit 0
```

### Adım 3: inject-pending-decisions.sh dosyasını oluştur

`scripts/claude-hooks/inject-pending-decisions.sh` yolunda şu içerikle bir dosya yaz:

```bash
#!/bin/bash
# SessionStart hook: if pending-decisions.md exists from a prior session,
# inject it as additionalContext so Claude can surface decisions to the
# user for confirmation and MD updates.

INPUT=$(cat 2>/dev/null || echo "{}")

parse() {
  python3 -c "import sys,json; d=json.loads(sys.argv[1] or '{}'); print(d.get('$1',''))" "$INPUT" 2>/dev/null
}

CWD=$(parse cwd)
[ -z "$CWD" ] && exit 0

SANITIZED=$(echo "$CWD" | sed 's|/|-|g')
PENDING="$HOME/.claude/projects/${SANITIZED}/pending-decisions.md"

if [ ! -f "$PENDING" ] || [ ! -s "$PENDING" ]; then
  exit 0
fi

CONTENT=$(cat "$PENDING")

MSG=$(cat <<EOF
ÖNCEKİ OTURUM(LAR)DA TESPİT EDİLMİŞ KARARLAR var. Haiku ile taranan transcript'lerden derlendi, henüz MD dosyalarına yazılmadı.

AKSİYON (kullanıcının mesajına cevap vermeden önce yap):
1. Aşağıdaki özeti kullanıcıya kısaca göster (bullet olarak).
2. Her karar için sor: "Bu kararı kaydedeyim mi? Hangi MD/memory dosyalarını güncelleyeyim?"
3. Onaylananı uygula (MEMORY.md, agent MD, project MD vs.).
4. Tüm kararlar işlendikten SONRA pending dosyasını sil:
   rm '$PENDING'
5. Atlanmış/reddedilmiş kararları dosyadan manuel düş, tamamen işlenmeden dosyayı silme.

Kararlar:

$CONTENT
EOF
)

python3 - "$MSG" <<'PY'
import json, sys
print(json.dumps({
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": sys.argv[1]
  }
}))
PY
```

### Adım 4: Script'leri çalıştırılabilir yap

```bash
chmod +x scripts/claude-hooks/capture-decisions.sh
chmod +x scripts/claude-hooks/inject-pending-decisions.sh
```

### Adım 5: .claude/settings.json dosyasını güncelle

**KRİTİK:** Bu dosyayı ASLA tamamen değiştirme. Önce oku, sonra mevcut hook'ları koruyarak ekle.

1. `.claude/` dizini yoksa: `mkdir -p .claude`
2. `.claude/settings.json` dosyasını oku. Yoksa, boş bir `{}` varsay.
3. Mevcut `hooks.SessionStart` ve `hooks.SessionEnd` array'leri varsa, onları bozmadan yanlarına aşağıdaki hook'ları ekle. Yoksa array'leri oluştur.

Eklenecek SessionStart hook entry'si:

```json
{
  "type": "command",
  "command": "bash \"$CLAUDE_PROJECT_DIR/scripts/claude-hooks/inject-pending-decisions.sh\"",
  "timeout": 10
}
```

Eklenecek SessionEnd hook entry'si:

```json
{
  "type": "command",
  "command": "bash \"$CLAUDE_PROJECT_DIR/scripts/claude-hooks/capture-decisions.sh\"",
  "timeout": 120,
  "async": true
}
```

Birleştirilmiş sonuç örneği (başka hook yoksa):

```json
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash \"$CLAUDE_PROJECT_DIR/scripts/claude-hooks/inject-pending-decisions.sh\"",
            "timeout": 10
          }
        ]
      }
    ],
    "SessionEnd": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash \"$CLAUDE_PROJECT_DIR/scripts/claude-hooks/capture-decisions.sh\"",
            "timeout": 120,
            "async": true
          }
        ]
      }
    ]
  }
}
```

### Adım 6: Doğrulama

Aşağıdakileri çalıştır ve sonuçlarını kullanıcıya göster:

```bash
# 1. Script'ler var mı ve çalıştırılabilir mi
ls -la scripts/claude-hooks/

# 2. Settings JSON geçerli mi
python3 -m json.tool .claude/settings.json > /dev/null && echo "settings.json valid"

# 3. Yeni hook'lar settings'e eklendi mi
python3 -c "
import json
with open('.claude/settings.json') as f:
    d = json.load(f)
hooks = d.get('hooks', {})
se = any('capture-decisions' in str(h) for h in hooks.get('SessionEnd', []))
ss = any('inject-pending' in str(h) for h in hooks.get('SessionStart', []))
print('SessionEnd capture hook:', 'OK' if se else 'MISSING')
print('SessionStart inject hook:', 'OK' if ss else 'MISSING')
"
```

### Adım 7: Rapor

Kurulum bittiğinde kullanıcıya şu raporu ver:

```
Kurulum tamamlandı.

Sonraki adımlar:
1. Claude Code'u yeniden başlat (yeni hook'lar ancak restart sonrası yüklenir).
2. Restart sonrası `/hooks` komutunu çalıştır, listede iki yeni hook'u gör.
3. Test: yeni bir oturum aç, bilerek bir karar ver ("X'i erteleyelim" gibi), pencereyi kapat.
4. Log: `tail -30 /tmp/claude-decision-capture.log` - karar yakalandıysa "appended to ..." satırı olmalı.
5. Yeni oturum aç. Claude sana geçen oturumdaki kararı geri getirip kaydetmek isteyip istemediğini sormalı.

Maliyet: oturum başına ~0.02 USD (Haiku). Günde 10 oturum ≈ ayda 5 USD.
Debug: /tmp/claude-decision-capture.log
```

### Hata durumları

- **python3 yok:** "python3 kurulu değil, macOS/Linux default gelir, Windows'ta manuel kurman gerek" de ve dur.
- **claude CLI yok:** "Claude Code CLI kurulu değil" de ve dur. Kurulum linki: https://docs.claude.com/en/docs/claude-code/overview
- **Mevcut settings.json parse edilemiyor:** Kullanıcıya göster ve "Settings dosyan bozuk, önce onu düzeltmen gerek, devam edeyim mi?" diye sor.
- **`$CLAUDE_PROJECT_DIR` çalışmıyor:** Claude Code eski versiyon olabilir. Bu env var'ı hook içinde otomatik sağlar. Sorun olursa path'leri kullanıcının absolute project path'i ile değiştir.

---

## Kurulum sonrası

Bu paket sadece karar yakalama için default'tur. Aynı mantıkla başka şeyler de yakalayabilirsin: bug fix'ler, haftalık özetler, müşteri toplantı kararları. `capture-decisions.sh` içindeki Haiku prompt'unu değiştirerek kendi ihtiyacına uyarla.

Sorun/öneri olursa İş Güç Yapay Zeka topluluğunda paylaş.
