| name | gh |
| description | Use when the user mentions `gh`, `gh api`, the GitHub CLI, the GitHub API, or wants to view, query, search, or change GitHub. Covers querying the GitHub API, raw API calls, PRs/pull requests, issues, workflows/Actions/CI, releases, repos, notifications, status, and any task that views or queries GitHub data. |
| user-invocable | true |
GitHub CLI (gh) Reference
Pull Requests
gh pr list
gh pr list --state merged --limit 10
gh pr list --json number,title,headRefName,statusCheckRollup
gh pr view 123
gh pr view 123 --comments
gh pr view 123 --json state,mergeable,mergeStateStatus | jq
gh pr create --fill
gh pr create --title "feat: add X" --body "..." --draft
gh pr create --base main --reviewer alice,bob --label "needs-review"
gh pr merge 123 --squash --delete-branch
gh pr merge 123 --auto --squash
gh pr review 123 --comment --body "LGTM"
gh pr review 123 --request-changes --body "Please fix X"
gh pr comment 123 --body "LGTM"
gh pr comment 123 --edit-last --body "Updated: LGTM"
gh pr checks 123
gh pr checks 123 --watch
gh pr edit 123 --add-label "bug" --add-reviewer charlie
gh pr edit 123 --base develop --title "Updated title"
gh pr checkout 123
gh pr diff 123
gh pr revert 123 --title "revert: undo X"
gh pr ready 123
Issues
gh issue list
gh issue list --assignee @me --state open
gh issue list --label "bug" --json number,title,state
gh issue view 456
gh issue view 456 --comments
gh issue create --title "Bug: X fails" --body "Steps..." --label "bug" --assignee @me
gh issue edit 456 --add-label "priority" --milestone "v2.0"
gh issue close 456
gh issue reopen 456
gh issue comment 456 --body "Fixed in #123"
gh issue develop 456 --name "fix/issue-456"
CI / Actions
gh run list
gh run list --branch main --status failure --limit 5
gh run list --workflow build.yml --json name,status,conclusion,headBranch
gh run view 12345678
gh run view 12345678 --verbose
gh run view 12345678 --log-failed
gh run view 12345678 --log
gh run view 12345678 --exit-status
gh run view 12345678 --json jobs --jq '.jobs[] | {name, databaseId}'
gh run view 12345678 --job 98765432
gh run watch 12345678
gh run rerun 12345678
gh run rerun 12345678 --failed
gh run rerun 12345678 --debug
gh workflow run deploy.yml --ref main
gh workflow run deploy.yml -f env=staging -f version=1.2.3
gh workflow list
gh workflow view build.yml
Releases
gh release create v1.2.3 --generate-notes
gh release create v1.2.3 --title "v1.2.3" --notes "Fixes #123" dist/*.tar.gz
gh release create v1.2.3 --draft --prerelease
gh release create v1.2.3 --notes-from-tag
gh release upload v1.2.3 dist/binary.tar.gz
gh release list
gh release view v1.2.3
gh release download v1.2.3
Repository
gh repo view
gh repo view owner/repo --json name,description,defaultBranchRef,isPrivate
gh repo clone owner/repo
gh repo fork owner/repo --clone
gh repo create my-project --private --clone
gh repo create my-project --public --source=. --push
gh repo edit --default-branch main --enable-auto-merge
gh repo edit --description "New description" --homepage "https://example.com"
gh pr list -R owner/other-repo
Search
gh search repos "nix config" --language nix --stars ">100" --sort stars
gh search issues "memory leak" --repo owner/repo --state open
gh search prs "fix authentication" --author alice --merged
gh search prs --repo owner/repo --checks failure --state open
gh search code "sops.placeholder" --repo owner/repo --language nix
Raw API
Default to a dedicated gh subcommand. Use gh-api-safe only when no
subcommand fits. Reserve raw gh api for mutations or @file field
input, gated on explicit operator consent.
| Situation | Use |
|---|
| Read-only REST fetch | gh-api-safe <path> |
| GraphQL read (queries only) | gh-api-safe graphql -f query='…' |
| Dedicated subcommand exists | that subcommand (gh pr edit, gh issue edit, ...) |
| Mutation (POST/PATCH/PUT/DELETE) | gh api -X ... in unfenced shell |
Field input from file (-F x=@file) | raw gh api in unfenced shell |
gh-api-safe wraps gh api, enforces a read-shaped allow-list with a
defence-in-depth deny-list on the REST path, blocks
-X/--method/-f/-F/--field/--raw-field/--input (except query= value under graphql, where @file is still rejected), and runs a
best-effort GraphQL heuristic that rejects any query whose body contains
a surviving mutation or subscription keyword after comments and
string literals have been stripped. The heuristic is not a real GraphQL
parser; aliased mutations are out of scope and @file queries are
rejected outright. Policy rejections exit 64 with a single-line reason
on stderr; on rejection, switch to the matching dedicated subcommand or
escalate to an unfenced shell rather than retrying the same call. Run
gh-api-safe --help for the full policy summary.
Placeholders {owner}, {repo}, {branch} are replaced from current
git context. Default method is GET.
gh-api-safe repos/{owner}/{repo}/actions/runs \
--jq '.workflow_runs[:5] | .[] | {name, conclusion, html_url}'
gh-api-safe repos/{owner}/{repo}/issues --paginate --jq '.[].title'
gh-api-safe graphql -f query='{ viewer { login } }'
gh-api-safe graphql -f query='mutation { addStar(input: {starrableId: "X"}) { starrable { id } } }'
gh-api-safe graphql -f query=@query.graphql
gh-api-safe notifications --jq '.[] | {reason, subject: .subject.title}'
See home-manager/_mixins/agentic/fence/default.nix for the
authoritative command.allow / command.deny lists,
home-manager/_mixins/agentic/fence/README.md for the policy overview,
and home-manager/_mixins/development/github/gh-api-safe.sh for the
wrapper source.
Unsafe: requires unfenced shell
⚠️ The commands below mutate GitHub state. They use gh api directly
with -X / -F / --input and are rejected by gh-api-safe. They must
only be run in an unfenced shell with explicit operator consent. Prefer
the dedicated gh subcommands (gh issue edit, gh label create, etc.)
wherever they exist.
gh api repos/{owner}/{repo}/issues/456 -X PATCH -F state=closed
gh api repos/{owner}/{repo}/labels -F name="triage" -F color="e4e669"
gh api repos/{owner}/{repo}/issues -F title="Bug" -F body=@issue.md
JSON Output Pattern
Most commands accept --json fields with optional --jq expression:
gh pr list --json number,title,state,headRefName
gh run list --json name,status,conclusion,headBranch,createdAt
gh pr list --json number,title,statusCheckRollup \
--jq '.[] | select(.statusCheckRollup | any(.state == "FAILURE")) | .number'
gh pr view 123 --json mergeable,mergeStateStatus
gh issue list --json number,title,labels | jq '.[] | select(.labels | any(.name == "bug"))'
Status & Auth
gh status
gh auth status