Code Review

SkillAI & models

Structured code review using tiered persona agents, confidence-gated findings, and a merge/dedup pipeline. Use when reviewing code changes before creating a PR.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Code Review skill

What this skill tells your AI

The instructions your AI receives, as published by jesusfilm/core in .claude/skills/ce-code-review/SKILL.md and read by ahel’s review.

Reviews code changes using dynamically selected reviewer personas. Spawns parallel sub-agents that return structured JSON, then merges and deduplicates findings into a single report.

When to Use

  • Before creating a PR
  • After completing a task during iterative implementation
  • When feedback is needed on any code changes
  • Can be invoked standalone
  • Can run as a read-only or autofix review step inside larger workflows

Argument Parsing

Parse $ARGUMENTS for the following optional tokens. Strip each recognized token before interpreting the remainder as the PR number, GitHub URL, or branch name.

TokenExampleEffect
mode:autofixmode:autofixSelect autofix mode (see Mode Detection below)
mode:report-onlymode:report-onlySelect report-only mode
mode:headlessmode:headlessSelect headless mode for programmatic callers (see Mode Detection below)
base:<sha-or-ref>base:abc1234 or base:origin/mainSkip scope detection — use this as the diff base directly
plan:<path>plan:docs/plans/2026-03-25-001-feat-foo-plan.mdLoad this plan for requirements verification

All tokens are optional. Each one present means one less thing to infer. When absent, fall back to existing behavior for that stage.

Conflicting mode flags: If multiple mode tokens appear in arguments, stop and do not dispatch agents. If mode:headless is one of the conflicting tokens, emit the headless error envelope: Review failed (headless mode). Reason: conflicting mode flags — <mode_a> and <mode_b> cannot be combined. Otherwise emit the generic form: Review failed. Reason: conflicting mode flags — <mode_a> and <mode_b> cannot be combined.

Quick Review Short-Circuit

If $ARGUMENTS indicates the user wants a quick, fast, or light code review, do not dispatch the multi-agent flow.

Announce the chosen path before any other work (Quick review vs Multi-agent review).

Programmatic callers (when mode:autofix, mode:report-only, or mode:headless is present) skip this announcement -- the orchestrator owns user-facing messaging.

Sequence:

  1. Run the harness's built-in code review. If $ARGUMENTS contained a review target (PR number, GitHub URL, or branch name) after stripping recognized tokens, forward that target to the built-in. If no target was provided, run the bare command and let the built-in default to the current branch.

    • If you are Claude Code, run the /review tool, passing the target if present (e.g., /review 123, /review <PR-URL>, /review <branch>); otherwise run bare /review.
    • If you are Gemini, run a quick code review against the resolved target (or the current branch when none was provided).
    • For all other coding harnesses, run your built-in code review tool, forwarding the target when its syntax accepts one.

    Then stop. Do not dispatch the multi-agent reviewer pipeline.

  2. Exemption -- no built-in code review exists. If the current harness has no built-in code review command or skill, do not short-circuit. Continue into the full multi-agent review described in the rest of this skill (Tier 2).

  3. Programmatic callers bypass this short-circuit. When mode:autofix, mode:report-only, or mode:headless is present, ignore quick intent and run the full multi-agent review. Skill-to-skill callers that want the lightweight pass should invoke /review (or the harness equivalent) directly rather than route through this short-circuit.

Mode Detection

ModeWhenBehavior
Interactive (default)No mode token presentReview, apply safe_auto fixes automatically, present findings, ask for policy decisions on gated/manual findings, and optionally continue into fix/push/PR next steps
Autofixmode:autofix in argumentsNo user interaction. Review, apply only policy-allowed safe_auto fixes, re-review in bounded rounds, write a run artifact capturing residual downstream work
Report-onlymode:report-only in argumentsStrictly read-only. Review and report only, then stop with no edits, artifacts, commits, pushes, or PR actions
Headlessmode:headless in argumentsProgrammatic mode for skill-to-skill invocation. Apply safe_auto fixes silently (single pass), return all other findings as structured text output, write run artifacts, and return "Review complete" signal. No interactive prompts.

Autofix mode rules

  • Skip all user questions. Never pause for approval or clarification once scope has been established.
  • Apply only safe_auto -> review-fixer findings. Leave gated_auto, manual, human, and release work unresolved.
  • Write a run artifact under /tmp/compound-engineering/ce-code-review/<run-id>/ summarizing findings, applied fixes, residual actionable work, and advisory outputs. Orchestrators read this artifact to route residual downstream-resolver findings; the skill itself does not file tickets or prompt the user in autofix.
  • Emit a compact Residual Actionable Work summary in the autofix return listing each residual downstream-resolver finding with its stable #, severity, file:line, title, and autofix_class. Structure the summary as two separate contiguous sections: applied safe_auto fixes first, then residual non-auto findings. Within the residual section, reuse each finding's stable # from Stage 5 -- never renumber. Include the run-artifact path. Callers read this summary directly without parsing the artifact. When no residuals exist, state Residual actionable work: none. explicitly.
  • Never commit, push, or create a PR from autofix mode. Parent workflows own those decisions.

Report-only mode rules

  • Skip all user questions. Infer intent conservatively if the diff metadata is thin.
  • Never edit files or externalize work. Do not write /tmp/compound-engineering/ce-code-review/<run-id>/, do not file tickets, and do not commit, push, or create a PR.
  • Safe for parallel read-only verification. mode:report-only is the only mode that is safe to run concurrently with browser testing on the same checkout.
  • Do not switch the shared checkout. If the caller passes an explicit PR or branch target, mode:report-only must run in an isolated checkout/worktree or stop instead of running gh pr checkout / git checkout.
  • Do not overlap mutating review with browser testing on the same checkout. If a future orchestrator wants fixes, run the mutating review phase after browser testing or in an isolated checkout/worktree.

Headless mode rules

  • Skip all user questions. Never use the platform question tool (AskUserQuestion in Claude Code, request_user_input in Codex, ask_user in Gemini, ask_user in Pi (requires the pi-ask-user extension)) or other interactive prompts. Infer intent conservatively if the diff metadata is thin.
  • Require a determinable diff scope. If headless mode cannot determine a diff scope (no branch, PR, or base: ref determinable without user interaction), emit Review failed (headless mode). Reason: no diff scope detected. Re-invoke with a branch name, PR number, or base:<ref>. and stop without dispatching agents.
  • Apply only safe_auto -> review-fixer findings in a single pass. No bounded re-review rounds. Leave gated_auto, manual, human, and release work unresolved and return them in the structured output.
  • Return all non-auto findings as structured text output. Use the headless output envelope format (see Stage 6 below) preserving severity, autofix_class, owner, requires_verification, confidence, pre_existing, and suggested_fix per finding. Enrich with detail-tier fields (why_it_matters, evidence[]) from the per-agent artifact files on disk (see Detail enrichment in Stage 6).
  • Write a run artifact under /tmp/compound-engineering/ce-code-review/<run-id>/ summarizing findings, applied fixes, and advisory outputs. Include the artifact path in the structured output.
  • Do not file tickets or externalize work. The caller receives structured findings and routes downstream work itself.
  • Do not switch the shared checkout. If the caller passes an explicit PR or branch target, mode:headless must run in an isolated checkout/worktree or stop instead of running gh pr checkout / git checkout. When stopping, emit Review failed (headless mode). Reason: cannot switch shared checkout. Re-invoke with base:<ref> to review the current checkout, or run from an isolated worktree.
  • Not safe for concurrent use on a shared checkout. Unlike mode:report-only, headless mutates files (applies safe_auto fixes). Callers must not run headless concurrently with other mutating operations on the same checkout.
  • Never commit, push, or create a PR from headless mode. The caller owns those decisions.
  • End with "Review complete" as the terminal signal so callers can detect completion. If all reviewers fail or time out, emit Code review degraded (headless mode). Reason: 0 of N reviewers returned results. followed by "Review complete".

Interactive mode rules

  • Pre-load the platform question tool before any question fires. In Claude Code, AskUserQuestion is a deferred tool — its schema is not available at session start. At the start of Interactive-mode work (before Stage 2 intent-ambiguity questions, the After-Review routing question, walk-through per-finding questions, bulk-preview Proceed/Cancel, and tracker-defer failure sub-questions), call ToolSearch with query select:AskUserQuestion to load the schema. Load it once, eagerly, at the top of the Interactive flow — do not wait for the first question site and do not decide it on a per-site basis. On Codex, Gemini, and Pi this preload step does not apply.
  • The numbered-list fallback only applies when the harness genuinely lacks a blocking question toolToolSearch returns no match, the tool call explicitly fails, or the runtime mode does not expose it (e.g., Codex edit modes where request_user_input is unavailable). A pending schema load is not a fallback trigger; call ToolSearch first per the pre-load rule. Rendering a question as narrative text because the tool feels inconvenient, because the model is in report-formatting mode, or because the instruction was buried in a long skill is a bug. A question that calls for a user decision must either fire the tool or fall back loudly.

Severity Scale

All reviewers use P0-P3:

LevelMeaningAction
P0Critical breakage, exploitable vulnerability, data loss/corruptionMust fix before merge
P1High-impact defect likely hit in normal usage, breaking contractShould fix
P2Moderate issue with meaningful downside (edge case, perf regression, maintainability trap)Fix if straightforward
P3Low-impact, narrow scope, minor improvementUser's discretion

Action Routing

Severity answers urgency. Routing answers who acts next and whether this skill may mutate the checkout.

autofix_classDefault ownerMeaning
safe_autoreview-fixerLocal, deterministic fix suitable for the in-skill fixer when the current mode allows mutation
gated_autodownstream-resolver or humanConcrete fix exists, but it changes behavior, contracts, permissions, or another sensitive boundary that should not be auto-applied by default
manualdownstream-resolver or humanActionable work that should be handed off rather than fixed in-skill
advisoryhuman or releaseReport-only output such as learnings, rollout notes, or residual risk

Routing rules:

  • Synthesis owns the final route. Persona-provided routing metadata is input, not the last word.
  • Choose the more conservative route on disagreement. A merged finding may move from safe_auto to gated_auto or manual, but never the other way without stronger evidence.
  • Only safe_auto -> review-fixer enters the in-skill fixer queue automatically.
  • requires_verification: true means a fix is not complete without targeted tests, a focused re-review, or operational validation.

Reviewers

18 reviewer personas in layered conditionals, plus CE-specific agents. See the persona catalog included below for the full catalog.

Always-on (every review):

AgentFocus
ce-correctness-reviewerLogic errors, edge cases, state bugs, error propagation
ce-testing-reviewerCoverage gaps, weak assertions, brittle tests
ce-maintainability-reviewerCoupling, complexity, naming, dead code, abstraction debt
ce-project-standards-reviewerCLAUDE.md and AGENTS.md compliance -- frontmatter, references, naming, portability
ce-agent-native-reviewerVerify new features are agent-accessible
ce-learnings-researcherSearch docs/solutions/ for past issues related to this PR

Cross-cutting conditional (selected per diff):

AgentSelect when diff touches...
ce-security-reviewerAuth, public endpoints, user input, permissions
ce-performance-reviewerDB queries, data transforms, caching, async
ce-api-contract-reviewerRoutes, serializers, type signatures, versioning
ce-data-migrations-reviewerMigrations, schema changes, backfills
ce-reliability-reviewerError handling, retries, timeouts, background jobs
ce-adversarial-reviewerDiff >=50 changed non-test/non-generated/non-lockfile lines, or auth, payments, data mutations, external APIs
ce-previous-comments-reviewerReviewing a PR that has existing review comments or threads

Stack-specific conditional (selected per diff):

AgentSelect when diff touches...
ce-dhh-rails-reviewerRails architecture, service objects, session/auth choices, or Hotwire-vs-SPA boundaries
ce-kieran-rails-reviewerRails application code where conventions, naming, and maintainability are in play
ce-kieran-python-reviewerPython modules, endpoints, scripts, or services
ce-kieran-typescript-reviewerTypeScript components, services, hooks, utilities, or shared types
ce-julik-frontend-races-reviewerStimulus/Turbo controllers, DOM events, timers, animations, or async UI flows
ce-swift-ios-reviewerSwift files, SwiftUI views, UIKit controllers, entitlements, privacy manifests, Core Data models, SPM manifests, storyboards/XIBs, or semantic build-setting/target/signing changes in .pbxproj

CE conditional (migration-specific):

AgentSelect when diff includes migration files
ce-schema-drift-detectorCross-references schema.rb against included migrations
ce-deployment-verification-agentProduces deployment checklist with SQL verification queries

Review Scope

Every review spawns all 4 always-on personas plus the 2 CE always-on agents, then adds whichever cross-cutting and stack-specific conditionals fit the diff. The model naturally right-sizes: a small config change triggers 0 conditionals = 6 reviewers. A Rails auth feature might trigger security + reliability + kieran-rails + dhh-rails = 10 reviewers.

Protected Artifacts

The following paths are compound-engineering pipeline artifacts and must never be flagged for deletion, removal, or gitignore by any reviewer:

  • docs/brainstorms/* -- requirements documents created by ce-brainstorm
  • docs/plans/*.md -- plan files created by ce-plan (decision artifacts; execution progress is derived from git, not stored in plan bodies)
  • docs/solutions/*.md -- solution documents created during the pipeline

If a reviewer flags any file in these directories for cleanup or removal, discard that finding during synthesis.

How to Run

Stage 1: Determine scope

Compute the diff range, file list, and diff. Minimize permission prompts by combining into as few commands as possible.

If base: argument is provided (fast path):

The caller already knows the diff base. Skip all base-branch detection, remote resolution, and merge-base computation. Use the provided value directly:

BASE_ARG="{base_arg}"
BASE=$(git merge-base HEAD "$BASE_ARG" 2>/dev/null) || BASE="$BASE_ARG"

Then produce the same output as the other paths:

echo "BASE:$BASE" && echo "FILES:" && git diff --name-only $BASE && echo "DIFF:" && git diff -U10 $BASE && echo "UNTRACKED:" && git ls-files --others --exclude-standard

This path works with any ref — a SHA, origin/main, a branch name. Automated callers (ce-work, lfg, slfg) should prefer this to avoid the detection overhead. Do not combine base: with a PR number or branch target. If both are present, stop with an error: "Cannot use base: with a PR number or branch target — base: implies the current checkout is already the correct branch. Pass base: alone, or pass the target alone and let scope detection resolve the base." This avoids scope/intent mismatches where the diff base comes from one source but the code and metadata come from another.

If a PR number or GitHub URL is provided as an argument:

If mode:report-only or mode:headless is active, do not run gh pr checkout <number-or-url> on the shared checkout. For mode:report-only, tell the caller: "mode:report-only cannot switch the shared checkout to review a PR target. Run it from an isolated worktree/checkout for that PR, or run report-only with no target argument on the already checked out branch." For mode:headless, emit Review failed (headless mode). Reason: cannot switch shared checkout. Re-invoke with base:<ref> to review the current checkout, or run from an isolated worktree. Stop here unless the review is already running in an isolated checkout.

Skip-condition pre-check. Before checkout or scope detection, run a PR-state probe to decide whether the review should proceed:

gh pr view <number-or-url> --json state,title,body,files

Apply skip rules in order:

  • state is CLOSED or MERGED -> stop with message PR is closed/merged; not reviewing.
  • Trivial-PR judgment: spawn a lightweight sub-agent (use model: haiku in Claude Code; gpt-5.4-nano or equivalent in Codex) with the PR title, body, and changed file paths. The agent's task: "Is this an automated or trivial PR that does not warrant a code review? Consider: dependency lock-file or manifest-only bumps, automated release commits, chore version increments with no substantive code changes. When in doubt, answer no — false negatives (skipped reviews that should have run) are more costly than false positives (unnecessary reviews)." If the judgment returns yes: stop with message PR appears to be a trivial automated PR; not reviewing. Run without a PR argument to review the current branch, or pass base:<ref> if review is intended.

When any skip rule fires, emit the message and stop without dispatching reviewers, switching the checkout, or running scope detection. Standalone branch mode and base: mode are unaffected -- they always run the full review. Draft PRs are reviewed normally -- draft status is not a skip condition; early feedback on in-progress work is valuable.

If no skip rule fires, proceed to the checkout logic below.

First, verify the worktree is clean before switching branches:

git status --porcelain

If the output is non-empty, inform the user: "You have uncommitted changes on the current branch. Stash or commit them before reviewing a PR, or use standalone mode (no argument) to review the current branch as-is." Do not proceed with checkout until the worktree is clean.

Then check out the PR branch so persona agents can read the actual code (not the current checkout):

gh pr checkout <number-or-url>

Then fetch PR metadata. Capture the base branch name and the PR base repository identity, not just the branch name. Project reviews and comments to a hasPriorComments boolean via --jq -- counting only, not materializing review or comment bodies into the orchestrator's context. The reviews filter excludes approval-state submissions with empty bodies (approvals are not feedback to verify), so PRs with only approval clicks correctly fall through the gate. Stage 3 uses hasPriorComments to decide whether to spawn previous-comments:

gh pr view <number-or-url> --json title,body,baseRefName,headRefName,url,reviews,comments --jq '{title, body, baseRefName, headRefName, url, hasPriorComments: ((.reviews | map(select(.state != "APPROVED" or .body != "")) | length) > 0 or (.comments | length) > 0)}'

Use the repository portion of the returned PR URL as <base-repo> (for example, EveryInc/compound-engineering-plugin from https://github.com/EveryInc/compound-engineering-plugin/pull/348).

Then compute a local diff against the PR's base branch so re-reviews also include local fix commits and uncommitted edits. Substitute the PR base branch from metadata (shown here as <base>) and the PR base repository identity derived from the PR URL (shown here as <base-repo>). Resolve the base ref from the PR's actual base repository, not by assuming origin points at that repo:

PR_BASE_REMOTE=$(git remote -v | awk 'index($2, "github.com:<base-repo>") || index($2, "github.com/<base-repo>") {print $1; exit}')
if [ -n "$PR_BASE_REMOTE" ]; then PR_BASE_REMOTE_REF="$PR_BASE_REMOTE/<base>"; else PR_BASE_REMOTE_REF=""; fi
PR_BASE_REF=$(git rev-parse --verify "$PR_BASE_REMOTE_REF" 2>/dev/null || git rev-parse --verify <base> 2>/dev/null || true)
if [ -z "$PR_BASE_REF" ]; then
  if [ -n "$PR_BASE_REMOTE_REF" ]; then
    git fetch --no-tags "$PR_BASE_REMOTE" <base>:refs/remotes/"$PR_BASE_REMOTE"/<base> 2>/dev/null || git fetch --no-tags "$PR_BASE_REMOTE" <base> 2>/dev/null || true
    PR_BASE_REF=$(git rev-parse --verify "$PR_BASE_REMOTE_REF" 2>/dev/null || git rev-parse --verify <base> 2>/dev/null || true)
  else
    if git fetch --no-tags https://github.com/<base-repo>.git <base> 2>/dev/null; then
      PR_BASE_REF=$(git rev-parse --verify FETCH_HEAD 2>/dev/null || true)
    fi
    if [ -z "$PR_BASE_REF" ]; then PR_BASE_REF=$(git rev-parse --verify <base> 2>/dev/null || true); fi
  fi
fi
if [ -n "$PR_BASE_REF" ]; then BASE=$(git merge-base HEAD "$PR_BASE_REF" 2>/dev/null) || BASE=""; else BASE=""; fi
if [ -n "$BASE" ]; then echo "BASE:$BASE" && echo "FILES:" && git diff --name-only $BASE && echo "DIFF:" && git diff -U10 $BASE && echo "UNTRACKED:" && git ls-files --others --exclude-standard; else echo "ERROR: Unable to resolve PR base branch <base> locally. Fetch the base branch and rerun so the review scope stays aligned with the PR."; fi

Extract PR title/body, base branch, and PR URL from gh pr view, then extract the base marker, file list, diff content, and UNTRACKED: list from the local command. Do not use gh pr diff as the review scope after checkout -- it only reflects the remote PR state and will miss local fix commits until they are pushed. If the base ref still cannot be resolved from the PR's actual base repository after the fetch attempt, stop instead of falling back to git diff HEAD; a PR review without the PR base branch is incomplete.

If a branch name is provided as an argument:

Check out the named branch, then diff it against the base branch. Substitute the provided branch name (shown here as <branch>).

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
25
Forks
15
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
ce-code-review-jesusfilm
Source
github.com/jesusfilm/core