PostToolUse: non-blocking model-visible tool output replacement

Open 💬 1 comment Opened Jul 23, 2026 by Marcus-Rise

What variant of Codex are you using?

CLI and Desktop (native command hooks).

What feature would you like to see?

Add a non-blocking PostToolUse response that replaces only the output sent back to the model while preserving the tool call's successful semantics.

Proposed wire contract:

{
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "updatedToolOutput": "bounded replacement"
  }
}

The same generic field should work for successful shell and MCP tool results. Existing updatedMCPToolOutput should remain supported for compatibility. If several hooks return valid replacements, the last valid replacement should win; updatedToolOutput should take precedence over the MCP-specific field within one response. Invalid JSON kinds should be rejected without silently changing the typed tool result.

The original typed result should remain available to code mode, internal logging, and transcript/event consumers. Only the result supplied to the model should be replaced, without requiring decision: "block" and without converting a successful tool call into an error.

Additional information

This is intentionally narrower than #31015. It does not claim to remove sensitive content from the UI, logs, or persisted transcript; that requires a separate lifecycle/privacy design.

This proposal is a continuation of the model-visible replacement work in closed PR #20703, which was closed by the inactivity bot rather than rejected in review. That implementation should be audited and ported against current main, not cherry-picked blindly.

Relates #31015. Continuation of #20703.

View original on GitHub ↗

1 Comment

Marcus-Rise · 1 month ago

Implementation is ready in Marcus-Rise/codex at commit 697db0b173abbffc7e7a708f3fd78fe0f15ee71c: https://github.com/Marcus-Rise/codex/commit/697db0b173abbffc7e7a708f3fd78fe0f15ee71c. I audited closed PR #20703 and reimplemented the contract without cherry-picking it. The branch preserves original typed outputs for code mode/logging, validates JSON kind, keeps success semantics, and makes only the model-facing projection replaceable. Focused hook/core tests pass; full suite completed with only unrelated baseline/environment failures. Per the current invitation-only contribution policy, I have not opened an upstream PR. Happy to open the atomic branch if a maintainer invites it.