PostToolUse replacement is ignored for code-mode tool results
Version
- Codex CLI: 0.146.0
- Source: current
mainat3ca9f375aa2369eb901ccfc70e86c74dabc588b1 - Platform: macOS arm64
- Subscription/model: not relevant; this reproduces in the local tool dispatch path
What issue are you seeing?
A successful PostToolUse hook that returns continue: false plus a stopReason replaces the model-visible result for a direct tool call, but the replacement is ignored when the same tool runs inside code mode.
The hook runs once and receives the original result, yet the code-mode promise resolves with the original typed tool output. This breaks direct/code-mode parity and prevents a trusted hook from replacing a verbose result before the next model request.
Steps to reproduce
- Enable code mode and configure a trusted
PostToolUsecommand hook matchingBash. - Have the hook return a successful replacement using
continue: falseand a boundedstopReason. - Run one shell command through code mode.
- Inspect the nested
tools.exec_commandresult sent by code mode.
Actual: the nested result contains the original command output and omits the hook replacement.
Expected: the nested result contains the hook replacement and excludes the original output, matching the existing direct-tool behavior. Decision-block and exit-2 outcomes must continue to reject rather than resolve.
A discriminating integration test is available here:
https://github.com/jbknick/codex/commit/d90965579a8c6adfde66efafd2d26eccfafeb2fc
Root cause
PostToolUseFeedbackOutput::to_content() already delegates to model_visible, but PostToolUseFeedbackOutput::code_mode_result() delegates to original. Code mode calls result.code_mode_result(), so it bypasses the successful hook replacement.
The minimal correction is one line: delegate code_mode_result() to model_visible, exactly as the direct path does. Blocking outcomes are rejected before this wrapper is constructed, so their behavior is unchanged.
Validation
On the linked commit:
- baseline-fail/patched-pass integration regression: pass
- focused unit regression: pass
- all 23
PostToolUsetests: pass - complete
codex-coresuite: 3,247 passed, 19 skipped just fix -p codex-core: passjust fmt: pass- exact-diff review: pass with no correctness or security findings
The repository-wide suite is not claimed as passed: the workspace includes codex-code-mode-runtime, whose pinned rusty_v8 150.4.0 sandbox debug archive for Apple silicon currently returns HTTP 404.
Related: #31015 and #21753.
I understand external contributions are invitation-only, so I have not opened a pull request. If this scope is acceptable, would a maintainer be willing to invite a PR for the linked minimal fix and regression?