Resolve PR review comments from CodeRabbit (or any reviewer) with atomic commits and threaded replies
Enable Claude Code to systematically clear unresolved PR review threads: analyze all threads, group by logical issue, implement atomic fixes, create one commit per logical issue, and post threaded replies linking each comment to the commit that addresses it.
Key principle: Create atomic commits that make sense as standalone changes. Group related comments that address the same underlying issue into a single commit for clean git history.
/superpowers:write-plan – Create implementation plan
Example:
/superpowers:write-plan
Goal: Clear all unresolved review threads in PR ${PR} for ${REPO}.
Approach: Analyze all comments and group by logical issue. Create atomic commits per issue.
Deliverables:
- Grouping plan showing which comments address the same logical issue
- One commit per logical issue (e.g., "Add archived filters" for 3 related comments)
- Threaded replies to ALL comments in each group with the commit link
Constraints: Atomic commits that make sense standalone; preserve style; run tests before each commit.
RECOMMENDED: Use GraphQL to get unresolved review threads directly. This is more reliable than filtering REST API results.
REPO="stonelyd/altium-design-review" # Update with your repo
PR=5 # Update with your PR number
# Get all unresolved review threads with full comment details
readarray -t THREADS < <(
gh api graphql -f query='
query($owner:String!, $name:String!, $pr:Int!) {
repository(owner:$owner, name:$name) {
pullRequest(number:$pr) {
reviewThreads(first: 100) {
nodes {
id
isResolved
comments(first: 50) {
nodes {
databaseId
path
originalPosition
diffHunk
isMinimized
author { login }
}
}
}
}
}
}
}' \
-F owner="${REPO%%/*}" -F name="${REPO##*/}" -F pr="$PR" \
| jq -c '.data.repository.pullRequest.reviewThreads.nodes[]
| select(.isResolved==false)
| {thread_id:.id,
top_comment_id:(.comments.nodes[0].databaseId),
path:(.comments.nodes[0].path),
author:(.comments.nodes[0].author.login),
diff:(.comments.nodes[0].diffHunk)}')
# Display the threads
echo "=== Found ${#THREADS[@]} unresolved threads ==="
for i in "${!THREADS[@]}"; do
echo -e "\n--- Thread $((i+1)) ---"
echo "${THREADS[$i]}" | jq -r '"Comment ID: \(.top_comment_id)\nFile: \(.path)\nAuthor: \(.author)\nThread ID: \(.thread_id)"'
done
Alternative: REST API for comment bodies
Use REST API to get full comment bodies after you have the comment IDs from GraphQL.
# Save all comments to file for processing (includes threaded replies)
gh api repos/${REPO}/pulls/${PR}/comments --paginate > /tmp/all_comments.json
# Extract specific comment details
for CID in 2466210587 2466210599 2466210608; do
echo -e "\n=========================================="
echo "COMMENT ID: $CID"
cat /tmp/all_comments.json | jq -r ".[] | select(.id == $CID) | \"File: \(.path):\(.line // .original_line // \"null\")\\nAuthor: \(.user.login)\\n\\nBody:\\n\(.body)\\n\""
echo "=========================================="
done
After getting thread IDs from GraphQL, fetch full comment bodies from REST API:
# Method 1: Batch fetch all comments to file (recommended for many comments)
gh api repos/${REPO}/pulls/${PR}/comments --paginate > /tmp/all_comments.json
# Extract full body for specific comment IDs
for CID in "${COMMENT_IDS[@]}"; do
echo -e "\n=========================================="
echo "COMMENT ID: $CID"
cat /tmp/all_comments.json | jq -r ".[] | select(.id == $CID) | \"File: \(.path):\(.line // \"null\")\\nAuthor: \(.user.login)\\n\\nBody:\\n\(.body)\\n\""
echo "=========================================="
done
# Method 2: Fetch individual comment (for single/few comments)
CID=2466210587
gh api repos/${REPO}/pulls/${PR}/comments/${CID} | jq -r '"File: \(.path):\(.line // \"null\")\nAuthor: \(.user.login)\n\nBody:\n\(.body)"'
Key learnings:
databaseId matches REST API id fieldin_reply_to_id is null (GraphQL filters this automatically via reviewThreads)npm run check - TypeScript type checking and lintingnpm run test - Unit testsnpm run test:components - Component tests (if changes affect UI components)CRITICAL: Create one commit per logical issue/fix. Group related comments that address the same issue into a single atomic commit.
Commit strategy:
Examples:
FILE="path/from/context"
SUMMARY="Add archived=false filters to match functions"
git add "$FILE"
COMMIT_MSG=$(cat <<EOF