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:
| Kelompok | Event |
|---|---|
| Sesi | SessionStart, SessionEnd, Setup |
| Prompt | UserPromptSubmit, UserPromptExpansion |
| Alat | PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch |
| Izin | PermissionRequest, PermissionDenied |
| Giliran | Stop, StopFailure |
| Subagent dan tugas | SubagentStart, SubagentStop, TaskCreated, TaskCompleted, TeammateIdle |
| Konteks | PreCompact, PostCompact, InstructionsLoaded |
| Lingkungan | FileChanged, CwdChanged, ConfigChange |
| Worktree | WorktreeCreate, WorktreeRemove |
| Antarmuka | Notification, MessageDisplay |
| Elicitation MCP | Elicitation, ElicitationResult |

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, danSessionStart, 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:
- 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.
- 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.

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.
| Matcher | Dievaluasi sebagai |
|---|---|
"*", "", atau tidak diisi | cocok dengan semuanya |
Hanya huruf, angka, _, -, spasi, ,, | | string eksak, atau daftar string eksak yang dipisah oleh | atau , |
| Selain itu | ekspresi 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-reviewerdiperlakukan sebagai regex tanpa anchor, sehingga ikut terpicu untuksenior-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.
| Lokasi | Cakupan |
|---|---|
~/.claude/settings.json | semua proyek Anda, lokal di mesin Anda |
.claude/settings.json | satu proyek, bisa di-commit |
.claude/settings.local.json | satu proyek, di-gitignore oleh Claude Code |
| Managed policy settings | seluruh organisasi, dikendalikan admin |
hooks/hooks.json milik plugin | selama plugin aktif |
| Frontmatter skill atau agent | selama 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
disableAllHookstidak 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.

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 hook | Nilai timeout default |
|---|---|
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 | 1,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,UserPromptExpansiondanSessionStart. Di semua tempat lain, pakai exit 2 dengan stderr, atauadditionalContextdalam 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
How to Scale AI Coding Agents Across a Dev Team
One developer with a coding agent is a productivity story. Five developers with twenty agents is a coordination problem. Here is what breaks first when a team scales up, and the setup that holds: committed context files, clear file ownership, review by blast radius, and cost you can actually see.
Baca artikelAgentsRoom kini mendukung Kimi Code
Kimi Code, agen coding berbasis terminal dari Moonshot AI, kini menjadi provider penuh di AgentsRoom. Jalankan berdampingan dengan Claude, Codex, Antigravity CLI, OpenCode, Aider, Grok Build, dan Mistral Vibe, lalu berpindah di tengah percakapan.
Baca artikelApakah Anda Masih Harus Meninjau Kode AI Anda?
Agen Anda menulis kode yang lebih baik daripada setengah permintaan tarik yang biasa Anda gabungkan. Jadi, apakah Anda masih membaca setiap baris? Kasus jujur untuk kedua sisi, 10 sinyal yang memberi tahu Anda bahwa agen melakukan kesalahan, dan seberapa banyak tinjauan yang sebenarnya layak untuk setiap perubahan.
Baca artikel
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.
Aplikasi pendamping: pantau agen Anda saat bepergian
Gunakan Claude, Codex, Antigravity CLI, atau penyedia AI lainnya.
Kirim bug dan permintaan langsung ke backlog publik Anda.
Sekilas AgentsRoom dalam aksi.