Skip to content

Codex Desktop Windows: PostToolUse fires for successful Bash calls but not failing Bash calls; hook payload can carry stale session metadata #300

@Minghou-Lei

Description

@Minghou-Lei

Codex Desktop hook repro on Windows

Summary

I reproduced two Codex hook lifecycle issues while testing context-mode with Codex Desktop on Windows:

  1. SessionStart and PreToolUse fire reliably.
  2. PostToolUse fires for successful Bash tool calls, but does not fire for failing Bash tool calls with non-zero exit codes.
  3. The hook payload can carry a stale session_id and transcript_path from an older session.

Because PostToolUse does not fire for failing Bash calls, context-mode cannot record the expected error_tool event for those failures.

This is different from #225. On this machine the dispatcher path works and successful Bash calls do produce PostToolUse; the remaining problem is that failing Bash calls do not.

Environment

  • OS: Windows
  • Client: Codex Desktop
  • Model shown in hook payload: gpt-5.4
  • Permission mode shown in hook payload: bypassPermissions
  • context-mode version: 1.0.89
  • Project cwd used in repro: C:\Users\admin\Documents\CodexPlayground

Hook configuration used

Working command form for this machine:

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "C:\\Windows\\System32\\cmd.exe /d /c C:\\Users\\admin\\AppData\\Roaming\\npm\\context-mode.cmd hook codex pretooluse"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "C:\\Windows\\System32\\cmd.exe /d /c C:\\Users\\admin\\AppData\\Roaming\\npm\\context-mode.cmd hook codex posttooluse"
          }
        ]
      }
    ],
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "C:\\Windows\\System32\\cmd.exe /d /c C:\\Users\\admin\\AppData\\Roaming\\npm\\context-mode.cmd hook codex sessionstart"
          }
        ]
      }
    ]
  }
}

For diagnosis I replaced those commands with wrapper scripts that:

  • read the raw hook stdin
  • forward stdin to context-mode.cmd hook codex <mode>
  • record stdin/stdout/stderr/exit code to files

The wrappers did not change the forwarded payload or returned output.

Repro steps

  1. Enable codex_hooks = true.
  2. Configure SessionStart, PreToolUse, and PostToolUse for context-mode.
  3. Start Codex Desktop in C:\Users\admin\Documents\CodexPlayground.
  4. Run a successful Bash command:
Write-Output 'controlled-success-test'
  1. Wait about 1 second.
  2. Run a failing Bash command:
$ErrorActionPreference='Continue'; Write-Error 'controlled-failure-test'; exit 13
  1. Wait at least 5 seconds.

Observed behavior

A. SessionStart works

After restart, a new sessionstart wrapper log is written and context-mode creates a new session row in the project DB.

Example captured payload:

{
  "session_id": "019da370-60bd-7c63-8c93-97fd35b5def2",
  "transcript_path": "C:\\Users\\admin\\.codex\\sessions\\2026\\04\\19\\rollout-2026-04-19T09-52-24-019da370-60bd-7c63-8c93-97fd35b5def2.jsonl",
  "cwd": "C:\\Users\\admin\\Documents\\CodexPlayground",
  "hook_event_name": "SessionStart",
  "model": "gpt-5.4",
  "permission_mode": "bypassPermissions",
  "source": "resume"
}

B. Successful Bash call fires both PreToolUse and PostToolUse

Captured PreToolUse payload:

{
  "session_id": "019da370-60bd-7c63-8c93-97fd35b5def2",
  "turn_id": "019da38f-ac6a-7640-8839-0cf7add93766",
  "cwd": "C:\\Users\\admin\\Documents\\CodexPlayground",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "$ErrorActionPreference='Stop'; Write-Output 'controlled-success-test'"
  }
}

Captured PostToolUse payload:

{
  "session_id": "019da370-60bd-7c63-8c93-97fd35b5def2",
  "turn_id": "019da38f-ac6a-7640-8839-0cf7add93766",
  "cwd": "C:\\Users\\admin\\Documents\\CodexPlayground",
  "hook_event_name": "PostToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "$ErrorActionPreference='Stop'; Write-Output 'controlled-success-test'"
  },
  "tool_response": "controlled-success-test\r\n"
}

PostToolUse arrived with a small delay, around 0.7 seconds after PreToolUse.

C. Failing Bash call fires PreToolUse only

Captured PreToolUse payload:

{
  "session_id": "019da370-60bd-7c63-8c93-97fd35b5def2",
  "turn_id": "019da38f-ac6a-7640-8839-0cf7add93766",
  "cwd": "C:\\Users\\admin\\Documents\\CodexPlayground",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "$ErrorActionPreference='Continue'; Write-Error 'controlled-failure-test'; exit 13"
  }
}

Observed after waiting more than 5 seconds:

  • a new pretooluse.* log exists
  • no matching posttooluse.* log exists
  • no new error_tool event is written to the context-mode session DB

Additional issue: stale session metadata

Both the successful and failing Bash hook payloads above used the same old:

  • session_id = 019da370-60bd-7c63-8c93-97fd35b5def2
  • transcript_path = C:\Users\admin\.codex\sessions\2026\04\19\rollout-2026-04-19T09-52-24-019da370-60bd-7c63-8c93-97fd35b5def2.jsonl

But the actual latest context-mode session DB row for the project had already advanced to a newer session, for example:

  • session_id = 019da38c-a001-7fb1-80df-beea02017957
  • started_at = 2026-04-19 02:23:17

So the hook payload appears to be using stale session metadata even while new sessions are being created.

Expected behavior

  1. PostToolUse should fire for both successful and failing Bash tool invocations.
  2. Failing Bash commands should still produce a PostToolUse payload so downstream tools like context-mode can record error events.
  3. session_id and transcript_path in hook payloads should match the current active session, not an older one.

Actual behavior

  1. Successful Bash: PreToolUse + delayed PostToolUse
  2. Failing Bash: PreToolUse only, no PostToolUse
  3. Hook payload session metadata can be stale

Why this matters for context-mode

context-mode can tolerate delay, but it cannot recover from a missing PostToolUse because:

  • no tool_response arrives for failed Bash calls
  • no error_tool event can be extracted
  • session continuity and event analytics become incomplete

Local evidence files

Wrapper logs used for proof:

  • C:\Users\admin\.codex\hook-debug\logs\20260419-022356-766-sessionstart.stdin.json
  • C:\Users\admin\.codex\hook-debug\logs\20260419-022729-654-pretooluse.stdin.json
  • C:\Users\admin\.codex\hook-debug\logs\20260419-022730-329-posttooluse.stdin.json
  • C:\Users\admin\.codex\hook-debug\logs\20260419-022836-053-pretooluse.stdin.json

Project session DB:

  • C:\Users\admin\.codex\context-mode\sessions\f9ad9d0a70d1bd89.db

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions