Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Hook

Titik masuk yang dipanggil host agent. Anda tidak pernah mengetik ini; omni init menuliskannya ke konfigurasi host.

titik masukkapan host memanggilnya
omni --pre-hookSebelum sebuah tool berjalan
omni --post-hookSetelah sebuah tool menghasilkan keluaran
omni --hookDispatcher universal, untuk host dengan satu slot hook
omni --session-startSesi dimulai
omni --session-endSesi berakhir
omni --pre-compactSebelum host memadatkan percakapan
omni --mcpJalan sebagai server MCP lewat stdio
cmd | omniMode pipa, tanpa host sama sekali

Satu panggilan, dua hook

Shell menjalankan apa pun yang diserahkan pre-hook dan tidak pernah tahu OMNI ada. Hanya jawabannya yang ditulis ulang, dan itu sebabnya tidak ada apa pun di sini yang bisa mengubah apa yang dilakukan perintah Anda.

Apa yang dilakukan masing-masing

Pre-tool memutuskan apakah sebuah perintah perlu dilewatkan OMNI sama sekali, dan bisa menulis ulangnya menjadi omni exec. Tulis ulang itu membungkus seluruh string perintahnya, termasuk pengalihan keluaran, dan itu sebabnya berkas log di disk dari sebuah perintah yang cocok bisa ternyata versi sulingannya. Patahkan awalannya (env cargo test) ketika Anda butuh log mentahnya.

Post-tool acara utamanya: keluaran mentah datang, pipeline berjalan, dan hasil sulingannya diserahkan kembali untuk disubstitusi host.

Post-tool-failure ada karena perintah yang gagal harus lewat apa adanya, dan para host sangat tidak sepakat soal bagaimana mereka menyatakan sebuah perintah gagal. Claude Code mengirim string biasa, Error: Exit code N. Yang lain membawa penanda galat terstruktur. Membaca satu bentuk saja adalah bug yang pernah dimiliki proyek ini.

Session start menyuntikkan konteks proyek: berkas yang sedang panas, galat aktif terakhir, pengetahuan yang tersimpan, tujuan yang dipancang.

Session end menulis ringkasannya dan bisa mengekspor CSV.

Pre-compact adalah peringatan dari host bahwa percakapannya sebentar lagi dipendekkan.

Dua pintu menuju satu pipeline

post_tool dan pipe adalah titik masuk terpisah yang menjalankan tahapan yang sama, dan menjaga keduanya seiring sudah berulang kali jadi sumber bug. Tiga perbaikan terpisah masing-masing membetulkan satu salinan dan meninggalkan yang lain. Tahap ledger sempat ada di post_tool selama satu rilis sebelum pipe memilikinya sama sekali, jadi perintah yang ditulis ulang pre-hook menjadi omni exec mendapat penyaringnya dan tidak lebih.

Kalau Anda mengubah perilaku pipeline, ubah keduanya, atau periksa kenapa tidak.

Kenapa ia tidak pernah membuat agent Anda mati

Setiap hook berjalan di dalam catch_unwind, di titik masuk tertinggi. Panik di satu tahap berongkos satu penyulingan, bukan satu sesi. Basis data yang tidak mau dibuka berongkos konteks sesi, bukan pipeline-nya.

Itu aturan gagal terbuka, dan ia punya satu sisi tajam yang layak disebut: gagal terbuka berarti menyerahkan kembali byte mentahnya. Ia tidak berarti mengeluarkan ringkasan yang riang. Distiller yang tidak mengurai apa pun lalu mengembalikan 0 tests passed sedang gagal tertutup, dan dengan percaya diri.

Apa yang harus dilakukan sebuah host supaya semua ini berarti

Mendaftarkan hook-nya, lalu menghormati apa yang ia kembalikan.

Paruh kedua tidak dijamin. OMNI pernah mengeluarkan hasil sulingannya di bawah kunci yang diabaikan Claude Code, jadi tidak ada yang diterapkan di jalur itu selama dua rilis sementara OMNI mencatat sebuah penghematan dan mencetak catatan kaki untuk masing-masingnya. Perbaikannya membetulkan kuncinya dan meninggalkan bentuk nilainya tetap salah, dan gejalanya bertahan tanpa disadari.

Dua hal yang diajarkannya, keduanya tidak kentara:

  • Tulis ulangnya divalidasi terhadap skema keluaran milik tool host itu sendiri, satu bentuk per tool. Tidak ada bentuk universal.
  • Bidangnya saling bebas. Tulis ulang yang ditolak tetap meloloskan pesan konteksnya, jadi catatan kaki penghematan tercetak untuk penyulingan yang dibatalkan.

Jadi bukti sebuah hook bekerja bukan catatan kakinya dan bukan omni stats. Buktinya adalah transkrip sesi milik host sendiri:

grep -c hook_error_during_execution ~/.claude/projects/<proyek>/<sesi>.jsonl

Peringatan yang bisa Anda lihat bukan peringatan yang bisa dilihat agent. Lampiran seperti itu tidak pernah masuk ke konteks model, jadi sebuah agent bisa bilang hook-nya baik-baik saja sementara terminal Anda penuh penolakan.

Menguji sebuah hook dengan tangan

Beri ia muatan secara langsung ketimbang menebak jalur mana yang berjalan:

echo '<json muatan host>' | omni --post-hook

omni exec dan post-hook memilih rute yang berbeda, jadi hasil dari yang satu bukan bukti tentang yang lain.

Bentuk muatannya, dan ia berbeda per tool

Salah bentuk gagal secara diam-diam dan seragam: hook keluar 0, tidak mencetak apa pun, dan sebuah probe membacanya sebagai 0.0% saved. Tidak ada error untuk disadari, jadi distiller yang sebenarnya memotong 96% bisa dianggap tidak berjalan.

Bash menaruh keluarannya langsung di tool_response:

{ "session_id": "s1", "tool_name": "Bash",
  "tool_input":    { "command": "cat server.log" },
  "tool_response": { "content": "baris satu\nbaris dua\n" } }

Read membungkusnya di dalam file, dan kunci tambahannya bukan hiasan. startLine adalah titik hitung penomoran cat -n di sisi host, jadi fold yang membuang baris di atas baris yang selamat harus menggesernya:

{ "session_id": "s1", "tool_name": "Read",
  "tool_input":    { "path": "notes.txt" },
  "tool_response": { "file": { "filePath": "notes.txt", "content": "...",
                               "startLine": 1, "numLines": 40, "totalLines": 400 } } }

Balasannya berada di bawah hookSpecificOutput.updatedToolOutput, dan Claude Code memvalidasinya terhadap skema keluaran milik tool itu sendiri. Read yang terbungkus mendapat balasan file, dan itulah bentuk yang diterima host.

tool_response.content yang polos tidak mendapat balasan polos. Diverifikasi, bukan diasumsikan: ia kembali sebagai {status, result}, yaitu bentuk milik OMNI sendiri dan itulah pokok #187. Jadi bentuk polos berguna untuk menanyakan apa yang dilakukan ledger, dan balasannya bukan yang akan diterima Read sungguhan.

Kedua bentuk Read itu sama-sama sah dan keduanya mencapai tahap yang berbeda. Muatan Read dengan tool_response.content polos tetap diterima dan sampai ke ledger, sedangkan tool_response.file.content sampai ke distiller readfile dan ke penyesuaian startLine. Tidak ada yang salah; keduanya menjawab pertanyaan berbeda. Probe yang membidik satu tapi dibangun di atas yang lain mengembalikan nol bersih dan tampak seperti sebuah kesimpulan.