Skip to content

PreToolUse hooks do not fire for the internal patch/edit tool #26733

Description

@new-TonyWang

Summary

PreToolUse hooks registered for Write, Edit, and Bash matchers never fire when the Codex agent edits files, because the agent uses an internal patch tool that is not exposed as a matchable tool name.

Reproduction

  1. Build a minimal Codex plugin with a PreToolUse hook:
{
  "hooks": {
    "PreToolUse": [
      {"matcher": "Write", "hooks": [{"type": "command", "command": "$PLUGIN_ROOT/hooks/block.sh"}]},
      {"matcher": "Edit",  "hooks": [{"type": "command", "command": "$PLUGIN_ROOT/hooks/block.sh"}]},
      {"matcher": "Bash",  "hooks": [{"type": "command", "command": "$PLUGIN_ROOT/hooks/block.sh"}]}
    ]
  }
}

Where block.sh writes a marker file and exits 2.

  1. Install the plugin via local marketplace (codex plugin add).

  2. Launch Codex TUI:

codex --no-alt-screen --dangerously-bypass-hook-trust \
  -s workspace-write \
  "Write the text 'TEST' to test.txt using the Write tool. Then stop."
  1. Observe:
    • The agent responds: "I don't have a tool named Write in this environment, so I'll make the requested file edit with the available patch tool."
    • The file is modified (Added test.txt (+1 -0))
    • The marker file is never created — the hook never fired
    • This happens in both -s workspace-write and --dangerously-bypass-approvals-and-sandbox modes

Expected behavior

PreToolUse hooks should fire for the internal patch/edit tool, or a new matcher name (e.g., Patch, ApplyPatch, or FileEdit) should be documented so plugins can match it.

Actual behavior

The internal patch tool bypasses all PreToolUse hook matchers. There is no documented matcher name for it.

Impact

Plugins that rely on PreToolUse hooks for safety enforcement (e.g., blocking writes to protected files) cannot intercept file edits made by the Codex agent. The only remaining enforcement path is post-validation after the agent commits.

Environment

  • Codex CLI: v0.137.0
  • OS: Linux
  • Plugin hooks feature: enabled and working for Stop hooks (confirmed via marker files)

Notes

  • Stop hooks work correctly — confirmed with marker-based control tests (hook starts, times out as expected)
  • PreToolUse hooks work for Bash when the model explicitly uses the Bash tool (e.g., echo > file), but the model prefers the internal patch tool for file edits
  • The --dangerously-bypass-hook-trust flag is used; the issue is not about hook trust but about matcher coverage

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workinghooksIssues related to event hooks

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions