Summary
I'd like to propose adding first-class tool lifecycle hooks to the new hooks engine, specifically:
This would extend the current lifecycle coverage beyond SessionStart and Stop and make it possible to observe, validate, or block tool execution before and after a tool call runs.
I reviewed the recent hooks work in PR #13276 and built a prototype locally using the same overall architecture.
Motivation
The current lifecycle hooks cover session boundaries, but not the most important execution boundary in Codex: tool calls.
Tool-use hooks would enable workflows like:
- validating tool arguments before execution
- blocking risky tool invocations with feedback to the model
- logging tool usage for project memory / learning workflows
- post-tool verification, auditing, and automatic warnings
- Claude-style
PreToolUse / PostToolUse compatibility for users migrating workflows
Proposed design
Following the direction of the new hooks engine introduced in PR #13276, the proposal is:
- add new hook event names:
- support them in
hooks.json
- define explicit input/output schemas for both events
- route them through the same hook engine / dispatcher / output parser path as the existing lifecycle hooks
- emit
HookStarted / HookCompleted events for these hooks as well
- invoke them from the core tool dispatch path
Matching
Use the existing matcher-group pattern and match on tool_name, for example:
{
"hooks": {
"PreToolUse": [
{
"matcher": "shell_command|exec_command",
"hooks": [
{
"type": "command",
"command": "python my_pre_hook.py"
}
]
}
],
"PostToolUse": [
{
"matcher": "shell_command",
"hooks": [
{
"type": "command",
"command": "python my_post_hook.py"
}
]
}
]
}
}
Semantics
PreToolUse
- runs before the tool executes
- can block execution and provide feedback
PostToolUse
- runs after the tool executes
- receives execution metadata such as success, duration, and output preview
Example input fields
In the prototype, tool hook payloads include fields like:
sessionId
turnId
cwd
transcriptPath
model
permissionMode
callId
toolName
toolKind
toolInput
And for post-tool hooks additionally:
executed
success
durationMs
outputPreview
Local prototype status
I implemented this locally against the current hooks architecture and verified:
cargo check -p codex-core
cargo test -p codex-hooks
- a focused integration test that confirms both
PreToolUse and PostToolUse are actually triggered around a real shell_command
The integration test verifies that:
HookStarted / HookCompleted are emitted for both events
- the hook commands are executed
- the hook payloads contain the expected tool metadata
- the wrapped tool still executes normally
Question
Would the maintainers be open to this feature?
I saw the contribution policy in docs/contributing.md and understand that external PRs are only accepted when invited. If this direction makes sense, I'd be happy to open a PR from my prototype branch after maintainer guidance on:
- event naming / semantics
- expected schema shape
- whether
PostToolUse should support blocking vs warning-only behavior
- whether this should coexist with legacy
after_tool_use hooks or replace them over time
Summary
I'd like to propose adding first-class tool lifecycle hooks to the new hooks engine, specifically:
PreToolUsePostToolUseThis would extend the current lifecycle coverage beyond
SessionStartandStopand make it possible to observe, validate, or block tool execution before and after a tool call runs.I reviewed the recent hooks work in PR #13276 and built a prototype locally using the same overall architecture.
Motivation
The current lifecycle hooks cover session boundaries, but not the most important execution boundary in Codex: tool calls.
Tool-use hooks would enable workflows like:
PreToolUse/PostToolUsecompatibility for users migrating workflowsProposed design
Following the direction of the new hooks engine introduced in PR #13276, the proposal is:
PreToolUsePostToolUsehooks.jsonHookStarted/HookCompletedevents for these hooks as wellMatching
Use the existing matcher-group pattern and match on
tool_name, for example:{ "hooks": { "PreToolUse": [ { "matcher": "shell_command|exec_command", "hooks": [ { "type": "command", "command": "python my_pre_hook.py" } ] } ], "PostToolUse": [ { "matcher": "shell_command", "hooks": [ { "type": "command", "command": "python my_post_hook.py" } ] } ] } }Semantics
PreToolUsePostToolUseExample input fields
In the prototype, tool hook payloads include fields like:
sessionIdturnIdcwdtranscriptPathmodelpermissionModecallIdtoolNametoolKindtoolInputAnd for post-tool hooks additionally:
executedsuccessdurationMsoutputPreviewLocal prototype status
I implemented this locally against the current hooks architecture and verified:
cargo check -p codex-corecargo test -p codex-hooksPreToolUseandPostToolUseare actually triggered around a realshell_commandThe integration test verifies that:
HookStarted/HookCompletedare emitted for both eventsQuestion
Would the maintainers be open to this feature?
I saw the contribution policy in
docs/contributing.mdand understand that external PRs are only accepted when invited. If this direction makes sense, I'd be happy to open a PR from my prototype branch after maintainer guidance on:PostToolUseshould support blocking vs warning-only behaviorafter_tool_usehooks or replace them over time