Sitemap

Streamlining GitHub PR Reviews: Building a Custom Claude Code Slash Command for Automated Comment Resolution

8 min readAug 13, 2025

The Problem: Repetitive PR Review Workflows

If you’re like me, you’ve probably noticed a pattern when addressing PR review comments. Every single time, you go through the same tedious dance:

  1. Read and understand the comment
  2. Fix the code (suggestions often need tweaking to actually work)
  3. Commit and push your changes
  4. Reply to the comment with something like “Fixed in commit abc1234!”
  5. Resolve the thread (optional, but satisfying)

This workflow becomes especially repetitive when using AI-powered review tools like GitHub Copilot Review, which can generate dozens of helpful suggestions that all need individual attention.

When I started using Claude Code (Anthropic’s command-line coding assistant) to help with these tasks, I ran into two frustrating issues:

Issue #1: Verbose Instructions Every Single Time

To get Claude Code to handle a review comment properly, I had to write something like: “Please fix this comment, commit the changes, and then reply to the original comment with the commit hash.” Every. Single. Time. It felt like I was training a new intern for each comment.

Issue #2: Inconsistent Behavior

While Claude Code understands basic gh commands, natural language instructions led to unpredictable results:

  • The same instruction would execute differently each time (e.g., posting a general PR comment instead of replying to the specific review thread)
  • It would forget to reply to comments or generate poor commit messages
  • Complex operations requiring GraphQL API calls (like resolving threads) often failed after multiple attempts, burning through tokens and time

The Solution: Custom Slash Commands

To solve these issues, I created a custom slash command that explicitly defines the exact gh commands and execution sequence. This ensures consistent, high-quality execution with minimal input.

How It Works

Here’s the complete workflow:

Press enter or click to view image in full size

Real-world example:

  1. Reviewer comments: “Consider adding input validation for the email parameter”
  2. You run: /resolve-gh-review-comment https://github.com/owner/repo/pull/123#discussion_r2196280386
  3. Claude Code automatically:
  • Analyzes the comment
  • Reviews the relevant code
  • Implements the suggestion
  • Commits with a semantic message
  • Pushes to the branch
  • Replies with the commit hash
  • Optionally resolves the thread

Before: Manually review → fix → commit → reply → resolve (or write lengthy Claude Code instructions)
After: One command and done ✨

Understanding GitHub’s Comment Types

Before diving into the implementation, it’s crucial to understand that GitHub PRs have three distinct types of comments:

1. Issue Comments (General PR Comments)

These appear at the bottom of the PR, shown with a speech bubble icon.

Press enter or click to view image in full size

2. Review Comments (Line-specific Comments) ← Our Target

Comments attached to specific lines of code. These are what we want to automate.

You can fetch these using:

gh api /repos/OWNER/REPO/pulls/PULL_NUMBER/comments
Press enter or click to view image in full size

3. Review Summary Comments

Comments left when completing a review (not our focus).

GitHub API

1. Fetching a Specific Review Comment

gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/OWNER/REPO/pulls/comments/COMMENT_ID

2. Replying to a Comment

gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/OWNER/REPO/pulls/PULL_NUMBER/comments/COMMENT_ID/replies \
-f 'body=Fixed in commit abc1234. Added input validation as suggested.'

3. Resolving a Comment Thread

This requires GraphQL API. First, get the thread ID:

THREAD_ID=$(gh api graphql -f query='
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
id
comments(first: 100) {
nodes {
id
databaseId
}
}
}
}
}
}
}' -F owner=$OWNER -F repo=$REPO -F number=$PR_NUMBER | jq -r --arg comment_id "$COMMENT_ID" '
.data.repository.pullRequest.reviewThreads.nodes[] |
select(.comments.nodes[] | .databaseId == ($comment_id | tonumber)) |
.id
')

Then resolve the thread:

gh api graphql -f query='
mutation {
resolveReviewThread(input: {threadId: "'$THREAD_ID'"}) {
thread {
isResolved
}
}
}'

Building the Claude Code Slash Command

Create .claude/commands/resolve-gh-review-comment.md:

# Resolve GitHub PR Review Comment

---
description: Resolve GitHub PR Review Comment
argument-hint: <comment_id or comment url> [--resolve]
---

This guide explains how to resolve a specific review comment on a GitHub Pull Request.

If $ARGUMENTS contains `--resolve`, the comment will be resolved after replying.

## Steps

1. **Extract comment id**

Extract comment id from $ARGUMENTS if not directly specified.

- The comment ID can be found in the PR comment URL: `https://github.com/{owner}/{repo}/pull/{pr_number}#discussion_r{comment_id}`

2. **Check the specific comment**

```bash
gh api repos/{owner}/{repo}/pulls/comments/{comment_id}
```
Example:
```bash
gh api repos/nakamasato/github-actions-practice/pulls/comments/2196280386
```

3. **Read and check the relevant codes**

- Read the comment and suggestion.
- Check the relevant codes.
- Think deeply whether to follow the suggestion.

4. **Fix the issue**

- Make the necessary code changes based on the review feedback
- Ensure the fix addresses the reviewer's concerns

5. **Commit and push**

- Stage your changes
- Create a descriptive commit message
- Push to the feature branch

6. **Reply to the comment**

```bash
gh api -X POST repos/{owner}/{repo}/pulls/{pr_number}/comments/{comment_id}/replies \
-f body="Fixed in commit {commit_sha}. {description_of_fix}"
```

If fixed, please reply with commit link:

Example:
```bash
gh api -X POST repos/nakamasato/github-actions-practice/pulls/2239/comments/2196280386/replies \
-f body="Fixed in commit 2b36629. The redundant existence check has been removed since main() already validates the metadata file."
```
Otherwise, just reply to the comment.

7. **Resolve the review comment only if specified --resolve**

Resolve the review comment only when `--resolve` option is specified in $ARGUMENTS.

First, get the thread ID:
```bash
gh api graphql -f query='
query {
repository(owner: "{owner}", name: "{repo}") {
pullRequest(number: {pr_number}) {
reviewThreads(first: 50) {
nodes {
id
isResolved
comments(first: 1) {
nodes {
id
body
}
}
}
}
}
}
}'
```

Then resolve the thread:
```bash
gh api graphql -f query='
mutation {
resolveReviewThread(input: {threadId: "{thread_id}"}) {
thread {
isResolved
}
}
}'
```

Example:
```bash
gh api graphql -f query='
mutation {
resolveReviewThread(input: {threadId: "PRRT_kwDOOybamM5TqrEt"}) {
thread {
isResolved
}
}
}'
```

## Notes

- The comment ID can be found in the PR comment URL: `https://github.com/{owner}/{repo}/pull/{pr_number}#discussion_r{comment_id}`
- Thread IDs are different from comment IDs and must be retrieved via GraphQL
- Only users with write access can resolve review threads
- The thread will be automatically marked as resolved when using the GraphQL mutation

Usage Examples

Simple Fix (No Auto-Resolve)

/resolve-gh-review-comment https://github.com/owner/repo/pull/123#discussion_r2196280386

Fix and Resolve

/resolve-gh-review-comment 2196280386 --resolve

Real-World Example

Here’s an actual GitHub Copilot review comment I resolved using this command:

Press enter or click to view image in full size

Copilot’s suggestion: “The timestamp validation could be more robust by using regex pattern matching instead of just checking for a dot.”

Running the command: /resolve-gh-review-comment https://github.com/owner/repo/pull/123#discussion_r2196280386

Claude Code’s execution:

✻ Thinking…

Good! I've successfully:
1. Implemented the suggested fix by adding the re import and updating the timestamp validation
to use regex pattern matching
2. Ran tests to ensure everything still works (all 123 tests passed)
3. Ran lint to ensure code formatting is correct (all checks passed)
4. Committed the changes with a semantic commit message
5. Pushed the changes to the remote branch
6. Replied to the PR comment with the commit hash

The fix is a simple validation improvement that doesn't fundamentally change the logic, just
makes it more robust. Since this is a straightforward improvement suggested by Copilot and all
tests pass, I won't resolve the thread to let the reviewer decide if they're satisfied with the
fix.

⏺ I've successfully resolved the GitHub PR review comment. Here's what I did:

1. Analyzed the comment: The suggestion was to improve the Slack timestamp validation logic by
using a regex pattern instead of just checking for a dot in the string.
2. Implemented the fix:
- Added import re to the imports
- Changed the validation from if ts and ts != "" and "." in ts: to if ts and ts != "" and
re.match(r"^\d+\.\d+$", ts):
3. Verified the changes:
- All 123 tests passed ✓
- Lint checks passed ✓
- Type checking passed ✓
4. Committed and pushed: Created commit df1df82 with the fix
5. Replied to the comment: Notified that the issue was fixed in commit df1df82

The regex pattern ^\d+\.\d+$ properly validates Slack timestamps which follow the format of
digits, a dot, and more digits (e.g., "1234567890.123456"). This is much more robust than
simply checking for the presence of a dot.
  1. Analyzed the suggestion: Improve Slack timestamp validation from simple dot-check to regex pattern
  2. Implemented the fix: Changed from if ts and "." in ts: to if ts and re.match(r"^\d+\.\d+$", ts):
  3. Quality checks: ✅ All 123 tests passed, ✅ Lint checks passed, ✅ Type checking passed
  4. Committed: Created semantic commit with clear message
  5. Replied: “Fixed in commit df1df82. Improved timestamp validation using regex pattern matching as suggested.”

The regex pattern ^\d+\.\d+$ properly validates Slack timestamps (e.g., "1234567890.123456"), which is much more robust than simply checking for a dot.

Press enter or click to view image in full size

The Benefits

This custom slash command approach delivers several key advantages:

Clear Instructions

By explicitly defining GitHub API usage, we eliminate trial-and-error, saving tokens and time.

Explicit Control

The --resolve flag gives you control over thread resolution—sometimes you want the reviewer to confirm the fix first.

One-Command Simplicity

Just copy the comment URL and run the command. No more crafting detailed instructions.

Reviewer-Friendly

Automatic replies with commit hashes make it easy for reviewers to verify changes — just like a thoughtful human would do.

Conclusion

By creating a custom Claude Code slash command, I’ve transformed a tedious, error-prone process into a single, reliable command. This approach is particularly valuable when dealing with AI-generated reviews from tools like GitHub Copilot, which can produce dozens of helpful suggestions.

The key insight here is that explicit, structured commands beat natural language instructions when you need consistent, repeatable workflows. Instead of hoping Claude Code interprets your instructions correctly each time, you define the exact steps once and reuse them forever.

This pattern can be applied to many other repetitive development tasks. What workflows would you automate with custom slash commands?

Resources

If you found this helpful, consider creating your own custom slash commands for repetitive workflows. The time investment pays off quickly when you’re processing multiple PR reviews daily.

--

--

Masato Naka
Masato Naka

Written by Masato Naka

An SRE, mainly working on Kubernetes. CKA (Feb 2021). His Interests include Cloud-Native application development, and machine learning.

No responses yet