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
17 changes: 9 additions & 8 deletions plugins/codex/commands/review.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Run a Codex code review against local git state
argument-hint: '[--wait|--background] [--base <ref>] [--scope auto|working-tree|branch]'
argument-hint: '[--wait|--background|--ask] [--base <ref>] [--scope auto|working-tree|branch]'
disable-model-invocation: true
allowed-tools: Read, Glob, Grep, Bash(node:*), Bash(git:*), AskUserQuestion
---
Expand All @@ -16,26 +16,27 @@ Core constraint:
- Your only job is to run the review and return Codex's output verbatim to the user.

Execution mode rules:
- If the raw arguments include `--wait`, do not ask. Run the review in the foreground.
- If the raw arguments include `--background`, do not ask. Run the review in a Claude background task.
- Otherwise, estimate the review size before asking:
- If the raw arguments include `--wait`, run the review in the foreground.
- If the raw arguments include `--background`, run the review in a Claude background task.
- Estimate the review size in every remaining case:
- For working-tree review, start with `git status --short --untracked-files=all`.
- For working-tree review, also inspect both `git diff --shortstat --cached` and `git diff --shortstat`.
- For base-branch review, use `git diff --shortstat <base>...HEAD`.
- Treat untracked files or directories as reviewable work even when `git diff --shortstat` is empty.
- Only conclude there is nothing to review when the relevant working-tree status is empty or the explicit branch diff is empty.
- Recommend waiting only when the review is clearly tiny, roughly 1-2 files total and no sign of a broader directory-sized change.
- In every other case, including unclear size, recommend background.
- A review is "tiny" when it is clearly 1-2 files total with no sign of a broader directory-sized change. Everything else, including unclear size, is "non-tiny".
- When in doubt, run the review instead of declaring that there is nothing to review.
- Then use `AskUserQuestion` exactly once with two options, putting the recommended option first and suffixing its label with `(Recommended)`:
- If the raw arguments include `--ask`, use `AskUserQuestion` exactly once with two options, putting the recommended option first (tiny → `Wait for results`, non-tiny → `Run in background`) and suffixing its label with `(Recommended)`:
- `Wait for results`
- `Run in background`
- Otherwise (no `--wait` / `--background` / `--ask`), auto-decide without asking: tiny → foreground, non-tiny → background. This keeps `/codex:review` runnable unattended inside multi-step plans. Users who want the old prompt can pass `--ask`; users who want to force a mode can pass `--wait` or `--background`.

Argument handling:
- Preserve the user's arguments exactly.
- Do not strip `--wait` or `--background` yourself.
- Do not strip `--wait`, `--background`, or `--ask` yourself.
- Do not add extra review instructions or rewrite the user's intent.
- The companion script parses `--wait` and `--background`, but Claude Code's `Bash(..., run_in_background: true)` is what actually detaches the run.
- The companion script also accepts `--ask` as a no-op boolean so it can be safely forwarded in `$ARGUMENTS`. Only Claude's prompt logic above consumes it.
- `/codex:review` is native-review only. It does not support staged-only review, unstaged-only review, or extra focus text.
- If the user needs custom review instructions or more adversarial framing, they should use `/codex:adversarial-review`.

Expand Down
2 changes: 1 addition & 1 deletion plugins/codex/scripts/codex-companion.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ function enqueueBackgroundTask(cwd, job, request) {
async function handleReviewCommand(argv, config) {
const { options, positionals } = parseCommandInput(argv, {
valueOptions: ["base", "scope", "model", "cwd"],
booleanOptions: ["json", "background", "wait"],
booleanOptions: ["json", "background", "wait", "ask"],
aliasMap: {
m: "model"
}
Expand Down
6 changes: 4 additions & 2 deletions tests/commands.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ test("review command uses AskUserQuestion and background Bash while staying revi
assert.match(source, /git status --short --untracked-files=all/);
assert.match(source, /git diff --shortstat/);
assert.match(source, /Treat untracked files or directories as reviewable work/i);
assert.match(source, /Recommend waiting only when the review is clearly tiny, roughly 1-2 files total/i);
assert.match(source, /In every other case, including unclear size, recommend background/i);
assert.match(source, /A review is "tiny" when it is clearly 1-2 files total/i);
assert.match(source, /auto-decide without asking: tiny → foreground, non-tiny → background/i);
assert.match(source, /If the raw arguments include `--ask`/);
assert.match(source, /\[--wait\|--background\|--ask\]/);
assert.match(source, /The companion script parses `--wait` and `--background`/i);
assert.match(source, /Claude Code's `Bash\(..., run_in_background: true\)` is what actually detaches the run/i);
assert.match(source, /When in doubt, run the review/i);
Expand Down