Using GitHub API with gh CLI

This skill teaches how to access GitHub's REST and GraphQL APIs via gh api for inline PR comments, review threads, and data not available through standard gh commands. Use this when you need PR review comments, thread status, or other GitHub data that gh pr view doesn't provide.

16 stars

Best use case

Using GitHub API with gh CLI is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

This skill teaches how to access GitHub's REST and GraphQL APIs via gh api for inline PR comments, review threads, and data not available through standard gh commands. Use this when you need PR review comments, thread status, or other GitHub data that gh pr view doesn't provide.

Teams using Using GitHub API with gh CLI should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/using-github-api-with-gh-cli/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/tools/using-github-api-with-gh-cli/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/using-github-api-with-gh-cli/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How Using GitHub API with gh CLI Compares

Feature / AgentUsing GitHub API with gh CLIStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

This skill teaches how to access GitHub's REST and GraphQL APIs via gh api for inline PR comments, review threads, and data not available through standard gh commands. Use this when you need PR review comments, thread status, or other GitHub data that gh pr view doesn't provide.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Using GitHub API with gh CLI

The `gh` CLI doesn't have first-class support for inline/in-code pull request review comments (the line/thread comments on the "Files changed" tab). This skill shows how to access these and other GitHub data programmatically using `gh api`.

## What This Skill Does

- Access inline PR review comments
- Get review thread status (resolved/unresolved)
- Reply to inline review comments
- Resolve and unresolve review threads
- Use GitHub's REST API via gh api
- Use GitHub's GraphQL API via gh api
- Extract owner/repo/PR number from URLs
- Filter and query PR review data

## When You Need This Skill

Use this skill when:
- Standard `gh pr view` doesn't show the data you need
- You need inline/line-specific review comments from "Files changed" tab
- You need to check if review threads are resolved/unresolved
- You need to programmatically process review data

For day-to-day gh usage (viewing PRs, creating PRs, finding branch names), see the gh CLI section in CLAUDE.md.

## Prerequisites

1. **gh CLI installed** - Already available as `gh`
2. **Authenticated with GitHub** - Run `gh auth status` to verify
3. **jq** - For parsing JSON output (optional but recommended)

## Core Concepts

### What gh Commands Show vs Don't Show

**`gh pr view` shows:**
- PR conversation comments
- Review summaries
- Overall PR metadata

**`gh pr view` does NOT show:**
- Inline review comments (line-specific comments)
- Review thread resolved/unresolved status
- Code diff context for comments

**Use `gh api` when you need** the data that `gh pr view` doesn't provide.

### REST API vs GraphQL API

**REST API:**
- Simple for basic inline comment retrieval
- Returns arrays of comment objects
- Good for straightforward queries

**GraphQL API:**
- Better for complex queries
- Returns thread structure with resolved status
- Can fetch everything in one query
- Provides `isResolved` and `isOutdated` fields

## REST API Usage

### Get All Inline Review Comments for a PR

```bash
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments \
  -q '.[] | {id, path, line, body: .body, user: .user.login, created_at}'
```

**Endpoint:** `GET /repos/{owner}/{repo}/pulls/{pull_number}/comments`

**Returns:** Array of comment objects with:
- `id` - Comment ID
- `path` - File path
- `line` - Line number
- `body` - Comment text
- `user.login` - Author username
- `created_at` - Timestamp

**Reference:** [REST API endpoints for pull request review comments](https://docs.github.com/en/rest/pulls/comments)

### Get Inline Comments for a Specific Review

```bash
# First get reviews for the PR to find REVIEW_ID
gh api repos/OWNER/REPO/pulls/PR_NUMBER/reviews -q '.[].id'

# Then list the inline comments for one review
gh api repos/OWNER/REPO/pulls/PR_NUMBER/reviews/REVIEW_ID/comments \
  -q '.[] | {id, path, line, body: .body, author: .user.login}'
```

**Endpoints:**
- `GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews` (list reviews)
- `GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments` (list comments)

**Reference:** [REST API endpoints for pull request reviews](https://docs.github.com/en/rest/pulls/reviews)

### Get PR Conversation Comments (Non-Inline)

```bash
gh api repos/OWNER/REPO/issues/PR_NUMBER/comments \
  -q '.[] | {id, body: .body, author: .user.login}'
```

**Note:** PR conversation comments use the Issues API endpoint, not Pulls.

**Endpoint:** `GET /repos/{owner}/{repo}/issues/{issue_number}/comments`

**Reference:** [REST API endpoints for issue comments](https://docs.github.com/en/rest/issues/comments)

## GraphQL API Usage

### Get All Review Threads with Resolved Status

```bash
gh api graphql -f query='
  query($owner:String!, $repo:String!, $number:Int!, $n:Int=100) {
    repository(owner:$owner, name:$repo) {
      pullRequest(number:$number) {
        reviewThreads(first:$n) {
          nodes {
            id
            isResolved
            isOutdated
            comments(first:$n) {
              nodes {
                databaseId
                bodyText
                path
                diffHunk
                author { login }
                createdAt
                url
              }
            }
          }
        }
      }
    }
  }' -F owner=OWNER -F repo=REPO -F number=PR_NUMBER
```

**Key Fields:**
- `isResolved` - Whether the thread is marked as resolved
- `isOutdated` - Whether the thread is outdated due to code changes
- `diffHunk` - The code context for the comment
- `path` - File path
- `bodyText` - Comment content

**Reference:** [GraphQL API documentation](https://docs.github.com/en/graphql)

## When to Use REST vs GraphQL

### Use REST when:

- You just need inline comments (body, path/line, author, timestamps)
- You want simplicity and speed
- You're fetching data from a single PR
- You don't need resolved/unresolved status

### Use GraphQL when:

- You need thread structure and resolved/unresolved status
- You need `isOutdated` flags
- You want to fetch everything in one query
- REST doesn't expose the metadata you need
- You're building complex queries across related data

## Responding to Review Comments

### Reply to an Inline Comment

```bash
# Get comment IDs first
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments --jq '.[] | "\(.id) \(.path):\(.line)"'

# Reply to a specific comment
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments/COMMENT_ID/replies \
  -X POST -f body="Done. Fixed in latest commit."
```

**Endpoint:** `POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies`

**Reference:** [Create a reply for a review comment](https://docs.github.com/en/rest/pulls/comments#create-a-reply-for-a-review-comment)

### Resolve a Review Thread

Review threads can only be resolved via GraphQL. First get the thread ID, then resolve it:

```bash
# Get thread IDs (note: these start with PRRT_)
gh api graphql -f query='
query {
  repository(owner: "OWNER", name: "REPO") {
    pullRequest(number: PR_NUMBER) {
      reviewThreads(first: 10) {
        nodes {
          id
          isResolved
          comments(first: 1) {
            nodes {
              body
              path
            }
          }
        }
      }
    }
  }
}'

# Resolve the thread
gh api graphql -f query='
mutation {
  resolveReviewThread(input: {threadId: "PRRT_kwDOxxxxxx"}) {
    thread {
      isResolved
    }
  }
}'
```

**Note:** The `threadId` is the GraphQL node ID (starts with `PRRT_`), not the REST API comment ID.

### Unresolve a Review Thread

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

### Reply and Resolve in Sequence

A common workflow is to reply to feedback explaining what you did, then resolve the thread:

```bash
# 1. Reply to the comment (REST)
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments/COMMENT_ID/replies \
  -X POST -f body="Done. Created shared BigQuery bean."

# 2. Resolve the thread (GraphQL)
gh api graphql -f query='
mutation {
  resolveReviewThread(input: {threadId: "PRRT_kwDOxxxxxx"}) {
    thread { isResolved }
  }
}'
```

## Common Use Cases

### List All Unresolved Review Threads

```bash
gh api graphql -f query='
  query($owner:String!, $repo:String!, $number:Int!) {
    repository(owner:$owner, name:$repo) {
      pullRequest(number:$number) {
        reviewThreads(first:100) {
          nodes {
            isResolved
            comments(first:1) {
              nodes {
                path
                bodyText
                author { login }
              }
            }
          }
        }
      }
    }
  }' -F owner=OWNER -F repo=REPO -F number=PR_NUMBER \
  | jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)'
```

### Get All Comments by a Specific Reviewer

```bash
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments \
  | jq '.[] | select(.user.login == "username") | {path, line, body: .body}'
```

### Count Total Inline Comments

```bash
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments | jq '. | length'
```

### Get Comments with Specific Text

```bash
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments \
  | jq '.[] | select(.body | contains("TODO")) | {path, line, body: .body}'
```

## Extracting URL Components

### From PR URL

```bash
# From: https://github.com/owner/repo/pull/123
PR_URL="https://github.com/owner/repo/pull/123"

# Extract owner
OWNER=$(echo "$PR_URL" | cut -d'/' -f4)

# Extract repo
REPO=$(echo "$PR_URL" | cut -d'/' -f5)

# Extract PR number
PR_NUMBER=$(echo "$PR_URL" | cut -d'/' -f7)
```

### Using gh to Parse URL

```bash
gh pr view "$PR_URL" --json number,repository \
  -q '{number: .number, owner: .repository.owner.login, repo: .repository.name}'
```

This is more robust as it handles different URL formats.

## Examples

### Example 1: Get All Inline Comments for a PR

```bash
# User: "Show me all inline review comments on PR #123"

OWNER="food-truck"
REPO="mono"
PR_NUMBER="123"

gh api repos/${OWNER}/${REPO}/pulls/${PR_NUMBER}/comments \
  -q '.[] | "[\(.path):\(.line)] @\(.user.login): \(.body)"'
```

### Example 2: Find Unresolved Comments

```bash
# User: "What review comments are still unresolved on that PR?"

PR_URL="https://github.com/food-truck/mono/pull/123"

# Parse URL
OWNER=$(echo "$PR_URL" | cut -d'/' -f4)
REPO=$(echo "$PR_URL" | cut -d'/' -f5)
PR_NUMBER=$(echo "$PR_URL" | cut -d'/' -f7)

# Get unresolved threads
gh api graphql -f query='
  query($owner:String!, $repo:String!, $number:Int!) {
    repository(owner:$owner, name:$repo) {
      pullRequest(number:$number) {
        reviewThreads(first:100) {
          nodes {
            isResolved
            comments(first:1) {
              nodes {
                path
                bodyText
                author { login }
              }
            }
          }
        }
      }
    }
  }' -F owner=${OWNER} -F repo=${REPO} -F number=${PR_NUMBER} \
  | jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .comments.nodes[0] | "[\(.path)] @\(.author.login): \(.bodyText)"'
```

### Example 3: Get My Comments on a PR

```bash
# User: "What comments did I leave on PR #123?"

MY_USERNAME=$(gh api user -q '.login')

gh api repos/food-truck/mono/pulls/123/comments \
  | jq --arg user "$MY_USERNAME" '.[] | select(.user.login == $user) | {path, line, body: .body}'
```

### Example 4: Summary of Review Activity

```bash
# User: "Give me a summary of review activity on PR #123"

PR_NUMBER="123"
OWNER="food-truck"
REPO="mono"

# Total comments
TOTAL=$(gh api repos/${OWNER}/${REPO}/pulls/${PR_NUMBER}/comments | jq '. | length')

# Comments by reviewer
echo "Total inline comments: $TOTAL"
echo ""
echo "By reviewer:"
gh api repos/${OWNER}/${REPO}/pulls/${PR_NUMBER}/comments \
  | jq -r '.[] | .user.login' \
  | sort | uniq -c | sort -rn
```

## Verification

### Check gh Authentication

```bash
# Verify you're authenticated
gh auth status

# Expected output shows authenticated user and scopes
```

### Test API Access

```bash
# Test REST API access
gh api user -q '.login'

# Should return your GitHub username
```

### Verify Repository Access

```bash
# Check if you can access a repo
gh api repos/OWNER/REPO -q '.name'

# Should return the repo name
```

## Troubleshooting

### Issue: "Could not resolve to a Repository"

**Cause**: Incorrect owner/repo, or no access to repository

**Solution**:
```bash
# Verify owner and repo names
gh repo view OWNER/REPO

# Check if you have access
gh api repos/OWNER/REPO -q '.name'

# Verify authentication
gh auth status
```

### Issue: "Resource not accessible by integration"

**Cause**: Missing scopes in authentication token

**Solution**:
```bash
# Re-authenticate with required scopes
gh auth login --scopes repo,read:org

# Check current scopes
gh auth status
```

### Issue: Empty results for inline comments

**Cause**: PR has no inline comments, or querying wrong endpoint

**Solution**:
```bash
# Verify PR has inline comments by viewing in browser

# Check you're using pulls endpoint, not issues
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments

# For conversation comments, use issues endpoint
gh api repos/OWNER/REPO/issues/PR_NUMBER/comments
```

### Issue: GraphQL query syntax error

**Cause**: Malformed GraphQL query

**Solution**:
```bash
# Test query structure with simpler query first
gh api graphql -f query='
  query {
    viewer { login }
  }'

# Add complexity incrementally
# Check GitHub GraphQL Explorer for query validation
```

### Issue: Rate limiting

**Cause**: Too many API requests

**Solution**:
```bash
# Check rate limit status
gh api rate_limit

# Wait for rate limit reset
# Or use GraphQL (higher rate limits)
```

## Best Practices

1. **Parse URLs with gh when possible**
   - `gh pr view URL --json` is more robust than string parsing
   - Handles different URL formats automatically

2. **Use GraphQL for complex queries**
   - Single query vs multiple REST calls
   - Better for resolved/unresolved status
   - Higher rate limits

3. **Cache results locally**
   - API calls count against rate limits
   - Save results to file for repeated analysis

4. **Use jq for filtering**
   - Filter on client side to reduce API calls
   - Build up complex jq queries incrementally

5. **Check authentication first**
   - Always verify `gh auth status` before debugging
   - Saves time troubleshooting permission issues

6. **Use -q flag with gh api**
   - Provides cleaner output
   - Can extract specific fields directly

## Quick Reference

```bash
# Get inline PR comments (REST)
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments

# Get comment IDs with file/line info
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments --jq '.[] | "\(.id) \(.path):\(.line)"'

# Reply to a comment (REST)
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments/COMMENT_ID/replies -X POST -f body="Done."

# Get thread IDs and resolved status (GraphQL)
gh api graphql -f query='query { repository(owner:"OWNER", name:"REPO") { pullRequest(number:PR_NUMBER) { reviewThreads(first:10) { nodes { id isResolved } } } } }'

# Resolve a thread (GraphQL)
gh api graphql -f query='mutation { resolveReviewThread(input:{threadId:"PRRT_xxx"}) { thread { isResolved } } }'

# Unresolve a thread (GraphQL)
gh api graphql -f query='mutation { unresolveReviewThread(input:{threadId:"PRRT_xxx"}) { thread { isResolved } } }'

# Parse PR URL
gh pr view URL --json number,repository

# Count comments
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments | jq '. | length'

# Filter by author
gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments | jq '.[] | select(.user.login == "username")'

# Check rate limits
gh api rate_limit
```

## References

- [GitHub CLI Manual](https://cli.github.com/manual/)
- [GitHub REST API Quickstart](https://docs.github.com/rest/quickstart)
- [GitHub GraphQL API Documentation](https://docs.github.com/en/graphql)
- [gh cli Discussion #3993](https://github.com/cli/cli/discussions/3993) - Community discussion on retrieving PR reviews

## Related Skills

- **Git Workflow** - Understanding git operations for PR management
- **JSON Processing with jq** - Essential for parsing gh api output

Related Skills

when-managing-github-projects-use-github-project-management

16
from diegosouzapw/awesome-omni-skill

Comprehensive GitHub project management with swarm-coordinated issue tracking, project board automation, and sprint planning. Coordinates planner, issue-tracker, and project-board-sync agents to automate issue triage, sprint planning, milestone tracking, and project board updates. Integrates with GitHub Projects v2 API for advanced automation, custom fields, and workflow orchestration. Use when managing development projects, coordinating team workflows, or automating project management tasks.

using-superpowers

16
from diegosouzapw/awesome-omni-skill

Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions

using-skills

16
from diegosouzapw/awesome-omni-skill

Provides sub agents important information on how to use skills

using-mcp-tools-with-mcpc

16
from diegosouzapw/awesome-omni-skill

Use mcpc CLI to interact with MCP servers - call tools, read resources, get prompts. Use when working with Model Context Protocol servers, calling MCP tools, or accessing MCP resources programmatically; prefer key:=value bindings over raw JSON bodies.

using-git-worktrees

16
from diegosouzapw/awesome-omni-skill

(中文)Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification

using-contextd

16
from diegosouzapw/awesome-omni-skill

Use when starting any session with contextd - introduces core tools for cross-session memory, semantic code search, and error remediation. REQUIRES contextd MCP server.

review-github-actions

16
from diegosouzapw/awesome-omni-skill

Reviews GitHub Actions workflow files for best practices, ensuring workflows delegate commands to Makefile targets for maintainability and DRY principles. Enforces clean CI/CD patterns including proper caching, matrix strategies, and security practices.

python-github-actions

16
from diegosouzapw/awesome-omni-skill

Complete Python GitHub Actions system. PROACTIVELY activate for: (1) uv-based CI workflows (10-100x faster), (2) Matrix testing across Python versions, (3) Dependency caching with setup-uv, (4) Parallel test execution, (5) Reusable workflows, (6) Publishing to PyPI with trusted publishing, (7) Code coverage with codecov, (8) Security scanning. Provides: Workflow templates, caching config, matrix strategies, composite actions. Ensures fast, reliable CI/CD pipelines.

github.com/n-r-w/ctxlog guidelines

16
from diegosouzapw/awesome-omni-skill

Guidelines and examples for using the ctxlog logging package.

github-workflows

16
from diegosouzapw/awesome-omni-skill

Initialize or update GitHub Actions workflows for Go projects with comprehensive CI/CD pipelines including linting, testing, coverage, snapshot builds, and releases. Use when setting up GitHub Actions automation for Go projects. Trigger with "setup github actions", "add github workflows", or "configure ci/cd".

github-search

16
from diegosouzapw/awesome-omni-skill

Search GitHub for repos, code, and usage examples using gh CLI. Capabilities: repo discovery, code search, finding library usage patterns, issue/PR search. Actions: search, find, discover repos/code/examples. Keywords: gh, github, search repos, search code, find examples, how to use library, stars, language filter. Use when: finding repositories, searching code patterns, discovering how libraries are used, exploring open source.

github-repo-skill

16
from diegosouzapw/awesome-omni-skill

Guide for creating new GitHub repos and best practice for existing GitHub repos, applicable to both code and non-code projects