Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions plugins/codex/agents/codex-rescue.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ Forwarding rules:
- Return the stdout of the `codex-companion` command exactly as-is.
- If the Bash call fails or Codex cannot be invoked, return nothing.

Prompt assembly and background handling:

- Pass the task prompt inline, as the last arguments and after a `--` delimiter: `task [runtime options] -- '<prompt>'`. Without `--`, option-like text inside the prompt such as `--write` is parsed as a runtime flag and stripped from the prompt.
- Single-quote the prompt so Bash performs no expansion, and escape every embedded single quote as `'\''` (so `don't stop` is passed as `'don'\''t stop'`). Never wrap the prompt in double quotes: `$(...)`, backticks, `$VAR`, and a bare `"` would be expanded or would terminate the argument locally before the companion receives the text.
- Do not write prompt files to disk using `node`, `fs`, shell heredocs, or any other interpreter in order to consume them with `--prompt-file`.
- Do not poll, `pgrep`, `watch`, `tail` logs, or run wait loops for a background task. When the call uses `--background`, return the printed job ID and the suggested `/codex:status <id>` command exactly as output and stop.
- A foreground call that the Bash harness moves to the background after its timeout never prints a companion job ID, and the harness identifier is not one. Return whatever the harness printed as-is; do not invent a job ID or suggest a `/codex:status` command for it.

Response style:

- Do not add commentary before or after the forwarded `codex-companion` output.
9 changes: 8 additions & 1 deletion plugins/codex/skills/codex-cli-runtime/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,15 @@ Command selection:
- `--effort`: accepted values are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`.
- `task --resume-last`: internal helper for "keep going", "resume", "apply the top fix", or "dig deeper" after a previous rescue run.

Prompt and background handling:
- Pass the prompt inline, as the last arguments and after a `--` delimiter: `task [runtime options] -- '<prompt>'`. Without `--`, option-like text inside the prompt such as `--write` is parsed as a runtime flag and stripped from the prompt.
- Single-quote the prompt so Bash performs no expansion, and escape every embedded single quote as `'\''` (so `don't stop` is passed as `'don'\''t stop'`). Never wrap the prompt in double quotes: `$(...)`, backticks, `$VAR`, and a bare `"` would be expanded or would terminate the argument locally before the companion receives the text.
- Do not write prompt files to disk with `node`, `fs`, shell heredocs, or any other interpreter in order to consume them with `--prompt-file`.
- Do not poll, `pgrep`, `watch`, `tail` logs, or run wait loops for a background task. When `task` is invoked with `--background`, return the job ID and suggested `/codex:status <id>` command exactly as output and stop.
- A foreground call that the Bash harness moves to the background never prints a companion job ID, and the harness identifier is not one. Return whatever the harness printed as-is; do not invent a job ID or suggest a `/codex:status` command for it.

Safety rules:
- Default to write-capable Codex work in `codex:codex-rescue` unless the user explicitly asks for read-only behavior.
- Default to write-capable Codex work in `codex:codex-rescue` unless the user explicitly asks for read-only behavior or only wants review, diagnosis, or research without edits.
- Preserve the user's task text as-is apart from stripping routing flags.
- Do not inspect the repository, read files, grep, monitor progress, poll status, fetch results, cancel jobs, summarize output, or do any follow-up work of your own.
- Return the stdout of the `task` command exactly as-is.
Expand Down
19 changes: 19 additions & 0 deletions tests/commands.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,25 @@ test("transfer, result, and cancel commands are exposed as deterministic runtime
assert.match(resultHandling, /if Codex was never successfully invoked, do not generate a substitute answer at all/i);
});

test("rescue agent forbids unsafe prompt writes, wait loops, and harness job-ID assumptions", () => {
const agent = read("agents/codex-rescue.md");
const runtimeSkill = read("skills/codex-cli-runtime/SKILL.md");

assert.match(agent, /Do not write prompt files to disk/i);
assert.match(agent, /node[^\n]*fs/i);
assert.match(agent, /Do not poll.*pgrep/i);
assert.match(agent, /return the printed job ID/i);
assert.match(agent, /task \[runtime options\] -- '<prompt>'/);
assert.match(agent, /escape every embedded single quote as `'\\''`.*Never wrap the prompt in double quotes/i);
assert.match(agent, /do not invent a job ID or suggest a `\/codex:status` command for it/i);
assert.match(runtimeSkill, /Do not write prompt files to disk/i);
assert.match(runtimeSkill, /Do not poll.*pgrep/i);
assert.match(runtimeSkill, /return the job ID and suggested/i);
assert.match(runtimeSkill, /task \[runtime options\] -- '<prompt>'/);
assert.match(runtimeSkill, /escape every embedded single quote as `'\\''`.*Never wrap the prompt in double quotes/i);
assert.match(runtimeSkill, /do not invent a job ID or suggest a `\/codex:status` command for it/i);
});

test("internal docs use task terminology for rescue runs", () => {
const runtimeSkill = read("skills/codex-cli-runtime/SKILL.md");
const promptingSkill = read("skills/gpt-5-4-prompting/SKILL.md");
Expand Down