github

SKILL.md

GitHub

All GitHub operations use the gh CLI. Prefer --json with --jq for structured, parseable output. Use --repo owner/repo when not inside a git repository with a configured remote. Use --web to open any resource in the browser.

Reference File Purpose
references/graphql-queries.md GraphQL query patterns, cost model, mutations, rate limit inspection
references/automation-workflows.md Multi-step workflow recipes for CI triage, PR lifecycle, releases, batch ops

Prerequisites and Auth

Installation

Platform Command
macOS brew install gh
Debian/Ubuntu sudo apt install gh
Windows winget install GitHub.cli

Authentication

Log in interactively (opens browser for OAuth):

gh auth login

Check current auth status and active account:

gh auth status

Required OAuth Scopes

Scope Grants Access To
repo Private repos, issues, PRs, commits, status
read:org Org membership, team listing
workflow Trigger and manage GitHub Actions workflows
gist Create and manage gists
delete_repo Delete repositories (not granted by default)
admin:org Manage org settings, teams, members
project Read/write access to ProjectV2 boards

Add missing scopes without re-authenticating from scratch:

gh auth refresh --scopes repo,read:org,workflow

Issues

Create

gh issue create --repo owner/repo --title "Login timeout on slow connections" --body "Users on 3G see a 504 after 8 seconds"

Create with labels, assignees, and milestone:

gh issue create --repo owner/repo \
  --title "Add rate limiting to /api/upload" \
  --body "Current endpoint has no throttle. Target: 100 req/min per user." \
  --label "enhancement,backend" \
  --assignee "username1,username2" \
  --milestone "v2.1"
Flag Purpose
--title Issue title (required unless --fill used)
--body Issue body in markdown
--label Comma-separated label names
--assignee Comma-separated GitHub usernames
--milestone Milestone name
--project Project board name
--web Open the new issue in browser after creation

List and Filter

gh issue list --repo owner/repo --state open --label "bug" --assignee "@me" --limit 20

Structured output with JSON:

gh issue list --repo owner/repo --json number,title,labels,assignees \
  --jq '.[] | "\(.number) [\(.labels | map(.name) | join(","))] \(.title)"'

View, Edit, Close

View issue details:

gh issue view 42 --repo owner/repo

View with comments:

gh issue view 42 --repo owner/repo --comments

Edit an existing issue:

gh issue edit 42 --repo owner/repo --add-label "priority:high" --add-assignee "username"

Close an issue with a comment:

gh issue close 42 --repo owner/repo --comment "Fixed in PR #87"

Comments

Add a comment to an issue:

gh issue comment 42 --repo owner/repo --body "Reproduced on v2.0.3. Stack trace attached."

Pull Requests

Create

Standard PR from current branch:

gh pr create --repo owner/repo --title "Add rate limiter middleware" --body "Implements token bucket at 100 req/min"

Draft PR with reviewers:

gh pr create --repo owner/repo \
  --title "Refactor auth module" \
  --body "Splits monolithic auth into JWT and session submodules" \
  --draft \
  --reviewer "reviewer1,reviewer2" \
  --label "refactor"

Auto-fill title and body from commit messages:

gh pr create --repo owner/repo --fill

Create PR targeting a specific base branch:

gh pr create --repo owner/repo --base develop --head feature/rate-limiter --fill

List and Filter

gh pr list --repo owner/repo --state open --author "@me" --label "needs-review"

JSON output with review status:

gh pr list --repo owner/repo --json number,title,reviewDecision,statusCheckRollup \
  --jq '.[] | "\(.number) \(.reviewDecision // "PENDING") \(.title)"'

View and Review

View PR details including diff stats:

gh pr view 55 --repo owner/repo

View the diff:

gh pr diff 55 --repo owner/repo

Approve a PR:

gh pr review 55 --repo owner/repo --approve --body "LGTM — tests pass, no security concerns"

Request changes:

gh pr review 55 --repo owner/repo --request-changes --body "Missing input validation on the upload handler"

Add a review comment without approving or requesting changes:

gh pr review 55 --repo owner/repo --comment --body "Consider caching the config lookup"

Merge

Merge with default strategy:

gh pr merge 55 --repo owner/repo

Squash merge and delete branch:

gh pr merge 55 --repo owner/repo --squash --delete-branch

Rebase merge:

gh pr merge 55 --repo owner/repo --rebase

Auto-merge when CI passes:

gh pr merge 55 --repo owner/repo --auto --squash

CI Status

Check CI status on a PR:

gh pr checks 55 --repo owner/repo

Watch CI and block until all checks complete:

gh pr checks 55 --repo owner/repo --watch

Edit, Ready, Close

Mark a draft PR as ready for review:

gh pr ready 55 --repo owner/repo

Edit PR metadata:

gh pr edit 55 --repo owner/repo --add-reviewer "reviewer3" --add-label "urgent"

Close a PR without merging:

gh pr close 55 --repo owner/repo --comment "Superseded by #60"

CI / Actions

List Workflow Runs

gh run list --repo owner/repo --limit 10

Filter by workflow name and branch:

gh run list --repo owner/repo --workflow "CI" --branch main --status failure --limit 5

JSON output:

gh run list --repo owner/repo --json databaseId,status,conclusion,headBranch,name \
  --jq '.[] | "\(.databaseId) \(.status) \(.conclusion // "running") \(.headBranch)"'

View Run Details

gh run view 123456789 --repo owner/repo

View logs for failed steps only:

gh run view 123456789 --repo owner/repo --log-failed

View full logs:

gh run view 123456789 --repo owner/repo --log

Trigger and Rerun

Trigger a workflow manually:

gh workflow run deploy.yml --repo owner/repo --ref main -f environment=staging

Rerun only the failed jobs in a run:

gh run rerun 123456789 --repo owner/repo --failed

Rerun the entire run:

gh run rerun 123456789 --repo owner/repo

Watch a Run

Stream live status updates until the run completes:

gh run watch 123456789 --repo owner/repo

Enable and Disable Workflows

gh workflow disable "Nightly Build" --repo owner/repo
gh workflow enable "Nightly Build" --repo owner/repo

Download Artifacts

gh run download 123456789 --repo owner/repo --name "build-output"

Download all artifacts from a run:

gh run download 123456789 --repo owner/repo

Repositories

Create

Create a new public repository:

gh repo create owner/new-repo --public --description "Service for handling webhooks"

Create from a template:

gh repo create owner/new-service --template owner/service-template --public --clone

Fork and Clone

gh repo fork owner/repo --clone
gh repo clone owner/repo

View and List

gh repo view owner/repo
gh repo view owner/repo --json name,description,defaultBranchRef --jq '.defaultBranchRef.name'

List repos in an org:

gh repo list some-org --limit 50 --json name,isArchived \
  --jq '.[] | select(.isArchived == false) | .name'

Edit Settings

gh repo edit owner/repo --description "Updated description" --enable-issues --enable-wiki=false

Archive and Delete

gh repo archive owner/repo --yes
gh repo delete owner/repo --yes

Releases

Create

Create a release with auto-generated notes:

gh release create v1.2.0 --repo owner/repo --generate-notes

Create with title, notes, and binary assets:

gh release create v1.2.0 --repo owner/repo \
  --title "v1.2.0 — Rate Limiter" \
  --notes "Adds token bucket rate limiting to all API endpoints" \
  ./dist/app-linux-amd64 ./dist/app-darwin-arm64

Create a prerelease:

gh release create v2.0.0-rc1 --repo owner/repo --prerelease --generate-notes

List and View

gh release list --repo owner/repo --limit 5
gh release view v1.2.0 --repo owner/repo

Edit and Upload Assets

gh release edit v1.2.0 --repo owner/repo --draft=false --prerelease=false

Upload additional assets to an existing release:

gh release upload v1.2.0 --repo owner/repo ./dist/app-windows-amd64.exe

Delete

gh release delete v1.0.0-beta --repo owner/repo --yes

Search

Repositories

gh search repos "rate limiter language:go" --limit 10 --json fullName,description,stargazersCount \
  --jq '.[] | "\(.stargazersCount) \(.fullName): \(.description)"'

Issues

gh search issues "memory leak is:open repo:owner/repo" --json number,title,url \
  --jq '.[] | "#\(.number) \(.title)"'

Pull Requests

gh search prs "review:approved is:merged repo:owner/repo" --json number,title,mergedAt \
  --jq '.[] | "\(.number) \(.mergedAt) \(.title)"'

Code

gh search code "func RateLimit repo:owner/repo" --json path,repository \
  --jq '.[] | "\(.repository.fullName) \(.path)"'

Commits

gh search commits "fix timeout repo:owner/repo" --json sha,commit \
  --jq '.[] | "\(.sha[:8]) \(.commit.message | split("\n") | .[0])"'

API: REST and GraphQL

REST: GET

gh api repos/owner/repo/pulls/55 --jq '{title: .title, state: .state, author: .user.login}'

REST: POST

gh api repos/owner/repo/issues/42/comments -f body="Automated comment from CI triage"

REST: PATCH

gh api repos/owner/repo/issues/42 -X PATCH -f state="closed"

Pagination

Paginate through all results automatically:

gh api repos/owner/repo/issues --paginate --jq '.[].number'

Rate Limit Check

gh api rate_limit --jq '{core: .resources.core, graphql: .resources.graphql}'

GraphQL Queries

Inline GraphQL query:

gh api graphql -f query='
  query {
    repository(owner: "owner", name: "repo") {
      issues(first: 5, states: OPEN) {
        nodes {
          number
          title
        }
      }
    }
  }
' --jq '.data.repository.issues.nodes[] | "\(.number) \(.title)"'

See references/graphql-queries.md for cost model, bulk queries, mutations, and rate limit management patterns.

REST vs GraphQL Decision Table

Scenario Use Reason
Fetch a single resource (one PR, one issue) REST (gh api) Simple, predictable, low overhead
Fetch nested or related data in one round-trip GraphQL Avoids N+1 requests; select only needed fields
Bulk operations across many resources GraphQL Query complexity points are cheaper than REST calls
Creating or updating a resource (mutation) Either REST: -X POST/PATCH; GraphQL: mutation {} block
Rate-limit-sensitive pipeline or script REST REST has a simple 5000 req/hr counter; easier to budget
ProjectV2 board operations GraphQL ProjectV2 has no REST API; GraphQL only

Inline Workflow Examples

PR Lifecycle

# 1. Create a draft PR from the current branch
gh pr create --repo owner/repo --title "Add rate limiter" --body "Token bucket at 100 req/min" --draft

# 2. Check CI status on the PR
gh pr checks 55 --repo owner/repo --watch

# 3. Mark ready once CI passes
gh pr ready 55 --repo owner/repo

# 4. Approve the PR
gh pr review 55 --repo owner/repo --approve --body "LGTM"

# 5. Squash-merge and delete branch
gh pr merge 55 --repo owner/repo --squash --delete-branch

See references/automation-workflows.md for the full lifecycle with label management and reviewer rotation.

CI Triage

# 1. Find the latest failed run on main
gh run list --repo owner/repo --branch main --status failure --limit 1 --json databaseId --jq '.[0].databaseId'

# 2. View failed step logs (substitute run ID from step 1)
gh run view 123456789 --repo owner/repo --log-failed

# 3. Rerun only failed jobs
gh run rerun 123456789 --repo owner/repo --failed

# 4. Watch until complete
gh run watch 123456789 --repo owner/repo

See references/automation-workflows.md for batch triage across multiple branches and failure pattern analysis.


Error Handling

Error Cause Resolution
HTTP 401 Unauthorized Token expired or revoked Run gh auth login to re-authenticate
HTTP 403 Forbidden Insufficient permissions or rate limited Check gh auth status for scopes; check gh api rate_limit
HTTP 404 Not Found Repo does not exist, is private without repo scope, or resource deleted Verify repo name; run gh auth refresh --scopes repo
HTTP 422 Unprocessable Entity Invalid payload — missing required field, validation error Check request body fields match API schema
HTTP 429 Too Many Requests REST rate limit exceeded (5000 req/hr authenticated) Wait for X-RateLimit-Reset timestamp; reduce request frequency
GraphQL rate limit exceeded Used more than 5000 points/hr Reduce query complexity or wait; see references/graphql-queries.md
"no git remotes found" Running gh outside a git repo without --repo Add --repo owner/repo to the command
Insufficient OAuth scopes Token lacks required scope for the operation Run gh auth refresh --scopes scope1,scope2
Duplicate issue/PR title Not a real error — GitHub allows duplicates, but check before creating Search with gh issue list or gh pr list first
Archived repo blocks writes Repo is archived; all write operations fail Unarchive with gh repo edit owner/repo --archived=false or use a different repo

Enable debug logging to see raw HTTP requests and responses:

GH_DEBUG=api gh pr list --repo owner/repo

Gists

Create

Create a public gist from a file:

gh gist create --public --desc "Rate limiter implementation" rate_limiter.py

Create from stdin:

echo '{"key": "value"}' | gh gist create --filename config.json

List, View, Edit, Delete

gh gist list --limit 10
gh gist view abc123def456
gh gist edit abc123def456 --add new_file.py
gh gist delete abc123def456

Organizations and Teams

List orgs for the authenticated user:

gh org list

List org members with pagination:

gh api orgs/some-org/members --paginate --jq '.[].login'

List teams in an org:

gh api orgs/some-org/teams --paginate --jq '.[] | "\(.slug): \(.description)"'

List members of a specific team:

gh api orgs/some-org/teams/backend-team/members --paginate --jq '.[].login'

Limitations

  • Network required — all gh commands require internet access; no offline mode.
  • GraphQL point budget — 5000 points/hr for authenticated users. Complex queries with high first/last values consume points faster. See references/graphql-queries.md.
  • Secrets are write-onlygh secret set works, but there is no gh secret get. Secret values cannot be retrieved after creation.
  • Org admin operations — managing org settings, teams, and SAML requires the admin:org scope, which is not granted by default.
  • Artifact retention — workflow artifacts are retained for 90 days by default. Expired artifacts cannot be downloaded.

Calibration Rules

  1. Prefer --json over parsing text output. Text output formats are unstable across gh versions. Always use --json field1,field2 to get machine-readable output.
  2. Use --jq to minimize output before processing. Filter at the source rather than piping large JSON blobs to external tools. --jq runs server-side and reduces data transferred.
  3. Prefer higher-level commands over raw API. Use gh issue create instead of gh api repos/.../issues -X POST. High-level commands handle auth, pagination, and error formatting automatically.
  4. Use --repo consistently when outside a git directory. Never rely on implicit repo detection in scripts or CI environments. Always pass --repo owner/repo explicitly.
  5. Use GraphQL only for nested or bulk data. For single-resource fetches and mutations with simple payloads, REST is faster to write, easier to debug, and predictable under rate limits.
Weekly Installs
20
GitHub Stars
11
First Seen
Feb 23, 2026
Installed on
opencode20
gemini-cli20
github-copilot20
codex20
kimi-cli20
amp20