30 Event Hook Terpicu dalam Satu Sesi Claude Code. Hanya 3 yang Bisa Menjawab.

Daftar lengkap event hook Claude Code, kapan masing-masing terpicu, 15 mana yang bisa memblokir, dan aturan stdout yang diam-diam menelan sebagian besar output hook. Referensi lapangan yang dibangun dari menjalankan hook di produksi pada ribuan sesi agen.

Dua kegagalan muncul berulang kali ketika orang memasang hook ke Claude Code, dan keduanya sama sekali tidak mirip.

Yang pertama: Anda menambahkan hook, tidak terjadi apa-apa. Tidak ada error, tidak ada peringatan, tidak ada baris log. Hook itu memang tidak pernah berjalan.

Yang kedua: hook jelas berjalan, efek sampingnya terlihat di disk, tetapi pesan yang dicetaknya untuk agen tidak pernah sampai. Agen berperilaku seolah-olah hook tidak mengatakan apa pun.

Keduanya berasal dari tempat yang sama. Sistem hook lebih besar dan kurang seragam dibanding segelintir event yang dibahas kebanyakan tulisan, dan aturan tentang siapa yang boleh berbicara ke agen bukan aturan yang akan Anda tebak. Ini adalah referensi yang dulu kami harapkan sudah ada. Kami membangun AgentsRoom di atas hook ini, dan semua yang ada di bawah dikutip dari referensi resmi atau diukur di produksi.

Ada 30 event, bukan enam

Kebanyakan panduan membahas PreToolUse, PostToolUse, UserPromptSubmit, Stop, Notification dan SubagentStop. Keenam event itu nyata, dan memikul sebagian besar pekerjaan yang berguna. Keenamnya juga hanya seperlima dari yang ada.

Daftar lengkapnya, dikelompokkan menurut apa yang diamati:

KelompokEvent
SesiSessionStart, SessionEnd, Setup
PromptUserPromptSubmit, UserPromptExpansion
AlatPreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch
IzinPermissionRequest, PermissionDenied
GiliranStop, StopFailure
Subagent dan tugasSubagentStart, SubagentStop, TaskCreated, TaskCompleted, TeammateIdle
KonteksPreCompact, PostCompact, InstructionsLoaded
LingkunganFileChanged, CwdChanged, ConfigChange
WorktreeWorktreeCreate, WorktreeRemove
AntarmukaNotification, MessageDisplay
Elicitation MCPElicitation, ElicitationResult

Diagram lini masa 30 event hook Claude Code dalam urutan terpicunya selama satu sesi agen, dari SessionStart melalui UserPromptSubmit, PreToolUse, PostToolUse, Stop hingga SessionEnd, memperlihatkan event mana saja yang bisa memblokir agen.

Urutan terpicunya event dalam satu sesi. Blok alat berulang sekali per pemanggilan alat, dan seluruh blok prompt berulang sekali per giliran.

Beberapa di antaranya mengubah cara Anda memandang sistem ini. PostToolUseFailure memang ada, jadi cabang "apakah alatnya berhasil" adalah sebuah event, bukan sesuatu yang Anda simpulkan dari payload. PostToolBatch terpicu sekali setelah satu batch pemanggilan alat paralel selesai, dan itu tempat yang tepat untuk menjalankan linter sekali saja alih-alih sekali per pengeditan. InstructionsLoaded terpicu ketika CLAUDE.md dibaca, yang memberi Anda titik hook untuk memeriksa bahwa agen benar-benar memuat aturan yang Anda kira sudah dimuat.

Aturan stdout yang menelan sebagian besar output hook

Ini hal paling berguna di halaman ini.

Pada exit code 0, Claude Code mem-parsing stdout untuk mencari field output JSON. Tetapi apakah stdout itu pernah ditampilkan ke agen bergantung pada eventnya, dan daftar pengecualiannya pendek. Dari referensi resmi:

Untuk sebagian besar event, stdout ditulis ke log debug tetapi tidak ditampilkan di transkrip. Pengecualiannya adalah UserPromptSubmit, UserPromptExpansion, dan SessionStart, di mana stdout ditambahkan sebagai konteks yang bisa dilihat dan ditindaklanjuti Claude.

Tiga event dari tiga puluh. Kalau Anda menjalankan echo "warning: this migration is destructive" dari hook PostToolUse dan berharap agen membacanya, agen tidak akan pernah membacanya. Teks Anda pergi ke log debug.

Ada tepat dua cara untuk menaruh teks di depan agen dari event lain mana pun:

  1. Exit 2 dan tulis ke stderr. Pada exit 2, Claude Code mengabaikan stdout dan JSON apa pun di dalamnya, lalu mengumpankan stderr kembali ke agen sebagai pesan error.
  2. Exit 0 dan cetak objek JSON yang membawa hookSpecificOutput.additionalContext.

Perhatikan asimetri pada cara pertama. Exit 0 berarti stdout yang penting dan stderr tidak. Exit 2 berarti stderr yang penting dan stdout dibuang sepenuhnya. Membalik dua hal ini adalah alasan sebuah hook bisa terlihat benar sepenuhnya dan tetap bisu.

Exit code lain apa pun adalah error non-blocking. Transkrip menampilkan pemberitahuan <hook name> hook error berisi baris pertama stderr, eksekusi berlanjut, dan seluruh stderr mendarat di log debug.

Diagram exit code hook Claude Code: exit 0 mengirim JSON stdout ke agen hanya pada tiga event, exit 2 memblokir aksi dan mengirim stderr ke agen, exit code lain apa pun adalah error non-blocking yang ditulis ke log debug.

Kanal mana yang sampai ke agen, per exit code. Jalur putus-putus adalah jalur yang orang kira ada, padahal tidak.

Tepat separuhnya bisa memblokir

Lima belas event menghentikan aksi pada exit 2. Lima belas mengabaikannya dan terus jalan.

Bisa memblokir: PreToolUse, PermissionRequest, UserPromptSubmit, UserPromptExpansion, Stop, SubagentStop, TeammateIdle, TaskCreated, TaskCompleted, ConfigChange, PostToolBatch, PreCompact, Elicitation, ElicitationResult, WorktreeCreate.

Tidak bisa memblokir: PostToolUse, PostToolUseFailure, PermissionDenied, StopFailure, Notification, SubagentStart, SessionStart, Setup, SessionEnd, CwdChanged, FileChanged, PostCompact, WorktreeRemove, InstructionsLoaded, MessageDisplay.

Konsekuensi praktisnya: pagar pengaman ditempatkan di PreToolUse, tidak pernah di PostToolUse. PostToolUse terpicu setelah alatnya berhasil. Exit 2 di sana tidak membatalkan penulisan, ia hanya mencetak error sementara kerusakannya sudah ada di disk. Kalau Anda ingin menghentikan rm -rf, Anda punya tepat satu tempat untuk melakukannya.

PostToolBatch yang bisa memblokir sementara PostToolUse tidak, itu layak dilihat dua kali. Artinya, pemeriksaan di tingkat batch masih bisa menghentikan giliran setelah pengeditan paralel mendarat, dan itulah yang paling mendekati hak veto pasca-penulisan yang ditawarkan sistem ini.

Matcher itu eksak, sampai tiba-tiba tidak

Field matcher berganti strategi evaluasi berdasarkan karakter yang ada di dalamnya sendiri, dan tidak ada yang memberi tahu Anda jalur mana yang diambil.

MatcherDievaluasi sebagai
"*", "", atau tidak diisicocok dengan semuanya
Hanya huruf, angka, _, -, spasi, ,, |string eksak, atau daftar string eksak yang dipisah oleh | atau ,
Selain ituekspresi reguler JavaScript tanpa anchor

Tanpa anchor itulah jebakannya. Referensi menyatakan secara eksplisit bahwa regexnya diuji dengan RegExp.prototype.test, yang berhasil bila ada kecocokan di mana pun dalam nilai tersebut. Jadi Edit.* cocok dengan Edit dan NotebookEdit. Kalau maksud Anda satu alat saja, tulis ^Edit$.

Dua perilaku yang bergantung pada versi, layak diketahui sebelum Anda mendebug hal yang salah:

  • Pemisah koma dan toleransi spasi butuh Claude Code v2.1.191 atau lebih baru.
  • Tanda hubung baru bergabung ke himpunan karakter pencocokan eksak di v2.1.195. Sebelum itu, matcher seperti code-reviewer diperlakukan sebagai regex tanpa anchor, sehingga ikut terpicu untuk senior-code-reviewer.

Di AgentsRoom kami membatasi hook atribusi file kami sendiri dengan Write|Edit|MultiEdit|NotebookEdit, yang tetap berada di jalur string eksak dan cocok dengan empat alat itu saja, tidak lebih. Hook siklus hidup yang kami pasang sama sekali tidak punya matcher, karena selalu menyangkut kami.

Enam tempat bisa mendefinisikan hook, dan semuanya digabung

Naluri pertama adalah mencari urutan prioritas. Urutan itu tidak ada, dan justru di situlah letak menariknya.

LokasiCakupan
~/.claude/settings.jsonsemua proyek Anda, lokal di mesin Anda
.claude/settings.jsonsatu proyek, bisa di-commit
.claude/settings.local.jsonsatu proyek, di-gitignore oleh Claude Code
Managed policy settingsseluruh organisasi, dikendalikan admin
hooks/hooks.json milik pluginselama plugin aktif
Frontmatter skill atau agentselama komponennya aktif

Dari referensi:

Entri hook digabung lintas level settings alih-alih saling menggantikan: settings user, project, dan local menambahkan hook mereka sendiri tanpa menghapus hook managed, dan setelan disableAllHooks tidak bisa menonaktifkan hook managed dari luar managed settings.

Jadi hook proyek tidak pernah menimpa hook global, ia menumpuk di atasnya. Enam sumber, semuanya aditif. Sebuah formatter PostToolUse yang didefinisikan di settings user Anda lalu didefinisikan lagi di proyek akan berjalan dua kali per pengeditan, dan satu-satunya gejalanya adalah semuanya terasa lambat.

Diagram yang menunjukkan enam lokasi settings Claude Code yang bisa mendefinisikan hook, semuanya digabung secara aditif menjadi satu himpunan hook alih-alih saling menimpa.

Enam sumber, satu himpunan gabungan. Tidak ada yang menimpa apa pun di sini.

Ini juga menjelaskan kenapa .claude/settings.local.json adalah tempat yang tepat bagi sebuah tool untuk memasang hook ke dalam proyek orang lain. File itu tercakup per proyek, di-gitignore oleh Claude Code, dan dimuat tanpa flag CLI apa pun. Di situlah AgentsRoom menulis entri-entrinya, sehingga .claude/settings.json yang di-commit pengguna tidak pernah tersentuh dan rekan-rekan kerjanya tidak pernah mewarisi path spesifik mesin.

Yang kami pelajari dari menjalankan hook di produksi

AgentsRoom memasang hook ke setiap proyek yang dibukanya, untuk melacak status agen secara deterministik dan mengatribusikan file yang diedit ke agen yang benar. Beberapa hal hanya muncul pada skala itu.

Nama event yang tidak dikenal diabaikan tanpa suara. Ini tidak ada di dokumentasi, dan kami bergantung padanya. Ketika kami menambahkan event siklus hidup baru ke installer kami, pengguna dengan CLI versi lama mendapat settings.local.json berisi nama event yang belum pernah didengar binernya. Tidak ada yang rusak, tidak ada peringatan, entri itu dilewati. Itulah yang membuat installer aman dirilis mendahului rilis CLI. Itu juga, mau tidak mau, alasan kenapa salah ketik menghasilkan keheningan total alih-alih error.

agent_id adalah cara Anda tahu bahwa Anda sedang berada di dalam subagent. Field ini hanya ada ketika hook terpicu di dalam pemanggilan subagent. Ini lebih penting daripada kedengarannya: Stop terpicu ketika sebuah subagent menyelesaikan gilirannya, bukan hanya agen utama. Aturan naif seperti "tandai sesi selesai pada Stop" akan menandai seluruh sesi selesai begitu subagent mana pun pertama kali kembali. Kami melewati event giliran yang membawa agent_id persis karena alasan ini.

Jangan baca transcript_path untuk giliran yang sedang berjalan. Referensi memperingatkan bahwa transkrip ditulis secara asinkron dan bisa tertinggal dari percakapan di memori, jadi pesan-pesan terbaru mungkin belum ada di sana saat hook Anda terpicu. Stop dan SubagentStop menerima last_assistant_message justru supaya Anda tidak pernah perlu berlomba dengan file itu.

Hook adalah satu-satunya sinyal status yang andal. Sebelum ada hook, kami mengorek PTY untuk menebak apakah sebuah agen sedang berpikir, menunggu, atau sudah selesai. Cara itu rusak begitu CLI merender lewat alternate screen buffer milik terminal, yang persis dilakukan /tui fullscreen. Hook terpicu identik di bawah renderer mana pun. Kalau Anda membangun apa pun yang mengamati agen dari luar, inilah lapisan yang harus dijadikan fondasi, dan pengorekan terminal paling banter tinggal jadi cadangan.

async: true tidak menelan biaya apa pun. Sebuah command hook bisa mendeklarasikan async: true, dan agen tidak menunggunya. Hook kami mengirim POST ke endpoint lokal dengan batas 2 detik lalu selesai; latensi giliran agen tidak terpengaruh bahkan ketika aplikasi penerimanya ditutup. Kalau hook Anda hanya mengamati dan tidak pernah memutuskan, jadikan async dan berhenti membayarnya.

Jangan pernah biarkan hook menulis sampah ke terminal. Skrip kami menelan setiap exception, termasuk di level teratas. Traceback yang tidak tertangani dari sebuah hook bukan cuma gagal diam-diam, ia mencetak stack trace Python ke sesi terminal pengguna di tengah pekerjaan mereka.

Timeout

Nilai defaultnya murah hati, dengan tiga pengecualian yang tidak:

Tipe hookNilai timeout default
command, http, mcp_tool600 s
prompt30 s
agent60 s
UserPromptSubmit (command, http, mcp_tool)30 s
MessageDisplay (command, http, mcp_tool)10 s
SessionEnd1,5 s dibagi bersama oleh semua hook, dinaikkan agar cocok dengan timeout per hook yang lebih panjang, sampai 60 s

Anggaran SessionEnd inilah yang mengejutkan orang. Ini anggaran bersama, bukan jatah per hook, jadi tiga hook pembersihan membagi 1,5 detik di antara mereka kecuali Anda menaikkannya secara eksplisit.

Versi singkatnya

  • 30 event itu ada. Enam di antaranya terkenal.
  • stdout sampai ke agen hanya pada UserPromptSubmit, UserPromptExpansion dan SessionStart. Di semua tempat lain, pakai exit 2 dengan stderr, atau additionalContext dalam JSON.
  • 15 event memblokir pada exit 2, 15 mengabaikannya. Pagar pengaman ditempatkan di PreToolUse.
  • Matcher adalah string eksak sampai sebuah karakter khusus mengubahnya jadi regex tanpa anchor.
  • Enam sumber settings digabung secara aditif. Tidak ada yang menimpa apa pun.
  • Nama event yang salah ketik gagal dalam keheningan total.

Kalau Anda lebih suka melihat event-event ini terpicu daripada menalarnya, itulah yang kami bangun: AgentsRoom menampilkan setiap pemicuan hook per agen, per proyek, per run, di puluhan agen paralel dan sesi subagent. Hook yang Anda konfigurasikan di settings Anda sendiri tetap bekerja persis seperti yang ditulis, karena AgentsRoom menjalankan CLI yang sebenarnya.

Lanjutkan membaca

Unduh AgentsRoom

Jalankan agen AI Anda (Claude, Codex, Antigravity CLI, OpenCode, Aider, Grok Build, Mistral Vibe, Kimi Code) di semua proyek Anda, dari satu jendela.

GratisUnduh AgentsRoom

Aplikasi pendamping: pantau agen Anda saat bepergian

Gunakan Claude, Codex, Antigravity CLI, atau penyedia AI lainnya.

Dapatkan ekstensi
Chrome Web Store

Kirim bug dan permintaan langsung ke backlog publik Anda.

Sekilas AgentsRoom dalam aksi.

Beberapa proyek
Multi-penyedia
Beberapa agen
Status langsung
File diff & commit
Pendamping mobile
Pratinjau langsung
Tim agen
Otomatisasi browser
Dev berbasis backlog
Pustaka prompt
Pustaka skill
Lihat semua fitur