Bir Claude Code Oturumunda 30 Hook Olayı Tetiklenir. Sadece 3'ü Cevap Verebilir.
Claude Code hook olaylarının eksiksiz listesi, her birinin ne zaman tetiklendiği, hangi 15'inin engelleyebildiği ve çoğu hook çıktısını sessizce yutan stdout kuralı. Binlerce ajan oturumunda hook'ları üretimde çalıştırarak oluşturulmuş bir saha referansı.
İnsanlar Claude Code'a hook bağlarken iki arıza tekrar tekrar ortaya çıkıyor ve bu ikisi birbirine hiç benzemiyor.
Birincisi: bir hook ekliyorsunuz, hiçbir şey olmuyor. Hata yok, uyarı yok, günlük satırı yok. Hook basitçe hiç çalışmıyor.
İkincisi: hook belli ki çalışıyor, yan etkilerini diskte görebiliyorsunuz, ama ajan için yazdırdığı mesaj asla ulaşmıyor. Ajan, hook hiçbir şey söylememiş gibi davranıyor.
İkisi de aynı yerden geliyor. Hook sistemi, çoğu yazının ele aldığı bir avuç olaydan daha geniş ve daha az tekdüze, ve ajanla kimin konuşabileceğini belirleyen kurallar tahmin edeceğiniz kurallar değil. Bu, keşke elimizde olsaydı dediğimiz referans. AgentsRoom'u bu hook'ların üzerine inşa ediyoruz ve aşağıdaki her şey ya resmî referanstan alıntı ya da üretimde ölçülmüş.
30 olay var, altı değil
Çoğu rehber PreToolUse, PostToolUse, UserPromptSubmit, Stop, Notification ve SubagentStop olaylarını ele alıyor. Bu altısı gerçek ve faydalı işin çoğunu taşıyorlar. Aynı zamanda var olanların yalnızca beşte biriler.
Tam liste, gözlemledikleri şeye göre gruplanmış hâliyle:
| Grup | Olaylar |
|---|---|
| Oturum | SessionStart, SessionEnd, Setup |
| Prompt | UserPromptSubmit, UserPromptExpansion |
| Araçlar | PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch |
| İzinler | PermissionRequest, PermissionDenied |
| Tur | Stop, StopFailure |
| Alt ajanlar ve görevler | SubagentStart, SubagentStop, TaskCreated, TaskCompleted, TeammateIdle |
| Bağlam | PreCompact, PostCompact, InstructionsLoaded |
| Ortam | FileChanged, CwdChanged, ConfigChange |
| Worktree'ler | WorktreeCreate, WorktreeRemove |
| Arayüz | Notification, MessageDisplay |
| MCP elicitation | Elicitation, ElicitationResult |

Tek bir oturumda olayların tetiklenme sırası. Araç bloğu her araç çağrısında bir kez, prompt bloğunun tamamı ise her turda bir kez tekrarlanır.
Bunlardan birkaçı sistemi düşünme biçiminizi değiştirir. PostToolUseFailure var, yani "araç çalıştı mı" dalı bir olaydır, bir payload'dan çıkarsadığınız bir şey değil. PostToolBatch, paralel araç çağrılarından oluşan bir grup tamamlandıktan sonra bir kez tetiklenir; linter'ı her düzenlemede bir kez değil de tek seferde çalıştırmanın doğru yeri burasıdır. InstructionsLoaded, CLAUDE.md okunduğunda tetiklenir ve ajanın gerçekten sizin sandığınız kuralları yüklediğini kontrol etmek için bir hook noktası verir.
Çoğu hook çıktısını yutan stdout kuralı
Bu sayfadaki en faydalı tek şey bu.
Çıkış kodu 0'da Claude Code, stdout'u JSON çıktı alanları için ayrıştırır. Ama o stdout'un ajana gösterilip gösterilmeyeceği olaya bağlıdır ve istisnalar kısa bir listedir. Referanstan:
Çoğu olayda stdout hata ayıklama günlüğüne yazılır ama dökümde gösterilmez. İstisnalar
UserPromptSubmit,UserPromptExpansionveSessionStart'tır; bu olaylarda stdout, Claude'un görebileceği ve üzerine hareket edebileceği bağlam olarak eklenir.
Otuz olaydan üçü. Bir PostToolUse hook'undan echo "warning: this migration is destructive" yapıp ajanın bunu okumasını beklerseniz, asla okumayacak. Metniniz hata ayıklama günlüğüne gitti.
Başka herhangi bir olaydan ajanın önüne metin koymanın tam olarak iki yolu var:
- 2 ile çıkın ve stderr'e yazın. Çıkış kodu 2'de Claude Code, stdout'u ve içindeki her türlü JSON'u yok sayar, stderr'i bir hata mesajı olarak ajana geri besler.
- 0 ile çıkın ve bir JSON nesnesi yazdırın: içinde
hookSpecificOutput.additionalContexttaşısın.
İlkindeki asimetriye dikkat edin. Çıkış 0, stdout'un önemli olduğu ve stderr'in olmadığı anlamına gelir. Çıkış 2, stderr'in önemli olduğu ve stdout'un tamamen atıldığı anlamına gelir. Bunu ters anlamak, bir hook'un tamamen doğru görünüp yine de dilsiz kalmasının sebebidir.
Başka herhangi bir çıkış kodu, engellemeyen bir hatadır. Döküm, stderr'in ilk satırıyla birlikte bir <hook name> hook error uyarısı gösterir, yürütme devam eder ve stderr'in tamamı hata ayıklama günlüğüne düşer.

Çıkış koduna göre hangi kanalın ajana ulaştığı. Kesik çizgili yol, herkesin var sandığı ama var olmayan yoldur.
Tam olarak yarısı engelleyebilir
On beş olay, çıkış 2'de eylemi durdurur. On beşi bunu yok sayıp devam eder.
Engelleyebilir: PreToolUse, PermissionRequest, UserPromptSubmit, UserPromptExpansion, Stop, SubagentStop, TeammateIdle, TaskCreated, TaskCompleted, ConfigChange, PostToolBatch, PreCompact, Elicitation, ElicitationResult, WorktreeCreate.
Engelleyemez: PostToolUse, PostToolUseFailure, PermissionDenied, StopFailure, Notification, SubagentStart, SessionStart, Setup, SessionEnd, CwdChanged, FileChanged, PostCompact, WorktreeRemove, InstructionsLoaded, MessageDisplay.
Pratik sonuç: bir koruma bariyerinin yeri PreToolUse'dur, asla PostToolUse değil. PostToolUse, araç başarılı olduktan sonra tetiklenir. Orada 2 ile çıkmak yazma işlemini geri almaz, hasar diskte dururken sadece bir hata yazdırır. Bir rm -rf komutunu durdurmak istiyorsanız, bunu yapabileceğiniz tam olarak tek bir yer var.
PostToolUse engellemezken PostToolBatch'in engelleyebilmesi ikinci bir bakışı hak ediyor. Bu, grup seviyesindeki bir kontrolün paralel düzenlemeler diske indikten sonra bile turu durdurabileceği anlamına gelir; sistemin sunduğu, yazma sonrası vetoya en yakın şey budur.
Matcher'lar tam eşleşmedir, ta ki birdenbire olmayana kadar
matcher alanı, kendi karakterlerine göre değerlendirme stratejisini değiştirir ve hangi yolu seçtiğini size hiçbir şey söylemez.
| Matcher | Şu şekilde değerlendirilir |
|---|---|
"*", "", ya da hiç yok | her şeyle eşleşir |
Yalnızca harfler, rakamlar, _, -, boşluklar, ,, | | tam dize, ya da | veya , ile bölünen tam dizeler listesi |
| Başka herhangi bir şey | sabitlenmemiş JavaScript düzenli ifadesi |
Tuzak, sabitlenmemiş olmasında. Referans, düzenli ifadenin RegExp.prototype.test ile test edildiğini açıkça söylüyor; bu da değerin herhangi bir yerindeki eşleşmede başarılı olur. Yani Edit.*, hem Edit hem de NotebookEdit ile eşleşir. Tek bir aracı kastettiyseniz ^Edit$ yazın.
Yanlış şeyin hatasını ayıklamadan önce bilinmesi gereken, sürüme bağlı iki davranış:
- Virgül ayırıcılar ve boşluk toleransı Claude Code v2.1.191 veya daha yenisini gerektirir.
- Tireler, tam eşleşme karakter kümesine v2.1.195'te katıldı. Ondan önce
code-reviewergibi bir matcher sabitlenmemiş bir regex olarak ele alınıyordu, dolayısıylasenior-code-revieweriçin de tetikleniyordu.
AgentsRoom'da kendi dosya atıfı hook'umuzu Write|Edit|MultiEdit|NotebookEdit ile sınırlıyoruz; bu, tam dize yolunda kalır ve yalnızca o dört araçla eşleşir, başka hiçbir şeyle değil. Kurduğumuz yaşam döngüsü hook'larının ise hiç matcher'ı yok, çünkü onlar bizi her zaman ilgilendiriyor.
Altı yer hook tanımlayabilir ve hepsi birleşir
İlk refleks bir öncelik sırası aramaktır. Böyle bir sıra yok ve asıl ilginç kısım da bu.
| Konum | Kapsam |
|---|---|
~/.claude/settings.json | tüm projeleriniz, makinenize özel |
.claude/settings.json | tek proje, commit edilebilir |
.claude/settings.local.json | tek proje, Claude Code tarafından gitignore'a alınır |
| Managed policy settings | kuruluş genelinde, yönetici kontrolünde |
Eklenti hooks/hooks.json | eklenti etkin olduğu sürece |
| Skill ya da ajan frontmatter'ı | bileşen aktif olduğu sürece |
Referanstan:
Hook girdileri birbirinin yerine geçmek yerine ayar seviyeleri arasında birleşir: kullanıcı, proje ve yerel ayarlar, yönetilen hook'ları kaldırmadan kendi hook'larını ekler ve
disableAllHooksayarı, yönetilen ayarların dışından yönetilen hook'ları devre dışı bırakamaz.
Yani bir proje hook'u asla genel bir hook'un yerine geçmez, onun üstüne eklenir. Altı kaynak, hepsi toplamalı. Kullanıcı ayarlarınızda ve bir de projede tanımlanmış bir PostToolUse biçimlendiricisi her düzenlemede iki kez çalışır ve tek belirti, işlerin yavaş hissettirmesidir.

Altı kaynak, tek bir birleşik küme. Burada hiçbir şey hiçbir şeyin yerine geçmez.
Bu aynı zamanda, bir aracın birinin projesine hook kurması için neden .claude/settings.local.json dosyasının doğru yer olduğunu açıklıyor. Proje kapsamındadır, Claude Code onu gitignore'a alır ve hiçbir CLI bayrağı olmadan yüklenir. AgentsRoom girdilerini oraya yazar; böylece kullanıcının commit ettiği .claude/settings.json dosyasına hiç dokunulmaz ve iş arkadaşları asla makineye özgü bir yol devralmaz.
Hook'ları üretimde çalıştırmak bize ne öğretti
AgentsRoom, ajan durumunu deterministik biçimde izlemek ve düzenlenen dosyaları doğru ajana atfetmek için açtığı her projeye hook kurar. Bazı şeyler ancak o ölçekte ortaya çıkıyor.
Bilinmeyen olay adları sessizce yok sayılır. Bu belgelerde yok ve biz buna güveniyoruz. Yükleyicimize yeni bir yaşam döngüsü olayı eklediğimizde, eski bir CLI kullanan kullanıcılar, ikili dosyalarının hiç duymadığı bir olay adını içeren bir settings.local.json alıyor. Hiçbir şey kırılmıyor, hiçbir uyarı çıkmıyor, girdi atlanıyor. Yükleyiciyi bir CLI sürümünden önce yayınlamayı güvenli kılan şey bu. Aynı zamanda, kaçınılmaz olarak, bir yazım hatasının hata yerine tam bir sessizlik üretmesinin sebebi de bu.
Bir alt ajanın içinde olduğunuzu agent_id sayesinde anlarsınız. Bu alan yalnızca hook bir alt ajan çağrısının içinde tetiklendiğinde bulunur. Bu, kulağa geldiğinden daha önemli: Stop, yalnızca ana ajan bittiğinde değil, bir alt ajan turunu bitirdiğinde de tetiklenir. Naif bir "Stop'ta oturumu tamamlandı olarak işaretle" kuralı, herhangi bir alt ajan ilk kez döndüğünde oturumun tamamını bitmiş sayar. Tur olaylarından agent_id taşıyanları tam olarak bu yüzden atlıyoruz.
Mevcut tur için transcript_path dosyasını okumayın. Referans, dökümün asenkron olarak yazıldığı ve bellekteki konuşmanın gerisinde kalabileceği konusunda uyarıyor; yani hook'unuz tetiklendiğinde en son mesajlar henüz orada olmayabilir. Stop ve SubagentStop, dosyayla yarışmak zorunda kalmayasınız diye last_assistant_message alanını alır.
Hook'lar tek güvenilir durum sinyalidir. Hook'lardan önce, bir ajanın düşündüğünü mü, beklediğini mi yoksa bitirdiğini mi anlamak için PTY'yi kazıyorduk. CLI, terminalin alternatif ekran tamponu üzerinden çizmeye başladığı anda bu bozuluyor; /tui fullscreen tam olarak bunu yapıyor. Hook'lar her çizim motorunda aynı şekilde tetikleniyor. Bir ajanı dışarıdan gözlemleyen bir şey inşa ediyorsanız, üzerine inşa edilecek katman budur ve ekran kazıma en iyi ihtimalle yedek çözüm olarak kalır.
async: true hiçbir şeye mal olmaz. Bir hook komutu async: true bildirebilir ve ajan onu beklemez. Bizim hook'umuz yerel bir uç noktaya 2 saniyelik bir üst sınırla POST atıp geri döner; alıcı uygulama kapalıyken bile ajanın tur gecikmesi etkilenmez. Hook'unuz yalnızca gözlemliyor ve hiçbir karar vermiyorsa, onu async yapın ve bedelini ödemeyi bırakın.
Bir hook'un terminale çöp yazmasına asla izin vermeyin. Betiğimiz, en üst seviye dahil olmak üzere her istisnayı yutar. Bir hook'tan gelen yakalanmamış bir traceback sadece sessizce başarısız olmaz, kullanıcının terminal oturumuna, işinin tam ortasına bir Python yığın izi yazdırır.
Zaman aşımları
Varsayılanlar cömert, cömert olmayan üç istisna dışında:
| Hook türü | Varsayılan zaman aşımı |
|---|---|
command, http, mcp_tool | 600 s |
prompt | 30 s |
agent | 60 s |
UserPromptSubmit (command, http, mcp_tool) | 30 s |
MessageDisplay (command, http, mcp_tool) | 10 s |
SessionEnd | tüm hook'lar arasında paylaşılan 1,5 s, daha uzun bir hook başına timeout değerine uyacak şekilde 60 s'ye kadar yükseltilir |
İnsanları şaşırtan, SessionEnd bütçesidir. Bu, hook başına bir tahsis değil, paylaşılan bir bütçedir; yani açıkça yükseltmediğiniz sürece üç temizlik hook'u 1,5 saniyeyi aralarında paylaşır.
Kısa versiyon
- 30 olay var. Altısı meşhur.
- stdout ajana yalnızca
UserPromptSubmit,UserPromptExpansionveSessionStartolaylarında ulaşır. Diğer her yerde stderr ile birlikte çıkış 2 kullanın ya da JSON içindeadditionalContextkullanın. - 15 olay çıkış 2'de engeller, 15'i bunu yok sayar. Koruma bariyerleri
PreToolUse'a konur. - Matcher'lar, özel bir karakter onları sabitlenmemiş bir regex'e dönüştürene kadar tam dizedir.
- Altı ayar kaynağı toplamalı biçimde birleşir. Hiçbir şey hiçbir şeyin yerine geçmez.
- Yanlış yazılmış bir olay adı tamamen sessizce başarısız olur.
Bu olaylar hakkında akıl yürütmek yerine tetiklenmelerini izlemek istiyorsanız, biz tam olarak bunu inşa ettik: AgentsRoom, her hook tetiklenmesini ajan başına, proje başına, çalıştırma başına gösterir; onlarca paralel ajan ve alt ajan oturumları genelinde. Kendi ayarlarınızda yapılandırdığınız hook'lar tam yazıldığı gibi çalışmaya devam eder, çünkü AgentsRoom gerçek CLI'yi çalıştırır.
Okumaya devam et
Bir Geliştirici Ekibi Üzerinde AI Kodlama Ajanlarını Nasıl Ölçeklendirirsiniz
Bir kodlama ajanına sahip bir geliştirici, bir verimlilik hikayesidir. Yirmi ajanla beş geliştirici, bir koordinasyon problemidir. Bir ekip büyüdüğünde ilk olarak neyin kırıldığını ve tutan ayarları burada bulabilirsiniz: taahhüt edilmiş bağlam dosyaları, net dosya sahipliği, patlama yarıçapına göre inceleme ve gerçekten görebileceğiniz maliyet.
Makaleyi oku2026'da Claude AI Ajanlarınız için En İyi Bellek Çözümleri
CLAUDE.md, mem0, Letta, Zep, basic-memory, Obsidian artı MCP, AgentsRoom Proje Belleği: AI kodlama ajanları için bellek seçeneklerinin dürüst bir haritası ve birini nasıl seçeceğiniz.
Makaleyi okuYapay Zeka Ajanınızın Kodunu Hala Gözden Geçirmeli Misiniz?
Ajanlarınız, bir zamanlar birleştirdiğiniz pull request'lerin yarısından daha iyi kod yazıyor. Peki, hala her satırı okur musunuz? Her iki taraf için dürüst bir durum, bir ajanın hata yaptığını gösteren 10 sinyal ve her değişikliğin gerçekten ne kadar gözden geçirilmesi gerektiği.
Makaleyi oku
AgentsRoom'u Indirin
Yapay zeka ajanlarınızı (Claude, Codex, Antigravity CLI, OpenCode, Aider, Grok Build, Mistral Vibe, Kimi Code) tüm projelerinizde tek bir pencereden çalıştırın.
Yardımcı uygulama: hareket halindeyken ajanlarinizi izleyin
Claude, Codex, Antigravity CLI veya başka bir AI sağlayıcı kullan.
Hataları ve istekleri doğrudan genel backlogunuza gönderin.
AgentsRoom'a kısa bir bakış.