鉤子
在 Codex 生命週期中執行確定性指令碼
鉤子是 Codex 的可擴展性框架。你可以藉助它們在智能體迴圈期間執行指令碼或 MCP 工具,從而實現以下功能:
- 將聊天傳送到自定義日誌記錄/分析引擎
- 掃描團隊的提示詞,防止意外貼上 API key
- 彙總聊天內容,自動建立持久記憶
- 在一輪聊天停止時執行自定義驗證檢查,以強制執行標準
- 在特定目錄中自定義提示方式
鉤子的執行方式:
- 來自多個檔案的所有匹配鉤子都會執行。
- 同一事件的多個匹配命令鉤子會並發啟動, 因此一個鉤子無法阻止另一個匹配鉤子啟動。
- 非受管鉤子必須先經過審查並受信任,才能執行。
鉤子會在對話的不同階段執行:
| 時機 | 鉤子 |
|---|---|
| 在一個輪次期間 | PreToolUse、PermissionRequest、PostToolUse、PreCompact、PostCompact、UserPromptSubmit、SubagentStop、Stop |
| 當你中斷活躍輪次時 | Interrupt(不為子智能體執行) |
| 當會話或子智能體啟動時 | SessionStart、SubagentStart |
| 當主聊天結束時 | SessionEnd(不為子智能體執行) |
Codex 在哪裡尋找鉤子
Codex 會在活躍設定層旁邊尋找以下任一形式的鉤子:
hooks.jsonconfig.toml內的內聯[hooks]表
已安裝的外掛也可以通過其外掛清單或預設的 hooks/hooks.json 檔案捆綁生命週期設定。
有關外掛打包規則,請參閱建置
外掛。
實際使用中,最有用的四個位置是:
~/.codex/hooks.json~/.codex/config.toml<repo>/.codex/hooks.json<repo>/.codex/config.toml
如果存在多個鉤子來源,Codex 會載入所有匹配的鉤子。
優先順序較高的設定層不會替換優先順序較低的鉤子。
如果同一層同時包含 hooks.json 和內聯 [hooks],Codex
會合併二者並在啟動時發出警告。每一層最好只使用一種表示方式。
Codex 還可以發現已啟用外掛中捆綁的鉤子。外掛捆綁的 鉤子會與其他鉤子來源一同載入,並採用與 其他非受管鉤子相同的信任審查流程。
僅當專案 .codex/ 層受信任時,才會載入專案本機鉤子。在
不受信任的專案中,Codex 仍會從各自的活躍設定層載入使用者和系統鉤子。
審查和信任鉤子
Codex 會先列出已設定的鉤子,再決定哪些可以執行。在 非受管鉤子執行之前,Codex 要求你審查並信任其確切的鉤子 定義。Codex 會針對鉤子當前的雜湊值記錄信任狀態,因此新增或 更改後的鉤子會被標記為待審查,並在獲得信任前跳過。
在 CLI 中使用 /hooks 可檢查鉤子來源、審查新增或更改的鉤子、
信任鉤子,或停用單個非受管鉤子。如果啟動時有鉤子需要審查,
Codex 會輸出警告,提示你開啟 /hooks。
來自系統、MDM、雲端或 requirements.toml 來源的受管鉤子會被標記為
受管項,根據策略受到信任,並且無法從使用者鉤子瀏覽器中停用。
對於已在 Codex 外部審查鉤子來源的一次性自動化任務,可傳入
--dangerously-bypass-hook-trust,從而在該次呼叫中執行已啟用的鉤子,且無需
持久儲存鉤子信任狀態。
設定結構
鉤子分為三個層級:
- 鉤子 事件,例如
PreToolUse、PostToolUse、PreCompact、SubagentStart或Stop - 用於決定該事件何時匹配的匹配器組
- 匹配器組命中時執行的一個或多個鉤子處理程序
{
"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
}
]
}
]
}
}注意:
description是hooks.json檔案的可選頂層後設資料。它 不會改變要執行哪些鉤子。timeout的單位為秒。- 如果省略
timeout,Codex 會對大多數鉤子使用600秒。SessionEnd和Interrupt預設使用1秒,最大支援3秒。
statusMessage是可選的。additionalContextLimit設定命令鉤子可向模型傳送多少additionalContext, 超出後 Codex 會將完整文本儲存到磁碟,並改為傳送較短的 預覽。請參閱大型鉤子輸出。commandWindows是僅適用於 Windows 的可選命令覆蓋項。在 TOML 中,請使用command_windows或commandWindows。- 將
async設為true,可在後臺執行命令鉤子。 - 支援
command和mcp_tool處理程序。prompt和agent處理程序會被解析,但會跳過執行。 - 命令會以會話的
cwd作為工作目錄執行。 - 對於儲存庫本機鉤子,建議從 git 根目錄解析路徑,而不是使用
.codex/hooks/...之類的相對路徑。Codex 可能從 子目錄啟動,而基於 git 根目錄的路徑可以保持鉤子位置穩定。
config.toml 中等效的內聯 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"MCP 工具鉤子
MCP 工具鉤子允許生命週期事件呼叫已連線 MCP server上的工具。它會將結構化參數直接傳送給該工具,並採用與命令鉤子 相同的信任審查和輸出約定。
設定 MCP 工具鉤子
此鉤子會要求 scanner MCP server 在 Codex 寫入或
編輯檔案後掃描每個補丁:
{
"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"
}
]
}
]
}
}| 欄位 | 含義 |
|---|---|
type |
必須為 mcp_tool。 |
server |
已連線 MCP server 的名稱,必填。 |
tool |
該伺服器所公開工具的名稱,必填。 |
input |
可選的參數模板 JSON 物件。預設為 {}。 |
timeout |
可選的活躍執行超時時間,單位為秒。預設為 600。 |
statusMessage |
鉤子 執行時顯示的可選訊息。 |
根據鉤子事件展開參數
使用 ${field.nested} 讀取鉤子事件中的點號分隔欄位。如果佔位符
填充整個值,則會保留其 JSON 類型。如果佔位符位於較長的
字串中,則會呈現為文本。Codex 會遞迴展開物件和陣列。
對於包含 {"tool_input":{"file_path":"src/main.rs","count":3}} 的事件,
以下參數模板:
{
"path": "${tool_input.file_path}",
"count": "${tool_input.count}",
"message": "Scanning ${tool_input.file_path}"
}會變為:
{
"path": "src/main.rs",
"count": 3,
"message": "Scanning src/main.rs"
}執行和生命週期
- 鉤子使用現有 MCP 連線,不會啟動或重新連線伺服器。
- 當工具傳回阻止決定時,鉤子可以阻止操作。 錯誤、伺服器缺失和工具不可用不會阻止操作。
- MCP 工具鉤子會同步執行。它們不會請求工具核准,也不會觸發 其他鉤子。
- 以鉤子或伺服器中較短的超時時間為準。等待 MCP 引導響應所用的時間不計入超時。
SessionStart鉤子可能在 MCP server 準備就緒前執行。如果發生這種情況, 它們不會阻止會話。SessionEnd不支援 MCP 工具鉤子。
關閉鉤子
鉤子預設啟用。要在 config.toml 中將其關閉,請設定:
[features]
hooks = false使用 hooks 作為功能鍵。codex_hooks 仍可用作
已棄用的別名。管理員也可以在
requirements.toml 中使用 [features].hooks = false,以同樣的方式強制關閉鉤子。
來自 requirements.toml 的受管鉤子
啟用受管策略和遠端鉤子後,具有本機存取權限的 Work Cloud 和 dots 會在雲端編排器上使用由管理員管理的遠端 MCP 鉤子。在全域 requirements.toml 中設定 mcp_tool 處理程序。不具有本機存取權限的 Work Cloud 和個人帳戶不使用這些企業鉤子。雲端編排不支援命令/shell、提示詞和智能體處理程序;來自本機設定、外掛或本機目錄的鉤子;限定於環境的鉤子;以及 SessionEnd MCP 鉤子,即使工具在本機執行也是如此。當編排和執行都在本機進行時,現有受支援的鉤子仍可在僅本機執行的 Work 和 Codex 聊天中使用。管理員仍可在 Agent Security 中為這些工作流程設定受支援的受管鉤子。
在依賴這些鉤子之前,請測試回呼連通性、所需事件和失敗時的行為。受支援的顯式拒絕可以阻止操作,但 PreToolUse 回呼出錯、超時或響應格式錯誤可能導致鉤子失敗,卻不會阻止工具執行。MCP 鉤子不提供完整的 Compliance API 審計記錄。
本節中的 Codex 說明仍適用於受支援的 Codex 工作流程。在為 Work Cloud 啟用本機電腦存取之前,請檢視同步設定和 Agent Security 中的相容性警告。參閱受管設定。
在 Codex 中,企業管理的要求可以在 [hooks] 下內聯定義鉤子。
下面的命令鉤子範例僅適用於 Codex。
當管理員希望強制執行鉤子設定,同時
通過 MDM 或其他裝置管理系統分發實際指令碼時,這種方式很有用。
要對在本機停用鉤子的使用者也強制啟用受管鉤子,請
在 requirements.toml 中與 [hooks] 一起固定設定 [features].hooks = true。要忽略
使用者、專案、會話和外掛鉤子,同時仍允許管理員
管理的鉤子,請設定 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"受管鉤子的注意事項:
managed_dir用於 macOS 和 Linux。windows_managed_dir用於 Windows。- Codex 不會分發
managed_dir中的指令碼;你的企業 工具必須單獨安裝和更新這些指令碼。 - 受管鉤子命令應使用所設定受管目錄下指令碼的絕對路徑。
allow_managed_hooks_only = true會跳過來自使用者、專案、會話和 外掛來源的鉤子,但仍會載入來自requirements.toml和 其他受管設定層的受管鉤子。
外掛捆綁的鉤子
啟用外掛後,Codex 可以載入該外掛中的生命週期鉤子, 並與使用者、專案和受管鉤子一同執行。
預設情況下,Codex 會在外掛根目錄中尋找 hooks/hooks.json。外掛
清單可以使用 .codex-plugin/plugin.json 中的 hooks 條目替代該預設設定。
清單條目可以是以 ./ 為字首的路徑、以 ./ 為字首的路徑陣列、
內聯鉤子物件,或內聯鉤子物件陣列。
{
"name": "repo-policy",
"hooks": "./hooks/hooks.json"
}清單鉤子路徑相對於外掛根目錄解析,且必須位於
該根目錄之內。如果清單定義了 hooks,Codex 將使用這些清單
條目,而不是預設的 hooks/hooks.json。
外掛鉤子命令會收到以下環境變數:
PLUGIN_ROOT是 Codex 專用環境變數,指向已安裝的 外掛根目錄。PLUGIN_DATA是 Codex 專用環境變數,指向外掛的 可寫資料目錄。- Codex 還會設定
CLAUDE_PLUGIN_ROOT和CLAUDE_PLUGIN_DATA,以便 與現有外掛鉤子保持相容。
外掛鉤子與其他鉤子使用相同的事件資料結構。安裝或啟用 外掛並不會自動信任其鉤子;在你審查並信任當前鉤子定義前, Codex 會跳過外掛捆綁的鉤子。
匹配器模式
matcher 欄位是一個正規表示式字串,用於篩選鉤子何時觸發。使用 "*"、
"",或完全省略 matcher,即可匹配受支援事件的每次
出現。
目前只有部分 Codex 事件會採用 matcher:
| 事件 | matcher 的篩選物件 |
說明 |
|---|---|---|
PermissionRequest |
工具名稱 | 支援 Bash、apply_patch* 和 MCP 工具名稱 |
PostToolUse |
工具名稱 | 請參閱工具覆蓋範圍 |
PostCompact |
壓縮觸發方式 | 值為 manual 或 auto |
PreCompact |
壓縮觸發方式 | 值為 manual 或 auto |
PreToolUse |
工具名稱 | 參見工具覆蓋範圍 |
SessionEnd |
結束原因 | 當前僅支援 other |
SessionStart |
啟動來源 | 值為 startup、resume、clear、compact 和 fork |
SubagentStart |
子智能體類型 | 值取決於所啟動的子智能體 |
SubagentStop |
子智能體類型 | 值取決於所停止的子智能體 |
UserPromptSubmit |
不支援 | 為此事件設定的任何 matcher 都會被忽略 |
Stop |
不支援 | 為此事件設定的任何 matcher 都會被忽略 |
Interrupt |
不支援 | 為此事件設定的任何 matcher 都會被忽略 |
*對於 apply_patch,matcher 值也可以使用 Edit 或 Write。
範例:
Bash^apply_patch$Edit|Writemcp__filesystem__read_filemcp__filesystem__.*startup|resume|clear|compact|forkmanual|auto
工具覆蓋範圍
PreToolUse 和 PostToolUse 可以觀察 shell 和 MCP 呼叫之外的操作。大多數
本機函式工具都使用相同的鉤子路徑,因此你可以匹配其工具名稱、
檢查其 JSON 參數,並通過 PreToolUse 阻止或重寫呼叫。
| 工具路徑 | PreToolUse |
PostToolUse |
備註 |
|---|---|---|---|
| Shell 命令 | 是 | 是 | 匹配為 Bash。 |
統一執行(exec_command) |
是 | 是 | 匹配為 Bash。後續 write_stdin 輪詢可在原始命令完成時傳遞其 PostToolUse。 |
apply_patch |
是 | 是 | 匹配為 apply_patch、Edit 或 Write。 |
| MCP 工具 | 是 | 是 | 匹配 MCP 工具名稱,例如 mcp__filesystem__read_file。 |
| 其他本機函式工具 | 是 | 是 | 匹配函式工具名稱,例如 update_plan。spawn_agent 也會匹配 Agent。 |
託管工具,例如 WebSearch |
否 | 否 | 這些工具不使用本機函式工具鉤子路徑。 |
write_stdin 是現有統一執行會話的傳輸機制。它在傳送輸入或輪詢
已通過 PreToolUse 的命令時,不會再次執行
PreToolUse。
某些專用工具路徑可以選擇不使用預設鉤子路徑。請將工具 鉤子視為實用的防護機制,而不是完整的強制執行邊界。
通用輸入欄位
每個命令鉤子都會在 stdin 上接收一個 JSON 物件。
以下是通常會用到的共享欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
session_id |
string |
當前 Codex 會話 ID。子智能體鉤子使用父會話 ID。 |
transcript_path |
string | null |
會話轉錄檔案的路徑(如果有) |
cwd |
string |
會話的工作目錄 |
hook_event_name |
string |
當前鉤子事件名稱 |
model |
string |
Codex 專用欄位。活躍模型 slug |
輪次範圍的鉤子會在其事件專用表中將 turn_id 列為 Codex 專用欄位。
SessionStart、PreToolUse、PermissionRequest、PostToolUse、
UserPromptSubmit、SubagentStart、SubagentStop、Stop 和 Interrupt 還會包含
permission_mode,用於描述當前權限模式,其值為 default、
acceptEdits、plan、dontAsk 或 bypassPermissions。
為了方便使用,transcript_path 指向聊天轉錄,但
轉錄格式並非鉤子的穩定介面,可能會隨時間變化。
如需完整的傳輸格式,請參閱資料結構。
通用輸出欄位
SessionStart、PreCompact、PostCompact、UserPromptSubmit、
SubagentStop 和 Stop 支援以下共享 JSON 欄位。SubagentStart
為 systemMessage 和鉤子專用上下文接受相同的結構,但
continue: false 不會停止子智能體:
{
"continue": true,
"stopReason": "optional",
"systemMessage": "optional",
"suppressOutput": false
}| 欄位 | 效果 |
|---|---|
continue |
如果為 false,將該次鉤子執行標記為已停止 |
stopReason |
記錄為停止原因 |
systemMessage |
在 UI 或事件流中顯示為警告 |
suppressOutput |
目前會被解析,但尚未實現 |
退出碼為 0 且沒有輸出時會被視為成功,Codex 將繼續執行。
PreToolUse 和 PermissionRequest 支援 systemMessage,但目前這些事件不支援
continue、stopReason 和 suppressOutput。
如果 PreToolUse 鉤子傳回其中一個不受支援的欄位,Codex 會將
該次鉤子執行標記為失敗、報告錯誤,然後繼續工具呼叫。
PostToolUse 支援 systemMessage、continue: false 和 stopReason。
suppressOutput 會被解析,但目前不支援用於該事件。
大型鉤子輸出
預設情況下,Codex 會將每條模型可見的鉤子輸出訊息限制在約
2,500 個 token。如果鉤子傳回的內容更多,Codex 會將完整文本儲存到
<temp_dir>/hook_outputs/<session_id>/<uuid>.txt 下,並向模型提供包含已儲存檔案路徑的
首尾預覽。此行為稱為
溢位:Codex 將過大的輸出儲存到磁碟,並替換為
模型可見的較短預覽。如果檔案無法寫入,模型仍會
收到截斷後的預覽。
對於任何傳回 additionalContext 的命令鉤子,可在處理程序上設定
additionalContextLimit,以自定義大致的 token
閾值:
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_start.py",
"additionalContextLimit": 5000
}省略 additionalContextLimit 即可使用預設的 2500 token 閾值。使用
正整數可選擇其他閾值,使用 0 則可將處理程序的
完整附加上下文直接傳給模型。Codex 會單獨評估每個
匹配的處理程序。對於無法生成附加
上下文的事件,Codex 會忽略 additionalContextLimit 並報告設定
警告。
該設定僅適用於 additionalContext。工具回饋和續接
提示詞仍使用預設限制。
由於過大的輸出可能會寫入磁碟,請避免在鉤子輸出中傳回金鑰或 其他敏感資料。
在後臺執行鉤子
預設情況下,Codex 會等待命令鉤子完成,再繼續執行
觸發它的操作。將 async 設為 true,即可在 Codex 繼續執行的同時,
在後臺執行命令鉤子。
設定後臺鉤子
在 hooks.json 的命令處理程序中新增 "async": true:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/post_tool_use.py",
"async": true,
"timeout": 120
}
]
}
]
}
}對於 config.toml 中的內聯鉤子,請設定 async = true:
[[hooks.PostToolUse]]
matcher = "Bash"
[[hooks.PostToolUse.hooks]]
type = "command"
command = "python3 ~/.codex/hooks/post_tool_use.py"
async = true
timeout = 120後臺鉤子與同步命令鉤子使用相同的輸入、matcher、信任審查、超時和
大型輸出處理方式。與其他命令鉤子一樣,timeout 以秒為單位,預設值為
600。Interrupt 鉤子的預設超時時間為一秒,上限為三秒,
在後臺執行時也是如此。
後臺鉤子的執行方式
後臺鉤子完成後,Codex 會在對話中的下一個安全時機傳遞 受支援的資訊性輸出:
- 如果一輪對話正在進行,Codex 會等待當前模型請求和工具呼叫 完成,然後讓該輸出可供本輪中的下一次模型請求使用。
- 如果當前沒有進行中的輪次,Codex 會等到下一個使用者輪次。後臺 鉤子完成不會啟動新的輪次。
請使用與同步鉤子相同的事件專用 JSON 輸出。Codex 會將
additionalContext 新增到模型上下文,並將 systemMessage 顯示為
警告。
限制
- Codex 在每個會話中最多並發運行八個後臺鉤子。其他 鉤子會等待執行中的鉤子完成。
- 每次匹配的呼叫都會獨立執行,後臺鉤子完成的 順序可能與啟動順序不同。
- 會話結束時,Codex 會取消尚未完成的後臺鉤子,並丟棄 尚未傳遞的輸出。
SessionEnd鉤子始終同步執行。
鉤子
SessionStart
此事件會將 matcher 應用於 source。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
source |
string |
會話的啟動方式:startup、resume、clear、compact 或 fork |
派生的執行緒使用 source: "fork"。使用提供的歷史記錄恢復執行緒時,
仍使用 source: "resume"。
stdout 上的純文本會被新增為額外的開發者上下文。
stdout 中的 JSON 支援通用輸出欄位以及
以下鉤子專用結構:
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "Load the workspace conventions before editing."
}
}其中的 additionalContext 文本會被新增為額外的開發者上下文。
Codex 壓縮根會話後,匹配
source: "compact" 的 SessionStart 鉤子會在下一次模型請求前執行。這也適用於
在一輪對話中途發生自動壓縮的情況:Codex 會將鉤子的
附加上下文傳遞給緊隨其後的續接過程,而不是等待
後續使用者輪次。如果鉤子傳回 continue: false,Codex 會結束該輪,
不再傳送模型請求。
SessionEnd
SessionEnd 允許你在會話結束時執行命令,例如儲存最終
備註或清理檔案。它會在以下情況下為主聊天執行:你歸檔或
刪除仍處於開啟狀態的對話、Codex 正常關閉,或某個
對話已閒置 30 分鐘且未在任何已連線的客戶端中開啟。
它不會為子智能體執行。
切換到其他對話或呼叫 thread/unsubscribe 不會立即結束
會話,因此不會立即執行 SessionEnd。鉤子 在執行時
仍可讀取會話轉錄。
此事件使用 matcher 篩選 reason。目前,reason 始終為 other。
你可以省略 matcher 或使用 other,以便在每個 SessionEnd 事件中執行。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
reason |
string |
會話結束的原因:other |
例如,SessionEnd 命令會收到:
{
"session_id": "thr_123",
"transcript_path": "/workspace/.codex/rollout.jsonl",
"cwd": "/workspace",
"hook_event_name": "SessionEnd",
"reason": "other"
}SessionEnd 鉤子始終同步執行,即使 async 為 true。它們
僅提供建議,因此其輸出不會引導 Codex,也不會讓執行緒保持開啟。如果
命令超時或以錯誤退出,Codex 會將其報告為鉤子失敗。
SubagentStart
此事件會將 matcher 應用於 agent_type。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
turn_id |
string |
Codex 專用欄位。活躍的 Codex 輪次 ID |
agent_id |
string |
子智能體識別符 |
agent_type |
string |
子智能體類型或設定檔 |
permission_mode |
string |
當前權限模式 |
stdout 上的純文本會被新增為子智能體的額外開發者上下文。
stdout 上的 JSON 支援 systemMessage 以及以下鉤子專用結構:
{
"hookSpecificOutput": {
"hookEventName": "SubagentStart",
"additionalContext": "Review the repository test conventions first."
}
}其中的 additionalContext 文本會被新增為子智能體的額外開發者上下文。
continue: false 會出於相容性目的進行解析,但不會阻止
子智能體啟動。
PreToolUse
PreToolUse 可以攔截 Bash、通過 apply_patch 執行的檔案編輯、
MCP 工具呼叫以及其他本機函式工具。有關受支援的路徑和例外情況,
請參閱工具覆蓋範圍。
matcher 會應用於 tool_name 及匹配器別名。對於通過
apply_patch 進行的檔案編輯,matcher 值可以使用 apply_patch、Edit 或 Write;鉤子輸入
仍會報告 tool_name: "apply_patch"。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
turn_id |
string |
Codex 專用欄位。活躍的 Codex 輪次 ID |
tool_name |
string |
規範鉤子工具名稱,例如 Bash、apply_patch,或 mcp__fs__read 之類的 MCP 名稱 |
tool_use_id |
string |
此次呼叫的工具呼叫 ID |
tool_input |
JSON value |
工具專用輸入。Bash 和 apply_patch 使用 tool_input.command。MCP 和其他本機函式工具會傳送其參數。 |
stdout 上的純文本會被忽略。
stdout 上的 JSON 可以使用 systemMessage。要拒絕受支援的工具呼叫,請傳回
以下鉤子專用結構:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Destructive command blocked by hook."
}
}Codex 也接受以下舊版阻止結構:
{
"decision": "block",
"reason": "Destructive command blocked by hook."
}你也可以使用退出碼 2,並將阻止原因寫入 stderr。
要在不阻止操作的情況下新增模型可見的上下文,請傳回
hookSpecificOutput.additionalContext:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "The pending command touches generated files."
}
}要在不阻止操作的情況下重寫受支援的工具呼叫,請傳回
包含 updatedInput 的 permissionDecision: "allow":
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"command": "echo rewritten"
}
}
}對於 Bash 命令和 apply_patch,updatedInput 必須包含字串
command 欄位。對於 MCP 和其他本機函式工具,updatedInput 是
替代參數物件。僅將 updatedInput 與
permissionDecision: "allow" 一同傳回;其他 updatedInput 結構會被報告為
錯誤。
permissionDecision: "ask"、舊版 decision: "approve"、continue: false、
stopReason 和 suppressOutput 會被解析,但尚不受支援。Codex 會將
該次鉤子執行標記為失敗、報告錯誤,然後繼續工具呼叫。
PermissionRequest
當 Codex 即將請求核准時(例如 shell 權限提升或受管網路核准),
PermissionRequest 會執行。它可以允許請求、拒絕請求,
也可以不作決定,讓正常的核准提示繼續出現。
對於無需核准的命令,它不會執行。
matcher 會應用於 tool_name 及匹配器別名。目前的規範
值包括 Bash、apply_patch 和 mcp__server__tool 等 MCP 工具名稱;
apply_patch 也會匹配 Edit 和 Write。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
turn_id |
string |
Codex 專用欄位。活躍的 Codex 輪次 ID |
tool_name |
string |
規範鉤子工具名稱,例如 Bash、apply_patch,或 mcp__fs__read 之類的 MCP 名稱 |
tool_input |
JSON value |
工具專用輸入。Bash 和 apply_patch 使用 tool_input.command,而 MCP 工具會傳送所有參數。 |
tool_input.description |
string | null |
供人閱讀的核准原因(如果 Codex 提供) |
stdout 上的純文本會被忽略。
某些工具輸入可能包含供人閱讀的描述,但不要假定
每種工具都有 tool_input.description 欄位。
要核准請求,請傳回:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "allow"
}
}
}要拒絕請求,請傳回:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "deny",
"message": "Blocked by repository policy."
}
}
}如果多個匹配鉤子傳回決定,則任何 deny 都優先。否則,
allow 會讓請求繼續,而不顯示核准提示。如果沒有
匹配的鉤子作出決定,Codex 會使用正常的核准流程。
請勿為 PermissionRequest 傳回 updatedInput、updatedPermissions 或 interrupt;
這些欄位為未來行為預留,目前會拒絕請求並終止相應操作。
PostToolUse
PostToolUse 會在受支援的工具產生輸出後執行,包括 Bash、
apply_patch、MCP 工具呼叫及其他本機函式工具。對於 Bash,
它也會在命令以非零狀態退出後執行。它無法撤銷
已執行工具產生的副作用。有關受支援的路徑和例外情況,
請參閱工具覆蓋範圍。
matcher 會應用於 tool_name 及匹配器別名。對於通過
apply_patch 進行的檔案編輯,matcher 值可以使用 apply_patch、Edit 或 Write;鉤子輸入
仍會報告 tool_name: "apply_patch"。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
turn_id |
string |
Codex 專用欄位。活躍的 Codex 輪次 ID |
tool_name |
string |
規範鉤子工具名稱,例如 Bash、apply_patch,或 mcp__fs__read 之類的 MCP 名稱 |
tool_use_id |
string |
此次呼叫的工具呼叫 ID |
tool_input |
JSON value |
工具專用輸入。Bash 和 apply_patch 使用 tool_input.command。MCP 和其他本機函式工具會傳送其參數。 |
tool_response |
JSON value |
工具專用輸出。MCP 工具會傳送 MCP 呼叫結果。其他本機函式工具通常會傳送面向模型的輸出。 |
stdout 上的純文本會被忽略。
stdout 上的 JSON 可以使用 systemMessage 及以下鉤子專用結構:
{
"decision": "block",
"reason": "The Bash output needs review before continuing.",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "The command updated generated files."
}
}其中的 additionalContext 文本會被新增為額外的開發者上下文。
對於此事件,decision: "block" 不會撤銷已完成的 Bash 命令。
相反,Codex 會記錄回饋、用該回饋替換工具結果,
並從鉤子提供的訊息處繼續執行模型。
你也可以使用退出碼 2,並將回饋原因寫入 stderr。
要在命令已經執行後停止對原始工具結果的正常處理,
請傳回 continue: false。Codex 會用你的回饋或停止文本替換工具結果,
然後從此處繼續。
updatedMCPToolOutput 和 suppressOutput 會被解析,但尚不受支援。
Codex 會將該次鉤子執行標記為失敗、報告錯誤,然後繼續
正常處理工具結果。
程式碼模式中的工具呼叫
當模型在程式碼模式下通過 JavaScript 呼叫工具時,鉤子決定會應用於
該巢狀呼叫。PreToolUse 可以在工具執行前將其停止或重寫
其輸入。具有阻止作用的 PostToolUse 無法撤銷工具的副作用,但可以
阻止原始結果到達正在執行的指令碼。
| 鉤子 結果 | 程式碼模式看到的內容 |
|---|---|
PreToolUse 阻止 |
工具 promise 會在工具執行前被拒絕。 |
PreToolUse 傳回 updatedInput |
工具使用重寫後的輸入執行,promise 以該結果兌現。 |
PostToolUse 傳回 decision: "block" 或以結束代碼 2 退出 |
工具先執行,然後 promise 會以鉤子原因為由被拒絕。 |
PostToolUse 傳回 continue: false |
Codex 將鉤子回饋用作模型可見結果,但不會拒絕巢狀工具 promise。 |
PreCompact
PreCompact 會在 Codex 壓縮聊天前執行。matcher 會應用於
trigger,其值為 manual 和 auto。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
turn_id |
string |
Codex 專用欄位。活躍的 Codex 輪次 ID |
trigger |
string |
壓縮的觸發方式:manual 或 auto |
stdout 上的純文本會被忽略。
stdout 上的 JSON 支援通用輸出欄位。如果匹配的
PreCompact 鉤子傳回 continue: false,Codex 會在壓縮前停止。
PostCompact
PostCompact 會在 Codex 壓縮聊天後執行。matcher 會應用於
trigger,其值為 manual 和 auto。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
turn_id |
string |
Codex 專用欄位。活躍的 Codex 輪次 ID |
trigger |
string |
壓縮的觸發方式:manual 或 auto |
stdout 上的純文本會被忽略。
stdout 上的 JSON 支援通用輸出欄位。如果匹配的
PostCompact 鉤子傳回 continue: false,Codex 會在壓縮後停止。
UserPromptSubmit
matcher 目前不用於此事件。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
turn_id |
string |
Codex 專用欄位。活躍的 Codex 輪次 ID |
prompt |
string |
即將傳送的使用者提示詞 |
stdout 上的純文本會被新增為額外的開發者上下文。
stdout 中的 JSON 支援通用輸出欄位以及
以下鉤子專用結構:
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "Ask for a clearer reproduction before editing files."
}
}其中的 additionalContext 文本會被新增為額外的開發者上下文。
要阻止提示詞,請傳回:
{
"decision": "block",
"reason": "Ask for confirmation before doing that."
}你也可以使用退出碼 2,並將阻止原因寫入 stderr。
SubagentStop
此事件會將 matcher 應用於 agent_type。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
turn_id |
string |
Codex 專用欄位。當前 Codex 輪次 ID |
agent_id |
string |
子智能體的識別符 |
agent_type |
string |
子智能體類型或設定檔 |
agent_transcript_path |
string | null |
子智能體記錄檔案的路徑(如有) |
stop_hook_active |
boolean |
此子智能體是否已繼續執行 |
last_assistant_message |
string | null |
最新的子智能體助手訊息(如有) |
SubagentStop 退出 0 時,要求在 stdout 上輸出 JSON。對於此事件,
純文本輸出無效。
stdout 上的 JSON 支援通用輸出欄位。若要讓
Codex 繼續子智能體流程,請傳回:
{
"decision": "block",
"reason": "Run one more focused pass inside the subagent."
}你也可以使用結束代碼 2,並將繼續執行的原因寫入 stderr。
如果任一匹配的 SubagentStop 鉤子傳回 continue: false,其優先順序將
高於其他匹配的 SubagentStop
鉤子所作的繼續執行決定。
Stop
matcher 目前不用於此事件。
除通用輸入欄位外,還包含以下欄位:
| 欄位 | 類型 | 含義 |
|---|---|---|
turn_id |
string |
Codex 專用欄位。當前 Codex 輪次 ID |
stop_hook_active |
boolean |
此輪次是否已由 Stop 繼續執行 |
last_assistant_message |
string | null |
最新的助手訊息文本(如有) |
Stop 退出 0 時,要求在 stdout 上輸出 JSON。對於此事件,純文本輸出
無效。
stdout 上的 JSON 支援通用輸出欄位。若要讓
Codex 繼續執行,請傳回:
{
"decision": "block",
"reason": "Run one more pass over the failing tests."
}你也可以使用結束代碼 2,並將繼續執行的原因寫入 stderr。
對於此事件,decision: "block" 不會拒絕該輪次。相反,它會指示
Codex 繼續執行,並自動建立一個新的繼續提示詞;該提示詞將作為
新的使用者提示詞,並以你的 reason 作為提示詞文本。
如果任一匹配的 Stop 鉤子傳回 continue: false,其優先順序將高於
其他匹配的 Stop 鉤子所作的繼續執行決定。
Interrupt
當你中斷主聊天上正在進行的輪次時,Interrupt 會執行。可使用它
記錄中斷,或清理由鉤子啟動的工作。它不會針對空閒聊天或子智能體執行,
並且會忽略任何已設定的 matcher。
除通用輸入欄位外,該事件還包括
turn_id(被中斷輪次的 id)和 permission_mode。
命令鉤子的預設超時時間為一秒。設定的超時時間
僅限一至三秒。鉤子輸出無法阻止
中斷或重新啟動輪次。以 0 退出且不輸出任何內容,或者傳回包含
可選 systemMessage 的 JSON 以顯示警告。純文本輸出對此事件無效。
{ "systemMessage": "Saved the interrupted turn to the local audit log." }資料結構
如果需要當前準確的傳輸格式,請參閱 Codex GitHub 儲存庫中生成的資料結構。
純文本別名
- string | null