Automate PR comment review, fix, and resolution workflow with atomic commits. Use when the user asks to "handle PR comments", "resolve PR review comments", "fix PR feedback", "process review comments", "address PR suggestions", "deal with review comments", or provides a GitHub PR URL with review comments. Also trigger when the user mentions unresolved PR threads or wants to batch-process reviewer feedback. Boundary: not for writing PR reviews (use code-review) or PR checklists (use checklist-runner).
From vp-pr-comment-resolvernpx claudepluginhub vdustr/vp-claude-code-marketplace --plugin vp-pr-comment-resolverThis skill uses the workspace's default tool permissions.
references/reply-templates.mdreferences/workflow.mdImplements structured self-debugging workflow for AI agent failures: capture errors, diagnose patterns like loops or context overflow, apply contained recoveries, and generate introspection reports.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Automate the process of handling GitHub PR review comments: evaluate each comment, fix issues with atomic commits, and reply with detailed resolution information.
User: Handle the comments on this PR: https://github.com/owner/repo/pull/123
Workflow:
User: Auto-resolve all comments on https://github.com/owner/repo/pull/123
Process all comments automatically, only pausing for truly ambiguous cases.
Use gh api graphql to retrieve all unresolved review comments:
gh api graphql -f query='
{
repository(owner: "<OWNER>", name: "<REPO>") {
pullRequest(number: <PR_NUMBER>) {
reviewThreads(first: 100) {
nodes {
id
isResolved
path
line
comments(first: 10) {
nodes {
body
author { login }
}
}
}
}
}
}
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)'
Extract key information:
Determine if each comment is from an AI reviewer. Only AI comments will be auto-resolved; human comments will only receive replies.
Bot Account Suffix: Check if author login ends with [bot]
github-actions[bot], dependabot[bot], copilot[bot]Known AI Services: Match against known AI code review services and LLMs
coderabbitai, codiumai, sourcery-ai, deepsource, sonarcloud, codeclimate, snykcopilot, claude, gemini, codex, openai, anthropic, chatgpt, gptgithub-actions, dependabot, renovate# AI/Bot Detection Logic (case-insensitive)
is_ai_comment=false
author_lower=$(echo "$author_login" | tr '[:upper:]' '[:lower:]')
# Combined pattern: [bot] suffix OR known AI services
ai_patterns='(\[bot\]$|coderabbitai|codiumai|sourcery-ai|deepsource|sonarcloud|codeclimate|snyk|copilot|claude|gemini|codex|openai|anthropic|chatgpt|gpt|github-actions|dependabot|renovate)'
if [[ "$author_lower" =~ $ai_patterns ]]; then
is_ai_comment=true
fi
| Author Type | Auto-Resolve | Action |
|---|---|---|
| AI/Bot | Yes | Reply and resolve after fix |
| Human | No | Reply only, let human resolve |
| Uncertain | Ask user | Prompt user: "Should I resolve this comment from @{author}?" |
Note: If the author doesn't match known AI patterns but has bot-like characteristics (e.g., automated messages, service accounts), ask the user whether to auto-resolve.
For each unresolved comment, critically assess whether the suggestion is correct before determining action:
| Decision | Criteria |
|---|---|
| Needs Fix | Valid point: actual bug, code issue, style violation, missing feature |
| No Fix Needed | Already addressed, misunderstanding, design choice, out of scope |
| Disagree | Reviewer's suggestion is incorrect, would introduce bugs, violates architecture, or is technically flawed |
| Uncertain | Ambiguous request, multiple interpretations, needs clarification |
β οΈ Important: Do not blindly accept all comments. Reviewers can make mistakes. Always verify the technical validity of each suggestion before implementing.
After each action, reply to the comment thread. Only auto-resolve if the comment is from an AI/bot; human comments require manual resolution.
| Comment Source | After Reply |
|---|---|
| AI/Bot | Auto-resolve the thread |
| Human | Do NOT resolve - let the reviewer close it |
β οΈ CRITICAL: You MUST use the GraphQL
addPullRequestReviewThreadReplymutation to reply directly to each review thread. Do NOT usegh pr commentas it posts to the PR bottom instead of the specific thread.
Reply format for fixes:
- [<short-hash> <commit-message>](<commit-url>)
**Files modified:**
- `<file-path>`
π€ Generated with [Claude Code](https://claude.com/claude-code)
Example:
- [a1b2c3f fix(auth): add null check for user session](https://github.com/owner/repo/commit/a1b2c3f)
**Files modified:**
- `src/auth/session.ts`
π€ Generated with [Claude Code](https://claude.com/claude-code)
Reply format for no-fix:
No changes needed.
**Reason:** <explanation of why no fix is required>
π€ Generated with [Claude Code](https://claude.com/claude-code)
After processing all comments, output a summary report:
## PR Comment Resolution Summary
**PR:** #<number> - <title>
**Processed:** <total> comments
### Commits
- [<hash> <message>](<url>)
- [<hash> <message>](<url>)
### Statistics
| Status | AI/Bot | Human | Total |
|--------|--------|-------|-------|
| Fixed & Resolved | <n> | - | <n> |
| Fixed (reply only) | - | <n> | <n> |
| No fix & Resolved | <n> | - | <n> |
| No fix (reply only) | - | <n> | <n> |
| Disagreed (pending) | <n> | <n> | <n> |
| Skipped | <n> | <n> | <n> |
### Details
| Comment | Author | Type | File | Action | Resolved |
|---------|--------|------|------|--------|----------|
| <summary> | @bot | π€ AI | `<path>` | Fixed [<hash>](<url>) | β
|
| <summary> | @human | π€ Human | `<path>` | Fixed [<hash>](<url>) | β³ Pending |
| <summary> | @bot | π€ AI | `<path>` | No fix | β
|
| <summary> | @human | π€ Human | `<path>` | Disagreed | β³ Pending |
# Get all review threads (requires GraphQL - gh pr view does not support reviewThreads)
gh api graphql -f query='
{
repository(owner: "<OWNER>", name: "<REPO>") {
pullRequest(number: <NUMBER>) {
reviewThreads(first: 100) {
nodes {
id
isResolved
path
line
comments(first: 10) {
nodes { body author { login } }
}
}
}
}
}
}'
# Get unresolved threads only (add jq filter)
# ... --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)'
gh api graphql -f query='
mutation($body: String!, $threadId: ID!) {
addPullRequestReviewThreadReply(input: {
pullRequestReviewThreadId: $threadId,
body: $body
}) {
comment { id }
}
}
' -f threadId="<THREAD_ID>" -f body="<REPLY_BODY>"
gh api graphql -f query='
mutation {
resolveReviewThread(input: {
threadId: "<THREAD_ID>"
}) {
thread { isResolved }
}
}
'
Follow conventional commit style. Describe the change, not the comment:
<type>(<scope>): <what was changed>
<why this change was needed - optional>
Important: Commit messages should describe the modification topic, NOT "address comment" or "per reviewer request". The commit should make sense even without PR context.
Example - Good:
fix(auth): add null check for user session
The session object may be undefined when the user
is not logged in. Added defensive check to prevent
TypeError.
Example - Bad:
fix: address PR review comments
Addresses PR review comment by @reviewer
Key principle: Group by modification topic, not by comment count.
Use one commit when comments point to the same logical change:
Comment A: "Add null check for session"
Comment B: "Handle undefined session gracefully"
Comment C: "Session might be null here"
All three β same topic (session null safety) β ONE commit
β Reply to all three comments with the same commit link
Use separate commits when comments are different concerns:
Comment A: "Add error handling"
Comment B: "Improve performance here"
Comment C: "Add input validation"
Three different topics β THREE separate commits
β Each comment gets its own commit link
| Scenario | Commits | Why |
|---|---|---|
| Same topic, different locations | 1 | Same logical change |
| Same function, different concerns | N | Different modifications |
| Same line, same fix | 1 | Literally one change |
| Related but independent | N | Can be reverted separately |
Comment Received
β
βΌ
βββββββββββββββββββ
β Is author βββYesβββΆ is_ai_comment = true
β AI/Bot? β
ββββββββββ¬βββββββββ
βNo
βΌ
βββββββββββββββββββ
β Uncertain? βββYesβββΆ Ask user: "Resolve comment from @{author}?"
β (bot-like but β ββββΆ User decides
β not in list) β
ββββββββββ¬βββββββββ
βNo
βΌ
is_ai_comment = false
β
βΌ
βββββββββββββββββββ
β Is the comment βββNoβββΆ Ask user for clarification
β clear? β
ββββββββββ¬βββββββββ
βYes
βΌ
βββββββββββββββββββ
β Is the comment βββNoβββΆ Discuss with user first
β technically β ββββΆ Politely disagree with evidence
β correct? β (Do NOT auto-resolve)
ββββββββββ¬βββββββββ
βYes
βΌ
βββββββββββββββββββ
β Is a code βββNoβββΆ Reply with explanation
β change needed? β ββββΆ If AI: resolve | If human: skip resolve
ββββββββββ¬βββββββββ
βYes
βΌ
Fix β Commit β Push β Reply
β
βΌ
βββββββββββββββββββ
β is_ai_comment? βββYesβββΆ Resolve thread
ββββββββββ¬βββββββββ
βNo
βΌ
Leave unresolved (human reviewer will close)
gh pr comment for replies - This posts to PR bottom, not to the review thread. Always use GraphQL addPullRequestReviewThreadReply for direct replies; use gh pr comment only as a fallback.| Error | Action |
|---|---|
| Comment already resolved | Skip and continue |
| File not found | Ask user for correct path |
| Commit fails | Report error, do not resolve |
| Push fails | Report error, suggest manual intervention |
| GraphQL API error | See the "Fallback Behavior" section |
For detailed workflows and templates:
references/workflow.md - Step-by-step workflow with examplesreferences/reply-templates.md - Copy-paste reply templates for common scenariosIf the GraphQL API fails to reply to a thread (e.g., network error, permission issue, thread already resolved):
gh pr comment with clear context:gh pr comment <PR_NUMBER> --body "$(cat <<'EOF'
**Re: Review comment on `<FILE_PATH>:<LINE>`**
> <ORIGINAL_COMMENT_EXCERPT>
<YOUR_REPLY_CONTENT>
---
*Note: Unable to reply directly to the review thread. This is a fallback comment.*
EOF
)"
Important: The fallback should only be used when GraphQL truly fails. Always attempt GraphQL first.
gh CLI authenticated with appropriate permissions