diff --git a/plugins/codex/agents/codex-rescue.md b/plugins/codex/agents/codex-rescue.md
index 2e8a028d..b985cda6 100644
--- a/plugins/codex/agents/codex-rescue.md
+++ b/plugins/codex/agents/codex-rescue.md
@@ -20,9 +20,9 @@ Selection guidance:
Forwarding rules:
- Use exactly one `Bash` call to invoke `node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task ...`.
-- If the user did not explicitly choose `--background` or `--wait`, prefer foreground for a small, clearly bounded rescue request.
-- If the user did not explicitly choose `--background` or `--wait` and the task looks complicated, open-ended, multi-step, or likely to keep Codex running for a long time, prefer background execution.
-- For any task expected to exceed a few minutes, add `--background` to the `task` invocation by default so a caller timeout cannot terminate it.
+- Default to `--background`. Rescue tasks are open-ended by nature and routinely exceed Claude's Bash-tool timeout; a foreground `task` that gets auto-backgrounded by the host at its timeout MUST be treated as terminal (see below) — it cannot be turned back into a foreground wait, so backgrounding from the start avoids the trap entirely. Only use foreground (no `--background`) when the caller passed `--wait` explicitly.
+- Add `--background` to the `task` invocation unless the caller explicitly chose `--wait`.
+- If the single `task` Bash call returns because it hit the host's Bash-tool timeout (foreground run that the host auto-backgrounded) — STOP. Do NOT issue a second Bash call. Do NOT poll `status`, `result`, `cat`, `sleep`, or `until grep`. Return the companion's stdout so far (possibly empty) as-is. The Codex turn keeps running in the background and is recovered later via `/codex:status` / `/codex:result` by the caller — never by this subagent.
- Treat `--cwd
` and `-C ` as workspace routing controls. Pass `--cwd ` explicitly on every `task` invocation, using the intended workspace root forwarded by the caller.
- You may use the `gpt-5-4-prompting` skill only to tighten the user's request into a better Codex prompt before forwarding it.
- Do not use that skill to inspect the repository, reason through the problem yourself, draft a solution, or do any independent work beyond shaping the forwarded prompt text.
@@ -41,7 +41,7 @@ Forwarding rules:
- Otherwise forward the task as a fresh `task` run.
- Preserve the user's task text as-is apart from stripping routing flags.
- Return the stdout of the `codex-companion` command exactly as-is.
-- If the Bash call fails or Codex cannot be invoked, return nothing.
+- If the Bash call fails, returns by host Bash-tool timeout, or Codex cannot be invoked, return nothing (or the partial stdout captured so far) and make NO further Bash calls. A timed-out foreground run is terminal, not a signal to poll.
Response style:
diff --git a/plugins/codex/commands/rescue.md b/plugins/codex/commands/rescue.md
index 6fed2a0f..dd30cfed 100644
--- a/plugins/codex/commands/rescue.md
+++ b/plugins/codex/commands/rescue.md
@@ -15,7 +15,7 @@ Execution mode:
- If the request includes `--background`, run the `codex:codex-rescue` subagent in the background.
- If the request includes `--wait`, run the `codex:codex-rescue` subagent in the foreground.
-- If neither flag is present, default to foreground.
+- If neither flag is present, default to `--background`. Rescue tasks are open-ended and routinely exceed Claude's Bash-tool timeout; starting in background avoids the auto-background trap (see Operating rules).
- `--background` and `--wait` are execution flags for Claude Code. Do not forward them to `task`, and do not treat them as part of the natural-language task text.
- `--model` and `--effort` are runtime-selection flags. Preserve them for the forwarded `task` call, but do not treat them as part of the natural-language task text.
- `--cwd ` and `-C ` are workspace-routing flags. Preserve the directory for the resume preflight and the forwarded `task` call, but do not treat either form as part of the natural-language task text.
@@ -46,7 +46,8 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task-resume-candidate -
Operating rules:
- The subagent is a thin forwarder only. It should use one `Bash` call to invoke `node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task ...` and return that command's stdout as-is.
-- Pass `--cwd ` explicitly for the intended workspace root. For work expected to exceed a few minutes, have the subagent add the task command's own `--background` flag so a caller timeout cannot terminate it.
+- Pass `--cwd ` explicitly for the intended workspace root. Add `--background` to the `task` invocation unless the caller explicitly chose `--wait`, so a caller Bash-tool timeout cannot terminate the run or force an auto-background.
+- Terminal-on-timeout: if the single `task` Bash call returns because the host auto-backgrounded it at the Bash-tool timeout, the subagent MUST make no second Bash call (no `status`, `result`, `cat`, `sleep`, or `until grep`). The Codex turn keeps running and is recovered later by the caller via `/codex:status` / `/codex:result`.
- Return the Codex companion stdout verbatim to the user.
- Do not paraphrase, summarize, rewrite, or add commentary before or after it.
- Do not ask the subagent to inspect files, monitor progress, poll `/codex:status`, fetch `/codex:result`, call `/codex:cancel`, summarize output, or do follow-up work of its own.
diff --git a/tests/commands.test.mjs b/tests/commands.test.mjs
index d3c4f8e1..5dce734a 100644
--- a/tests/commands.test.mjs
+++ b/tests/commands.test.mjs
@@ -133,7 +133,7 @@ test("rescue command absorbs continue semantics", () => {
assert.match(rescue, /Continue current Codex thread/);
assert.match(rescue, /Start a new Codex thread/);
assert.match(rescue, /run the `codex:codex-rescue` subagent in the background/i);
- assert.match(rescue, /default to foreground/i);
+ assert.match(rescue, /default to `--background`/i);
assert.match(rescue, /Do not forward them to `task`/i);
assert.match(rescue, /`--model` and `--effort` are runtime-selection flags/i);
assert.match(rescue, /Leave `--effort` unset unless the user explicitly asks for a specific reasoning effort/i);
@@ -155,9 +155,10 @@ test("rescue command absorbs continue semantics", () => {
assert.match(agent, /--resume/);
assert.match(agent, /--fresh/);
assert.match(agent, /thin forwarding wrapper/i);
- assert.match(agent, /prefer foreground for a small, clearly bounded rescue request/i);
- assert.match(agent, /If the user did not explicitly choose `--background` or `--wait` and the task looks complicated, open-ended, multi-step, or likely to keep Codex running for a long time, prefer background execution/i);
- assert.match(agent, /expected to exceed a few minutes.*`--background`/i);
+ assert.match(agent, /Default to `--background`/i);
+ assert.match(agent, /Add `--background` to the `task` invocation unless the caller explicitly chose `--wait`/i);
+ assert.match(rescue, /Terminal-on-timeout/i);
+ assert.match(agent, /A timed-out foreground run is terminal, not a signal to poll/i);
assert.match(agent, /pass `--cwd ` explicitly/i);
assert.match(agent, /`--cwd ` and `-C `.*workspace routing controls/i);
assert.match(agent, /Use exactly one `Bash` call/i);
@@ -168,7 +169,7 @@ test("rescue command absorbs continue semantics", () => {
assert.match(agent, /If the user asks for `spark`, map that to `--model gpt-5\.3-codex-spark`/i);
assert.match(agent, /If the user asks for a concrete model name such as `gpt-5\.4-mini`, pass it through with `--model`/i);
assert.match(agent, /Return the stdout of the `codex-companion` command exactly as-is/i);
- assert.match(agent, /If the Bash call fails or Codex cannot be invoked, return nothing/i);
+ assert.match(agent, /If the Bash call fails, returns by host Bash-tool timeout, or Codex cannot be invoked, return nothing/i);
assert.match(agent, /gpt-5-4-prompting/);
assert.match(agent, /only to tighten the user's request into a better Codex prompt/i);
assert.match(agent, /Do not use that skill to inspect the repository, reason through the problem yourself, draft a solution, or do any independent work/i);