From paxos
Fan out a multi-lens code review across Codex and area-focused Claude subagents, then synthesize their findings into a single prioritized punch list. Use this skill when the user asks for a thorough review of the current branch or a specific PR — especially when they want multiple perspectives (security, perf, types, tests, etc.) rather than a single-reviewer pass.
How this skill is triggered — by the user, by Claude, or both
Slash command
/paxos:multi-lens-reviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Run a parallel multi-lens review against the current branch (or a specific PR) and produce a consolidated, deduped, prioritized punch list.
Run a parallel multi-lens review against the current branch (or a specific PR) and produce a consolidated, deduped, prioritized punch list.
For a quick single-reviewer pass, prefer /codex:review or superpowers:requesting-code-review instead.
/paxos:review — review the current branch. If it has an open PR on origin, review that PR. Otherwise review against origin/main./paxos:review <PR#> — review the given PR (its base ref is honored).Each section below details one of these steps.
Compute BASE_SHA, HEAD_SHA, the unified diff, the changed-file list, the +X/-Y shortstat, and (when available) the PR description.
/paxos:review <num>)PR_NUM="<num>"
# PR metadata + base ref (do NOT assume main)
gh pr view "$PR_NUM" --json number,headRefName,baseRefName,headRefOid,body,title \
--jq '{number, head: .headRefName, base: .baseRefName, headSha: .headRefOid, title, body}'
# Resolve base SHA on the local clone (fetches origin if needed)
git fetch origin "$BASE_REF" 2>/dev/null || true
BASE_SHA=$(git rev-parse "origin/$BASE_REF")
HEAD_SHA="$HEAD_REF_OID" # from gh pr view above
# Diff + files
git diff --shortstat "$BASE_SHA...$HEAD_SHA"
git diff --name-only "$BASE_SHA...$HEAD_SHA"
git diff "$BASE_SHA...$HEAD_SHA"
# Does the current branch have an open PR on origin?
gh pr view --json number,baseRefName,headRefOid,body,title 2>/dev/null
If that returns a PR, use it (same flow as above).
If it returns nothing or errors:
# Local-only fallback: current branch vs origin/main
git fetch origin main 2>/dev/null || true
BASE_SHA=$(git rev-parse origin/main)
HEAD_SHA=$(git rev-parse HEAD)
git diff --shortstat "$BASE_SHA...$HEAD_SHA"
git diff --name-only "$BASE_SHA...$HEAD_SHA"
git diff "$BASE_SHA...$HEAD_SHA"
Hold these in your working notes for the rest of the run:
BASE_SHA, HEAD_SHACHANGED_FILES (list)DIFF (full unified diff text)SHORTSTAT (e.g. 8 files changed, 234 insertions(+), 91 deletions(-))PR_DESCRIPTION (or empty when local-only)SCOPE_LABEL — human-readable identifier, e.g. PR #1819 — paxos/check-public-share-flag → main or local: paxos/check-public-share-flag → origin/main<base>" and stop.gh unauthenticated and no arg given: proceed with local-only flow; mention that PR features will be skipped.Apply each rule below against CHANGED_FILES. A rule firing means the lens is suggested in the picker (pre-checked). The user makes the final call in step 3.
codex-review is always suggested.codex-adversarial is suggested when any of:
CHANGED_FILES has more than 5 entriespackage.json / lockfile changed (likely new dependency = approach question)| Lens | Suggested when CHANGED_FILES match |
|---|---|
security | **/auth/**, **/oauth*, **/session*, **/crypto*, **/secret*, **/.env*, **/middleware*auth*, files importing crypto/bcrypt/jsonwebtoken |
api-contracts | **/*.proto, **/*.openapi.*, api/src/routes/**, api/src/schema/**, generated SDK files |
tests | **/*.test.*, **/*.spec.*, **/__tests__/**, OR added prod-code lines without commensurate test changes |
perf | Files with for/while loops over collections, DB query files, frontend/src/** bundle-affecting changes (large new components, new heavy deps) |
frontend-ux | frontend/** (any file) |
db-migrations | **/migrations/**, **/*.sql, schema definition files |
observability | Files touching logging, error handling, tracing, metrics — keywords console.*, logger., Sentry, captureException, try/catch blocks added or modified |
deps | package.json, pnpm-lock.yaml, yarn.lock, Cargo.toml, go.mod |
For ambiguous matches (e.g. a route file might be both api-contracts and security), suggest both — they read different things.
If no Claude lens matched, suggest code-quality so there's at least one Claude reviewer alongside Codex. Final fallback roster: codex-review + codex-adversarial + code-quality.
A list SUGGESTED_LENSES of lens names ready for the picker.
Show the user the suggested roster and let them edit it before fan-out.
Use mcp__conductor__AskUserQuestion with one question, multi-select, one option per lens. Pre-check SUGGESTED_LENSES.
Question shape:
Roster for {SCOPE_LABEL} ({SHORTSTAT}). Tick the lenses to run:
Options (one per lens — show all 10, even ones not auto-suggested, so the user can opt in):
| Option label | Description shown to user | Pre-checked |
|---|---|---|
codex-review | Codex native review (general defect hunt) | always |
codex-adversarial | Codex challenges the approach and design | iff in SUGGESTED_LENSES |
security | Auth, secrets, injection, authZ | iff in SUGGESTED_LENSES |
api-contracts | Breaking changes, proto compat, OpenAPI drift | iff in SUGGESTED_LENSES |
tests | Coverage gaps, brittle patterns, missing edges | iff in SUGGESTED_LENSES |
perf | N+1, hot paths, bundle / cold-start cost | iff in SUGGESTED_LENSES |
frontend-ux | A11y, loading/empty/error states, responsive | iff in SUGGESTED_LENSES |
db-migrations | Locking, backfills, index coverage, rollback | iff in SUGGESTED_LENSES |
observability | Log noise vs signal, swallowed errors, traces | iff in SUGGESTED_LENSES |
deps | Justification, maintenance posture, license | iff in SUGGESTED_LENSES |
Whatever the user returns is the final ROSTER.
If mcp__conductor__AskUserQuestion is unavailable, print the suggested roster as a plain-text list and ask:
Suggested roster for {SCOPE_LABEL} ({SHORTSTAT}):
[x] codex-review Codex native review
[x] codex-adversarial Codex challenges the approach
[x] security Auth, secrets, injection, authZ
[x] api-contracts Breaking changes, proto compat
[ ] tests not auto-suggested
[ ] perf not auto-suggested
[ ] frontend-ux not auto-suggested
[ ] db-migrations not auto-suggested
[ ] observability not auto-suggested
[ ] deps not auto-suggested
Reply 'go' to run as suggested, or edit (e.g. 'go but add tests, drop adversarial').
Parse the user's reply into the final ROSTER. If the user does not respond with go or an edit, treat it as a cancel.
If the user cancels (closes the picker, replies "no" / "cancel" / similar):
For each Codex lens in ROSTER, launch a background Bash call. All Codex launches must happen in the same Claude turn as the Claude Agent dispatches in section 4b so they run truly concurrently.
The codex plugin lives in a separate marketplace from paxos, so ${CLAUDE_PLUGIN_ROOT} (which points at the current plugin's root) is no help here. Resolve the absolute path before fan-out:
# Try the canonical install location first.
CODEX_SCRIPT="/Users/pd/.claude/plugins/marketplaces/openai-codex/plugins/codex/scripts/codex-companion.mjs"
[ -f "$CODEX_SCRIPT" ] && echo "$CODEX_SCRIPT"
If the file does not exist, search the cache as a fallback:
# Fallback: find the latest installed codex companion.
find /Users/pd/.claude/plugins -name 'codex-companion.mjs' -path '*/codex/scripts/*' 2>/dev/null | head -1
If neither finds it, the codex plugin isn't installed — skip both Codex lenses and proceed with Claude lenses only (see section 7). Hold the resolved path as CODEX_SCRIPT_PATH for the launches below.
Launch with Bash:
Bash({
command: `node "${CODEX_SCRIPT_PATH}" review --base ${BASE_SHA}`,
description: "Codex review (background)",
run_in_background: true,
});
Launch with Bash:
Bash({
command: `node "${CODEX_SCRIPT_PATH}" adversarial-review --base ${BASE_SHA}`,
description: "Codex adversarial review (background)",
run_in_background: true,
});
bashId so you can poll via BashOutput in section 5.--wait or --background flags — let run_in_background: true control detachment. The companion will exit when the underlying Codex job completes.--base ${BASE_SHA} makes Codex compare HEAD against the resolved base from section 1, regardless of where the user's branch points.For each Claude lens in ROSTER (everything except codex-review / codex-adversarial):
Read tool. The path is ${CLAUDE_PLUGIN_ROOT}/skills/multi-lens-review/lenses/<lens-name>.md — CLAUDE_PLUGIN_ROOT is set by the runtime to the paxos plugin's root when this skill executes. If the env var isn't set in your runtime (older Claude Code versions), fall back to Glob for **/skills/multi-lens-review/lenses/<lens-name>.md and pick the result whose path contains /paxos/.{BASE_SHA} → the resolved base SHA{HEAD_SHA} → the resolved head SHA{SCOPE_LABEL} → human-readable scope{PR_DESCRIPTION} → PR body or empty string{CHANGED_FILES} → newline-separated file list{DIFF} → the unified diffAgent({ subagent_type: "general-purpose", description: "<lens> review", prompt: <substituted template> }).All Agent dispatches AND all Codex Bash(run_in_background: true) launches MUST go out in the same Claude turn (one tool-use block, multiple tool calls). This is what makes them parallel. Sequential dispatch defeats the entire point of this skill.
Each Agent call gets ONLY the substituted lens template — no session history, no other context from this conversation. The lens template is fully self-contained for this reason.
If the diff exceeds ~2000 lines:
Agent calls return synchronously when the agent finishes (the runtime parallelizes them under the hood). Hold each return as LENS_RESULTS[<lens-name>]. If an agent errors, store the error message instead and continue.
By the time the Agent dispatches return, Claude lens results are already collected. Codex jobs may still be running.
For each Codex bashId from section 4a:
BashOutput(bashId) until the process status is completed or failed.LENS_RESULTS["codex-review"] / LENS_RESULTS["codex-adversarial"].If a Codex job is still running after a long wall time (~10 min), surface a one-line update to the user — "Codex still running, 3 of 5 lenses ready" — and keep polling.
If a job fails, capture the error message and mark that lens as failed in the synthesis ("4 of 5 lenses returned").
Read every entry in LENS_RESULTS and produce ONE markdown response in this shape:
# Review: {SCOPE_LABEL}
{SHORTSTAT} — reviewed by N lenses
## Per-reviewer summaries
- **<lens-name>** — <pull the `### Summary` line from that lens's output, plus a finding count: "3 findings (1 important, 2 minor)">
## Consensus (2+ reviewers agree)
For each topic flagged by 2+ reviewers:
1. **[Severity]** `<file>:<line>` — <one-line title>
_Flagged by:_ <lens, lens>
<2-3 line synthesis of why it matters and the suggested fix.>
(omit this section entirely if no consensus issues)
## Outliers (single reviewer)
Findings raised by exactly one reviewer. Include them — single-reviewer doesn't mean wrong, but lower confidence.
1. **[Severity]** `<file>:<line>` — <title>
_Flagged by:_ <lens>
<2-3 line synthesis.>
(omit if empty)
## Disagreements
Where two reviewers reach different verdicts on the same code.
- `<file>:<line>` — <topic>
- <lens A> says: <position>
- <lens B> says: <position>
(omit if empty)
## Suggested next steps
1. Address Critical / Important consensus first ({count} fixes).
2. Decide on outliers ({count}) — read the source reviewer's reasoning before accepting/rejecting.
3. Resolve any disagreements ({count}) — usually a quick code read.
(scale this list to what the synthesis actually surfaced — don't include lines that don't apply)
Two findings from different lenses are "the same issue" if they:
This is judgment work. Err toward listing in Consensus rather than Outliers when in doubt, but flag the uncertainty in your synthesis prose if the match is loose.
After printing the synthesis, ask the user (one question, two options):
.context/reviews/<timestamp>-<scope>.md?"If saved, write the same markdown to that path. Make sure .context/reviews/ exists; create it if not.
| Case | What to do |
|---|---|
| No diff against base | Print "nothing to review against <base>"; stop. |
| Branch has 2+ open PRs | Use the first; tell the user which one and that there are others. |
gh unauthenticated | Drop to local-only flow; tell the user PR-dependent features are skipped. |
Codex companion not installed (scripts/codex-companion.mjs missing) | Skip Codex lenses; note in synthesis ("Codex unavailable — N Claude lenses ran"); continue. |
| A Codex job errors mid-run | Mark that lens failed; include error in synthesis; continue. |
| A Claude lens agent errors | Same — mark failed, continue. |
| User cancels picker | Stop cleanly. No agents launched. |
| Diff > ~2000 lines | Warn before fan-out (token cost); offer scope-down or cancel. |
mcp__conductor__AskUserQuestion unavailable | Use plain-text fallback in section 3. |
Surface what failed, keep going with what works. The synthesis section already accommodates partial results ("4 of 5 lenses returned"). Never refuse to produce a synthesis when at least one reviewer succeeded.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub paxos/claude --plugin paxos