This posts a REAL review to GitHub or Gitea (comments, and an approve/request-changes/comment verdict). It fetches a pull request's diff, runs the same multi-agent analysis as review-full, applies any project-specific review rules, then submits the review via the platform's API. For reviewing local diffs that aren't an open PR, use review-full or review-diff instead.
Step 0: Resolve the PR and detect the platform
- Determine the target PR from
$ARGUMENTS(a number or URL). If empty, detect the PR for the current branch. - Detect the git host from
git remote get-url origin:github.com-> GitHub. Use theghCLI (assume it is already authenticated).- Anything else (self-hosted Gitea/Forgejo/Gogs, e.g. a company git server) -> Gitea-style REST API via
curl.
- For Gitea, locate this project's own credentials rather than asking every time:
- Check whether the project's
CLAUDE.md@imports a credentials file (commonlyrules/credentials.md; this mirrors a common per-project credentials-import convention). - If none is found, ask the user for the base URL and a
username:token, and offer to save them into a new, gitignored file (e.g.rules/credentials.md). Never write real secrets into a tracked file, an.exampletemplate, or any file already committed to git.
- Check whether the project's
Step 1: Load PR context
- Fetch PR metadata (title, author, base/head branch, mergeable state, description) and the unified diff:
- GitHub:
gh pr view <N> --json title,author,baseRefName,headRefName,mergeable,body,gh pr diff <N> - Gitea:
GET /repos/{owner}/{repo}/pulls/{n}andGET /repos/{owner}/{repo}/pulls/{n}.diff
- GitHub:
- Count
diff --githeaders in the diff and record the file count (checked again in Step 5). - Determine reviewer identity. Compare the authenticated account against the PR author:
- GitHub:
gh api user --jq .login - Gitea: the username from the credentials file
- Record whether this is a self-review (author == reviewer). Both platforms reject
APPROVE/REQUEST_CHANGESon your own PR, so a self-review always posts asCOMMENT.
- GitHub:
- Check for a prior review from this reviewer account (
gh api repos/{o}/{r}/pulls/{n}/reviews, or the Gitea equivalent):- No prior review -> first-pass review.
- Prior review exists -> list commits and check for any commit after that review's
submitted_at.- New commits -> re-review mode: only findings still present in the new diff are valid; call out previously-flagged items now fixed.
- No new commits -> stop and report "No new commits since my last review: nothing to re-review." Do not re-run the full checklist.
Step 2: Load project-specific review rules (if any)
- Read the target project's
CLAUDE.md. If it@imports rule files (naming conventions, architecture patterns, framework-specific rules, etc.), read those too and apply them in Step 4 alongside the generic checks. - If the project defines a cross-module impact table (e.g. "field X renamed -> grep the other repo for consumers"), run it: for each matching pattern in the diff, grep the referenced codebase paths, read every hit, and record any broken consumer as a finding.
- If the project has no documented review rules, proceed with the generic checks only. Do not invent stack-specific rules that aren't written down anywhere.
Step 3: Determine PR scope
Look at the diff's file paths to scope which rules apply (e.g. frontend-only, backend-only, or mixed changes) and skip rules tagged for the side the PR doesn't touch.
Step 4: Multi-agent analysis
Follow the review-full skill's Steps 1-6 (spawn code-reviewer, security-reviewer, db-analyst, and architecture-reviewer as applicable) using the fetched PR diff as the change set, plus any project-specific rules loaded in Step 2. Produce the standard findings table:
| # | Severity | File:Line | Finding | Recommendation |
Step 5: Mandatory self-verification (do not skip; runs before posting)
- Grep verification. For every project-specific "must fix"-style rule with a greppable pattern, re-run the grep against the diff and confirm every match is either included as a finding or explicitly justified as not a violation.
- Rule/agent coverage line. State which agents ran and which project rules were checked, e.g. "checked code-reviewer, security-reviewer, rules A1-A2, G1-G8: N rules/checks in scope, M findings raised."
- Sanity check. If the diff touches 5+ files and zero findings were raised, write one sentence justifying why (e.g. "pure rename refactor", "config-only change"). Zero findings on a large diff is suspicious and must be justified, not assumed clean.
- File coverage check. Confirm the number of files examined equals the
diff --gitcount recorded in Step 1.
Step 6: Build the review payload and pick the verdict
| Reviewer vs. author | Findings | event |
|---|---|---|
| Self-review (author == reviewer) | Any | COMMENT (always; platform rejects APPROVE/REQUEST_CHANGES on your own PR) |
| Reviewer != author | Any CRITICAL/HIGH | REQUEST_CHANGES |
| Reviewer != author | Only MEDIUM/LOW | COMMENT ("LGTM with notes") |
| Reviewer != author | None | APPROVE |
If a POST with event: APPROVE or REQUEST_CHANGES fails with 403/422 (some Gitea instances permission-block certain accounts from approving), retry the same payload with event: COMMENT and say so explicitly in the summary. Do not silently swallow the failure.
Review body (top-level summary, opens every review body):
<severity emoji + count summary, e.g. "CRITICAL 2, HIGH 3, MEDIUM 1"> <DO NOT MERGE: N blocking item(s), only if any CRITICAL/HIGH present> Blocking: 1. path/to/file.ts:47: <short description> ... See inline comments for full detail per finding.
Inline comment format (one per finding that has a specific line):
<emoji> [SEVERITY] <Module/symbol>: <what is wrong>. <Concrete suggested fix>.
Severity emoji: CRITICAL, HIGH, MEDIUM, LOW map to plain-language tags in the body; use these emoji inline: ❌ CRITICAL, ⚠️ HIGH, 🔍 MEDIUM ("verify"), 💡 LOW ("minor"), ✅ OK (previously-flagged issue now fixed), ℹ️ NOTE (informational, non-blocking).
Positioning: a finding on a line in the new file goes in comments with that line number; a finding only on a deleted line uses the old-file line number instead; a PR-level finding with no specific line is omitted from comments and goes in body only.
Step 7: Post the review
- GitHub:
gh api repos/{owner}/{repo}/pulls/{n}/reviews -X POST --input payload.jsonwith body{"body": "...", "event": "...", "comments": [{"path": "...", "line": N, "body": "..."}]}. - Gitea:
curl -u "${AUTH}" -X POST -H "Content-Type: application/json" -d @payload.json "${BASE_URL}/api/v1/repos/{owner}/{repo}/pulls/{n}/reviews"with the same payload shape, except inline comments usenew_position/old_positioninstead ofline. - Before posting, re-check for existing reviews from this account against the current head commit, to avoid double-posting if this workflow already ran for the same commit.
Step 8: Verify
- Confirm the response contains a valid review
id. A missing/nullidmeans the POST failed silently. Read the error body and report the real failure; do not report success. - Confirm file coverage matches the count recorded in Step 1.
- Re-read each cited finding's lines to confirm the finding text still matches the actual code before declaring the review posted.
- Never say "review posted" without having confirmed a valid
id.
Review discipline
- Finish the current PR before moving to the next one flagged in conversation.
- Pre-existing issues outside the PR's own diff get an ℹ️ NOTE, not a blocking finding, unless the PR's changes directly break them.
- If the PR description claims something was tested and the change is non-trivial, look for evidence (screenshots, test output, added tests). If none is provided, flag with 🔍 SHOULD VERIFY.
- Read the full diff before forming any finding. Never post a review based on a partial read.


