Codex review
"Review with codex" means codex exec from the shell, with a prompt you write yourself that knows this repo. Do not substitute a subagent of your own model or a generic built-in review command: the point is a second model family reading the diff against this repo's own invariants.
Invocation
bashcodex exec -C <repoDir> -s read-only -c approval_policy="never" \ --output-last-message "$TMPDIR/codex_review.txt" "$(cat "$TMPDIR/prompt.txt")" </dev/null
Read the report from the --output-last-message file.
Four ways this fails silently
- End with
</dev/null. It forces stdin to EOF at once. Backgrounded without it, codex waits forever. - Never pipe codex's stdout. A pipe makes it think stdin is wanted; it hits EOF, exits 0, and never writes the
--output-last-messagefile. For a log, redirect:> log 2>&1 </dev/null. - Run it in the foreground. Backgrounded with
> file, the output is buffered and the file sits at one line, which looks like a hang. -s read-onlyneeds-c approval_policy="never". Without it, a session with no TTY waits for an approval that never comes.
Writing the prompt
Inline the diff and forbid exploring: "Do NOT explore the repository, do NOT open files, do NOT run commands. Review only the diff inlined below."
Four parts:
- Stack facts it needs. Module layout, the database and its migration discipline, earlier behaviour the diff relies on without restating. codex cannot see the repo; anything load-bearing goes here.
- What the change should do. One paragraph, so it reviews against intent instead of guessing it.
- Numbered review targets that are this diff's own invariants. "Does X hold on every path", "does anything change Y without going through Z". This is where the value is; a generic checklist is not.
- Output discipline. Concrete defects only, with
file:lineand the input or sequence that triggers each one, ranked by severity; one line per clean target; no summary of the diff, no praise.
The diff: git diff {{BASE_BRANCH}}...HEAD -- {{REVIEW_GLOBS}}.
Fallback: OpenRouter (optional, billed per call)
Only when codex exec exits on a usage limit (its log ends with "You've hit your usage limit" and the output file is never written). Send the same prompt as one call:
bashset -a && . {{OPENROUTER_ENV_FILE}} && set +a && \ python3 <this skill's directory>/openrouter_review.py --prompt "$TMPDIR/prompt.txt" --out "$TMPDIR/review.md"
- One call per review. The script re-sends the same request only on a 5xx, a timeout or a connection failure, at most twice. If the result is weak, stop and give it to the user; never rewrite the prompt and run again on your own.
- Before use, list
https://openrouter.ai/api/v1/modelsforopenai/gpt-*; pass--modelwhen a newer flagship exists. - Never print the key.
- Report it as what it is: codex did not run; GPT through OpenRouter did.
Reading the result
codex reports existing behaviour as a finding when the diff makes it visible. Decide deliberately: fixing the visibility belongs in this change; fixing the old quirk itself is often a separate decision with its own blast radius. Say which one you are doing and record the other.
Rule
The reviewer model must differ from the model that wrote the change.


