nvidia/github
Interact with GitHub using the gh CLI restricted to REST API only (no GraphQL). Use when the user wants to work with GitHub issues, pull requests, repos, releases, or Actions — especially in sandboxed environments where the GraphQL endpoint may be blocked. Trigger keywords - github, gh, pull request, PR, github issue, github actions, workflow, release, gh api.
npx skills add https://github.com/NVIDIA/OpenShell-Community --skill github
Always prefer using the github cli. do not use git for any operations except cloning.
Work with GitHub using gh api and REST-only subcommands. Many gh subcommands (gh pr list, gh issue list, gh issue view, gh pr view, etc.) use GraphQL internally and will fail if the sandbox blocks api.github.com/graphql. Always prefer gh api hitting REST endpoints.
Use required_permissions: ["full_network"] for all gh commands (they need to reach api.github.com).
| Endpoint | Status |
| --------------------------------- | ---------------------- |
| api.github.com/graphql | Blocked in sandbox |
| api.github.com/repos/... (REST) | Allowed |
Rule: Never use gh subcommands that call GraphQL. When in doubt, use gh api with an explicit REST path.
gh pr list, gh pr view, gh pr status, gh pr checksgh issue list, gh issue view, gh issue statusgh project (all subcommands)gh search (all subcommands)gh label listgh api <REST-path> — always REST when given a path (not graphql)gh pr create — uses RESTgh pr merge — uses RESTgh release * — uses RESTgh run * — uses RESTgh workflow * — uses RESTgh auth status — local/RESTgh repo clone / gh repo view --json — may use GraphQL; prefer gh apigh auth status
If not authenticated, instruct the user to run gh auth login.
gh api repos/{owner}/{repo}
gh api "users/{username}/repos?per_page=30&sort=updated"
gh api "orgs/{org}/repos?per_page=30&sort=updated"
gh api "repos/{owner}/{repo}/issues?state=open&per_page=30" \
| jq '.[] | {number, title, state, user: .user.login, labels: [.labels[].name]}'
Filter options (query params): state (open/closed/all), labels (comma-separated), assignee, creator, milestone, sort (created/updated/comments), direction (asc/desc), since (ISO 8601), per_page, page.
gh api repos/{owner}/{repo}/issues/{number}
gh api repos/{owner}/{repo}/issues \
-f title="Issue title" \
-f body="Issue description" \
-f "labels[]=bug" \
-f "assignees[]={username}"
gh api repos/{owner}/{repo}/issues/{number}/comments \
-f body="Comment text"
gh api repos/{owner}/{repo}/issues/{number} -X PATCH -f state=closed
gh api repos/{owner}/{repo}/issues/{number} -X PATCH -f state=open
gh api repos/{owner}/{repo}/issues/{number}/labels \
-f "labels[]=bug" -f "labels[]=priority-high"
gh api "repos/{owner}/{repo}/pulls?state=open&per_page=30" \
| jq '.[] | {number, title, state, user: .user.login, head: .head.ref, base: .base.ref}'
Filter options: state (open/closed/all), head (filter by head user/org and branch: user:ref-name), base (filter by base branch), sort (created/updated/popularity/long-running), direction, per_page, page.
gh api repos/{owner}/{repo}/pulls/{number} \
| jq '{number, title, state, body, user: .user.login, head: .head.ref, base: .base.ref, mergeable: .mergeable, merged: .merged}'
gh api repos/{owner}/{repo}/pulls/{number} \
-H "Accept: application/vnd.github.diff"
gh api "repos/{owner}/{repo}/pulls/{number}/files?per_page=100" \
| jq '.[] | {filename, status, additions, deletions, changes}'
gh pr create is REST-safe and the easiest way:
gh pr create --title "PR title" --body "PR description" --base main --head feature-branch
Or via gh api:
gh api repos/{owner}/{repo}/pulls \
-f title="PR title" \
-f body="PR description" \
-f head="feature-branch" \
-f base="main"
gh pr merge {number} --squash # REST-safe
Or via gh api:
gh api repos/{owner}/{repo}/pulls/{number}/merge \
-X PUT -f merge_method=squash
gh api repos/{owner}/{repo}/pulls/{number}/requested_reviewers \
-f "reviewers[]={username}"
gh api "repos/{owner}/{repo}/pulls/{number}/reviews" \
| jq '.[] | {user: .user.login, state, body}'
gh api "repos/{owner}/{repo}/pulls/{number}/comments" \
| jq '.[] | {user: .user.login, path, body, line}'
PRs use the issues comments endpoint:
gh api repos/{owner}/{repo}/issues/{number}/comments \
-f body="Comment text"
gh api "repos/{owner}/{repo}/branches?per_page=30" \
| jq '.[].name'
gh api repos/{owner}/{repo}/commits/{sha} \
| jq '{sha, message: .commit.message, author: .commit.author.name, date: .commit.author.date}'
gh api "repos/{owner}/{repo}/compare/{base}...{head}" \
| jq '{ahead_by, behind_by, total_commits, files: [.files[] | {filename, status, additions, deletions}]}'
gh api "repos/{owner}/{repo}/commits?sha={branch}&per_page=20" \
| jq '.[] | {sha: .sha[:8], message: (.commit.message | split("\n")[0]), date: .commit.author.date}'
gh run list --limit 10 # REST-safe
Or via gh api:
gh api "repos/{owner}/{repo}/actions/runs?per_page=10" \
| jq '.workflow_runs[] | {id, name, status, conclusion, head_branch, created_at}'
gh api repos/{owner}/{repo}/actions/runs/{run_id} \
| jq '{id, name, status, conclusion, head_branch, html_url}'
gh api "repos/{owner}/{repo}/actions/runs/{run_id}/jobs" \
| jq '.jobs[] | {id, name, status, conclusion, started_at, completed_at}'
gh run view {run_id} --log # REST-safe
gh api repos/{owner}/{repo}/actions/runs/{run_id}/rerun -X POST
gh api repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs -X POST
gh api "repos/{owner}/{repo}/actions/workflows" \
| jq '.workflows[] | {id, name, state, path}'
gh api repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches \
-f ref=main -f "inputs[key]=value"
gh api "repos/{owner}/{repo}/releases?per_page=10" \
| jq '.[] | {tag_name, name, draft, prerelease, published_at}'
gh api repos/{owner}/{repo}/releases/latest \
| jq '{tag_name, name, body, published_at, assets: [.assets[] | {name, download_count, browser_download_url}]}'
gh api repos/{owner}/{repo}/releases \
-f tag_name="v1.0.0" \
-f name="Release v1.0.0" \
-f body="Release notes here" \
-F draft=false \
-F prerelease=false
gh api "repos/{owner}/{repo}/commits/{ref}/check-runs" \
| jq '.check_runs[] | {name, status, conclusion, html_url}'
gh api "repos/{owner}/{repo}/commits/{ref}/status" \
| jq '{state, total_count, statuses: [.statuses[] | {context, state, description}]}'
GitHub REST API returns at most 100 items per page. Use per_page and page query params:
gh api "repos/{owner}/{repo}/issues?state=all&per_page=100&page=1"
gh api "repos/{owner}/{repo}/issues?state=all&per_page=100&page=2"
Or use --paginate to auto-follow Link headers (returns all pages concatenated):
gh api "repos/{owner}/{repo}/issues?state=all&per_page=100" --paginate \
| jq '.[] | {number, title}'
If the user doesn't specify a repo, infer from the current git remote:
gh api repos/:owner/:repo
gh api resolves :owner and :repo from the current git remote automatically.
gh auth status; may need gh auth logingh api rate_limitTake nvidia/github from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.