[codex plugin 1.0.2] Broker IPC hangs on Windows (~20% failure rate) — skill dispatch never completes
Environment
- OS: Windows 11 Pro 10.0.26200
- Claude Code: 2.1.109
- Shell: Git Bash
- Node: v24.14.0
- codex plugin:
openai-codex/codexv1.0.2 (installed 2026-04-04) - codex CLI: 0.118.0 (npm global)
Summary
Invoking /codex:rescue, /codex:review, /codex:adversarial-review through the skill dispatch hangs indefinitely about 20% of the time. The turn never completes — no output, no error, no timeout. Direct invocation of codex exec from Git Bash always works.
Observed Behavior
- Skill dispatch: ~80% succeed normally, ~20% hang for >20 minutes with no output
- No stderr, no recovery — user must abandon the turn
- Happens across all three commands (
rescue,review,adversarial-review) - Over one day of normal use: 80+ invocations, 18+ hangs
Forensic Evidence
After a hang, the following zombie state is left behind:
- Stale broker directory
/tmp/cxc-<id>/persists with:
broker.pidcontaining a PID that is no longer alivebroker.logcontaining only deprecation warnings, no IPC activity- No
*.sockfile (socket never bound, or cleaned on crash)
- Empty state directory
/tmp/codex-companion/<workspace-hash>/exists butjobs/was never created — indicatingwriteJobFile()was never reached. - PID in
broker.pidis a genuine zombie —kill -0 $PIDreturns failure, but directory is not cleaned.
Root Cause Analysis
Tracing through the plugin source (paths under ~/.claude/plugins/cache/openai-codex/codex/1.0.2/):
User /codex:rescue
→ skill wrapper (rescue.md)
→ node codex-companion.mjs task
→ withAppServer(cwd, fn) [codex.mjs:607]
→ CodexAppServerClient.connect(cwd) [codex.mjs:610]
→ ensureBrokerSession(cwd) [broker-lifecycle.mjs:113]
→ spawnBrokerProcess() [broker-lifecycle.mjs:59-70]
→ waitForBrokerEndpoint(2000ms) [broker-lifecycle.mjs:149]
⨯ HANGS HERE on Windows
Hypotheses (Windows-specific)
- Unix socket path emulation:
brokerEndpointat/tmp/cxc-*/*.sockis created under Windows' emulated/tmp. Under Node.js on Windows, unix socket connection is unreliable — especially when the broker child process is spawned withdetached: true, stdio: ["ignore", logFd, logFd](broker-lifecycle.mjs:59-70). File descriptor writes are not atomic on Windows. - Line buffering + CRLF:
handleLine()inapp-server.mjs:117-128splits JSON-RPC messages on\n. If the broker emits\r\non Windows, upstream parsers may drop notifications — including the completion signal. - Race condition in
scheduleInferredCompletion()(codex.mjs:367-388): uses a 250mssetTimeoutto detect "inferred completion" againststate.pendingCollaborationsandstate.activeSubagentTurns. A missed notification + stale set membership → turn never completes →captureTurn()(codex.mjs:553-605) never resolves. - Broker race on cold start: first connection after a new broker spawn is where the 20% failure clusters. Warm broker (previous task succeeded) tends to stay stable.
Minimal Repro Attempt
No reliable repro — it's intermittent. Rough steps:
- Leave codex plugin idle for 30+ minutes (broker dies)
- Invoke
/codex:rescue "any prompt" - ~1 in 5 invocations hangs indefinitely; rest complete normally
Workaround
Bypass the skill entirely and call codex exec directly from bash. Example wrapper:
\\\`bash
direct codex exec + zombie cleanup
shopt -s nullglob
for dir in /tmp/cxc-*; do
PID=\$(cat "\$dir/broker.pid" 2>/dev/null)
if [[ -n "\$PID" ]] && kill -0 "\$PID" 2>/dev/null; then continue; fi
AGE_MIN=\$(( ( \$(date +%s) - \$(stat -c %Y "\$dir") ) / 60 ))
[[ \$AGE_MIN -ge 30 ]] && rm -rf "\$dir"
done
codex exec "\$PROMPT"
\\\`
This is stable across 100+ invocations, confirming the issue is in the broker/IPC layer, not codex CLI itself.
Requested Fix Direction
- Treat
waitForBrokerEndpoint()timeout as fatal — surface an error to Claude Code instead of hanging Promise forever - Add CRLF normalization in
handleLine()before JSON-RPC parse - On Windows, fall back from unix socket to named pipe (
\.\pipe\codex-*) which is native Windows IPC and better supported by Node.js - Add pre-flight cleanup of stale
/tmp/cxc-*directories inensureBrokerSession()
Impact
For users running Claude Code on Windows, this silently burns 20% of codex-related interactions. Hard to diagnose without plugin internals, and no user-visible error means users often blame their own prompts.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗