Bahasa Indonesia

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 dalam config.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, atau Stop
  • 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:

  • description adalah metadata tingkat atas opsional untuk file hooks.json. Metadata ini tidak mengubah hook yang dijalankan.
  • timeout dinyatakan dalam detik.
  • Jika timeout dihilangkan, Codex menggunakan 600 detik untuk sebagian besar hook.
    • SessionEnd dan Interrupt secara default menggunakan 1 detik dan mendukung hingga 3 detik.
  • statusMessage bersifat opsional.
  • additionalContextLimit menetapkan jumlah additionalContext yang 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.
  • commandWindows adalah penggantian perintah opsional khusus Windows. Dalam TOML, gunakan command_windows atau commandWindows.
  • Tetapkan async ke true untuk menjalankan hook perintah di latar belakang.
  • Handler command dan mcp_tool didukung. Handler prompt dan agent diuraikan tetapi dilewati.
  • Perintah berjalan dengan cwd sesi 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 SessionStart dapat berjalan sebelum server MCP siap. Jika hal itu terjadi, hook tersebut tidak memblokir sesi.
  • SessionEnd tidak mendukung hook alat MCP.

Menonaktifkan hook

Hook diaktifkan secara default. Untuk menonaktifkannya dalam config.toml, tetapkan:

[features]
hooks = false

Gunakan 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_dir digunakan pada macOS dan Linux.
  • windows_managed_dir digunakan 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 = true melewati hook dari sumber pengguna, proyek, sesi, dan plugin, tetapi tetap memuat hook terkelola dari requirements.toml dan 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_ROOT adalah ekstensi khusus Codex yang menunjuk ke root plugin yang terinstal.
  • PLUGIN_DATA adalah ekstensi khusus Codex yang menunjuk ke direktori data plugin yang dapat ditulis.
  • Codex juga menetapkan CLAUDE_PLUGIN_ROOT dan CLAUDE_PLUGIN_DATA untuk 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|Write
  • mcp__filesystem__read_file
  • mcp__filesystem__.*
  • startup|resume|clear|compact
  • manual|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 = 120

Hook 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 SessionEnd selalu 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