GitHub PR review
Resolves Pull Request review comments with severity-based prioritization, fix application, and thread replies.
Current PR
!gh pr view --json number,title,state,milestone -q '"PR #\(.number): \(.title) (\(.state)) | Milestone: \(.milestone.title // "none")"' 2>/dev/null
Core workflow
1. Fetch, filter, and classify comments
REPO=$(gh repo view --json nameWithOwner -q '.nameWithOwner')
PR=$(gh pr view --json number -q '.number')
LAST_PUSH=$(git log -1 --format=%cI HEAD)
# Inline review comments - filter out replies (keep only originals)
gh api repos/$REPO/pulls/$PR/comments?per_page=100 --jq '
[.[] | select(.in_reply_to_id == null) |
{id, path, user: .user.login, created_at, body: .body[0:200]}]
'
# PR-level reviews with non-empty body (CodeRabbit sections, Gemini, etc.)
gh api repos/$REPO/pulls/$PR/reviews?per_page=100 --jq '
[.[] | select(.body | length > 0) |
{id, user: .user.login, state, submitted_at, body: .body[0:500]}]
'
Cross-check review-attached comments: CodeRabbit's review body states "Actionable comments posted: N". If the general pulls/$PR/comments endpoint returns fewer than N new originals from that reviewer, some comments are only available via the review-specific endpoint. Fetch them and merge by comment ID:
# $REVIEW_ID from the reviews fetch above; $EXPECTED from parsing "Actionable comments posted: N"
gh api repos/$REPO/pulls/$PR/reviews/$REVIEW_ID/comments?per_page=100 --jq '
[.[] | select(.in_reply_to_id == null) |
{id, path, user: .user.login, created_at, body: .body[0:200]}]
'
Deduplicate by id before continuing. Comments found only via the review-specific endpoint are valid inline comments and should be treated identically (same classification, same in_reply_to reply mechanism).
Filter new vs already-seen: compare created_at/submitted_at with $LAST_PUSH. Comments posted after the last push are new. Mark older comments as "previous round" in the summary table.
Parse CodeRabbit review bodies: the initial fetch truncates bodies for classification. For reviews from CodeRabbit (user.login starts with coderabbitai), fetch the full body separately:
gh api repos/$REPO/pulls/$PR/reviews?per_page=100 --jq '
[.[] | select(.user.login | startswith("coderabbitai")) |
{id, submitted_at, body}]
'
CodeRabbit posts structured <details> blocks containing outside-diff, duplicate, and nitpick comments. Each block includes file path, line range, severity, and optionally a "Prompt for AI Agents" with pre-built context. See references/coderabbit_parsing.md for full parsing guide.
Use CodeRabbit AI prompts when available: if a comment (or the review body) contains a "Prompt for AI Agents" <details> block, use it to understand the issue and suggested approach. Always read the actual code before proposing a fix. If the review body contains a "Prompt for all review comments with AI agents" block, read it first for cross-comment context before processing individual comments.
Classify all comments by severity and process in order: CRITICAL > HIGH > MEDIUM > LOW.
| Severity | Indicators | Action |
|---|---|---|
| CRITICAL | critical.svg, _🔒 Security_, _🚨 Critical_, _🔴 Critical_, "security", "vulnerability" | Must fix |
| HIGH | high-priority.svg, _⚠️ Potential issue_, _🐛 Bug_, _⚡ Performance_, _🟠 Major_, "High Severity" | Should fix |
| MEDIUM | medium-priority.svg, _🛠️ Refactor suggestion_, _💡 Suggestion_, "Medium Severity" | Recommended |
| LOW | low-priority.svg, _🧹 Nitpick_, _🔧 Optional_, _🟡 Minor_, _🔵 Trivial_, _⚪ Info_, "style", "nit" | Optional |
When a comment has both a type label and a secondary color badge (e.g., _💡 Suggestion_ | _🟠 Major_), the color badge is the binding severity and overrides the type-based default.
See references/severity_guide.md for full detection patterns (Gemini badges, CodeRabbit emoji, Cursor comments, keyword fallback, related comments heuristics).
2. Show review summary table
Before processing, display a structured overview of all comments:
| # | ID | Severity | File:Line | Type | Status | Summary |
|---|------------|----------|--------------------|----------|----------|--------------------|
| 1 | 123456789 | CRITICAL | src/auth.py:45 | inline | new | SQL injection risk |
| 2 | 987654321 | HIGH | src/db.py:346-350 | outside | new | Missing join cond |
| 3 | 555555555 | HIGH | src/chunk.py:188 | duplicate| previous | Stale metadata |
| 4 | 444444444 | LOW | tests/test_q.py:12 | nitpick | previous | Naming convention |
- Type:
inline,outside(outside diff),duplicate,minor,nitpick(from CodeRabbit sections), orreview(generic PR-level) - Status:
new(posted after last push) orprevious(from earlier rounds) - Group related comments (same file, same root cause, "also applies to" ranges) and note clusters
- Deduplicate: if the same issue appears both as an inline comment and in a CodeRabbit review body section (e.g., duplicate), keep one entry and note both sources
If there are more than 10 comments, suggest saving a review summary to Claude's memory for tracking across sessions. The summary should include: PR number, comment IDs, severity, status (new/addressed/deferred/won't fix), and brief description. This helps maintain continuity when new comments arrive after subsequent pushes.
3. Process each comment
For each comment, in severity order:
- Show context: comment ID, severity, file:line, quote
- Check for AI prompt: if CodeRabbit "Prompt for AI Agents" is available for this comment, use it to understand the issue and suggested approach
- Check for proposed fix: if CodeRabbit includes a "Proposed fix" or "Suggested fix" code block, use it as a starting point (but verify correctness)
- Read affected code and propose fix (always read the actual code, even when an AI prompt or proposed fix provides context)
- Handle "also applies to": if the comment references additional line ranges, include all locations in the fix
- Confirm with user before applying
- Apply fix if approved
- Verify ALL issues in the comment are addressed (multi-issue comments are common)
4. Commit changes
Use git-commit skill format. Functional fixes get separate commits, cosmetic fixes are batched:
| Change type | Strategy |
|---|---|
| Functional (CRITICAL/HIGH) | Separate commit per fix |
| Cosmetic (MEDIUM/LOW) | Single batch style: commit |
Reference the comment ID in the commit body.
5. Reply to threads
Inline comments
Important: use --input - with JSON. The -f in_reply_to=... syntax does NOT work.
COMMIT=$(git rev-parse --short HEAD)
gh api repos/$REPO/pulls/$PR/comments \
--input - <<< '{"body": "Fixed in '"$COMMIT"'. Brief explanation.", "in_reply_to": 123456789}'
Non-inline comments (CodeRabbit review body)
Comments embedded in the review body (outside diff, duplicate, nitpick) do not have inline threads. The GitHub API does not support replying to a review body directly. Post a general PR comment referencing the specific issue:
gh pr comment $PR --body "Fixed in $COMMIT. Addresses outside-diff comment on file/path.py:346-350."
Reply templates (no emojis, minimal and professional):
| Situation | Template |
|---|---|
| Fixed | Fixed in [hash]. [brief description of fix] |
| Won't fix | Won't fix: [reason] |
| By design | By design: [explanation] |
| Deferred | Deferred to [issue/task]. Will address in future iteration. |
| Acknowledged | Acknowledged. [brief note] |
6. Run tests and push
Run the project test suite. All tests must pass before pushing. Push all fixes together to minimize review loops.
7. Submit review (optional)
Af