gh-pr-review is a GitHub CLI extension that finally brings inline PR review comments to the terminal.
GitHub’s built-in gh tool does not show inline comments or review threads — but this extension does.
With gh-pr-review, you can:
- View complete inline review threads with file and line context
- See unresolved comments during code review
- Reply to inline comments directly from the terminal
- Resolve review threads programmatically
- Export structured output ideal for LLMs and automated PR review agents
Designed for developers, DevOps teams, and AI systems that need full pull request review context, not just top-level comments.
Blog post: gh-pr-review: LLM-friendly PR review workflows in your CLI — explains the motivation, design principles, and CLI + JSON output examples.
The quickest path from opening a pending review to resolving threads:
-
Install or upgrade the extension.
gh extension install agynio/gh-pr-review # Update an existing installation gh extension upgrade agynio/gh-pr-review -
Start a pending review (GraphQL). Capture the returned
id(GraphQL node).gh pr-review review --start -R owner/repo 42 { "id": "PRR_kwDOAAABbcdEFG12", "state": "PENDING" }Pending reviews omit
submitted_at; the field appears after submission. -
Add inline comments with the pending review ID (GraphQL). The
review --add-commentcommand fails fast if you supply a numeric ID instead of the requiredPRR_…GraphQL identifier.gh pr-review review --add-comment \ --review-id PRR_kwDOAAABbcdEFG12 \ --path internal/service.go \ --line 42 \ --body "nit: use helper" \ -R owner/repo 42 { "id": "PRRT_kwDOAAABbcdEFG12", "path": "internal/service.go", "is_outdated": false, "line": 42 }
-
Inspect review threads (GraphQL).
review viewsurfaces pending review summaries, thread state, and inline comment metadata. Thread IDs are always included; enable--include-comment-node-idwhen you also need the individual comment node identifiers.gh pr-review review view --reviewer octocat -R owner/repo 42 { "reviews": [ { "id": "PRR_kwDOAAABbcdEFG12", "state": "COMMENTED", "comments": [ { "thread_id": "PRRT_kwDOAAABbcdEFG12", "path": "internal/service.go", "body": "nit: prefer helper", "is_resolved": false, "is_outdated": false, "thread": [] } ] } ] }Use the
thread_idvalues withcomments replyto continue discussions. If you are replying inside your own pending review, pass the associatedPRR_…identifier with--review-id.gh pr-review comments reply \ --thread-id PRRT_kwDOAAABbcdEFG12 \ --body "Follow-up addressed in commit abc123" \ -R owner/repo 42 -
Submit the review (GraphQL). Reuse the pending review
PRR_…identifier when finalizing. Successful submissions emit a status-only payload. GraphQL-level errors are returned as structured JSON for troubleshooting.gh pr-review review --submit \ --review-id PRR_kwDOAAABbcdEFG12 \ --event REQUEST_CHANGES \ --body "Please add tests" \ -R owner/repo 42 { "status": "Review submitted successfully" }
On GraphQL errors, the command exits non-zero after emitting:
{ "status": "Review submission failed", "errors": [ { "message": "mutation failed", "path": ["mutation", "submitPullRequestReview"] } ] } -
Inspect and resolve threads (GraphQL). Array responses are always
[]when no threads match.gh pr-review threads list --unresolved --mine -R owner/repo 42 [ { "threadId": "R_ywDoABC123", "isResolved": false, "path": "internal/service.go", "line": 42, "isOutdated": false } ]gh pr-review threads resolve --thread-id R_ywDoABC123 -R owner/repo 42 { "thread_node_id": "R_ywDoABC123", "is_resolved": true }
gh pr-review review view emits a GraphQL-only snapshot of pull request
discussion. The response groups reviews → parent inline comments → thread
replies, omitting optional fields entirely instead of returning null.
Run it with either a combined selector or explicit flags:
gh pr-review review view -R owner/repo --pr 3Install or upgrade to v1.6.0 or newer (GraphQL-only thread resolution and minimal comment replies):
gh extension install agynio/gh-pr-review
# Update an existing installation
gh extension upgrade agynio/gh-pr-review- Single GraphQL operation per invocation (no REST mixing).
- Includes all reviewers, review states, and threads by default.
- Replies are sorted by
created_atascending. - Output exposes
author_loginonly—no user objects orhtml_urlfields. - Optional fields (
body,submitted_at,line,thread) are omitted when empty; empty reply lists render as"thread": [].
| Flag | Purpose |
|---|---|
--reviewer <login> |
Only include reviews authored by <login> (case-insensitive). |
--states <list> |
Comma-separated review states (APPROVED, CHANGES_REQUESTED, COMMENTED, DISMISSED). |
--unresolved |
Keep only unresolved threads. |
--not_outdated |
Exclude threads marked as outdated. |
--tail <n> |
Retain only the last n replies per thread (0 = all). The parent inline comment is always kept; only replies are trimmed. |
--include-comment-node-id |
Add GraphQL comment node identifiers to parent comments and replies. |
# Default: return all reviews, states, threads
gh pr-review review view -R owner/repo --pr 3
# Unresolved threads only
gh pr-review review view -R owner/repo --pr 3 --unresolved
# Focus changes requested from a single reviewer; keep only latest reply per thread
gh pr-review review view -R owner/repo --pr 3 --reviewer alice --states CHANGES_REQUESTED --tail 1
# Drop outdated threads and include comment node IDs
gh pr-review review view -R owner/repo --pr 3 --not_outdated --include-comment-node-id{
"reviews": [
{
"id": "PRR_…",
"state": "APPROVED|CHANGES_REQUESTED|COMMENTED|DISMISSED",
"author_login": "…",
"body": "…", // omitted if empty
"submitted_at": "…", // omitted if absent
"comments": [ // omitted if none
{
"thread_id": "PRRT_…",
"comment_node_id": "PRRC_…", // omitted unless requested
"path": "…",
"line": 21, // omitted if null
"author_login": "…",
"body": "…",
"created_at": "…",
"is_resolved": true,
"is_outdated": false,
"thread": [ // replies only; sorted asc; tail applies
{
"comment_node_id": "PRRC_…", // omitted unless requested
"author_login": "…",
"body": "…",
"created_at": "…"
}
]
}
]
}
]
}Use the thread_id values surfaced in the report when replying.
gh pr-review comments reply 3 -R owner/repo \
--thread-id PRRT_kwDOAAABbcdEFG12 \
--body "Follow-up addressed in commit abc123"
Each command binds to a single GitHub backend—there are no runtime fallbacks.
| Command | Backend | Notes |
|---|---|---|
review --start |
GraphQL | Opens a pending review via addPullRequestReview. |
review --add-comment |
GraphQL | Requires a PRR_… review node ID. |
review view |
GraphQL | Aggregates reviews, inline comments, and replies (used for thread IDs). |
review --submit |
GraphQL | Finalizes a pending review via submitPullRequestReview using the PRR_… review node ID (executed through the internal gh api graphql wrapper). |
comments reply |
GraphQL | Replies via addPullRequestReviewThreadReply; supply --review-id when responding from a pending review. |
threads list |
GraphQL | Enumerates review threads for the pull request. |
threads resolve / unresolve |
GraphQL | Mutates thread resolution via resolveReviewThread / unresolveReviewThread; supply GraphQL thread node IDs (PRRT_…). |
- docs/USAGE.md — Command-by-command inputs, outputs, and examples for v1.6.0.
- docs/SCHEMAS.md — JSON schemas for each structured response (optional fields omitted rather than set to null).
- docs/AGENTS.md — Agent-focused workflows, prompts, and best practices.
gh-pr-review is designed to give LLMs and agents the exact PR review context they need — without the noisy, multi-step GitHub API workflow.
-
Replaces multi-call API chains with one command
Instead of callinglist reviews → list thread comments → list comments,
a singlegh pr-review review viewcommand returns the entire, assembled review structure. -
Deterministic, stable output
Consistent formatting, stable ordering, and predictable field names make parsing reliable for agents. -
Compact, meaningful JSON
Only essential fields are returned. Low-signal metadata (URLs, hashes, unused fields) is stripped out to reduce token usage. -
Pre-joined review threads
Threads come fully reconstructed with inline context — no need for agents to merge comments manually. -
Server-side filters for token efficiency
Options like--unresolvedand--tailhelp reduce payload size and keep inputs affordable for LLMs.
“A good tool definition should define a clear, narrow purpose, return exactly the meaningful context the agent needs, and avoid burdening the model with low-signal intermediate results.”
Run the test suite and linters locally with cgo disabled (matching the release build):
CGO_ENABLED=0 go test ./...
CGO_ENABLED=0 golangci-lint runReleases are built using the
cli/gh-extension-precompile
workflow to publish binaries for macOS, Linux, and Windows.