process-reviews
Process Reviews
Autonomous loop that finds PRs ready for review, delegates each to the code-review skill, and updates labels based on the result. A human always makes the final merge decision.
Comment Authorship
All comments posted by this workflow run under the same GitHub account as the user. To distinguish AI comments from human comments, every comment posted by AI MUST start with **[AI]**. When reading comments, use this rule:
- Starts with
**[AI]**→ posted by AI (previous runs) - Does NOT start with
**[AI]**→ posted by a human
Worktree Isolation
This skill MUST run in its own git worktree to avoid conflicts with other parallel Claude instances.
Before starting, check if already in a worktree:
git rev-parse --show-toplevel
If NOT already in a worktree for this skill, create one and switch to it using the EnterWorktree tool (if available). If EnterWorktree is not available, create one manually and prefix ALL subsequent commands with cd <worktree-path> &&:
WORKTREE=$(git rev-parse --show-toplevel)/../$(basename "$(git rev-parse --show-toplevel)")-reviews
git worktree add --detach "$WORKTREE" main 2>/dev/null || true
Using --detach is important because main is typically already checked out in the primary worktree — git worktree add "$WORKTREE" main will silently fail in that case.
Then for every command in this skill, prefix with:
cd $WORKTREE && <command>
This is necessary because cd does not persist between Bash calls.
Loop Cycle
Each cycle:
- Pre-flight checks — verify the environment is ready
- Find PRs needing review
- Review each PR (delegate to
code-review) - Update labels based on the verdict
- Report what was reviewed
Phase 0: Pre-flight Checks
Run these before every cycle. If any fail, stop and report the problem.
# Clean up stale worktrees
git worktree prune
# Check gh is authenticated
gh auth status
# Check working tree is clean
git status --porcelain
If git status --porcelain produces output, stop: "Working tree is dirty. Commit or stash changes before running."
If gh auth status fails, stop: "GitHub CLI is not authenticated. Run gh auth login."
Ensure required labels exist:
for label in ai-ready ai-in-progress ai-done ai-blocked ai-needs-input needs-ai-review ai-changes-requested ai-approved prd; do
gh label create "$label" 2>/dev/null || true
done
Check for the ai-pause label — create it to pause, delete it (gh label delete ai-pause -y) to resume:
gh label list --search "ai-pause" --json name --jq '.[].name' | grep -qx "ai-pause"
The --search flag is a fuzzy substring match (it returns labels like ai-ready, ai-done too), so pipe through grep -qx for an exact match. If grep matches, the label exists — stop. If grep exits non-zero, no exact match — proceed.
If the ai-pause label exists, stop: "ai-pause label detected. Stopping gracefully. Delete the label (gh label delete ai-pause -y) to resume."
Set up the repo variable for API calls used later:
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
Phase 1: Find PRs needing review
Process up to 5 PRs per cycle. If more remain, they'll be handled in the next cycle. Collect candidates from all sources below, deduplicate by PR number, then take the first 5.
Labeled PRs (primary signal)
gh pr list --state open --label "needs-ai-review" --json number,title,url,isDraft,author --limit 100
Skip any draft PRs. Re-check draft status at review time as well — a PR could be converted to draft between detection and review.
Stale ai-approved PRs (new commits since approval)
PRs labeled ai-approved need re-review if new commits were pushed after the approval. Check for these to avoid a blind spot where post-approval changes go unreviewed:
gh pr list --state open --label "ai-approved" --json number,title,url,isDraft,author,updatedAt --limit 50
For each non-draft ai-approved PR, compare the latest commit date against the last **[AI]** review comment date:
# Get last commit date
gh pr view <number> --json commits --jq '.commits[-1].committedDate'
# Get last AI review comment date — check BOTH issue comments (top-level) and review comments (inline on diff)
gh pr view <number> --json comments --jq '[.comments[] | select(.body | startswith("**[AI]**")) | .createdAt] | sort | last'
Note: use gh pr view --json comments (issue-level comments where review summaries appear), NOT gh api repos/$REPO/pulls/<number>/comments (which returns inline diff comments only). AI reviews post their summary as a review body which shows up in issue comments.
If the last commit is newer than the last AI review, the PR needs re-review. Remove the stale label:
gh pr edit <number> --remove-label "ai-approved" --add-label "needs-ai-review"
Unlabeled PRs (fallback detection)
Only check up to 15 unlabeled PRs per cycle to avoid excessive API calls:
gh pr list --state open --json number,title,url,isDraft,author,labels --limit 50
Filter to non-draft PRs without an ai-changes-requested, needs-ai-review, or ai-approved label. Take the first 15 after filtering, then for each, read comments:
gh pr view <number> --json comments
A PR needs review if:
- It has no
**[AI]**review comments at all (needs first review) - It has previous AI review feedback AND new commits were pushed after the last AI review (needs re-review)
To determine if new commits exist since the last AI review, compare dates:
# Last AI review comment timestamp
gh pr view <number> --json comments --jq '[.comments[] | select(.body | startswith("**[AI]**")) | .createdAt] | sort | last'
# Last commit timestamp
gh pr view <number> --json commits --jq '.commits[-1].committedDate'
Skip PRs where the last AI review found no issues and no new commits exist since.
Determine review type
For each PR needing review, determine if this is:
- First review — no previous
**[AI]**review comments exist - Re-review — previous AI feedback exists, but feedback was addressed (new commits pushed, or human replied)
Phase 2: Review each PR
For each PR needing review:
Checkout the PR branch
The code-review skill needs to read source files (not just diffs) to understand the full context of changes. Checkout the PR branch so file reads reflect the PR's state, including newly added files:
gh pr checkout <number> --detach
Re-check that the PR is not a draft (it could have been converted since Phase 1):
gh pr view <number> --json isDraft --jq '.isDraft'
If it's now a draft, skip it — checkout main and move to the next PR.
Delegate to code-review
Pass to the code-review skill:
- The PR number
- Whether this is a first review or re-review
The code-review skill will:
- Read the diff and surrounding context
- Check the linked issue
- Analyze for bugs, security, performance, style, tests, issue alignment
- Post inline review comments
- Return a verdict: approve or request-changes
If code-review fails or returns no verdict (e.g., it encounters an error), log the issue and skip to the next PR — don't update labels. The PR will be picked up again in the next cycle.
Return to main
After each review (success or failure), return to a clean state before processing the next PR. In a detached worktree, use git checkout --detach origin/main since main may be checked out elsewhere:
git checkout --detach origin/main
Phase 3: Update labels
Based on the verdict from code-review:
If verdict is request-changes:
gh pr edit <number> --remove-label "needs-ai-review" --add-label "ai-changes-requested"
If verdict is approve:
gh pr edit <number> --remove-label "needs-ai-review" --remove-label "ai-changes-requested" --add-label "ai-approved"
The ai-approved label signals that the AI review found no issues. A human reviewer should still verify and make the final merge decision — the AI never merges or formally approves PRs.
Phase 4: Report
After reviewing all PRs in this cycle, report a summary:
Reviewed N PRs:
- #123 "Add user auth" → ai-changes-requested (1 bug, 2 suggestions)
- #456 "Fix pagination" → ai-approved (no issues)
Then loop back to Phase 0 for the next cycle.
Usage with /loop
/loop 10m /process-reviews
Safety Rails
- Never merge PRs — only post review comments and update labels
- Never use
APPROVEorREQUEST_CHANGESGitHub review events — onlyCOMMENT - Skip draft PRs (check at detection AND before review — status can change between phases)
- Human always makes the final merge decision
- The
ai-approvedlabel means "AI found no issues" — not "approved to merge" - If a
ghcommand fails with HTTP 403 or "rate limit exceeded", stop the current cycle and report: "GitHub API rate limit hit. Wait before retrying." Do not retry immediately.
More from hifisaputra/skills
brainstorm-to-issues
Interactive brainstorming session that refines an idea into a PRD and breaks it into GitHub issues labeled ai-ready. Use when user wants to brainstorm, plan a feature, has an idea to discuss, says "brainstorm", "let's plan", "I have an idea", or wants to break work into issues.
15code-review
Thorough code review of a PR — checks correctness, security, performance, style consistency, test coverage, and verifies the PR addresses its linked issue. Use when user says "review this PR", "check this PR", "look at this diff", or any request to review code changes.
11process-issues
Autonomous loop that picks up ai-ready GitHub issues, handles PR feedback, and asks clarifying questions when blocked. Use when user says "work issues", "start working", "process backlog", or wants AI to autonomously implement GitHub issues.
9code-implementation
Implements a code task using a structured plan-first approach with TDD when tests exist, or direct implementation for docs/config changes. Use when user says "implement this", "build this feature", "fix this bug", or any request to write code for a well-defined task.
9work-issues
Autonomous loop that implements ai-ready GitHub issues, handles PR feedback, and asks clarifying questions when blocked. Use when user says "work issues", "start working", "process backlog", or wants AI to autonomously implement GitHub issues.
5review-prs
Poll for open PRs ready for review and post AI code reviews. Use with /loop to continuously monitor repos. Use when user says "review PRs", "check for PRs", or "start reviewing".
4