Hook
Hook
Jalankan skrip deterministik selama siklus hidup Codex
Hook adalah kerangka kerja ekstensibilitas untuk Codex. Hook memungkinkan Anda menjalankan skrip atau alat MCP selama loop agen, sehingga mendukung fitur seperti:
- Mengirim percakapan ke mesin pencatatan/analitik khusus
- Memindai prompt tim Anda untuk mencegah penempelan API key secara tidak sengaja
- Meringkas percakapan untuk membuat memori persisten secara otomatis
- Menjalankan pemeriksaan validasi khusus saat giliran percakapan berhenti untuk menegakkan standar
- Menyesuaikan prompt saat berada di direktori tertentu
Perilaku runtime yang perlu diperhatikan:
- Semua hook yang cocok dari beberapa file akan dijalankan.
- Beberapa hook perintah yang cocok untuk peristiwa yang sama diluncurkan secara bersamaan, sehingga satu hook tidak dapat mencegah hook lain yang cocok untuk mulai berjalan.
- Hook yang tidak dikelola harus ditinjau dan dipercaya sebelum dijalankan.
Hook berjalan pada titik-titik berbeda dalam percakapan:
| Waktu | Hook |
|---|---|
| Selama giliran | PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop |
| Saat Anda menginterupsi giliran aktif | Interrupt (tidak dijalankan untuk subagen) |
| Saat sesi atau subagen dimulai | SessionStart, SubagentStart |
| Saat thread utama berakhir | SessionEnd (tidak berjalan untuk subagen) |
Tempat Codex mencari hook
Codex menemukan hook di samping lapisan konfigurasi aktif dalam salah satu bentuk berikut:
hooks.json- tabel
[hooks]sebaris di dalamconfig.toml
Plugin yang terinstal juga dapat menyertakan konfigurasi siklus hidup melalui manifes
plugin atau file hooks/hooks.json default. Lihat Membuat
plugin untuk mengetahui
aturan pengemasan plugin.
Dalam praktiknya, empat lokasi yang paling berguna adalah:
~/.codex/hooks.json~/.codex/config.toml<repo>/.codex/hooks.json<repo>/.codex/config.toml
Jika terdapat lebih dari satu sumber hook, Codex memuat semua hook yang cocok.
Lapisan konfigurasi dengan prioritas lebih tinggi tidak menggantikan hook dari lapisan berprioritas lebih rendah.
Jika satu lapisan berisi hooks.json sekaligus [hooks] sebaris, Codex
menggabungkannya dan menampilkan peringatan saat dimulai. Sebaiknya gunakan satu representasi per lapisan.
Codex juga dapat menemukan hook yang disertakan dalam plugin aktif. Hook bawaan plugin dimuat bersama sumber hook lainnya dan menggunakan alur peninjauan kepercayaan yang sama seperti hook lain yang tidak dikelola.
Hook lokal proyek hanya dimuat jika lapisan .codex/ proyek dipercaya. Dalam
proyek yang tidak dipercaya, Codex tetap memuat hook pengguna dan sistem dari
lapisan konfigurasi aktifnya masing-masing.
Meninjau dan memercayai hook
Codex mencantumkan hook yang dikonfigurasi sebelum menentukan hook mana yang dapat dijalankan. Sebelum hook yang tidak dikelola dapat berjalan, Codex mengharuskan Anda meninjau dan memercayai definisi hook yang persis sama. Codex mencatat kepercayaan berdasarkan hash hook saat ini, sehingga hook baru atau yang berubah ditandai untuk ditinjau dan dilewati sampai dipercaya.
Gunakan /hooks di CLI untuk memeriksa sumber hook, meninjau hook baru atau yang berubah,
memercayai hook, atau menonaktifkan hook tertentu yang tidak dikelola. Jika hook perlu ditinjau saat
startup, Codex menampilkan peringatan yang meminta Anda membuka /hooks.
Hook terkelola dari sumber sistem, MDM, cloud, atau requirements.toml ditandai
sebagai terkelola, dipercaya berdasarkan kebijakan, dan tidak dapat dinonaktifkan dari penjelajah hook pengguna.
Untuk otomatisasi satu kali yang sudah memeriksa sumber hook di luar Codex, teruskan
--dangerously-bypass-hook-trust agar hook aktif dijalankan tanpa memerlukan
kepercayaan hook yang disimpan untuk pemanggilan tersebut.
Bentuk konfigurasi
Hook disusun dalam tiga tingkat:
- Peristiwa hook seperti
PreToolUse,PostToolUse,PreCompact,SubagentStart, atauStop - Grup pencocok yang menentukan kapan peristiwa tersebut cocok
- Satu atau beberapa handler hook yang berjalan saat grup pencocok cocok
{
"description": "Optional lifecycle hooks for this workspace.",
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_start.py",
"statusMessage": "Loading session notes",
"additionalContextLimit": 5000
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_end.py",
"timeout": 3
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py\"",
"statusMessage": "Checking Bash command"
}
]
}
],
"PermissionRequest": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/permission_request.py\"",
"statusMessage": "Checking approval request"
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use_review.py\"",
"statusMessage": "Reviewing Bash output"
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/user_prompt_submit_data_flywheel.py\""
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/stop_continue.py\"",
"timeout": 30
}
]
}
]
}
}Catatan:
descriptionadalah metadata tingkat atas opsional untuk filehooks.json. Metadata ini tidak mengubah hook yang dijalankan.timeoutdinyatakan dalam detik.- Jika
timeoutdihilangkan, Codex menggunakan600detik untuk sebagian besar hook.SessionEnddanInterruptsecara default menggunakan1detik dan mendukung hingga3detik.
statusMessagebersifat opsional.additionalContextLimitmenetapkan jumlahadditionalContextyang dapat dikirim hook perintah ke model sebelum Codex menyimpan teks lengkap ke disk dan sebagai gantinya mengirim pratinjau yang lebih singkat. Lihat Output hook berukuran besar.commandWindowsadalah penggantian perintah opsional khusus Windows. Dalam TOML, gunakancommand_windowsataucommandWindows.- Tetapkan
asyncketrueuntuk menjalankan hook perintah di latar belakang. - Handler
commanddanmcp_tooldidukung. Handlerpromptdanagentdiuraikan tetapi dilewati. - Perintah berjalan dengan
cwdsesi sebagai direktori kerja. - Untuk hook lokal repositori, sebaiknya selesaikan jalur dari root git, bukan menggunakan
jalur relatif seperti
.codex/hooks/.... Codex mungkin dimulai dari subdirektori, sedangkan jalur berbasis root git menjaga lokasi hook tetap stabil.
TOML sebaris yang setara dalam config.toml:
[[hooks.SessionStart]]
matcher = "^compact$"
[[hooks.SessionStart.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/session_start.py"'
additionalContextLimit = 5000
[[hooks.PreToolUse]]
matcher = "^Bash$"
[[hooks.PreToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py"'
timeout = 30
statusMessage = "Checking Bash command"
[[hooks.PostToolUse]]
matcher = "^Bash$"
[[hooks.PostToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use_review.py"'
timeout = 30
statusMessage = "Reviewing Bash output"Hook alat MCP
Hook alat MCP memungkinkan peristiwa siklus hidup memanggil alat pada server MCP yang sudah terhubung. Hook ini mengirim argumen terstruktur langsung ke alat dan menggunakan peninjauan kepercayaan serta kontrak output yang sama seperti hook perintah.
Mengonfigurasi hook alat MCP
Hook ini meminta server MCP scanner untuk memindai setiap patch setelah Codex menulis atau
mengedit file:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "mcp_tool",
"server": "scanner",
"tool": "scan_patch",
"input": { "patch": "${tool_input.command}" },
"timeout": 30,
"statusMessage": "Scanning edited files"
}
]
}
]
}
}| Bidang | Arti |
|---|---|
type |
Harus berupa mcp_tool. |
server |
Nama wajib dari server MCP yang sudah terhubung. |
tool |
Nama wajib dari alat yang diekspos oleh server tersebut. |
input |
Objek JSON opsional berisi templat argumen. Default-nya {}. |
timeout |
Batas waktu eksekusi aktif opsional dalam detik. Default-nya 600. |
statusMessage |
Pesan opsional yang ditampilkan saat hook berjalan. |
Memperluas argumen dari peristiwa hook
Gunakan ${field.nested} untuk membaca bidang bertitik dari peristiwa hook. Placeholder
yang mengisi seluruh nilai mempertahankan tipe JSON-nya. Placeholder di dalam string
yang lebih besar dirender sebagai teks. Codex memperluas objek dan array secara rekursif.
Untuk peristiwa yang berisi {"tool_input":{"file_path":"src/main.rs","count":3}},
templat argumen ini:
{
"path": "${tool_input.file_path}",
"count": "${tool_input.count}",
"message": "Scanning ${tool_input.file_path}"
}menjadi:
{
"path": "src/main.rs",
"count": 3,
"message": "Scanning src/main.rs"
}Eksekusi dan siklus hidup
- Hook menggunakan koneksi MCP yang sudah ada. Hook tidak memulai atau menghubungkan ulang server.
- Hook dapat memblokir operasi saat alat mengembalikan keputusan pemblokiran. Kesalahan, server yang tidak ditemukan, dan alat yang tidak tersedia tidak memblokir operasi.
- Hook alat MCP berjalan secara sinkron. Hook tidak meminta persetujuan alat atau memicu hook lain.
- Batas waktu hook atau server yang lebih singkat akan berlaku. Waktu untuk menunggu respons elisitasi MCP tidak dihitung dalam batas waktu.
- Hook
SessionStartdapat berjalan sebelum server MCP siap. Jika hal itu terjadi, hook tersebut tidak memblokir sesi. SessionEndtidak mendukung hook alat MCP.
Menonaktifkan hook
Hook diaktifkan secara default. Untuk menonaktifkannya dalam config.toml, tetapkan:
[features]
hooks = falseGunakan hooks sebagai kunci fitur kanonis. codex_hooks masih berfungsi sebagai
alias yang tidak digunakan lagi. Admin dapat memaksa hook dinonaktifkan dengan cara yang sama dalam
requirements.toml menggunakan [features].hooks = false.
Hook terkelola dari requirements.toml
Persyaratan yang dikelola perusahaan juga dapat mendefinisikan hook sebaris di bawah [hooks].
Ini berguna saat admin ingin memberlakukan konfigurasi hook sekaligus
mengirimkan skrip sebenarnya melalui MDM atau sistem pengelolaan perangkat lain.
Untuk memberlakukan hook terkelola bahkan bagi pengguna yang menonaktifkan hook secara lokal, sematkan
[features].hooks = true dalam requirements.toml bersama [hooks]. Untuk mengabaikan
hook pengguna, proyek, sesi, dan plugin sambil tetap mengizinkan hook terkelola
administrator, tetapkan allow_managed_hooks_only = true.
allow_managed_hooks_only = true
[features]
hooks = true
[hooks]
managed_dir = "/enterprise/hooks"
windows_managed_dir = 'C:\enterprise\hooks'
[[hooks.PreToolUse]]
matcher = "^Bash$"
[[hooks.PreToolUse.hooks]]
type = "command"
command = "python3 /enterprise/hooks/pre_tool_use_policy.py"
command_windows = 'py -3 C:\enterprise\hooks\pre_tool_use_policy.py'
timeout = 30
statusMessage = "Checking managed Bash command"Catatan untuk hook terkelola:
managed_dirdigunakan pada macOS dan Linux.windows_managed_dirdigunakan pada Windows.- Codex tidak mendistribusikan skrip dalam
managed_dir; alat perusahaan Anda harus menginstal dan memperbaruinya secara terpisah. - Perintah hook terkelola harus menggunakan jalur skrip absolut di bawah direktori terkelola yang dikonfigurasi.
allow_managed_hooks_only = truemelewati hook dari sumber pengguna, proyek, sesi, dan plugin, tetapi tetap memuat hook terkelola darirequirements.tomldan lapisan konfigurasi terkelola lainnya.
Hook bawaan plugin
Saat plugin diaktifkan, Codex dapat memuat hook siklus hidup dari plugin tersebut bersama hook pengguna, proyek, dan terkelola.
Secara default, Codex mencari hooks/hooks.json di dalam root plugin. Manifes
plugin dapat mengganti default tersebut dengan entri hooks dalam
.codex-plugin/plugin.json. Entri manifes dapat berupa jalur berawalan ./,
array jalur berawalan ./, objek hook sebaris, atau array objek
hook sebaris.
{
"name": "repo-policy",
"hooks": "./hooks/hooks.json"
}Jalur hook manifes diselesaikan secara relatif terhadap root plugin dan harus tetap
berada di dalam root tersebut. Jika manifes mendefinisikan hooks, Codex menggunakan entri
manifes tersebut sebagai pengganti hooks/hooks.json default.
Perintah hook plugin menerima variabel lingkungan berikut:
PLUGIN_ROOTadalah ekstensi khusus Codex yang menunjuk ke root plugin yang terinstal.PLUGIN_DATAadalah ekstensi khusus Codex yang menunjuk ke direktori data plugin yang dapat ditulis.- Codex juga menetapkan
CLAUDE_PLUGIN_ROOTdanCLAUDE_PLUGIN_DATAuntuk kompatibilitas dengan hook plugin yang sudah ada.
Hook plugin menggunakan skema peristiwa yang sama seperti hook lainnya. Menginstal atau mengaktifkan plugin tidak secara otomatis membuat hook-nya dipercaya; Codex melewati hook bawaan plugin sampai Anda meninjau dan memercayai definisi hook saat ini.
Pola pencocok
Bidang matcher adalah string regex yang memfilter kapan hook dipicu. Gunakan "*",
"", atau hilangkan matcher sepenuhnya untuk mencocokkan setiap kemunculan peristiwa
yang didukung.
Hanya beberapa peristiwa Codex saat ini yang mematuhi matcher:
| Peristiwa | Yang difilter matcher |
Catatan |
|---|---|---|
PermissionRequest |
nama alat | Dukungan mencakup Bash, apply_patch*, dan nama alat MCP |
PostToolUse |
nama alat | Lihat Cakupan alat |
PostCompact |
pemicu pemadatan | Nilainya adalah manual atau auto |
PreCompact |
pemicu pemadatan | Nilainya adalah manual atau auto |
PreToolUse |
nama alat | Lihat Cakupan alat |
SessionEnd |
alasan berakhir | Saat ini hanya other |
SessionStart |
sumber awal | Nilainya adalah startup, resume, clear, dan compact |
SubagentStart |
tipe subagen | Nilai bergantung pada subagen yang dimulai |
SubagentStop |
tipe subagen | Nilai bergantung pada subagen yang berhenti |
UserPromptSubmit |
tidak didukung | Setiap matcher yang dikonfigurasi diabaikan untuk peristiwa ini |
Stop |
tidak didukung | Setiap matcher yang dikonfigurasi diabaikan untuk peristiwa ini |
Interrupt |
tidak didukung | Setiap matcher yang dikonfigurasi diabaikan untuk peristiwa ini |
*Untuk apply_patch, nilai matcher juga dapat menggunakan Edit atau Write.
Contoh:
Bash^apply_patch$Edit|Writemcp__filesystem__read_filemcp__filesystem__.*startup|resume|clear|compactmanual|auto
Cakupan alat
PreToolUse dan PostToolUse dapat mengamati lebih dari sekadar panggilan shell dan MCP. Sebagian besar
alat fungsi lokal menggunakan jalur hook yang sama, sehingga Anda dapat mencocokkan nama alat,
memeriksa argumen JSON-nya, dan, untuk PreToolUse, memblokir atau menulis ulang panggilan.
| Jalur alat | PreToolUse |
PostToolUse |
Catatan |
|---|---|---|---|
| Perintah shell | Ya | Ya | Cocokkan sebagai Bash. |
Unified exec (exec_command) |
Ya | Ya | Cocokkan sebagai Bash. Polling write_stdin berikutnya dapat mengirimkan PostToolUse perintah asli saat perintah itu selesai. |
apply_patch |
Ya | Ya | Cocokkan sebagai apply_patch, Edit, atau Write. |
| Alat MCP | Ya | Ya | Cocokkan nama alat MCP, seperti mcp__filesystem__read_file. |
| Alat fungsi lokal lainnya | Ya | Ya | Cocokkan nama alat fungsi, seperti update_plan. spawn_agent juga cocok dengan Agent. |
Alat yang di-host, seperti WebSearch |
Tidak | Tidak | Alat ini tidak menggunakan jalur hook alat fungsi lokal. |
write_stdin adalah transportasi untuk sesi unified-exec yang sudah ada. Transportasi ini tidak menjalankan
PreToolUse lagi saat mengirim input atau melakukan polling terhadap perintah yang sudah melewati
PreToolUse.
Beberapa jalur alat khusus dapat memilih untuk tidak menggunakan jalur hook default. Perlakukan hook alat sebagai pagar pengaman yang berguna, bukan batas penegakan yang menyeluruh.
Bidang input umum
Setiap hook perintah menerima satu objek JSON pada stdin.
Berikut bidang bersama yang biasanya akan Anda gunakan:
| Bidang | Tipe | Arti |
|---|---|---|
session_id |
string |
ID sesi Codex saat ini. Hook subagen menggunakan ID sesi induk. |
transcript_path |
string | null |
Jalur ke file transkrip sesi, jika ada |
cwd |
string |
Direktori kerja untuk sesi |
hook_event_name |
string |
Nama peristiwa hook saat ini |
model |
string |
Ekstensi khusus Codex. Slug model aktif |
Hook yang tercakup dalam giliran mencantumkan turn_id sebagai ekstensi khusus Codex dalam
tabel khusus peristiwanya.
SessionStart, PreToolUse, PermissionRequest, PostToolUse,
UserPromptSubmit, SubagentStart, SubagentStop, Stop, dan Interrupt juga menyertakan
permission_mode, yang menjelaskan mode izin saat ini sebagai default,
acceptEdits, plan, dontAsk, atau bypassPermissions.
transcript_path menunjuk ke transkrip percakapan untuk memudahkan penggunaan, tetapi
format transkrip bukan antarmuka yang stabil untuk hook dan dapat berubah seiring waktu.
Jika Anda memerlukan format wire lengkap, lihat Skema.
Bidang output umum
SessionStart, PreCompact, PostCompact, UserPromptSubmit,
SubagentStop, dan Stop mendukung bidang JSON bersama berikut. SubagentStart
menerima bentuk yang sama untuk systemMessage dan konteks khusus hook, tetapi
continue: false tidak menghentikan subagen:
{
"continue": true,
"stopReason": "optional",
"systemMessage": "optional",
"suppressOutput": false
}| Bidang | Efek |
|---|---|
continue |
Jika false, menandai proses hook tersebut sebagai dihentikan |
stopReason |
Dicatat sebagai alasan penghentian |
systemMessage |
Ditampilkan sebagai peringatan di UI atau aliran peristiwa |
suppressOutput |
Saat ini diuraikan tetapi belum diimplementasikan |
Keluar dengan 0 tanpa output dianggap berhasil dan Codex melanjutkan.
PreToolUse dan PermissionRequest mendukung systemMessage, tetapi continue,
stopReason, dan suppressOutput saat ini tidak didukung untuk peristiwa tersebut.
Jika hook PreToolUse mengembalikan salah satu bidang yang tidak didukung tersebut, Codex menandai
proses hook itu sebagai gagal, melaporkan kesalahan, dan melanjutkan panggilan alat.
PostToolUse mendukung systemMessage, continue: false, dan stopReason.
suppressOutput diuraikan tetapi saat ini tidak didukung untuk peristiwa tersebut.
Output hook berukuran besar
Secara default, Codex membatasi setiap pesan output hook yang terlihat oleh model hingga sekitar
2.500 token. Jika hook mengembalikan lebih banyak, Codex menyimpan teks lengkap di
<temp_dir>/hook_outputs/<session_id>/<uuid>.txt dan memberi model
pratinjau bagian awal dan akhir beserta jalur file yang disimpan. Perilaku ini disebut
spilling: Codex menyimpan output yang terlalu besar pada disk dan menggantinya dengan
pratinjau lebih singkat yang terlihat oleh model. Jika file tidak dapat ditulis, model tetap
menerima pratinjau yang dipotong.
Untuk setiap hook perintah yang mengembalikan additionalContext, tetapkan
additionalContextLimit pada handler untuk menyesuaikan perkiraan ambang batas
token:
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_start.py",
"additionalContextLimit": 5000
}Hilangkan additionalContextLimit untuk menggunakan ambang batas default 2500 token. Gunakan
bilangan bulat positif untuk memilih ambang batas lain, atau 0 untuk meneruskan seluruh
konteks tambahan handler langsung ke model. Codex mengevaluasi setiap
handler yang cocok secara independen. Untuk peristiwa yang tidak dapat menghasilkan konteks
tambahan, Codex mengabaikan additionalContextLimit dan melaporkan peringatan
konfigurasi.
Pengaturan ini hanya berlaku untuk additionalContext. Umpan balik alat dan prompt
kelanjutan tetap menggunakan batas default.
Karena output yang terlalu besar dapat ditulis ke disk, hindari mengembalikan rahasia atau data sensitif lainnya dalam output hook.
Menjalankan hook di latar belakang
Secara default, Codex menunggu hook perintah selesai sebelum melanjutkan
operasi yang memicunya. Tetapkan async ke true untuk menjalankan hook perintah di
latar belakang saat Codex melanjutkan.
Mengonfigurasi hook latar belakang
Tambahkan "async": true ke handler perintah dalam hooks.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/post_tool_use.py",
"async": true,
"timeout": 120
}
]
}
]
}
}Untuk hook sebaris dalam config.toml, tetapkan async = true:
[[hooks.PostToolUse]]
matcher = "Bash"
[[hooks.PostToolUse.hooks]]
type = "command"
command = "python3 ~/.codex/hooks/post_tool_use.py"
async = true
timeout = 120Hook latar belakang menggunakan input, pencocok, peninjauan kepercayaan, batas waktu, dan
penanganan output berukuran besar yang sama seperti hook perintah sinkron. Seperti
hook perintah lainnya, timeout diukur dalam detik dan nilai default-nya adalah
600. Hook Interrupt menggunakan nilai default satu detik dan batas maksimum tiga detik,
termasuk saat dijalankan di latar belakang.
Cara hook latar belakang berjalan
Saat hook latar belakang selesai, Codex mengirimkan output informasional yang didukung pada titik aman berikutnya dalam percakapan:
- Jika suatu giliran aktif, Codex menunggu permintaan model dan panggilan alat saat ini selesai, lalu menyediakan output untuk permintaan model berikutnya dalam giliran tersebut.
- Jika tidak ada giliran aktif, Codex menunggu hingga giliran pengguna berikutnya. Selesainya hook latar belakang tidak memulai giliran baru.
Gunakan output JSON khusus peristiwa yang sama seperti hook sinkron. Codex menambahkan
additionalContext ke konteks model dan menampilkan systemMessage sebagai
peringatan.
Batasan
- Codex menjalankan hingga delapan hook latar belakang secara bersamaan per sesi. Hook tambahan menunggu hingga hook yang sedang berjalan selesai.
- Setiap pemanggilan yang cocok berjalan secara independen, dan hook latar belakang dapat selesai dalam urutan yang berbeda dari urutan dimulainya.
- Saat sesi berakhir, Codex membatalkan hook latar belakang yang belum selesai dan membuang output yang belum dikirimkan.
- Hook
SessionEndselalu berjalan secara sinkron.
Hook
SessionStart
matcher diterapkan pada source untuk peristiwa ini.
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
source |
string |
Cara sesi dimulai: startup, resume, clear, atau compact |
Teks biasa pada stdout ditambahkan sebagai konteks developer tambahan.
JSON pada stdout mendukung Bidang output umum dan
bentuk khusus hook berikut:
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "Load the workspace conventions before editing."
}
}Teks additionalContext tersebut ditambahkan sebagai konteks developer tambahan.
Setelah Codex memadatkan sesi root, hook SessionStart yang cocok dengan
source: "compact" berjalan sebelum permintaan model berikutnya. Ini juga berlaku saat
pemadatan otomatis terjadi di tengah giliran: Codex mengirimkan konteks tambahan hook
ke kelanjutan langsung, bukan menunggu giliran pengguna
berikutnya. Jika hook mengembalikan continue: false, Codex mengakhiri giliran
tanpa mengirim permintaan model lain.
SessionEnd
SessionEnd memungkinkan Anda menjalankan perintah saat sesi berakhir, misalnya untuk menyimpan catatan
akhir atau membersihkan file. Hook ini berjalan untuk thread utama saat Anda mengarsipkan atau
menghapus percakapan yang masih terbuka, saat Codex ditutup secara normal, atau setelah
percakapan tidak aktif dan tidak terbuka di klien terhubung mana pun selama 30
menit. Hook ini tidak berjalan untuk subagen.
Beralih dari percakapan atau memanggil thread/unsubscribe tidak langsung mengakhiri
sesi, sehingga tidak akan segera menjalankan SessionEnd. Hook Anda masih dapat
membaca transkrip sesi saat berjalan.
matcher memfilter reason untuk peristiwa ini. Untuk saat ini, reason selalu other.
Anda dapat menghilangkan matcher atau menggunakan other agar berjalan pada setiap peristiwa SessionEnd.
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
reason |
string |
Alasan sesi berakhir: other |
Sebagai contoh, perintah SessionEnd menerima:
{
"session_id": "thr_123",
"transcript_path": "/workspace/.codex/rollout.jsonl",
"cwd": "/workspace",
"hook_event_name": "SessionEnd",
"reason": "other"
}Hook SessionEnd selalu berjalan secara sinkron, bahkan saat async adalah true. Hook
ini bersifat informatif, sehingga output-nya tidak akan mengarahkan Codex atau menjaga thread tetap terbuka. Jika
perintah kehabisan waktu atau keluar dengan kesalahan, Codex melaporkannya sebagai kegagalan hook.
SubagentStart
matcher diterapkan pada agent_type untuk peristiwa ini.
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
turn_id |
string |
Ekstensi khusus Codex. ID giliran Codex aktif |
agent_id |
string |
Pengidentifikasi untuk subagen |
agent_type |
string |
Tipe atau profil subagen |
permission_mode |
string |
Mode izin saat ini |
Teks biasa pada stdout ditambahkan sebagai konteks developer tambahan untuk subagen.
JSON pada stdout mendukung systemMessage dan bentuk khusus hook berikut:
{
"hookSpecificOutput": {
"hookEventName": "SubagentStart",
"additionalContext": "Review the repository test conventions first."
}
}Teks additionalContext tersebut ditambahkan sebagai konteks developer tambahan untuk
subagen. continue: false diuraikan untuk kompatibilitas, tetapi tidak menghentikan
subagen agar tidak dimulai.
PreToolUse
PreToolUse dapat mencegat Bash, pengeditan file yang dilakukan melalui apply_patch,
panggilan alat MCP, dan alat fungsi lokal lainnya. Lihat Cakupan
alat untuk mengetahui jalur yang didukung dan pengecualiannya.
matcher diterapkan pada tool_name dan alias pencocok. Untuk pengeditan file melalui
apply_patch, nilai matcher dapat menggunakan apply_patch, Edit, atau Write; input hook
tetap melaporkan tool_name: "apply_patch".
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
turn_id |
string |
Ekstensi khusus Codex. ID giliran Codex aktif |
tool_name |
string |
Nama alat hook kanonis, seperti Bash, apply_patch, atau nama MCP seperti mcp__fs__read |
tool_use_id |
string |
ID panggilan alat untuk pemanggilan ini |
tool_input |
JSON value |
Input khusus alat. Bash dan apply_patch menggunakan tool_input.command. MCP dan alat fungsi lokal lainnya mengirim argumennya. |
Teks biasa pada stdout diabaikan.
JSON pada stdout dapat menggunakan systemMessage. Untuk menolak panggilan alat yang didukung, kembalikan
bentuk khusus hook berikut:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Destructive command blocked by hook."
}
}Codex juga menerima bentuk blok lama berikut:
{
"decision": "block",
"reason": "Destructive command blocked by hook."
}Anda juga dapat menggunakan kode keluar 2 dan menulis alasan pemblokiran ke stderr.
Untuk menambahkan konteks yang terlihat oleh model tanpa memblokir, kembalikan
hookSpecificOutput.additionalContext:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "The pending command touches generated files."
}
}Untuk menulis ulang panggilan alat yang didukung tanpa memblokir, kembalikan
permissionDecision: "allow" dengan updatedInput:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"command": "echo rewritten"
}
}
}Untuk perintah Bash dan apply_patch, updatedInput harus menyertakan bidang string
command. Untuk MCP dan alat fungsi lokal lainnya, updatedInput adalah
objek argumen pengganti. Kembalikan updatedInput hanya bersama
permissionDecision: "allow"; bentuk updatedInput lainnya dilaporkan sebagai
kesalahan.
permissionDecision: "ask", decision: "approve" lama, continue: false,
stopReason, dan suppressOutput diuraikan tetapi belum didukung. Codex menandai
proses hook sebagai gagal, melaporkan kesalahan, dan melanjutkan panggilan alat.
PermissionRequest
PermissionRequest berjalan saat Codex hendak meminta persetujuan, misalnya untuk
eskalasi shell atau persetujuan jaringan terkelola. Hook dapat mengizinkan permintaan, menolak
permintaan, atau tidak memberikan keputusan dan membiarkan prompt persetujuan normal dilanjutkan.
Hook ini tidak berjalan untuk perintah yang tidak memerlukan persetujuan.
matcher diterapkan pada tool_name dan alias pencocok. Nilai kanonis
saat ini mencakup Bash, apply_patch, dan nama alat MCP seperti
mcp__server__tool; apply_patch juga cocok dengan Edit dan Write.
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
turn_id |
string |
Ekstensi khusus Codex. ID giliran Codex aktif |
tool_name |
string |
Nama alat hook kanonis, seperti Bash, apply_patch, atau nama MCP seperti mcp__fs__read |
tool_input |
JSON value |
Input khusus alat. Bash dan apply_patch menggunakan tool_input.command, sedangkan alat MCP mengirim semua argumen. |
tool_input.description |
string | null |
Alasan persetujuan yang mudah dibaca manusia, jika tersedia di Codex |
Teks biasa pada stdout diabaikan.
Beberapa input alat mungkin menyertakan deskripsi yang mudah dibaca manusia, tetapi jangan mengandalkan
bidang tool_input.description untuk setiap alat.
Untuk menyetujui permintaan, kembalikan:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "allow"
}
}
}Untuk menolak permintaan, kembalikan:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "deny",
"message": "Blocked by repository policy."
}
}
}Jika beberapa hook yang cocok mengembalikan keputusan, deny selalu diutamakan. Jika tidak,
allow memungkinkan permintaan dilanjutkan tanpa menampilkan prompt persetujuan. Jika tidak ada
hook yang cocok memberikan keputusan, Codex menggunakan alur persetujuan normal.
Jangan kembalikan updatedInput, updatedPermissions, atau interrupt untuk
PermissionRequest; bidang tersebut dicadangkan untuk perilaku mendatang dan saat ini akan gagal
dalam keadaan tertutup.
PostToolUse
PostToolUse berjalan setelah alat yang didukung menghasilkan output, termasuk Bash,
apply_patch, panggilan alat MCP, dan alat fungsi lokal lainnya. Untuk Bash, hook ini
juga berjalan setelah perintah keluar dengan status bukan nol. Hook ini tidak dapat membatalkan efek
samping dari alat yang sudah berjalan. Lihat Cakupan alat untuk
mengetahui jalur yang didukung dan pengecualiannya.
matcher diterapkan pada tool_name dan alias pencocok. Untuk pengeditan file melalui
apply_patch, nilai matcher dapat menggunakan apply_patch, Edit, atau Write; input hook
tetap melaporkan tool_name: "apply_patch".
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
turn_id |
string |
Ekstensi khusus Codex. ID giliran Codex aktif |
tool_name |
string |
Nama alat hook kanonis, seperti Bash, apply_patch, atau nama MCP seperti mcp__fs__read |
tool_use_id |
string |
ID panggilan alat untuk pemanggilan ini |
tool_input |
JSON value |
Input khusus alat. Bash dan apply_patch menggunakan tool_input.command. MCP dan alat fungsi lokal lainnya mengirim argumennya. |
tool_response |
JSON value |
Output khusus alat. Alat MCP mengirim hasil panggilan MCP. Alat fungsi lokal lainnya biasanya mengirim output yang ditujukan bagi model. |
Teks biasa pada stdout diabaikan.
JSON pada stdout dapat menggunakan systemMessage dan bentuk khusus hook berikut:
{
"decision": "block",
"reason": "The Bash output needs review before continuing.",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "The command updated generated files."
}
}Teks additionalContext tersebut ditambahkan sebagai konteks developer tambahan.
Untuk peristiwa ini, decision: "block" tidak membatalkan perintah Bash yang sudah selesai.
Sebagai gantinya, Codex mencatat umpan balik, mengganti hasil alat dengan umpan balik
tersebut, dan melanjutkan model dari pesan yang diberikan hook.
Anda juga dapat menggunakan kode keluar 2 dan menulis alasan umpan balik ke stderr.
Untuk menghentikan pemrosesan normal hasil alat asli setelah perintah sudah
berjalan, kembalikan continue: false. Codex akan mengganti hasil alat dengan
umpan balik atau teks penghentian Anda, lalu melanjutkan dari sana.
updatedMCPToolOutput dan suppressOutput diuraikan tetapi belum didukung.
Codex menandai proses hook sebagai gagal, melaporkan kesalahan, dan melanjutkan pemrosesan
normal hasil alat.
Panggilan alat dari mode kode
Saat model menggunakan mode kode untuk memanggil alat dari JavaScript, keputusan hook berlaku
untuk panggilan bersarang tersebut. PreToolUse dapat menghentikan alat sebelum berjalan atau menulis ulang
input-nya. PostToolUse yang memblokir tidak dapat membatalkan efek samping alat, tetapi dapat
mencegah hasil asli mencapai skrip yang sedang berjalan.
| Hasil hook | Yang terlihat oleh mode kode |
|---|---|
PreToolUse memblokir |
Promise alat ditolak sebelum alat berjalan. |
PreToolUse mengembalikan updatedInput |
Alat berjalan dengan input yang ditulis ulang dan promise diselesaikan dengan hasil tersebut. |
PostToolUse mengembalikan decision: "block" atau keluar dengan kode 2 |
Alat berjalan, lalu promise ditolak dengan alasan dari hook. |
PostToolUse mengembalikan continue: false |
Codex menggunakan umpan balik hook sebagai hasil yang terlihat oleh model, tetapi tidak menolak promise alat bersarang. |
PreCompact
PreCompact berjalan sebelum Codex memadatkan percakapan. matcher diterapkan
pada trigger, yang nilainya adalah manual dan auto.
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
turn_id |
string |
Ekstensi khusus Codex. ID giliran Codex aktif |
trigger |
string |
Pemicu pemadatan: manual atau auto |
Teks biasa pada stdout diabaikan.
JSON pada stdout mendukung Bidang output umum. Jika hook
PreCompact yang cocok mengembalikan continue: false, Codex berhenti sebelum
memadatkan.
PostCompact
PostCompact berjalan setelah Codex memadatkan percakapan. matcher diterapkan
pada trigger, yang nilainya adalah manual dan auto.
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
turn_id |
string |
Ekstensi khusus Codex. ID giliran Codex aktif |
trigger |
string |
Pemicu pemadatan: manual atau auto |
Teks biasa pada stdout diabaikan.
JSON pada stdout mendukung Bidang output umum. Jika hook
PostCompact yang cocok mengembalikan continue: false, Codex berhenti setelah
memadatkan.
UserPromptSubmit
matcher saat ini tidak digunakan untuk peristiwa ini.
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
turn_id |
string |
Ekstensi khusus Codex. ID giliran Codex aktif |
prompt |
string |
Prompt pengguna yang akan dikirim |
Teks biasa pada stdout ditambahkan sebagai konteks developer tambahan.
JSON pada stdout mendukung Bidang output umum dan
bentuk khusus hook berikut:
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "Ask for a clearer reproduction before editing files."
}
}Teks additionalContext tersebut ditambahkan sebagai konteks developer tambahan.
Untuk memblokir prompt, kembalikan:
{
"decision": "block",
"reason": "Ask for confirmation before doing that."
}Anda juga dapat menggunakan kode keluar 2 dan menulis alasan pemblokiran ke stderr.
SubagentStop
matcher diterapkan pada agent_type untuk peristiwa ini.
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
turn_id |
string |
Ekstensi khusus Codex. ID giliran Codex aktif |
agent_id |
string |
Pengidentifikasi untuk subagen |
agent_type |
string |
Tipe atau profil subagen |
agent_transcript_path |
string | null |
Jalur ke file transkrip subagen, jika ada |
stop_hook_active |
boolean |
Apakah subagen ini sudah dilanjutkan |
last_assistant_message |
string | null |
Pesan asisten subagen terbaru, jika tersedia |
SubagentStop mengharapkan JSON pada stdout saat keluar dengan 0. Output teks biasa
tidak valid untuk peristiwa ini.
JSON pada stdout mendukung Bidang output umum. Untuk meminta
Codex melanjutkan alur subagen, kembalikan:
{
"decision": "block",
"reason": "Run one more focused pass inside the subagent."
}Anda juga dapat menggunakan kode keluar 2 dan menulis alasan kelanjutan ke stderr.
Jika hook SubagentStop mana pun yang cocok mengembalikan continue: false, keputusan tersebut
diutamakan daripada keputusan kelanjutan dari hook SubagentStop lain
yang cocok.
Stop
matcher saat ini tidak digunakan untuk peristiwa ini.
Bidang selain Bidang input umum:
| Bidang | Tipe | Arti |
|---|---|---|
turn_id |
string |
Ekstensi khusus Codex. ID giliran Codex aktif |
stop_hook_active |
boolean |
Apakah giliran ini sudah dilanjutkan oleh Stop |
last_assistant_message |
string | null |
Teks pesan asisten terbaru, jika tersedia |
Stop mengharapkan JSON pada stdout saat keluar dengan 0. Output teks biasa tidak valid
untuk peristiwa ini.
JSON pada stdout mendukung Bidang output umum. Agar
Codex terus berjalan, kembalikan:
{
"decision": "block",
"reason": "Run one more pass over the failing tests."
}Anda juga dapat menggunakan kode keluar 2 dan menulis alasan kelanjutan ke stderr.
Untuk peristiwa ini, decision: "block" tidak menolak giliran. Sebagai gantinya, nilai tersebut meminta
Codex untuk melanjutkan dan secara otomatis membuat prompt kelanjutan baru yang bertindak
sebagai prompt pengguna baru, dengan menggunakan reason Anda sebagai teks prompt tersebut.
Jika hook Stop mana pun yang cocok mengembalikan continue: false, keputusan tersebut diutamakan
daripada keputusan kelanjutan dari hook Stop lain yang cocok.
Interrupt
Interrupt berjalan saat Anda menginterupsi giliran aktif pada thread utama. Gunakan hook ini
untuk mencatat interupsi atau membersihkan pekerjaan yang dimulai oleh hook. Hook ini tidak berjalan
untuk thread yang tidak aktif atau subagen, dan setiap matcher yang dikonfigurasi akan diabaikan.
Selain Bidang input umum, peristiwa ini menyertakan
turn_id, ID giliran yang diinterupsi, dan permission_mode.
Hook perintah memiliki batas waktu default satu detik. Batas waktu yang dikonfigurasi
dibatasi antara satu hingga tiga detik. Output hook tidak dapat mencegah
interupsi atau memulai ulang giliran. Gunakan kode keluar 0 tanpa output, atau kembalikan JSON dengan
systemMessage opsional untuk menampilkan peringatan. Output teks biasa tidak valid
untuk peristiwa ini.
{ "systemMessage": "Saved the interrupted turn to the local audit log." }Skema
Jika Anda memerlukan format wire saat ini secara persis, lihat skema yang dihasilkan dalam repositori GitHub Codex.
Alias teks biasa
- string | null