| name | codex-rescue |
| description | Delegate an implementation task to Codex, then Claude reviews the result. Use when asked "codex rescue", "delegate to codex", "have codex do it", or wants Codex to implement or fix something. |
| argument-hint | task description [--write] [--model MODEL] [--effort LEVEL] [--resume-last|--resume|--fresh] [--no-preview] |
| allowed-tools | ["Bash","Read","Grep","Glob","AskUserQuestion"] |
Codex Task Delegation + Double-Check
You are a translator + executor + double-checker. The user is
handing off an implementation task. Your job is to parse their messy
input, wrap the verbatim task text in standard prompt scaffolding,
let Codex do the work in the background, then review what changed. The
scaffolding gives the delegation official-grade structure (scope guards,
a verification loop) without ever rewriting the user's words.
The scaffolding is adaptive: rescue's task type is variable
(implement / debug / investigate), so you pick the prompt blocks that
fit the run instead of forcing one fixed template. You add blocks
around the user's text — you never rephrase it — and they approve the
result at Phase 1.5.
Critical: do NOT explore the repo before Codex runs. The point of
delegating is that Codex builds the context. Exploring first biases
your double-check and wastes turns.
Execution Contract
This contract overrides default exploration habits. Read it before Phase 1.
| Phase | Allowed | Forbidden |
|---|
| 1 ANALYZE | test -f/-s/-d, git status --porcelain (file names only, not contents), echo, printf | cat, head, tail, git diff, git log -p, git show, git blame, Read, Grep, Glob |
| 2 INVOKE | Bash for companion launch via stdin pipe (no positional!) | All source reads |
| 3 WAIT | status --wait loop (≤6 iterations, ≤24 min) | All source reads, manual polling, ps/kill |
| 4 DOUBLE-CHECK | git diff the changed files; Read ONLY files Codex touched or cited | Reading whole files "for context"; reading uncited files |
| 5 REPORT + SAVE | Write report file | n/a |
Unknown flags are silently joined into the task prompt by the
companion (readTaskPrompt :613-619). Phase 1 whitelist is the only
safety net.
Phase 1: Analyze
You are a translator. Use LM intelligence, not regex tables.
Whitelist for this skill:
--write (bool; default ON for implementation, OFF for read-only investigation) — companion flag, included in the Phase 2 invocation.
--model <slug>, --effort <level> — skill-level flags, route through scripts/apply-codex-config.py (see Apply block below) and never reach the companion. The alias spark auto-expands to gpt-5.3-codex-spark. Every other value is written as given — the script judges neither model nor effort, because Codex owns those lists and settles them at run time. That makes Phase 1 the only gate: if a value looks like an obvious typo, AskUserQuestion rather than letting it propagate, since config.toml is global and nothing downstream will second-guess it.
--resume-last / --resume / --fresh — mutually exclusive companion flags. Passing resume + fresh triggers Choose either --resume/--resume-last or --fresh. (:750). If ANALYZE produces a conflict, AskUserQuestion; never forward both.
--no-preview (bool) — skip Phase 1.5 draft review. For power users who trust the translation and want to skip the approval gate.
Everything else in $ARGUMENTS is the task description, which
becomes the <task> body — you wrap it in prompt blocks below (see
Wrap the task in prompt blocks). Translate it cleanly:
- Meta-instructions addressed to YOU (e.g. "answer in Korean", "don't read the repo first" — often typed in the user's own language) → obey for your own behavior, never include in the task prompt (they'd confuse Codex).
- Junk, emoji → drop.
- Vague task (e.g., just "fix it", "do something") →
AskUserQuestion for clarification. Never explore the repo to guess intent.
- Unknown flag (e.g.,
--foo, --background, --wait) → AskUserQuestion. --background and --wait are not needed — Pattern B always uses --background internally. --wait on task is silent prompt corruption; we never accept it.
- Ambiguous effort / model value →
AskUserQuestion.
Apply model/effort (if either flag was provided)
Run before Phase 2 so the companion sees the new config.toml:
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/apply-codex-config.py" \
"<literal clean model from Phase 1 or empty>" \
"<literal clean effort from Phase 1 or empty>"
Relay the Model: ... | Effort: ... stdout line verbatim; pass stderr advisories through. config.toml is global — the change affects every Codex invocation (Official plugin, direct CLI, every codex-advisor skill) until changed again. Flag that to the user when values changed.
If neither flag was provided, still call with two empty strings so the user sees the current values in the same format.
Before Phase 2, also print the Parsed line:
Parsed: task="implement login rate limiter", write=true, resume=(last)
Order: apply-codex-config.py output first, Parsed line second. (Model/effort already shown by the apply script — don't duplicate them in Parsed.)
For edge cases, read ${CLAUDE_PLUGIN_ROOT}/references/companion-usage.md §7.
Wrap the task in prompt blocks
The cleaned task text is not sent bare. Wrap it in standard
scaffolding so the delegation carries the same structure verify/research
get — but keep the user's words verbatim inside <task> (no
summarizing, no rewording). You add blocks around their text; you
never rewrite it. That's the whole point: structure without distortion.
Pick the blocks by task type — --write is the signal. An
implementation or fix mutates the repo, so it needs scope + verification
guards; a read-only investigation needs grounding instead.
- Always:
<task> — the approved task text, verbatim.
--write ON (implement / fix): add <completeness_contract>, <verification_loop>, <action_safety>.
--write OFF (read-only investigation): add <completeness_contract>, <grounding_rules>.
Block bodies — copy exactly:
<completeness_contract>
Resolve the task fully before stopping.
Do not stop at the first plausible answer.
Check whether there are follow-on fixes, edge cases, or cleanup needed for a correct result.
</completeness_contract>
<verification_loop>
Before finalizing, verify the result against the task requirements and the changed files or tool outputs.
If a check fails, revise the answer instead of reporting the first draft.
</verification_loop>
<action_safety>
Keep changes tightly scoped to the stated task.
Avoid unrelated refactors, renames, or cleanup unless they are required for correctness.
Call out any risky or irreversible action before taking it.
</action_safety>
<grounding_rules>
Ground every claim in the provided context or your tool outputs.
Do not present inferences as facts.
If a point is a hypothesis, label it clearly.
</grounding_rules>
Assemble the wrapped prompt with <task> first, then the selected
blocks in the order listed. This wrapped XML — not the bare task
text — is what Phase 1.5 previews and Phase 2 writes to PROMPT_FILE.
Because wrapping happens here in Phase 1, it still applies when
--no-preview skips the preview gate.
Phase 1.5: Draft Review
Skip this phase entirely if --no-preview was parsed in Phase 1.
Before sending anything to Codex, show the user exactly what will be
sent. The user approved the intent — now they approve the prompt.
Display the draft
Show the wrapped XML prompt (everything that will go into
PROMPT_FILE) in a fenced code block, along with the companion flags that
will be used — <task> holds their verbatim text, surrounded by the
blocks selected in Phase 1.
**Prompt to send to Codex:**
```xml
<task>
<the approved task description from Phase 1 — verbatim, nothing added>
</task>
<completeness_contract>
Resolve the task fully before stopping.
Do not stop at the first plausible answer.
Check whether there are follow-on fixes, edge cases, or cleanup needed for a correct result.
</completeness_contract>
<verification_loop>
Before finalizing, verify the result against the task requirements and the changed files or tool outputs.
If a check fails, revise the answer instead of reporting the first draft.
</verification_loop>
<action_safety>
Keep changes tightly scoped to the stated task.
Avoid unrelated refactors, renames, or cleanup unless they are required for correctness.
Call out any risky or irreversible action before taking it.
</action_safety>
```
Flags: `--write` `--resume-last`
The example above shows the --write block set. For a read-only run,
swap <verification_loop> + <action_safety> for <grounding_rules>
(per the Phase 1 selection). The fenced block must contain the exact
wrapped XML that will be written to PROMPT_FILE — the user's text
verbatim inside <task>, no summarization, no rewording.
Ask for approval
Use AskUserQuestion exactly once:
- Question: "This prompt will be sent to Codex task."
- Options:
- "Approve — execute as shown"
- "Needs changes"
- "Cancel"
Handle the response
- Approve → proceed to Phase 2 with the displayed text.
- Needs changes → the user will describe what to change. Apply
their edit to the draft, then re-display and re-ask. No loop
limit — the user controls when to stop.
- Cancel → stop execution. Do not proceed to Phase 2.
Phase 2: Invoke (Pattern B — companion --background + stdin pipe)
task --background is honored by the companion (:758-790 →
enqueueBackgroundTask). It returns a job payload immediately.
set -o pipefail
CODEX_COMPANION=$("${CLAUDE_PLUGIN_ROOT}/scripts/resolve-companion.sh") \
|| { echo "Official Codex plugin not found — run /codex-setup" >&2; exit 1; }
mkdir -p "${CLAUDE_PLUGIN_DATA}/tmp"
TS=$(date +%s%N)
PROMPT_FILE="${CLAUDE_PLUGIN_DATA}/tmp/rescue-prompt-${TS}.txt"
JOB_JSON_FILE="${CLAUDE_PLUGIN_DATA}/tmp/rescue-job-${TS}.json"
PRE_LIST="${CLAUDE_PLUGIN_DATA}/tmp/rescue-pre-${TS}.list"
PRE_SHA="${CLAUDE_PLUGIN_DATA}/tmp/rescue-pre-${TS}.sha"
echo "PROMPT_FILE=$PROMPT_FILE"
echo "JOB_JSON_FILE=$JOB_JSON_FILE"
echo "PRE_LIST=$PRE_LIST"
echo "PRE_SHA=$PRE_SHA"
git status --porcelain > "$PRE_LIST" 2>/dev/null || true
git rev-parse HEAD > "$PRE_SHA"
cat > "$PROMPT_FILE" <<'EOF'
<literal approved wrapped XML prompt from Phase 1.5 (or the Phase 1 wrapped prompt if --no-preview)>
EOF
cat "$PROMPT_FILE" | node "$CODEX_COMPANION" task --background --json \
--write \
--resume-last \
> "$JOB_JSON_FILE" 2> "${JOB_JSON_FILE}.stderr" \
|| { echo "task launch failed:" >&2; cat "${JOB_JSON_FILE}.stderr" >&2; exit 1; }
JOB_ID=$(node -e 'const fs=require("fs");try{const j=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));if(!j.jobId)throw new Error("no jobId");process.stdout.write(j.jobId);}catch(e){process.stderr.write("JOB_ID parse failed: "+e.message+"\n");process.exit(1);}' "$JOB_JSON_FILE") \
|| { echo "raw companion stdout:" >&2; cat "$JOB_JSON_FILE" >&2; exit 1; }
echo "JOB_ID=$JOB_ID"
Each flag line in the template is optional — include only what Phase 1
parsed. Replace <literal ...> values with the actual strings from
Phase 1. --write defaults to ON for implementation; omit for
read-only investigation.
Remember the literal PROMPT_FILE, JOB_JSON_FILE, PRE_LIST,
PRE_SHA, and JOB_ID values. Re-inject these as literal strings in
every subsequent Bash call — shell variables do not survive across calls.
Phase 3: Wait (status --wait loop)
Each status --wait call blocks ≤4 min (under Bash 300s). Re-call on
timeout. Cap total iterations at 6 (24 minutes).
node "$CODEX_COMPANION" status --wait "<literal JOB_ID>" \
--timeout-ms 240000 --json
Inspect the returned JSON:
status === "completed" → proceed to fetch result
status === "failed" → categorize per §6, save failure report
waitTimedOut === true and status still queued/running → re-call (iteration budget permitting)
- 6 iterations exhausted →
wait-timeout (§6). Do NOT silently cancel; leave the job running. Show the user the JOB_ID and suggest /codex:status <JOB_ID> for manual follow-up.
Fetch the final result:
node "$CODEX_COMPANION" result "<literal JOB_ID>" --json
Full error table: ${CLAUDE_PLUGIN_ROOT}/references/companion-usage.md §6.
Notable cases:
Task <id> is still running. Use /codex:status before continuing it. → a previous task is still in flight. Show the user the active jobId and stop. Never silently cancel.
Stored job <id> is missing its task request payload. → detached worker couldn't load the request. recovery-impossible. Save failure report.
Phase 4: Double-check
Now — and only now — you may read the code.
Read ${CLAUDE_PLUGIN_ROOT}/references/evaluation.md.
If Codex made code changes (--write)
git diff
git diff --stat
git status --porcelain
For each changed file:
- Read the diff, then read only the relevant sections of the file.
- Evaluate:
- Does the change actually solve the task?
- Correctness — any bugs introduced?
- Scope — any files modified that shouldn't have been? Cross-check against the pre-snapshot file list.
- Side effects — does it break something nearby?
If Codex returned investigation results (read-only)
Apply the Peer AI Evaluation in evaluation.md:
- Agree — claim matches the code
- Disagree — claim contradicts the code, with evidence
- Nuance — real insight, but missing context
- False Positive (hallucination) — Codex cited a file / function /
line that does not exist in the current source tree
- Uncited — no concrete citation. Surface as "verification
deferred". Never invent citations.
Phase 5: Report + save
mkdir -p "${CLAUDE_PLUGIN_DATA}/reviews"
Success: save to
${CLAUDE_PLUGIN_DATA}/reviews/rescue-<YYYYMMDD-HHMMSS>.md with:
- The task description
- Codex's output verbatim
- The diff (if any)
- Claude's per-finding / per-file evaluation
- Verdict: appropriate / has issues / needs rework
- Do NOT auto-accept changes. Present, wait for user.
Failure: save to
${CLAUDE_PLUGIN_DATA}/reviews/rescue-<YYYYMMDD-HHMMSS>-failed.md with
the §6 error category and captured stderr.
Clean up temp files using literal paths:
rm -f "<literal PROMPT_FILE path>" "<literal JOB_JSON_FILE path>" "<literal JOB_JSON_FILE.stderr path>" \
"<literal pre.list path>" "<literal pre.sha path>"
Gotchas
--model / --effort go through apply-codex-config.py, not the companion. config.toml becomes the single source of truth; routing keeps every codex-advisor skill identical, lets the value persist for the next session without re-typing, and is the only way to set effort for review/adversarial (whose valueOptions = [base, scope, model, cwd] does not include effort). apply-codex-config.py writes whatever it's given without judging it — Codex is the authority on valid models and efforts, so a bad value surfaces there, not here.
- Never combine
--resume / --resume-last with --fresh. The companion rejects the combination (:750).
- Never pass a positional argument with Pattern B's stdin pipe.
readTaskPrompt short-circuits on positionalPrompt || readStdinIfPiped() (:619); a positional silently drops the entire task description.
--wait on task is silent prompt corruption. It becomes part of the task prompt body. ANALYZE must reject it.
- Do NOT explore the repo in Phase 1. The point of delegation is that Codex builds the context. Exploring biases the double-check.
For the full shared gotchas list, read
${CLAUDE_PLUGIN_ROOT}/references/companion-usage.md §10.