Claude Code Plugins

Community-maintained marketplace

Feedback

Use when querying GitHub via GraphQL. Provides patterns for PR threads, comments, and mutations.

Install Skill

Shared

Installs to .agents/skills, used by Codex, Amp, Warp, Cursor, OpenCode, and more.

CodexAmp
Warp
CursorOpenCode
Cline
Gemini CLI
GitHub Copilot
Personal

Available across projects.

$npx skills-installer add @majiayu000/claude-skill-registry/github-graphql --client shared
Project

Writes to .agents/skills.

$npx skills-installer add @majiayu000/claude-skill-registry/github-graphql -p --client shared
Note: Review the skill instructions before using it.

SKILL.md

name github-graphql
description Use when querying GitHub via GraphQL. Provides patterns for PR threads, comments, and mutations.
version 1.0.0
author JacobPEvans

GitHub GraphQL Patterns

Standardized GraphQL patterns for GitHub PR and review thread operations. All commands that interact with GitHub's GraphQL API should reference this skill instead of duplicating queries.

Critical Requirements

1. Single-Line Format Required

ALWAYS use single-line GraphQL queries with --raw-field in Claude Code.

Multi-line GraphQL queries cause encoding issues. Use this pattern:

# CORRECT: Single-line with --raw-field
gh api graphql --raw-field 'query=query { repository(owner: "{OWNER}", name: "{REPO}") { pullRequest(number: {NUMBER}) { reviewThreads(last: 100) { nodes { id isResolved } } } } }'

Shell Quoting Notes:

  • Single quotes (as above) prevent shell variable expansion - use when query contains literal placeholders like {OWNER}
  • Double quotes needed only for shell variable substitution (e.g., $OWNER) - must escape inner quotes with \"
  • Single-line refers to the GraphQL query itself (no newlines), not shell quoting style
  • Placeholders like {OWNER}, {REPO}, {NUMBER} are documentation notation - replace with actual values before running

2. Always Use last: 100 Not first: ##

NEVER use first: ## in GraphQL queries. Always use last: 100 to ensure you get ALL recent items and don't miss threads/comments due to pagination cutoff.

3. No For Loops

NEVER use for loops or while loops - they require permission prompts and break automation. Instead:

  • Run single gh api graphql commands against single thread IDs
  • Process threads one at a time with individual approved commands
  • If possible, include multiple thread IDs as separate parameters in a single call

4. Commits Must Be Signed

When making direct commits for PR changes, ALL commits MUST be signed.

Core Query Patterns

1. Get Review Threads

Purpose: Fetch all review threads for a PR with resolution status and comments.

gh api graphql --raw-field 'query=query { repository(owner: "{OWNER}", name: "{REPO}") { pullRequest(number: {NUMBER}) { reviewThreads(last: 100) { nodes { id isResolved path line startLine comments(last: 100) { nodes { id databaseId body author { login } createdAt } } } } } } }'

Key Fields:

Field Description
id Thread ID for resolution (format: PRRT_xxx)
isResolved Boolean resolution status
path File path the comment is on
line/startLine Line numbers in the file
comments.nodes[].body Comment text
comments.nodes[].databaseId Numeric ID for REST API operations

2. Resolve Review Thread

Purpose: Mark a review thread as resolved.

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

Requirements:

  • Thread ID must be a valid GraphQL node ID starting with PRRT_
  • You must have write access to the repository

3. Verify All Threads Resolved

Purpose: Check if any unresolved threads remain on a PR.

gh api graphql --raw-field 'query=query { repository(owner: "{OWNER}", name: "{REPO}") { pullRequest(number: {NUMBER}) { reviewThreads(last: 100) { nodes { isResolved } } } } }' | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length'

Success Criteria: Returns 0 (no unresolved threads).

4. Get PR Mergeable Status

Purpose: Check if a PR can be merged.

gh api graphql --raw-field 'query=query { repository(owner: "{OWNER}", name: "{REPO}") { pullRequest(number: {NUMBER}) { mergeable statusCheckRollup { state } reviewDecision } } }'

Mergeable Values:

  • MERGEABLE - Can be merged
  • CONFLICTING - Has merge conflicts
  • UNKNOWN - Status still being calculated

Thread Resolution Workflow

Step 1: Get Unresolved Thread IDs

Run the query to get all threads, then use jq to extract unresolved thread IDs:

gh api graphql --raw-field 'query=query { repository(owner: "{OWNER}", name: "{REPO}") { pullRequest(number: {NUMBER}) { reviewThreads(last: 100) { nodes { id isResolved } } } } }' | jq -r '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .id'

Step 2: Resolve Each Thread Individually

For each thread ID from Step 1, run the resolve mutation as a separate command:

gh api graphql --raw-field 'query=mutation { resolveReviewThread(input: {threadId: "PRRT_kwDOxxxxx"}) { thread { id isResolved } } }'

Important: Do NOT use loops. Run each resolve command individually.

Step 3: Verify Resolution

After resolving all threads, verify none remain unresolved:

gh api graphql --raw-field 'query=query { repository(owner: "{OWNER}", name: "{REPO}") { pullRequest(number: {NUMBER}) { reviewThreads(last: 100) { nodes { isResolved } } } } }' | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length'

Node ID Handling

GitHub uses two ID systems. Understanding when to use each is critical.

GraphQL Node IDs (base64 encoded)

Used for GraphQL operations:

  • Review thread: PRRT_kwDOO1m-OM5gtgeQ
  • PR comment: PRRC_kwDOO1m-OM5gtgeR
  • Pull request: PR_kwDOO1m-OM4...

Get via GraphQL query nodes[].id fields.

REST API Numeric IDs

Used for REST API operations:

  • Get via: gh api repos/{OWNER}/{REPO}/pulls/{NUMBER}/comments | jq '.[].id'
  • Or via GraphQL: comments.nodes[].databaseId

ID Usage Table

Operation ID Type How to Get
Resolve thread GraphQL node ID (PRRT_xxx) From reviewThreads.nodes[].id
Reply to comment Numeric ID From REST API or databaseId
React to comment Numeric ID From REST API or databaseId
Get thread status GraphQL node ID From reviewThreads.nodes[].id

Making Changes to PRs

When resolving review threads requires code changes:

Option 1: Use Worktree (Preferred)

  1. Create or switch to the PR's worktree:

    BRANCH="{BRANCH}"
    SANITIZED_BRANCH="$(printf '%s' "$BRANCH" | tr -c 'A-Za-z0-9._-' '_')"
    git worktree add "$HOME/git/{REPO}/$SANITIZED_BRANCH" "$BRANCH"
    cd "$HOME/git/{REPO}/$SANITIZED_BRANCH"
    
  2. Make changes normally

  3. Commit with signature: git commit -S -m "message"

  4. Push: git push origin {BRANCH}

Option 2: Direct Signed Commit (Small Changes Only)

For small single-file fixes, you can commit directly if and only if commits are signed:

# Ensure GPG signing is configured
git config --global commit.gpgsign true
git config --global user.signingkey {YOUR_KEY_ID}

# Make the change and commit with signature
git commit -S -m "fix: address review feedback"
git push origin {BRANCH}

Never:

  • Create branches in /tmp folders
  • Output temporary scripts
  • Make unsigned commits

Placeholder Reference

NOTE: Placeholders below use {CURLY_BRACES} notation for documentation clarity. These are NOT bash variables and will NOT be expanded by the shell. You must manually replace them with actual values before running commands.

Placeholder Description Example
{OWNER} Repository owner (replace with actual value) JacobPEvans
{REPO} Repository name (replace with actual value) ai-assistant-instructions
{NUMBER} PR number integer (replace with actual value) 123
{THREAD_ID} Thread ID from GraphQL query (replace with actual value) PRRT_kwDOO1m-OM5gtgeQ
{BRANCH} Branch name (replace with actual value) fix/my-feature

Common Errors and Solutions

Error Cause Solution
"Field 'reviewThreads' doesn't exist" Wrong API version Use GraphQL v4 (default)
"Resource not accessible by integration" Missing permissions Check gh auth status, ensure repo access
"Invalid node ID" Wrong ID format Verify ID starts with correct prefix (PRRT_, etc.)
Encoding/parsing issues Multi-line query Use single-line format with --raw-field
"Could not resolve to a PullRequest" Wrong PR number Verify PR exists and number is correct

Commands Using This Skill

  • /resolve-pr-review-thread [all] - Primary consumer for thread resolution
  • /manage-pr - Thread resolution during PR management
  • /review-pr - Creating and reading review threads
  • /pr-review-feedback - Reference documentation for GraphQL patterns

Best Practices

  1. Always use last: 100: Never use first: ## to avoid missing threads
  2. No loops: Run individual commands, don't batch with loops
  3. Verify resolution: After resolving, query again to confirm isResolved: true
  4. Sign all commits: Use git commit -S for all direct commits
  5. Use worktrees: Prefer worktrees over /tmp folders for code changes
  6. Check permissions first: Run gh auth status before GraphQL operations
  7. Use jq for parsing: Extract specific fields with jq rather than parsing raw JSON