Files
Jason Woltje d9bcdc4a8d feat: Initial agent-skills repo — 4 adapted skills for Mosaic Stack
Skills included:
- pr-reviewer: Adapted for Gitea/GitHub via platform-aware scripts
  (dropped fetch_pr_data.py and add_inline_comment.py, kept generate_review_files.py)
- code-review-excellence: Methodology and checklists (React, TS, Python, etc.)
- vercel-react-best-practices: 57 rules for React/Next.js performance
- tailwind-design-system: Tailwind CSS v4 patterns, CVA, design tokens

New shell scripts added to ~/.claude/scripts/git/:
- pr-diff.sh: Get PR diff (GitHub gh / Gitea API)
- pr-metadata.sh: Get PR metadata as normalized JSON

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:03:39 -06:00

8.4 KiB

GitHub CLI (gh) Guide for PR Reviews

This reference provides quick commands and patterns for accessing PR data using the GitHub CLI.

Prerequisites

Install GitHub CLI: https://cli.github.com/

Authenticate:

gh auth login

Basic PR Information

View PR Details

gh pr view <number> --repo <owner>/<repo>

# With JSON output
gh pr view <number> --repo <owner>/<repo> --json number,title,body,state,author,headRefName,baseRefName

View PR Diff

gh pr diff <number> --repo <owner>/<repo>

# Save to file
gh pr diff <number> --repo <owner>/<repo> > pr_diff.patch

List PR Files

gh pr view <number> --repo <owner>/<repo> --json files --jq '.files[].path'

PR Comments and Reviews

Get PR Comments (Review Comments on Code)

gh api /repos/<owner>/<repo>/pulls/<number>/comments

# Paginate through all comments
gh api /repos/<owner>/<repo>/pulls/<number>/comments --paginate

# With JQ filtering
gh api /repos/<owner>/<repo>/pulls/<number>/comments --jq '.[] | {path, line, body, user: .user.login}'

Get PR Reviews

gh api /repos/<owner>/<repo>/pulls/<number>/reviews

# With formatted output
gh api /repos/<owner>/<repo>/pulls/<number>/reviews --jq '.[] | {state, user: .user.login, body}'

Get Issue Comments (General PR Comments)

gh api /repos/<owner>/<repo>/issues/<number>/comments

Commit Information

List PR Commits

gh api /repos/<owner>/<repo>/pulls/<number>/commits

# Get commit messages
gh api /repos/<owner>/<repo>/pulls/<number>/commits --jq '.[] | {sha: .sha[0:7], message: .commit.message}'

# Get latest commit SHA
gh api /repos/<owner>/<repo>/pulls/<number>/commits --jq '.[-1].sha'

Get Commit Details

gh api /repos/<owner>/<repo>/commits/<sha>

# Get commit diff
gh api /repos/<owner>/<repo>/commits/<sha> -H "Accept: application/vnd.github.diff"

Branches

Get Branch Information

# Source branch (head)
gh pr view <number> --repo <owner>/<repo> --json headRefName --jq '.headRefName'

# Target branch (base)
gh pr view <number> --repo <owner>/<repo> --json baseRefName --jq '.baseRefName'

Compare Branches

gh api /repos/<owner>/<repo>/compare/<base>...<head>

# Get files changed
gh api /repos/<owner>/<repo>/compare/<base>...<head> --jq '.files[] | {filename, status, additions, deletions}'

Get Linked Issues

# Get PR body which may contain issue references
gh pr view <number> --repo <owner>/<repo> --json body --jq '.body'

# Search for issue references (#123 format)
gh pr view <number> --repo <owner>/<repo> --json body --jq '.body' | grep -oE '#[0-9]+'

Get Issue Details

gh issue view <number> --repo <owner>/<repo>

# JSON format
gh issue view <number> --repo <owner>/<repo> --json number,title,body,state,labels,assignees

Get Issue Comments

gh api /repos/<owner>/<repo>/issues/<number>/comments

PR Status Checks

Get PR Status

gh pr checks <number> --repo <owner>/<repo>

# JSON format
gh api /repos/<owner>/<repo>/commits/<sha>/status

Get Check Runs

gh api /repos/<owner>/<repo>/commits/<sha>/check-runs

Adding Comments

Add Inline Code Comment

gh api -X POST /repos/<owner>/<repo>/pulls/<number>/comments \
  -f body="Your comment here" \
  -f commit_id="<sha>" \
  -f path="src/file.py" \
  -f side="RIGHT" \
  -f line=42

Add Multi-line Inline Comment

gh api -X POST /repos/<owner>/<repo>/pulls/<number>/comments \
  -f body="Multi-line comment" \
  -f commit_id="<sha>" \
  -f path="src/file.py" \
  -f side="RIGHT" \
  -f start_line=40 \
  -f start_side="RIGHT" \
  -f line=45

Add General PR Comment

gh pr comment <number> --repo <owner>/<repo> --body "Your comment"

# Or via API
gh api -X POST /repos/<owner>/<repo>/issues/<number>/comments \
  -f body="Your comment"

Creating a Review

Create Review with Comments

gh api -X POST /repos/<owner>/<repo>/pulls/<number>/reviews \
  -f body="Overall review comments" \
  -f event="COMMENT" \
  -f commit_id="<sha>" \
  -f comments='[{"path":"src/file.py","line":42,"body":"Comment on line 42"}]'

Submit Review (Approve/Request Changes)

# Approve
gh api -X POST /repos/<owner>/<repo>/pulls/<number>/reviews \
  -f body="LGTM!" \
  -f event="APPROVE" \
  -f commit_id="<sha>"

# Request changes
gh api -X POST /repos/<owner>/<repo>/pulls/<number>/reviews \
  -f body="Please address these issues" \
  -f event="REQUEST_CHANGES" \
  -f commit_id="<sha>"

Searching and Filtering

Search Code in PR

# Get PR diff and search
gh pr diff <number> --repo <owner>/<repo> | grep "search_term"

# Search in specific files
gh pr view <number> --repo <owner>/<repo> --json files --jq '.files[] | select(.path | contains("search_term"))'

Filter by File Type

gh pr view <number> --repo <owner>/<repo> --json files --jq '.files[] | select(.path | endswith(".py"))'

Labels, Assignees, and Metadata

Get Labels

gh pr view <number> --repo <owner>/<repo> --json labels --jq '.labels[].name'

Get Assignees

gh pr view <number> --repo <owner>/<repo> --json assignees --jq '.assignees[].login'

Get Reviewers

gh pr view <number> --repo <owner>/<repo> --json reviewRequests --jq '.reviewRequests[].login'

Advanced Queries

Get PR Timeline

gh api /repos/<owner>/<repo>/issues/<number>/timeline

Get PR Events

gh api /repos/<owner>/<repo>/issues/<number>/events

Get All PR Data

gh pr view <number> --repo <owner>/<repo> --json \
  number,title,body,state,author,headRefName,baseRefName,\
  commits,reviews,comments,files,labels,assignees,milestone,\
  createdAt,updatedAt,mergedAt,closedAt,url,isDraft

Common JQ Patterns

Extract specific fields

--jq '.field'
--jq '.array[].field'
--jq '.[] | {field1, field2}'

Filter arrays

--jq '.[] | select(.field == "value")'
--jq '.[] | select(.field | contains("substring"))'

Count items

--jq '. | length'
--jq '.array | length'

Map and transform

--jq '.array | map(.field)'
--jq '.[] | {newField: .oldField}'

Line Number Considerations for Inline Comments

IMPORTANT: The line parameter for inline comments refers to the line number in the diff, not the absolute line number in the file.

Understanding Diff Line Numbers

In a diff:

  • Lines are numbered relative to the diff context, not the file
  • The side parameter determines which version:
    • "RIGHT": New version (after changes)
    • "LEFT": Old version (before changes)

Finding Diff Line Numbers

# Get diff with line numbers
gh pr diff <number> --repo <owner>/<repo> | cat -n

# Get specific file diff
gh api /repos/<owner>/<repo>/pulls/<number>/files --jq '.[] | select(.filename == "path/to/file")'

Example Diff

@@ -10,7 +10,8 @@ def process_data(data):
     if not data:
         return None

-    result = old_function(data)
+    # New implementation
+    result = new_function(data)
     return result

In this diff:

  • Line 13 (old) would be side: "LEFT"
  • Line 14-15 (new) would be side: "RIGHT"
  • Line numbers are relative to the diff hunk starting at line 10

Error Handling

Common Errors

Resource not found:

# Check repo access
gh repo view <owner>/<repo>

# Check PR exists
gh pr list --repo <owner>/<repo> | grep <number>

API rate limit:

# Check rate limit
gh api /rate_limit

# Use authentication to get higher limits
gh auth login

Permission denied:

# Check authentication
gh auth status

# May need additional scopes
gh auth refresh -s repo

Tips and Best Practices

  1. Use --paginate for large result sets (comments, commits)
  2. Combine with jq for powerful filtering and formatting
  3. Cache results by saving to files to avoid repeated API calls
  4. Check rate limits when making many API calls
  5. Use --json output for programmatic parsing
  6. Specify --repo when outside repository directory
  7. Get latest commit before adding inline comments
  8. Test comments on draft PRs or test repositories first