pr-fix-loop
PR Review Workflow
Systematic workflow for checking, responding to, and reporting on PR feedback from any source — human reviewers, review bots (CodeRabbit, Gemini, Codex, Snyk, etc.), or AI agents.
Requirements: GitHub repository with GitHub CLI (gh) installed and authenticated.
Key insight: PR feedback arrives through three different channels (conversation comments, inline threads, review submissions). Missing any channel means missing feedback. This skill ensures all channels are checked systematically.
Modes
| Mode | When | What happens |
|---|---|---|
| loop (default) | No mode specified | Full fix-review cycle: check → fix → report → re-invoke → repeat until done (max 5 rounds) |
| check | "check", "status" | Show current feedback from all channels, then stop |
| invoke | "invoke", "invoke gemini" | Invoke review agents (all or named), then stop |
| single-pass | "single-pass", "once" | Check → fix → report once, no re-invoke or looping |
Invocation examples:
/pr-fix-loop→ loop mode (default)/pr-fix-loop check→ just show feedback/pr-fix-loop invoke→ invoke all review agents/pr-fix-loop invoke gemini,codex→ invoke specific agents/pr-fix-loop single-pass→ one round of fixes, no loop
Self-Contained Constraint
ALL operations MUST go through the provided scripts. Never run raw git, gh, date, or bash heredocs (cat > file << 'EOF') when a script or agent tool covers the same operation.
| Instead of (prohibited) | Use |
|---|---|
git status, git branch, gh pr view, gh repo view |
get-context.sh |
git add, git commit, git push |
commit-and-push.sh |
git checkout -b, git switch -c |
open-branch.sh |
gh pr create |
create-pr.sh |
gh api repos/.../comments, gh pr view --json |
check-pr-feedback.sh |
gh api ... -f body= (posting comments) |
post-fix-report.sh or reply-to-inline.sh |
date -u +%Y-%m-%dT%H:%M:%SZ |
get-context.sh (outputs timestamp: field) |
cat > file.md << 'EOF' (bash heredoc) |
Agent's native Write tool to .agents/scratch/, then pass file path to script |
echo "..." | script.sh (piped stdin) |
Script's direct flag: -m, --body, or file-path argument |
Entry point: Always start with get-context.sh to detect current state. Use its output to decide next steps via the Decision Tree below.
File creation: When a script accepts a file path (e.g., create-pr.sh --body, post-fix-report.sh), write the file to .agents/scratch/ using the agent's native Write tool, then pass the path to the script. Never use bash heredocs to create temp files.
- Directory:
.agents/scratch/— inside the repo, avoids out-of-tree write permission prompts - Setup: Run
mkdir -p .agents/scratchbefore the first write if it doesn't exist - Gitignore: Ensure
.agents/is in the project's.gitignore - Cleanup: Scripts auto-delete scratch files after reading them, so the file won't exist on subsequent runs (no overwrite prompts)
Acceptable raw commands: Project-specific test/build commands (npm test, npm run <script>, pytest, make build, etc.) are fine — these are not PR workflow operations. For creating test fixtures, use the agent's native Write tool (write to .agents/scratch/) instead of printf or echo redirects. Avoid echo ... | command — piped commands trigger permission prompts in sandboxed environments.
Entry Point
Always start with get-context.sh to detect current state. Then select the mode from the user's prompt (see Modes above) and follow the matching workflow below.
check mode
get-context.sh— detect PR numbercheck-pr-feedback.sh— show all feedback from all channels- Stop. No commits, no invocations, no looping.
invoke mode
get-context.sh— detect PR number- If no PR exists: inform user, stop
invoke-review-agents.sh[with--agentsif user named specific agents]- Inform user that triggers were posted
- Stop. No fixes, no commits, no looping.
single-pass mode
get-context.sh— detect state- Follow the setup table below to ensure a PR exists
check-pr-feedback.sh— get all feedback- Fix code based on feedback
commit-and-push.sh -m "fix: address review feedback"reply-to-inline.shfor each addressed inline comment- Post Fix Report via
post-fix-report.sh - Stop. No re-invocation, no looping.
loop mode (default)
get-context.sh— detect state- Follow the setup table below to ensure a PR exists
- Continue with the Loop Mode workflow (step 3 onward in the Loop Mode section)
Setup table (for single-pass and loop modes)
Based on get-context.sh output, ensure a branch and PR exist before proceeding:
on_default |
has_changes |
pr_number |
Action sequence |
|---|---|---|---|
true |
true |
empty | open-branch.sh → commit-and-push.sh → create-pr.sh --invoke --title "..." |
true |
false |
empty | Ask user what to do (no changes to work with) |
false |
any | has number | Continue (PR exists) |
false |
true |
empty | commit-and-push.sh → create-pr.sh --invoke --title "..." |
false |
false |
empty | create-pr.sh --invoke --title "..." (branch exists, already pushed) |
Quick Commands
Script path resolution: Before running any script, determine the correct base path. Check in this order:
~/.claude/skills/pr-fix-loop/scripts/— global install for Claude Code- Other global paths by preference of the agent
Use whichever path exists. Script paths below use the global form; substitute accordingly for your agent or install method.
Get Context (Entry Point)
~/.claude/skills/pr-fix-loop/scripts/get-context.sh
Outputs key-value pairs: branch, on_default, has_changes, change_summary, pr_number, pr_url, pr_state, timestamp, repo. Use timestamp for wait-for-reviews.sh --since. Gracefully handles missing gh (empty PR/repo fields). Exits 1 only on detached HEAD or not in a git repo.
Open Branch (Idempotent)
~/.claude/skills/pr-fix-loop/scripts/open-branch.sh [BRANCH_NAME]
If already on a non-main/master branch, prints branch name and exits. If on main/master, creates branch, switches, and pushes with -u. Default name: review-loop-YYYYMMDD-HHMMSS.
Check All Feedback (CRITICAL - Use First)
~/.claude/skills/pr-fix-loop/scripts/check-pr-feedback.sh [PR_NUMBER]
Checks all three channels: conversation comments, inline comments, reviews.
If no PR number provided, detects current PR from branch.
Reply to Inline Comment
~/.claude/skills/pr-fix-loop/scripts/reply-to-inline.sh <COMMENT_ID> "Your message"
~/.claude/skills/pr-fix-loop/scripts/reply-to-inline.sh <COMMENT_ID> .agents/scratch/reply.md
Replies in-thread to inline comments. Accepts message as inline text or a file path (auto-detects). Use file path when message contains ${...} or other shell-sensitive syntax to avoid permission prompts. Uses -F flag (not --raw-field) which properly handles numeric ID conversion in gh CLI.
Must be run from repository root with an active PR branch.
Important: Always sign inline replies with your agent identity (e.g., —Claude Sonnet 4.5, —GPT-4, —Custom Agent) to distinguish agent responses from human responses in the GitHub UI.
Invoke Review Agents
~/.claude/skills/pr-fix-loop/scripts/invoke-review-agents.sh [--agents SLUG,...] [--format-only] [PR_NUMBER]
Posts trigger comments to start agent reviews. Without --agents, invokes all known agents (Codex, Gemini, CodeRabbit). Use --list to see available agents. Use --format-only to print trigger text to stdout without posting (for embedding in PR body).
Post Fix Report
~/.claude/skills/pr-fix-loop/scripts/post-fix-report.sh [PR_NUMBER] .agents/scratch/fix-report.md
Create PR (Idempotent)
~/.claude/skills/pr-fix-loop/scripts/create-pr.sh --title "PR title" --body .agents/scratch/pr-body.md [--invoke]
Or body as inline text:
~/.claude/skills/pr-fix-loop/scripts/create-pr.sh --title "PR title" --body "Short description"
--body auto-detects: if the value is a readable file, reads from it; otherwise treats as text. Idempotent: if a PR already exists, outputs its info. Refuses to run on main/master. Pushes branch if not yet pushed.
--invoke appends review agent trigger text to the PR body (via invoke-review-agents.sh --format-only), avoiding a separate trigger comment that causes double-invocations when auto-review is enabled.
Output prefixes (machine-parseable):
EXISTS: <url>— PR already existed for this branchCREATED: <url>— new PR was created
Commit and Push
~/.claude/skills/pr-fix-loop/scripts/commit-and-push.sh -m "fix: address review feedback"
Stages all changes, commits, and pushes. Refuses to run on main/master. Never force-pushes. Outputs commit hash and branch.
Wait for Reviews
~/.claude/skills/pr-fix-loop/scripts/wait-for-reviews.sh [PR_NUMBER] --since TIMESTAMP [--timeout 600] [--interval 30]
Polls all three feedback channels for new comments posted after TIMESTAMP by non-self users. Exits 0 when new feedback detected, exits 1 on timeout. Default: 10 min timeout, 30s interval.
Check New Feedback (Differential)
~/.claude/skills/pr-fix-loop/scripts/check-new-feedback.sh [PR_NUMBER] --since TIMESTAMP
Like check-pr-feedback.sh but only shows feedback created after TIMESTAMP, excluding self-posted comments. Use in loop mode to distinguish new from already-addressed feedback. Ends with a summary line: Summary: N conversation, M inline, K reviews.
Commit Workflows
Always use commit-and-push.sh for committing. It stages all changes, commits, pushes, and enforces branch safety (refuses main/master, never force-pushes).
~/.claude/skills/pr-fix-loop/scripts/commit-and-push.sh -m "<type>: <outcome>"
Commit Type Conventions
Types: feat, fix, refactor, docs, chore, test
Self-Check Before Commit
Before committing, verify:
- Test changes — Run project-specific tests (
npm test,pytest, etc.) if modifying working code - Check latest feedback — Run
check-pr-feedback.shto catch any new comments - User confirmation — If user is active in session, ask before committing
- Verify claims — If Fix Report says "verified:", actually verify
PR Creation
Set Up Template (Once)
Create .github/pull_request_template.md:
## Summary
-
## How to test
-
## Notes
- Review feedback may arrive in conversation comments, inline threads, or review submissions. Check all channels.
Or copy from assets/pr_template.md.
Create PR
Fill Summary, How to test, and Notes sections.
Code Review Coordination
Feedback Channels
| Channel | Reviewer Type | Format |
|---|---|---|
| Conversation | AI agents, humans | Top-level comments |
| Inline | Review bots (CodeRabbit, Gemini, Codex, Snyk, etc.), humans | File/line threads |
| Reviews | Humans, some bots | Approve/Request Changes + optional body |
Critical Rule: Check ALL Three Channels
~/.claude/skills/pr-fix-loop/scripts/check-pr-feedback.sh
Why: Different reviewers post in different channels. Missing any channel = missing feedback.
Three channels:
- Conversation comments — general discussion, agent reviews
- Inline comments — file/line-specific feedback from any reviewer
- Reviews — approval state + optional body
Critical Evaluation of Feedback
Never trust review feedback at face value. Before acting on any comment — whether from a human reviewer, review bot, or AI agent — critically evaluate it:
- Verify the claim — Read the actual code being referenced. Does the reviewer's description match reality? Reviewers (especially bots) may misread context, reference wrong lines, or describe code that doesn't exist.
- Check for hallucinations — Review bots may fabricate issues: non-existent variables, imagined type mismatches, phantom security vulnerabilities. Always confirm the issue exists before fixing it.
- Assess correctness — Even if the issue is real, the suggested fix may be wrong. Evaluate whether the suggestion would break existing behavior, introduce regressions, or conflict with project conventions.
- Test before committing — If a suggestion modifies working code, run tests before and after to confirm the change is actually an improvement.
If a review comment is incorrect, respond with a clear explanation of why rather than applying a bad fix. Use WONTFIX status with reasoning in the Fix Report.
Responding to Inline Comments
- Critically evaluate the feedback (see above), then address it in code if valid
- Reply inline to each comment (sign with agent identity):
# Short messages — inline text:
~/.claude/skills/pr-fix-loop/scripts/reply-to-inline.sh <COMMENT_ID> "Fixed @ abc123. [details] —[Your Agent Name]"
# Messages with ${...} or shell-sensitive syntax — write to file first, pass path:
~/.claude/skills/pr-fix-loop/scripts/reply-to-inline.sh <COMMENT_ID> .agents/scratch/reply.md
- Include in Fix Report (conversation comment) — the Fix Report summarizes all changes, but inline replies ensure each comment gets a direct acknowledgment
Invoking Review Agents
Run invoke-review-agents.sh when check-pr-feedback.sh returns empty output from all three channels — no feedback means no agents have reviewed yet.
# No feedback on the PR? Invoke all agents:
~/.claude/skills/pr-fix-loop/scripts/invoke-review-agents.sh
# User mentioned specific agents (e.g., "ask Gemini and Codex to review"):
~/.claude/skills/pr-fix-loop/scripts/invoke-review-agents.sh --agents gemini,codex
Agent selection from prompt: If the user's prompt names specific agents (e.g., "have Codex review this"), use --agents with the matching slug(s). Otherwise invoke all.
Embedding in PR body: When creating a new PR with create-pr.sh --invoke, trigger text is appended to the PR body automatically (via --format-only). This avoids a separate trigger comment that would cause double-invocations when auto-review is enabled. Only use invoke-review-agents.sh directly when the PR already exists.
After invoking: Inform the user that trigger comments were posted and suggest running check-pr-feedback.sh again once agents have had time to respond (typically a few minutes).
See references/review-agents.md for the full agent registry and instructions for adding new agents.
Fix Reporting
After addressing feedback, always post ONE conversation comment (Fix Report). This is separate from requesting re-review — the Fix Report documents what was done, even if no re-review is needed.
Write the report with the agent's Write tool (e.g., to .agents/scratch/fix-report.md), then post it:
~/.claude/skills/pr-fix-loop/scripts/post-fix-report.sh .agents/scratch/fix-report.md
Fix Report format:
### Fix Report
- [file.ext:L10 Symbol]: FIXED @ abc123 — verified: `npm test` passes
- [file.ext:L42 fn]: WONTFIX — reason: intentional per AGENTS.md
- [file.ext:L100 class]: DEFERRED — tracking: #123
- [file.ext:L200 method]: QUESTION — Should this handle X?
Optionally, if re-review is needed, add @reviewer-username please re-review. at the end of the body.
Fix Statuses
| Status | Required Info |
|---|---|
| FIXED | Commit hash + verification command/result |
| WONTFIX | Reason (cite docs if applicable) |
| DEFERRED | Issue/ticket link |
| QUESTION | Specific question to unblock |
See references/fix-report-examples.md for real-world examples.
Use assets/fix-report-template.md as starting point.
Review Format (For Agent-Reviewers)
Agent-reviewers MUST post ONE top-level conversation comment:
### Review - Actionable Findings
**Blocking**
- path/file.ext:L10-L15 (Symbol): Issue → Fix → Verify: `command`
**Optional**
- path/file.ext:L100 (class): Improvement → Fix
Rules:
- Blocking MUST include verification (runnable command or objective check)
- Use
file:line+ symbol anchor - Actionable, not prose
- Group by severity
Do NOT:
- Create inline file/line comments
- Submit GitHub review submissions
- Post multiple separate comments
Why: Inline comments harder to retrieve. Conversation comments deterministic.
Re-Review Loop
After Fix Report:
- Request re-review:
@reviewer please re-review. See Fix Report. - Tag ALL reviewers who provided feedback
- If QUESTION items: Wait for clarification
- If blocking feedback was only provided inline: Mention it was addressed, optionally ask to mirror to conversation for future determinism
Loop Mode
Loop mode is the default. Run the full review-fix-review cycle autonomously until no new feedback remains.
Default max rounds: 5. Override with user instruction if needed.
Loop workflow:
- Branch —
open-branch.sh(idempotent — creates branch if on main/master) - PR —
create-pr.sh --invoke --title "..." --body <path>— write body with agent Write tool, pass path. Capture output prefix (CREATED:/EXISTS:) - Invoke — Round 1: if step 1 output
CREATED:, skip (triggers in PR body). IfEXISTS:, runinvoke-review-agents.sh. Rounds 2+: agents triggered by @-mentions in previous Fix Report footer (no separate invoke step) - Wait —
wait-for-reviews.sh --since <timestamp>— usetimestampfromget-context.sh(run after last commit, or after step 1 for round 1). Polls until new feedback or timeout - Check —
check-pr-feedback.sh(ALL feedback, all channels) - Process — compare all feedback against previous Fix Reports. Address only: (a) items not covered in any Fix Report, (b) items with new follow-up comments after the last Fix Report. Critically evaluate each item before fixing
- Fix code, commit —
commit-and-push.sh -m "fix: address review feedback round N" - Get timestamp —
get-context.sh(capturetimestampfor next wait step) - Reply inline —
reply-to-inline.shfor each addressed inline comment; sign with agent identity; tag the reviewer's@github-user - Fix Report — write report with agent Write tool, then
post-fix-report.sh <PR> <path>- Before max: footer has @-mentions +
@coderabbitai reviewon its own line - At max: footer has max-reached message (see below)
- Before max: footer has @-mentions +
- Loop — if
ROUND < MAX_ROUNDS, go to step 3
Why full check instead of differential: Using check-new-feedback.sh --since in the check step risks missing feedback that arrives during the fix phase (e.g., Gemini posts while agent is fixing Codex's comments). The full check + Fix Report comparison approach is gap-free.
Termination conditions (any):
- Step 5 finds nothing new to process (all feedback already addressed in Fix Reports)
wait-for-reviews.shtimes out (no new feedback after invocation)- A reviewer posts an Approve review
- User explicitly stops the loop
- Max rounds reached
Final round Fix Report footer:
Max review rounds (N) reached. Remaining items addressed above. Manual re-review recommended.
Inline reply tagging: When replying to a bot/agent inline comment, include the reviewer's GitHub username in the reply (e.g., —Claude Sonnet 4.6 | addressed @gemini-code-assist feedback).
See references/fix-report-examples.md Examples 7–8 for loop-mode Fix Reports.
Multi-Reviewer Patterns
Duplicate Feedback
If multiple reviewers flag the same issue:
- [file.php:L42 (ALL flagged)]: FIXED @ abc123 — verified: `npm test` passes
- Gemini: "use const"
- Codex: "prefer immutable"
- Claude: "const prevents reassignment"
Conflicting Suggestions
- [file.php:L100]: QUESTION — Gemini suggests pattern A, Codex suggests pattern B. Which aligns with project conventions? See AGENTS.md.
Finding Comments by Reviewer
Use check-pr-feedback.sh — its output already includes [user.login] for every comment across all three channels. Filter the output for the reviewer you need:
~/.claude/skills/pr-fix-loop/scripts/check-pr-feedback.sh | grep "coderabbitai"
Troubleshooting
"Can't find review comments"
→ Check all three channels. Use ~/.claude/skills/pr-fix-loop/scripts/check-pr-feedback.sh, not just gh pr view.
"Reviewer posted inline, should I reply inline?" → Yes, always. Reply inline with a brief ack so the comment can be resolved in GitHub UI. Also include in Fix Report.
"Multiple reviewers flagged same issue" → Fix once, report once (note all sources), tag all reviewers.
"Conflicting suggestions" → Mark QUESTION, check project docs, cite specific suggestions.
"Script can't detect PR" → Run from repository root. Must be on branch with open PR.
"Reply script fails with HTTP 422"
→ Use -F in_reply_to=ID not --raw-field. The -F flag works correctly with gh CLI for numeric IDs.
"Review suggestion broke working code" → Never trust suggestions blindly. Verify the issue exists, evaluate the fix, and test before committing. Review bots frequently hallucinate problems or suggest incorrect fixes.
"No feedback on PR — all three channels empty"
→ Agents haven't reviewed yet. Run ~/.claude/skills/pr-fix-loop/scripts/invoke-review-agents.sh to trigger them, then wait and re-check.
"Committed before checking latest feedback" → Run feedback check script immediately before declaring PR "ready" or "complete."
Summary
Key principles:
- Always check all three channels (conversation + inline + reviews)
- Critically evaluate every comment — reviewers can be wrong, misread context, or hallucinate issues
- Any reviewer (human, bot, agent) can post in any channel
- One Fix Report per round
- Tag all reviewers explicitly
- If no feedback exists, invoke agents first — never declare a PR complete without at least one review round
Most common mistakes:
❌ Only checking conversation or gh pr view
✅ Always run ~/.claude/skills/pr-fix-loop/scripts/check-pr-feedback.sh
❌ Blindly applying review suggestions without verifying the issue exists ✅ Read the actual code, confirm the problem, test the fix