Claude
Skills
Sign in
Back

attach-review-to-pr

Included with Lifetime
$97 forever

Add line-specific review comments to pull requests using GitHub CLI API

Backend & APIs

What this skill does


# How to Attach Line-Specific Review Comments to Pull Requests

This guide explains how to add line-specific review comments to pull requests using the GitHub CLI (`gh`) API or `mcp__github_inline_comment__create_inline_comment` if it not available, similar to how the GitHub UI allows commenting on specific lines of code.

## Preferred Approach: Using MCP GitHub Tools

**If available**, use the `mcp__github_inline_comment__create_inline_comment` MCP tool for posting line-specific inline comments on pull requests. This approach provides better integration with GitHub's UI and is the recommended method.

**Fallback**: If the MCP tool is not available, use the GitHub CLI (`gh`) API methods described below:

- For single comments: Use the `/comments` endpoint (see [Adding a Single Line-Specific Comment](#adding-a-single-line-specific-comment))
- For multiple comments: Use the `/reviews` endpoint (see [Adding Multiple Line-Specific Comments Together](#adding-multiple-line-specific-comments-together))

## Overview

While `gh pr review` provides basic review functionality (approve, request changes, general comments), it **does not support line-specific comments directly**. To add comments on specific lines of code, you must use the lower-level `gh api` command to call GitHub's REST API directly.

## Prerequisites

1. GitHub CLI installed and authenticated:

   ```bash
   gh auth status
   ```

2. Access to the repository and pull request you want to review

## Understanding GitHub's Review Comment System

GitHub has two types of PR comments:

1. **Issue Comments** - General comments on the PR conversation
2. **Review Comments** - Line-specific comments on code changes

Review comments can be added in two ways:

- **Single comment** - Using the `/pulls/{pr}/comments` endpoint
- **Review with multiple comments** - Using the `/pulls/{pr}/reviews` endpoint

## Adding a Single Line-Specific Comment

### Basic Syntax

```bash
gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \
  -f body='Your comment text here' \
  -f commit_id='<commit-sha>' \
  -f path='path/to/file.js' \
  -F line=42 \
  -f side='RIGHT'
```

### Parameters Explained

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `body` | string | Yes | The text of the review comment (supports Markdown) |
| `commit_id` | string | Yes | The SHA of the commit to comment on |
| `path` | string | Yes | Relative path to the file being commented on |
| `line` | integer | Yes | The line number in the diff (use `-F` for integers) |
| `side` | string | Yes | `RIGHT` for new/modified lines, `LEFT` for deleted lines |
| `start_line` | integer | No | For multi-line comments, the starting line |
| `start_side` | string | No | For multi-line comments, the starting side |

### Parameter Flags

- `-f` (--field) - For string values
- `-F` (--field) - For integer values (note the capital F)

### Complete Example

```bash
# First, get the latest commit SHA for the PR
gh api repos/NeoLabHQ/learning-platform-app/pulls/4 --jq '.head.sha'

# Then add your comment
gh api repos/NeoLabHQ/learning-platform-app/pulls/4/comments \
  -f body='Consider adding error handling here. Should we confirm the lesson was successfully marked as completed before navigating away?' \
  -f commit_id='e152d0dd6cf498467eadbeb638bf05abe11c64d4' \
  -f path='src/components/LessonNavigationButtons.tsx' \
  -F line=26 \
  -f side='RIGHT'
```

### Understanding Line Numbers

The `line` parameter refers to the **position in the diff**, not the absolute line number in the file:

- For **new files**: Line numbers match the file's line numbers
- For **modified files**: Use the line number as it appears in the "Files changed" tab
- For **multi-line comments**: Use `start_line` and `line` to specify the range

### Response

On success, returns a JSON object with comment details:

```json
{
  "id": 2532291222,
  "pull_request_review_id": 3470545909,
  "path": "src/components/LessonNavigationButtons.tsx",
  "line": 26,
  "body": "Consider adding error handling here...",
  "html_url": "https://github.com/NeoLabHQ/learning-platform-app/pull/4#discussion_r2532291222",
  "created_at": "2025-11-16T22:40:46Z"
}
```

## Adding Multiple Line-Specific Comments Together

To add multiple comments across different files in a single review, use the `/reviews` endpoint with JSON input.

### Why Use Reviews for Multiple Comments?

- **Atomic operation** - All comments are added together
- **Single notification** - Doesn't spam with multiple notifications
- **Better UX** - Appears as one cohesive review
- **Same mechanism as GitHub UI** - "Start a review" → "Finish review"

### Basic Syntax

```bash
cat <<'EOF' | gh api repos/{owner}/{repo}/pulls/{pr_number}/reviews --input -
{
  "event": "COMMENT",
  "body": "Overall review summary (optional)",
  "comments": [
    {
      "path": "file1.tsx",
      "body": "Comment on file 1",
      "side": "RIGHT",
      "line": 15
    },
    {
      "path": "file2.tsx",
      "body": "Comment on file 2",
      "side": "RIGHT",
      "line": 30
    }
  ]
}
EOF
```

### Review Event Types

| Event | Description | When to Use |
|-------|-------------|-------------|
| `COMMENT` | General review comment | Just leaving feedback without approval |
| `APPROVE` | Approve the PR | Changes look good, ready to merge |
| `REQUEST_CHANGES` | Request changes | Issues that must be fixed before merge |

### Complete Example

```bash
cat <<'EOF' | gh api repos/NeoLabHQ/learning-platform-app/pulls/4/reviews --input -
{
  "event": "COMMENT",
  "body": "Testing multiple line-specific comments via gh api",
  "comments": [
    {
      "path": "src/components/CourseCard.tsx",
      "body": "Test comment generated by Claude",
      "side": "RIGHT",
      "line": 15
    },
    {
      "path": "src/components/CourseProgressWidget.tsx",
      "body": "Test comment generated by Claude",
      "side": "RIGHT",
      "line": 30
    },
    {
      "path": "src/components/LessonProgressTracker.tsx",
      "body": "Test comment generated by Claude",
      "side": "RIGHT",
      "line": 20
    }
  ]
}
EOF
```

### Response

```json
{
  "id": 3470546747,
  "state": "COMMENTED",
  "html_url": "https://github.com/NeoLabHQ/learning-platform-app/pull/4#pullrequestreview-3470546747",
  "submitted_at": "2025-11-16T22:42:43Z",
  "commit_id": "e152d0dd6cf498467eadbeb638bf05abe11c64d4"
}
```

## Common Issues and Solutions

### Issue 1: "user_id can only have one pending review per pull request"

**Error Message:**

```
gh: Validation Failed (HTTP 422)
{"message":"Validation Failed","errors":[{"resource":"PullRequestReview","code":"custom","field":"user_id","message":"user_id can only have one pending review per pull request"}]}
```

**Cause:** GitHub only allows one pending (unsubmitted) review per user per PR. If you previously started a review through the UI or API and didn't submit it, it blocks new review creation.

**Solution 1: Submit the pending review**

```bash
# Check for pending reviews
gh api repos/{owner}/{repo}/pulls/{pr_number}/reviews | jq '.[] | select(.state=="PENDING")'

# Submit it through the UI or ask the user to submit it
```

**Solution 2: Use the single comment endpoint instead**

```bash
# Add individual comments without creating a review
gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \
  -f body='Comment text' \
  -f commit_id='<sha>' \
  -f path='file.tsx' \
  -F line=26 \
  -f side='RIGHT'
```

### Issue 2: Array syntax not working with --raw-field

**Failed Attempt:**

```bash
# This does NOT work - GitHub API receives an object, not an array
gh api repos/{owner}/{repo}/pulls/{pr}/reviews \
  --raw-field 'comments[0][path]=file1.tsx' \
  --raw-field 'comments[0][line]=15' \
  --raw-field 'comments[1][path]=file2.tsx' \
  --raw-field 'comments[1][line]=30'
```

**Error:**

```
Invalid request. For 'properties/comments', {"0" => {...}, "1" => {...}} is not an array.
```

**Solution:** Use JSON input vi

Related in Backend & APIs