2 2
3> For the complete documentation index, see [llms.txt](https://learn.chatgpt.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.3> For the complete documentation index, see [llms.txt](https://learn.chatgpt.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.
4 4
5Hooks are an extensibility framework for Codex. They allow5Hooks are an extensibility framework for Codex. They let you run scripts or MCP
6you to inject your own scripts into the agentic loop, enabling features such as:6tools during the agentic loop, enabling features such as:
7 7
8- Send the chat to a custom logging/analytics engine8- Send the chat to a custom logging/analytics engine
9- Scan your team's prompts to block accidentally pasting API keys9- Scan your team's prompts to block accidentally pasting API keys
16- Matching hooks from multiple files all run.16- Matching hooks from multiple files all run.
17- Multiple matching command hooks for the same event are launched concurrently,17- Multiple matching command hooks for the same event are launched concurrently,
18 so one hook can't prevent another matching hook from starting.18 so one hook can't prevent another matching hook from starting.
19- Non-managed command hooks must be reviewed and trusted before they run.19- Non-managed hooks must be reviewed and trusted before they run.
20 20
21Hooks run at different points in a conversation:21Hooks run at different points in a conversation:
22 22
61## Review and trust hooks61## Review and trust hooks
62 62
63Codex lists configured hooks before deciding which ones can run. Before a63Codex lists configured hooks before deciding which ones can run. Before a
64non-managed command hook can run, Codex requires you to review and trust the64non-managed hook can run, Codex requires you to review and trust the exact hook
65exact hook definition. Codex records trust against the hook's current hash, so65definition. Codex records trust against the hook's current hash, so new or
66new or changed hooks are marked for review and skipped until trusted.66changed hooks are marked for review and skipped until trusted.
67 67
68Use `/hooks` in the CLI to inspect hook sources, review new or changed hooks,68Use `/hooks` in the CLI to inspect hook sources, review new or changed hooks,
69trust hooks, or disable individual non-managed hooks. If hooks need review at69trust hooks, or disable individual non-managed hooks. If hooks need review at
189 `command_windows` or `commandWindows`.189 `command_windows` or `commandWindows`.
190- Set `async` to `true` to [run a command hook in the190- Set `async` to `true` to [run a command hook in the
191 background](#run-hooks-in-the-background).191 background](#run-hooks-in-the-background).
192- Only `type: "command"` handlers run today. `prompt` and `agent` handlers are192- `command` and `mcp_tool` handlers are supported. `prompt` and `agent`
193 parsed but skipped.193 handlers are parsed but skipped.
194- Commands run with the session `cwd` as their working directory.194- Commands run with the session `cwd` as their working directory.
195- For repo-local hooks, prefer resolving from the git root instead of using a195- For repo-local hooks, prefer resolving from the git root instead of using a
196 relative path such as `.codex/hooks/...`. Codex may be started from a196 relative path such as `.codex/hooks/...`. Codex may be started from a
226statusMessage = "Reviewing Bash output"226statusMessage = "Reviewing Bash output"
227```227```
228 228
229## MCP tool hooks
230
231An MCP tool hook lets a lifecycle event call a tool on an already-connected MCP
232server. It sends structured arguments directly to the tool and uses the same
233trust review and output contract as a command hook.
234
235### Configure an MCP tool hook
236
237This hook asks the `scanner` MCP server to scan each patch after Codex writes or
238edits files:
239
240```json
241{
242 "hooks": {
243 "PostToolUse": [
244 {
245 "matcher": "Write|Edit",
246 "hooks": [
247 {
248 "type": "mcp_tool",
249 "server": "scanner",
250 "tool": "scan_patch",
251 "input": { "patch": "${tool_input.command}" },
252 "timeout": 30,
253 "statusMessage": "Scanning edited files"
254 }
255 ]
256 }
257 ]
258 }
259}
260```
261
262| Field | Meaning |
263| --------------- | ---------------------------------------------------------------- |
264| `type` | Must be `mcp_tool`. |
265| `server` | Required name of an already-connected MCP server. |
266| `tool` | Required name of a tool exposed by that server. |
267| `input` | Optional JSON object of argument templates. Defaults to `{}`. |
268| `timeout` | Optional active execution timeout in seconds. Defaults to `600`. |
269| `statusMessage` | Optional message shown while the hook runs. |
270
271### Expand arguments from the hook event
272
273Use `${field.nested}` to read a dotted field from the hook event. A placeholder
274that fills an entire value keeps its JSON type. A placeholder inside a larger
275string is rendered as text. Codex expands objects and arrays recursively.
276
277For an event containing `{"tool_input":{"file_path":"src/main.rs","count":3}}`,
278this argument template:
279
280```json
281{
282 "path": "${tool_input.file_path}",
283 "count": "${tool_input.count}",
284 "message": "Scanning ${tool_input.file_path}"
285}
286```
287
288becomes:
289
290```json
291{
292 "path": "src/main.rs",
293 "count": 3,
294 "message": "Scanning src/main.rs"
295}
296```
297
298### Execution and lifecycle
299
300- Hooks use an existing MCP connection. They don't start or reconnect servers.
301- A hook can block an operation when the tool returns a blocking decision.
302 Errors, missing servers, and unavailable tools don't block the operation.
303- MCP tool hooks run synchronously. They don't request tool approval or trigger
304 other hooks.
305- The shorter hook or server timeout applies. Time spent waiting for an MCP
306 elicitation response doesn't count against the timeout.
307- `SessionStart` hooks can run before an MCP server is ready. If that happens,
308 they don't block the session.
309- `SessionEnd` doesn't support MCP tool hooks.
310
229## Turn hooks off311## Turn hooks off
230 312
231Hooks are enabled by default. To turn them off in `config.toml`, set:313Hooks are enabled by default. To turn them off in `config.toml`, set: