From pr-review-loop
Manage the PR review feedback loop: monitor CI checks, fetch review comments, and iterate on fixes. Use when: (1) pushing changes to a PR and waiting for CI/reviews, (2) user says "new reviews available", (3) iterating on PR feedback from Gemini, Cursor, Claude, or other reviewers, (4) monitoring PR status. Supports multiple review bots: Gemini Code Assist, Cursor Bugbot, and Claude agent fallback. Also supports custom agent reviewers defined in AGENT-REVIEWERS.md for focused reviews (security, DRY, etc.). Automatically detects priority levels from different bot formats and handles rate limits. IMPORTANT: Do NOT run the main review loop as a background Task agent. Tasks cannot spawn sub-Tasks, so agent reviewers (from AGENT-REVIEWERS.md) will silently fail to run. Execute the review loop directly in the main conversation so it can spawn agent reviewer Tasks. CRITICAL: When using this skill, NEVER use raw git commit/push commands. ALWAYS use commit-and-push.sh script. The user has NOT granted permission for raw git commands - only the script is allowed.
npx claudepluginhub devonjones/devon-claude-skills --plugin pr-review-loopThis skill uses the workspace's default tool permissions.
**FIRST**, use the Glob tool to find the scripts:
scripts/_jq_helpers.shscripts/check-gemini-quota.shscripts/claude-review.shscripts/commit-and-push.shscripts/get-agent-comments.shscripts/get-review-comments.shscripts/post-line-comment.shscripts/reopen-comment.shscripts/reply-to-comment.shscripts/resolve-comment.shscripts/summarize-reviews.shscripts/trigger-review.shscripts/watch-pr.shCreates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
FIRST, use the Glob tool to find the scripts:
Glob pattern: **/pr-review-loop/*/scripts/commit-and-push.sh
Path: ~/.claude/plugins/cache
This gives you the full absolute path to the scripts directory.
Then use the full literal path for every script call. For example:
/home/user/.claude/plugins/cache/devon-claude-skills/pr-review-loop/1.0.0/skills/pr-review-loop/scripts/commit-and-push.sh "msg"
NEVER use variables like $SCRIPTS/commit-and-push.sh — this breaks permission matching.
NEVER use compound commands like export PATH=... && commit-and-push.sh — this also breaks permissions.
Always inline the full absolute path in every Bash call.
| ❌ FORBIDDEN | ✅ USE INSTEAD |
|---|---|
git commit | scripts/commit-and-push.sh "msg" |
git commit -m "..." | scripts/commit-and-push.sh "msg" |
git push | scripts/commit-and-push.sh "msg" |
git push origin | scripts/commit-and-push.sh "msg" |
If you use git commit or git push directly, it will be BLOCKED.
The PR review loop MUST run in the main conversation, NOT as a background Task.
Tasks cannot spawn sub-Tasks. If the review loop runs as a Task, agent reviewers (from AGENT-REVIEWERS.md) will silently fail to spawn — they require the Task tool, which is only available in the main conversation.
What to do instead: Execute the review loop steps directly in the main conversation. This allows you to spawn agent reviewer Tasks in parallel (step 5 of each round) while keeping Gemini/bot comment handling inline.
Individual agent reviewers (leaf-level Tasks that don't need to spawn further Tasks) should still be spawned via the Task tool — that works because they're called from the main conversation, not from within another Task.
Streamline the push-review-fix cycle for PRs with automated reviewers.
| Bot | Trigger | Priority Format |
|---|---|---|
| Gemini Code Assist | /gemini review comment | ![critical], ![high], ![medium], ![low] |
| Cursor Bugbot | Auto on push | <!-- **High Severity** -->, ### Bug: |
| Claude | Manual via script | **Critical**, ### Critical Issues |
Priority detection automatically parses all formats when summarizing and fetching comments.
Different bots use different comment formats:
reply-to-comment.sh <PR> <comment-id> "Fixed"role_summaries_controller.rb:60")Handling Claude's PR comments:
Fetch the comment to get the comment ID:
gh pr view <PR> --json comments --jq '.comments[] | select(.author.login == "claude") | {id: .id, body: .body}'
Parse issues from the structured markdown:
### **1. BREAKING CHANGE: ...****Location:** linesReply with a consolidated response addressing each issue:
gh pr comment <PR> --body "## Response to Claude Review
**Issue 1 (Breaking API change):** Fixed - added deprecation support for old parameter name
**Issue 2 (Missing validation):** Fixed - added ALLOWED_VIEW_ROLES validation
**Issue 3 (Logic change):** Won't fix - this is intentional, documented in PR description
**Issue 4 (Missing tests):** Fixed - added RSpec tests for SystemRoles methods
"
Individual issues can also be addressed via separate replies if preferred:
gh pr comment <PR> --body "**Re: Issue #2 (Missing Input Validation):** Fixed in commit abc123 - added validation for view_role parameter"
The key difference: Claude comments don't have "threads" to resolve - you reply to the main PR comment referencing which issues you're addressing.
Not all suggestions are good. Evaluate each review comment critically:
Skip suggestions that are:
When in doubt, ask the user rather than blindly applying changes.
Track review rounds. After 2-3 iterations, evaluate:
ONE MORE LOOP rule: When a full round (Gemini + other bots + agent reviewers) produces no actionable feedback (or only "Won't fix" responses), do ONE additional round to catch any final feedback.
Tracking state: Use TodoWrite to track whether you're in the "final verification round". Create a todo like "Final verification round - if no actionable feedback, ready to merge".
Reset condition: If the final verification round produces feedback you actually fix (not just "Won't fix"), remove the "final verification round" todo - you need a fresh "one more" after pushing those fixes.
Exit condition: If the "final verification round" todo exists AND the round produces no actionable feedback (only nitpicks/won't-fix responses), you're done - ask about merge.
After the final round, ask the user: "We've completed the review cycles. Ready to merge, or want to address more?"
CRITICAL RULES - NEVER VIOLATE THESE:
commit-and-push.sh - NEVER git commit or git push (see table at top of document)reply-to-comment.shgh pr comment with consolidated response--wait flag when checking for comments - this ensures proper 5-minute pollingget-review-comments.sh --wait to wait for the first review⚠️ CRITICAL: Each round includes ALL reviewer types before triggering the next cycle.
DO NOT run multiple Gemini rounds before checking other reviewers. After addressing Gemini comments, you MUST check for other bot comments and run agent reviewers BEFORE triggering another Gemini review. This interleaving is essential because:
EACH ROUND (all steps before next review trigger):
┌─────────────────────────────────────────────────────────────┐
│ 1. Get Gemini comments (--wait only on first check) │
│ 2. Address ALL Gemini comments │
│ 3. Check for other bot PR comments (Claude, Cursor, etc.) │
│ 4. Address ALL other bot comments │
│ 5. Run agent reviewers (AGENT-REVIEWERS.md) │
│ 6. Address ALL agent comments │
│ 7. Commit and push (if ANY fixes were made in steps 2,4,6) │
│ 8. Trigger next review (--wait) │
└─────────────────────────────────────────────────────────────┘
│
▼
Go to step 1 (next round)
Step details:
--wait to poll up to 5 minutes--wait is already triggered by step 8reply-to-comment.sh <PR> <comment-id> "response" (handles PR comments)trigger-review.sh <PR> --waitCOMPLETION: When a full round produces no actionable feedback (Gemini + other bots + agents all stable) AND this was the "final verification" round:
1. Check for unresolved Gemini line comments (ALWAYS use --wait for first check after PR creation or push):
scripts/summarize-reviews.sh <PR>
scripts/get-review-comments.sh <PR> --with-ids --wait
The --wait flag polls every 30s for up to 5 minutes, waiting for Gemini to respond. Do NOT skip this or use a shorter timeout.
The --with-ids flag outputs comment IDs needed for replies. Example output:
=== Comment ID: 2710906366 | Node ID: PRRC_kwDOD3ZsRc6hlSX- ===
File: pfsrd2/equipment.py:84
Priority: high
The function appears to duplicate functionality...
Use the Node ID (PRRC_...) when replying to comments. The Node ID is required for reply-to-comment.sh to properly attach your reply to the review thread.
2. Address Gemini line comments (MANDATORY - never skip this):
# Use the Node ID (PRRC_...) from get-review-comments.sh --with-ids output
scripts/reply-to-comment.sh <PR> PRRC_kwDOD3ZsRc6hlSX- "Fixed - description"
# OR for bad/inappropriate suggestions:
scripts/reply-to-comment.sh <PR> PRRC_kwDOD3ZsRc6hlSX- "Won't fix - reason"
# OR for good suggestions outside PR scope - see "Out of Scope Suggestions" section:
scripts/reply-to-comment.sh <PR> PRRC_kwDOD3ZsRc6hlSX- "Out of scope - tracked in BD-XXX"
3. Check for other bot PR comments (Claude, Cursor, Copilot):
These bots post single PR comments (not line comments) containing multiple issues:
# Find Claude's review comment
gh pr view <PR> --json comments --jq '.comments[] | select(.author.login == "claude") | {id: .id, body: .body[:500]}'
For each issue in the comment:
gh pr comment <PR> --body "## Response to Claude Review
**Issue 1 (name):** Fixed - description
**Issue 2 (name):** Won't fix - reason
**Issue 3 (name):** Out of scope - tracked in BD-XXX
"
4. Run agent reviewers (if AGENT-REVIEWERS.md exists):
5. Commit and push (ALWAYS use the script, NEVER raw git) - if any fixes were made:
scripts/commit-and-push.sh "fix: description"
This script runs pre-commit, commits with proper footer, and pushes.
6. Trigger next review and wait for response:
scripts/trigger-review.sh <PR> --wait
The --wait flag polls for up to 5 minutes until new comments appear. Do NOT use sleep or manual polling.
7. When new reviews detected, go to step 1
ALWAYS reply using reply-to-comment.sh. Templates:
Reply using gh pr comment with a consolidated response:
## Response to Claude Review
**Issue 1 (Breaking API change):** Fixed - added backward compatibility
**Issue 2 (Missing validation):** Fixed - added input validation in controller
**Issue 3 (Behavior change):** Won't fix - intentional, see PR description
**Issue 4 (Missing tests):** Out of scope - tracked in BD-XXX
When a review suggestion is good but outside the scope of this PR, capture it for later rather than losing it.
Decision tree:
Check if beads is installed:
bd --version
If beads is available, create a ticket:
bd create
Include in the ticket:
gh api /repos/{owner}/{repo}/pulls/{PR}/comments/{comment-id}
Then reply to the comment:
scripts/reply-to-comment.sh <PR> <comment-id> "Out of scope - tracked in BD-XXX"
Track the ticket for reporting at the end of the review loop. Keep a list of all created tickets (ID and title) to include in the completion summary.
If beads is NOT installed, just reply without creating a ticket:
scripts/reply-to-comment.sh <PR> <comment-id> "Out of scope for this PR"
scripts/trigger-review.sh <PR> --gemini --wait
Gemini has a daily quota. When exceeded, the skill automatically detects this and suggests alternatives.
scripts/trigger-review.sh <PR> --cursor --wait
Cursor auto-reviews on push, so --cursor just waits for comments to appear (typically 1-2 minutes).
scripts/trigger-review.sh <PR> --claude
Uses a Claude agent to review the PR and post comments. Useful when:
When using Claude fallback:
Run the script to get the prompt:
scripts/claude-review.sh <PR>
Use the Task tool with the generated prompt:
Task tool:
subagent_type: general-purpose
description: Review PR #<PR>
prompt: (copy from /tmp/claude_review_prompt_<PR>.txt)
The agent will post the review as a PR comment
Continue the normal review loop - address comments using reply-to-comment.sh
Run custom agent reviewers defined in AGENT-REVIEWERS.md files as part of each review round.
Two types of H1 sections:
# Agents - Defines custom agent reviewers (H2 headings become agent names)# Agents
## security-reviewer
Focus on security vulnerabilities: injection attacks, auth bypasses, secrets in code,
unsafe deserialization, path traversal, etc. Flag anything that could be exploited.
## dry-reviewer
Identify code duplication. Look for repeated logic that could be abstracted.
Consider whether abstraction would actually improve maintainability.
# Guidelines
When reviewing this codebase:
- All database queries must use parameterized statements
- Prefer composition over inheritance
- Error messages should never expose internal paths or stack traces
# Context
This is a Ruby on Rails API backend. The frontend is a separate React app.
Authentication uses JWT tokens stored in httpOnly cookies.
How sections are used:
# Agents → H2 headings define agent reviewers with their specialized instructions# Guidelines, # Context, etc.) → Passed to the main pr-review-loop task as context, similar to CLAUDE.md contentAGENT-REVIEWERS.md files can exist at any directory level. Agents and context sections are scoped to their directory and below.
Resolution rules:
AGENT-REVIEWERS.md files from its directory up to repo root# Agents: each agent only reviews changes within its directory scope and belowExample structure:
/AGENT-REVIEWERS.md # Agents: clarity-reviewer, dry-reviewer
# Guidelines: general repo rules
/plugins/AGENT-REVIEWERS.md # Agents: dry-reviewer (overrides root), plugin-structure-reviewer
# Guidelines: plugin-specific rules (overrides root)
/plugins/auth/AGENT-REVIEWERS.md # Agents: security-reviewer
# Context: auth-specific context
Result for a PR touching plugins/auth/login.py and plugins/utils.py:
Agents:
clarity-reviewer (from root) → sees all changesdry-reviewer (from /plugins/, overrides root) → sees all changes under /plugins/plugin-structure-reviewer (from /plugins/) → sees all changes under /plugins/security-reviewer (from /plugins/auth/) → sees only changes under /plugins/auth/Context for main review loop:
plugins/auth/login.py: combines # Guidelines from /plugins/ + # Context from /plugins/auth/plugins/utils.py: uses # Guidelines from /plugins/Discovery algorithm:
# For each unique directory containing changed files:
# 1. Walk up to repo root collecting AGENT-REVIEWERS.md paths
# 2. Parse each file, building agent map (lower wins on name collision)
# 3. Track each agent's scope (directory where it was defined)
Agent reviewers run as part of each review round, after addressing Gemini and other bot comments.
On the first round (or when new agents are discovered), discover agent reviewers:
# Get list of changed files
gh pr diff <PR> --name-only
# For each unique parent directory, check for AGENT-REVIEWERS.md up to repo root
Spawn non-retired agents in parallel at step 4 of each round. Track per-agent state to avoid re-running retired agents.
For each agent discovered (after merging and scoping), spawn a Task:
Task tool:
subagent_type: general-purpose
model: sonnet
description: <agent-name> review for PR #<PR>
prompt: |
You are the "<agent-name>" code reviewer for PR #<PR>.
Your focus: <instructions from AGENT-REVIEWERS.md>
**Your scope: <scope-path>/**
You should ONLY review changes to files under this path. Ignore changes outside your scope.
## Your workflow:
1. **Check your prior comments** (if any):
```bash
scripts/get-agent-comments.sh <PR> <agent-name> --with-replies
```
2. **Evaluate replies to your prior comments**:
- If the response is reasonable (good explanation, valid fix, or acceptable tradeoff), do NOT re-raise
- If the response is UNREASONABLE (dismissive, incorrect, or ignores the issue), reopen:
```bash
scripts/reopen-comment.sh <PR> <comment-id> <agent-name> "Reopening - <reason why response is insufficient>"
```
3. **Review the PR diff** (filter to your scope):
```bash
gh pr diff <PR> -- '<scope-path>/*'
```
If scope is repo root, use `gh pr diff <PR>` without path filter.
4. **Post NEW findings** as line comments (only issues not already raised, only files in your scope):
```bash
scripts/post-line-comment.sh <PR> <file> <line> <agent-name> "Issue description and suggestion"
```
The script automatically adds `<!-- Agent: <agent-name> -->` signature.
5. **Return** - Do NOT fix anything. Your job is review only.
## Important:
- Be thorough but not pedantic - only flag real issues within your focus area
- Consider project context - not all best practices apply everywhere
- If you have no findings and all prior comments have reasonable responses, simply return "No issues found"
Available scripts: See pr-review-loop skill documentation for full script reference.
Spawn all agents in parallel - use multiple Task tool calls in a single message.
Agent reviewers are part of each round, running after Gemini and other bot comments are addressed:
After agent Tasks return, address agent comments using the same flow as Gemini:
Update per-agent tracking based on results (productive / final-verification / retired)
After all comments in the round are addressed (Gemini + other bots + agents):
scripts/commit-and-push.sh "fix: address review comments"scripts/trigger-review.sh <PR> --waitApply the same heuristic as Gemini, but per agent:
"<agent-name>: final verification loop"Example tracking:
- "security-reviewer: 2 cycles, still productive" (keep calling)
- "dry-reviewer: final verification loop" (one more, then retire if no actionable feedback)
- "error-handling-reviewer: retired" (no longer called)
As agents reach diminishing returns, stop calling them. The main loop should:
AGENT-REVIEWERS.md to get all agent namesThis keeps the review loop efficient while ensuring all perspectives are heard at least once.
The scripts automatically detect Gemini quota limits by checking for:
"You have reached your daily quota limit"
When detected, the script suggests:
--cursor --wait--claude| Script | Purpose |
|---|---|
commit-and-push.sh "msg" | ALWAYS USE - Never use raw git commit/push |
reply-to-comment.sh <PR> <id> "msg" | ALWAYS USE - Reply and auto-resolve every comment |
get-review-comments.sh <PR> [--with-ids] [--wait] | USE --wait - Fetch comments, polls 5min if --wait |
trigger-review.sh [PR] [--gemini|--cursor|--claude] [--wait] | USE --wait - Trigger review and poll for response |
summarize-reviews.sh <PR> [--all] | Summary of unresolved by priority/file |
watch-pr.sh <PR> | Background monitor (optional, for long-running watches) |
claude-review.sh <PR> | Generate Claude agent prompt for code review |
check-gemini-quota.sh <PR> | Check if Gemini is rate-limited |
resolve-comment.sh <node-id> [reason] | Manually resolve a thread |
post-line-comment.sh <PR> <file> <line> <agent> "msg" | Post line comment with agent signature |
get-agent-comments.sh <PR> <agent> [--with-replies] | Fetch agent's own comments and replies |
reopen-comment.sh <PR> <comment-id> <agent> "reason" | Reply to resolved thread with Claude attribution |
To enable autonomous loops, user should grant access:
Bash(scripts/commit-and-push.sh:*)
Bash(scripts/reply-to-comment.sh:*)
Bash(scripts/trigger-review.sh:*)
Bash(scripts/post-line-comment.sh:*)
Bash(scripts/get-agent-comments.sh:*)
Bash(scripts/reopen-comment.sh:*)
gh CLI authenticatedjq - JSON processor for parsing GitHub API responses
Install with: apt install jq (Ubuntu/Debian) or brew install jq (macOS)pre-commit (optional) - If .pre-commit-config.yaml exists in the repo, pre-commit will be run.
If pre-commit is not installed, a warning is shown but commits proceed.
Install with: pip install pre-commit && pre-commit installbd (beads) (optional) - Issue tracker for capturing out-of-scope suggestions as tickets.
If not installed, out-of-scope suggestions are handled with "Out of scope for this PR" replies.
See: https://github.com/steveyegge/beads