fix: unblock /codex:rescue (context: fork) and long /codex:review runs (120s Bash cap)#239
Open
moabualruz wants to merge 1 commit intoopenai:mainfrom
Open
fix: unblock /codex:rescue (context: fork) and long /codex:review runs (120s Bash cap)#239moabualruz wants to merge 1 commit intoopenai:mainfrom
moabualruz wants to merge 1 commit intoopenai:mainfrom
Conversation
Two independent bugs prevented Codex from ever being reached from
/codex:rescue, /codex:review, and /codex:adversarial-review:
1. /codex:rescue silently no-ops.
commands/rescue.md runs with `context: fork`, which spawns a
forked subagent whose prompt is the command body. The body says
"Route this request to the `codex:codex-rescue` subagent", but
Claude Code subagents cannot spawn other subagents (per
code.claude.com/docs/en/sub-agents), so the fork has no
executable path: it can't call the Agent tool, and the rescue
companion is never invoked.
Fix: keep `context: fork` (the isolation is valuable for long
Codex turns) and rewrite the fork's self-references in the body
so it runs `codex-companion.mjs task` directly via its existing
`Bash(node:*)` allowlist entry. Frontmatter is unchanged.
`agents/codex-rescue.md` stays in place for callers that invoke
the rescue subagent via the Agent tool from the main session.
2. /codex:review and /codex:adversarial-review time out in
foreground.
Both commands' Foreground flow runs the companion script via a
plain ```bash ...``` block, which Claude Code's Bash tool runs
with the default 120 000 ms timeout. Real Codex reviews on
non-trivial diffs take 3-10 minutes, so the Bash call is killed
before Codex returns and the job record is left as `running`.
Fix: switch Foreground flow to the same TypeScript-style
`Bash({...})` form the Background flow already uses, with
`timeout: 600000` (the 10-minute maximum). Tiny reviews stay
fast; larger ones now have room to finish.
Repro + verification
- Repro for /codex:rescue: tail a recent session transcript and
you'll see `Skill({skill:"codex:rescue"})` rejected with
"User rejected tool use" — the fork's body has no executable
path, so the tool call is the only visible attempt, and
Codex never runs.
- Verified fix: after the patch, `/codex:rescue reply the
single word PONG` returns `PONG` in a fresh session.
Scope and non-goals
- Not fixing: `/codex:status <job> --wait --timeout-ms <n>`
when n > 120000 uses `!`-prefix bang-exec in status.md and
can hit the same framework cap. Changing the dispatch style
is a separate, more invasive edit and a rarer flag
combination. Flagged here for maintainers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two independent bugs prevented Codex from ever being reached from the plugin's slash commands. Both are fixed here with surgical edits:
/codex:rescuesilently no-ops because the forked subagent's body tells it to delegate to another subagent, which Claude Code does not allow./codex:reviewand/codex:adversarial-reviewin foreground get killed mid-run because the foreground flow uses a plain bash code block, which Claude Code'sBashtool runs with its default 120 s timeout — well under a real Codex review's 3-10 min runtime.No frontmatter semantics change.
context: fork,disable-model-invocation, and allowlists are untouched.Bug 1:
/codex:rescue— unexecutable delegation inside a forkRepro
Run
/codex:rescue <anything>(or mention/codex:rescuein a longer prompt so Claude dispatches via theSkilltool). Command appears to hang and nothing Codex-side ever runs.Root cause
commands/rescue.mddeclarescontext: fork. Per the official Claude Code docs:The rule is categorical and overrides
allowed-tools. But the command body says:The forked subagent therefore has no executable path: it can't call the
Agenttool (subagents can't spawn subagents), and the companion script is never invoked. The visible artifact in session transcripts is aSkill({skill:\"codex:rescue\"})tool use followed bytoolUseResult: \"User rejected tool use\"— no Bash, no codex-companion, no subagent call.Fix
Keep
context: fork(the isolation is valuable — long Codex output stays out of the main conversation's context). Rewrite the body's self-references so the fork itself runscodex-companion.mjs taskdirectly via its existingBash(node:*)allowlist entry. The instructions the body already spells out (flag stripping,--writedefault,sparkmodel mapping, resume question flow) remain intact — only the "subagent" references change:Route this request to the codex:codex-rescue subagent.Forward this request to Codex via the codex-companion.mjs task script.run the codex:codex-rescue subagent in the backgroundrun the codex-companion.mjs task Bash call in the backgroundrun the codex:codex-rescue subagent in the foregroundrun the codex-companion.mjs task Bash call in the foregroundadd --resume before routing to the subagentadd --resume before invoking codex-companion.mjs taskadd --fresh before routing to the subagentadd --fresh before invoking codex-companion.mjs taskThe subagent is a thin forwarder only. It should use one Bash call ...You are a thin forwarder only. Use one Bash call ...Do not ask the subagent to inspect files ... or do follow-up work of its own.Do not inspect files ... or do follow-up work of your own.The subagent handles that routing when it builds the task command.Apply them when building the task command.agents/codex-rescue.mdis unchanged and still works for callers that invoke the rescue subagent via theAgenttool from a main-session context (e.g. proactive use by the main Claude outside this slash command).Bug 2:
/codex:reviewand/codex:adversarial-review— 120 s Bash cap kills long reviewsRepro
Run
/codex:review --waitagainst a working tree with ~30+ file diff. Companion starts, issues real tool calls, then is killed before finishing; the job is left withstatus: runningin state.Root cause
The Foreground flow in both commands is documented as:
Claude Code's
Bashtool, when the prompt doesn't tell it otherwise, defaults to a 120 000 ms timeout. Real Codex reviews over non-trivial diffs take several minutes (verified locally at ~5 m 30 s for a 44-file / 827-insertion working tree). The Bash call is SIGTERM'd before Codex returns; the detached companion state is left dangling.Fix
Switch the Foreground flow to the same TypeScript-style
Bash({...})form the Background flow already documents, withtimeout: 600000(the 10-minute maximum Claude Code allows):Same change applied to
adversarial-review.md. Tiny reviews are unaffected; larger ones now have room to finish.Not fixed (flagged for maintainers)
commands/status.mdruns!\node ... status "$ARGUMENTS"`via the!-prefix bang-exec form. If a user passes/codex:status --wait --timeout-mswithn > 120000, the same 120 s cap likely applies, since bang-exec goes through the same Bash runner. TheDEFAULT_STATUS_WAIT_TIMEOUT_MSincodex-companion.mjsis 240 000, so the default behaviour can also hit the cap when--waitis passed with no--timeout-ms`. Changing the dispatch style is a more invasive edit and the flag combination is rarer, so leaving it here for the maintainers to decide.Verification
/codex:rescue reply the single word PONGproduced no Bash call, no Codex call, and the Skill-tool dispatch was rejected (reproduced in live session transcript)./codex:rescue reply the single word PONGreturnsPONGin a fresh Claude Code session./codex:review --waiton small diffs still returns as before. Large-diff runs that previously died at ~120 s now complete end-to-end up to the 10-min Bash cap.Test plan
/codex:rescue reply the single word PONGreturnsPONGin a fresh session/codex:rescue <multi-line task>runs codex-companion with--write, returns stdout verbatim/codex:rescue --fresh <task>skips resume prompt;/codex:rescue --resume <task>passes--resume-last/codex:rescue --background <task>returns immediately with a job id;/codex:status <id>tracks it/codex:review --waiton a ~30-file diff completes past the old 120 s cap/codex:adversarial-review --wait <focus>also completes past the old cap/codex:review(no flag) still asks "Wait for results" vs "Run in background"