Agent skill

resolve-pr-comments

Stars 3,695
Forks 418

Install this agent skill to your Project

npx add-skill https://github.com/maximhq/bifrost/tree/main/.claude/skills/resolve-pr-comments

SKILL.md


name: resolve-pr-comments description: Resolve all unresolved PR comments interactively. Use when asked to resolve PR comments, address review feedback, handle CodeRabbit comments, or fix PR review issues. Invoked with /resolve-pr-comments <PR_NUMBER> or /resolve-pr-comments <owner/repo> <PR_NUMBER>. allowed-tools: Read, Grep, Glob, Bash, Edit, Write, WebFetch, Task, AskUserQuestion, TodoWrite

Resolve PR Comments

An interactive workflow to systematically address all unresolved PR review comments.

Usage

/resolve-pr-comments <PR_NUMBER>
/resolve-pr-comments <owner/repo> <PR_NUMBER>

If no repo is specified, uses the current git repository's remote origin.

Before starting the workflow - if the flow is in Plan Model - ask if the user wants to move to default mode to solve the comments one by one. Mention that each PR resolve has planning attached to it.

Workflow Overview

  1. Detect repository - Get owner/repo from git remote or user input
  2. Fetch unresolved comments - Use GitHub GraphQL API (REST doesn't expose resolved status). Paginate through reviewThreads (cursor-based) so all pages are checked when a PR has more than 100 threads.
  3. Create tracking file - Maintain state across the session
  4. For each comment:
    • Get full details and any existing replies
    • Show the diff view of existing code in a proper diff view
    • Before suggesting the fix - do the research via documentations. And present all that docs research and relevant links to the user with the fix. Use context 7. MAKE SURE YOU DO THIS ALWAYS
    • Present to user with options (FIX, REPLY, SKIP)
    • Wait for user decision
    • Execute the action
    • Update tracking
  5. Verify resolution - Check remaining unresolved count
  6. Repeat until done - Continue until all comments resolved

Step 1: Detect Repository

If repository not provided, detect from git remote:

bash
git remote get-url origin | sed -E 's|.*github.com[:/]([^/]+/[^/.]+)(\.git)?|\1|'

Step 2: Fetch Unresolved Comments (GraphQL)

The REST API does NOT expose resolved/unresolved status. Use GraphQL.

Important: reviewThreads returns at most 100 threads per request. PRs with many review threads (e.g. large CodeRabbit reviews) need pagination or you will only see the first 100 threads and miss unresolved ones on later pages. Always paginate until pageInfo.hasNextPage is false so the count and list are complete.

Single-page query (first 100 threads only)

bash
gh api graphql -f query='
{
  repository(owner: "OWNER", name: "REPO") {
    pullRequest(number: PR_NUMBER) {
      reviewThreads(first: 100) {
        pageInfo { hasNextPage endCursor }
        nodes {
          isResolved
          comments(first: 1) {
            nodes {
              databaseId
              path
              body
              author { login }
            }
          }
        }
      }
    }
  }
}'

Extract unresolved (single page):

bash
... | jq -r '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | "\(.comments.nodes[0].databaseId)|\(.comments.nodes[0].path)|\(.comments.nodes[0].author.login)"'

Avoid parsing body in the same jq pass if you paginate—comment bodies can contain control characters and break jq. Fetch full body per comment via REST when presenting (see Step 4).

Paginate to collect all unresolved threads

Use cursor-based pagination so every thread is considered:

  1. First request: reviewThreads(first: 100) (no after).
  2. From the response: read pageInfo.hasNextPage and pageInfo.endCursor.
  3. Next request: reviewThreads(first: 100, after: $endCursor).
  4. Append unresolved from this page to your list (id, path, author only).
  5. Repeat from step 2 until hasNextPage is false.

Example loop (collects id|path|author for all unresolved; write to a file or variable):

bash
CURSOR=""
while true; do
  if [ -z "$CURSOR" ]; then
    RESP=$(gh api graphql -f query='
      query {
        repository(owner: "OWNER", name: "REPO") {
          pullRequest(number: PR_NUMBER) {
            reviewThreads(first: 100) {
              pageInfo { hasNextPage endCursor }
              nodes {
                isResolved
                comments(first: 1) {
                  nodes { databaseId path author { login } }
                }
              }
            }
          }
        }
      }')
  else
    RESP=$(gh api graphql -f query='
      query($after: String) {
        repository(owner: "OWNER", name: "REPO") {
          pullRequest(number: PR_NUMBER) {
            reviewThreads(first: 100, after: $after) {
              pageInfo { hasNextPage endCursor }
              nodes {
                isResolved
                comments(first: 1) {
                  nodes { databaseId path author { login } }
                }
              }
            }
          }
        }
      }' -f after="$CURSOR")
  fi
  # Append unresolved from this page (id|path|author only; no body to avoid control chars)
  echo "$RESP" | jq -r '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .comments.nodes[0] | "\(.databaseId)|\(.path)|\(.author.login)"'
  HAS_NEXT=$(echo "$RESP" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')
  CURSOR=$(echo "$RESP" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor // ""')
  [ "$HAS_NEXT" != "true" ] || [ -z "$CURSOR" ] && break
done

Total unresolved count = number of lines output. Use the comment databaseId values to fetch full body via REST when presenting each comment (Step 4).

Step 3: Create Tracking File

Create at /tmp/pr-review/pr-<NUMBER>-comments.md:

markdown
# PR #<NUMBER> Comment Review (<owner>/<repo>)

## Summary
- Total unresolved: <count>
- Fixed: 0
- Replied: 0
- Skipped: 0

## Comments to Address
| # | ID | File | Issue | Status |
|---|-----|------|-------|--------|
| 1 | 12345 | src/foo.ts | Missing validation | pending |

## Actions Taken
| ID | Action | Details |
|----|--------|---------|

Step 4: Present Each Comment

For each unresolved comment, present in this format:

**Comment #<N>/<TOTAL>: ID <ID> - <File>**

**What it says:**
<Summary of the comment's concern>

**Current code state:**
<Show relevant code snippet if applicable - READ THE FILE>

**Documentations referred**
For anything related to LLM calls (in /core module) - make sure you refer to the documentation. You have access to web_search and context7. and show that too 

**Options:**
1. **FIX** - <Describe what the fix would be>
2. **REPLY** - <Describe the reply explaining why no fix needed>
3. **SKIP** - Move on without action

**My recommendation:** <OPTION> - <Brief reasoning>

Go ahead?

Getting Full Comment Details

bash
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments --paginate | jq -r '.[] | select(.id == COMMENT_ID) | .body'

Checking for Existing Replies

bash
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments --paginate | jq '.[] | select(.id == COMMENT_ID or .in_reply_to_id == COMMENT_ID) | {id, user: .user.login, body: (.body | gsub("\n"; " ") | .[0:150])}'

Step 5: Execute Actions

CRITICAL: Do NOT reply to PR comments until changes are pushed to the remote. The reviewer cannot verify fixes until the code is pushed. Collect all fixes locally first, then push, then reply.

For FIX:

  1. Make the code change using Edit tool
  2. Before applying the changes take approval from the user. DO NOT DIRECTLY MAKE CHANGE BEFORE user says yes. Also give an option to suggest the changes to code.
  3. Track the fix locally in the tracking file (do NOT reply yet)
  4. Continue to next comment

For REPLY (non-code responses like "out of scope", "intentional design"):

These can be posted immediately since they don't require code verification. Use the replies endpoint only (see below).

Reply endpoint (use this only)

To reply to a review comment, use the dedicated replies endpoint. Do not use POST .../pulls/PR_NUMBER/comments with in_reply_to — that returns 422 (in_reply_to is not a permitted key for create review comment).

bash
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments/COMMENT_ID/replies -X POST -f body="<your reply>"
  • COMMENT_ID is the numeric comment id (same as GraphQL databaseId from the thread's first comment).
  • Request body: only body (string). No in_reply_to, commit_id, or path params.

Step 5b: Push and Reply to FIX comments

After ALL comments have been addressed locally:

  1. Ask user if they have pushed these changes to remote. Yes/No
  2. Only after push succeeds, reply to each FIX comment using the replies endpoint:
    bash
    gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments/COMMENT_ID/replies -X POST -f body="Fixed - <description of change>. See updated code."
    

Batch workflow (fix all → push → post all)

If the user says e.g. "resolve all comments then push then post", you may:

  1. Apply all FIX and REPLY decisions locally (with user approval per comment or bulk approval).
  2. Ask user to push.
  3. After push, post all replies in sequence: FIX replies first, then any REPLY-only replies, using the same .../comments/COMMENT_ID/replies endpoint for each.

Common Reply Templates

Out of scope:

This is a valid improvement but out of scope for this PR. Tracked for future work.

Already addressed:

Already addressed - <variable/file> now has <fix>. See line <N>.

Intentional design:

This is intentional. <Explanation of why the current approach is correct>.

Different module:

This comment refers to <module> which is a different module not modified in this PR. It's working as-is.

Asking bot to verify:

This is solved, can you check and resolve if done properly?

Step 6: Verify Resolution

After addressing comments, check remaining unresolved count. If the PR has more than 100 review threads, use the same pagination loop as in Step 2 and count unresolved across all pages; a single-page query only sees the first 100 threads.

Single-page check (first 100 threads only):

bash
gh api graphql -f query='...' | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length'

If count is 0 (across all pages), report success. If comments remain:

  • Some bots (like CodeRabbit) take time to auto-resolve
  • User may need to push code changes first
  • Re-run the workflow to address remaining comments

Important Notes

  1. NEVER reply "Fixed" until code is pushed - The reviewer cannot verify fixes until they're on the remote. Make all fixes locally, push, THEN reply.
  2. Always read the file before suggesting fixes - understand context
  3. Check for existing replies in the thread before responding
  4. Wait for user approval on each action - never auto-fix without confirmation
  5. Update tracking file after each action
  6. Some bots are slow - CodeRabbit may take minutes to auto-resolve after push
  7. Push code changes before expecting auto-resolution of FIX actions

Error Handling

  • If gh not authenticated: gh auth login
  • If repo not found: verify owner/repo spelling
  • If PR not found: verify PR number exists
  • If comment ID invalid: re-fetch unresolved comments (may have been resolved)
  • If reply returns 422 "in_reply_to is not a permitted key": you are using the wrong endpoint. Use POST .../pulls/PR_NUMBER/comments/COMMENT_ID/replies with only -f body="...", not the create-comment endpoint.

Expand your agent's capabilities with these related and highly-rated skills.

maximhq/bifrost

changelog-writer

Write changelogs for Bifrost releases. Reads git history, bumps module versions following the core→framework→plugins→transport hierarchy, writes transports/changelog.md (enterprise-style) and per-module changelog.md files, and updates version files. Invoked with /changelog-writer or /changelog-writer <transport-version>.

3,695 418
Explore
maximhq/bifrost

investigate-issue

Investigate a GitHub issue by fetching details, analyzing the codebase, researching documentation, and presenting an actionable implementation plan with test guidance. Use when asked to investigate, analyze, triage, or plan work for a GitHub issue. Invoked with /investigate-issue <ISSUE_ID> or /investigate-issue (prompts for ID).

3,695 418
Explore
maximhq/bifrost

e2e-test

3,695 418
Explore
maximhq/bifrost

docs-writer

Write, update, and review Mintlify MDX documentation for Bifrost features. Explores the full codebase (UI, Go backend, config schema), validates config.json examples, places screenshot placeholders, and presents outlines for approval before writing. Invoked with /docs-writer <feature-name>, /docs-writer update <doc-path>, or /docs-writer review <doc-path>.

3,695 418
Explore
petekp/claude-code-setup

ubiquitous-language

Extract a DDD-style ubiquitous language glossary from the current conversation, flagging ambiguities and proposing canonical terms. Saves to UBIQUITOUS_LANGUAGE.md. Use when user wants to define domain terms, build a glossary, harden terminology, create a ubiquitous language, or mentions "domain model" or "DDD".

20 6
Explore
petekp/claude-code-setup

every-style-editor

This skill should be used when reviewing or editing copy to ensure adherence to Every's style guide. It provides a systematic line-by-line review process for grammar, punctuation, mechanics, and style guide compliance.

20 6
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results