Proposal: add PreToolUse/PostToolUse lifecycle hooks to Codex hooks engine
Summary
I'd like to propose adding first-class tool lifecycle hooks to the new hooks engine, specifically:
PreToolUsePostToolUse
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/PostToolUsecompatibility 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:
PreToolUsePostToolUse- 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/HookCompletedevents 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:
sessionIdturnIdcwdtranscriptPathmodelpermissionModecallIdtoolNametoolKindtoolInput
And for post-tool hooks additionally:
executedsuccessdurationMsoutputPreview
Local prototype status
I implemented this locally against the current hooks architecture and verified:
cargo check -p codex-corecargo test -p codex-hooks- a focused integration test that confirms both
PreToolUseandPostToolUseare actually triggered around a realshell_command
The integration test verifies that:
HookStarted/HookCompletedare 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
PostToolUseshould support blocking vs warning-only behavior - whether this should coexist with legacy
after_tool_usehooks or replace them over time
6 Comments
Additional context: my main reason for wanting tool-use hooks is usage analysis.
I want to track which tools I use most, which tool sequences repeat in real work, and which tools tend to be used together. I am mainly using this as a foundation for lightweight workflow analysis and continuous learning.
A big reference for me is the
everything-claude-codeproject. What is useful there is not just session memory, but observing tool behavior over time and learning from repeated patterns.That is why
PreToolUse/PostToolUsematter more than session-only hooks for my use case. If I want to understand real Codex workflows, the important signals are around tool boundaries:So for me, this feature is mainly about tool statistics and workflow learning, not just blocking or policy enforcement.
This hook would be a very valuable addition, and a concrete use case is RTK: https://github.com/rtk-ai/rtk
Specifically:
PreToolUsehook and OpenCode providestool.execute.before.Native support for a
PreToolUse-style hook in Codex would be much cleaner.If this is not something you plan to support, I would still appreciate guidance on whether it makes sense for me to continue maintaining the experimental RTK workaround.
@etraut-openai I'm very excited to submit this PR!!! Could you consider opening permissions, or are there other options?
I read the merged hooks work, the current
codex-rs/hooksimplementation, and the open proposals. I think the narrowest useful proposal to discuss here is smaller than a fullPreToolUse + PostToolUseexpansion plus a separatePermissionRequesthook.What seems already true:
StopandUserPromptSubmithooks already show how blocking / feedback semantics are encoded at the hook layer#15211shows that a shell-focusedPreToolUsepath is implementable with the current plumbing#13498is useful context, but it is an open PR aimed at broader lifecycle coverage and is explicitly narrower than the broader Claude-compatible hooks lineIf the goal is to land something practical first, the smallest cut that still looks useful to me is:
PreToolUsePostToolUse,PermissionRequest, persistent allow rules, and non-shell tool coverageI think that version is easier to review because it fits the current hooks engine, solves an obvious use case, and keeps the schema and test surface much smaller than a combined Pre/Post/PermissionRequest feature.
It would still cover a lot of real workflows, including the command-gating cases described in
#14754, while leaving room for a later step toward#15311if maintainers want a dedicated approval-oriented hook afterPreToolUseexists.If this direction sounds right, I’d expect the next step to be one of:
#15211toward the agreed MVP shapeI’m not posting code here because
docs/contributing.mdis explicit that external code contributions are by invitation only and unsolicited PRs will be closed. I wanted to sanity-check the scope here before going further.Indexed this hook ticket in the umbrella tracker: #21753
Goal: collect the scattered Codex hook requests and bugs into one parity matrix for Full Claude Code Hook Parity (29+), while preserving this issue as the detailed thread for its specific behavior.
For design reference: agent-manual (https://github.com/Ar9av/agent-manual) documents how Claude Code and Gemini CLI implement these hooks today.
Claude Code fires
PreToolUsebefore every tool call with a JSON stdin payload (session_id,transcript_path,hook_event_name,tool_name,tool_input). Exit code 2 blocks the call and sends stderr back to the model as context.PostToolUseruns after with the same fields plustool_response. Both support amatcherfield so hooks can target specific tools (e.g. onlyBash, ormcp__github__*).Gemini CLI calls them
BeforeToolandAfterTool. Same general pattern but withhook_event_nameinstead ofevent, and AfterTool can suppress the tool output from reaching the model viadecision: deny— which Claude Code's PostToolUse doesn't support.The biggest divergence is blocking on
PostToolUse/AfterTool: Claude Code treats it as observe-only; Gemini CLI lets you intercept. Worth deciding which way Codex goes before shipping.