Overview

gh is the official GitHub CLI. It replaces most browser workflows for PRs, issues, releases, and CI with terminal commands that compose cleanly with jq-syntax and bash-one-liners. All commands require authentication via gh auth login.

Auth

Set up once per machine; tokens are stored in the system keychain.

CommandWhat it does
gh auth loginInteractive login via browser or token.
gh auth login --with-token <<< $GITHUB_TOKENLogin with a token from stdin; useful in CI.
gh auth statusShow current auth status and scopes.
gh auth logoutRemove stored credentials.
gh auth refresh -s repo,workflowRequest additional OAuth scopes.

Use a fine-grained personal access token with the minimum required scopes. Avoid classic tokens with broad repo scope.

Pull requests

Create and manage PRs without leaving the terminal.

CommandWhat it does
gh pr create --title "feat: ..." --body "..."Open a PR on the current branch.
gh pr create --draftOpen a draft PR.
gh pr create --base main --head feature-xSpecify base and head branches explicitly.
gh pr listList open PRs in the current repo.
gh pr list --state allAll PRs (open, closed, merged).
gh pr view 42View PR #42.
gh pr view --webOpen current branch’s PR in the browser.
gh pr checkout 42Check out a PR branch locally.
gh pr merge 42 --squash --delete-branchSquash-merge and delete the branch.
gh pr review --approveApprove the current PR.
gh pr review --request-changes -b "Needs tests."Request changes.
gh pr close 42Close without merging.
gh pr diffShow the diff for the current PR.
gh pr statusSummary of open, requested, and authored PRs.

Issues

CommandWhat it does
gh issue create --title "Bug: ..."Create an issue interactively.
gh issue create --title "Bug" --body "Steps..." --label bugCreate with a label.
gh issue listList open issues.
gh issue list --label bug --assignee @meFilter by label and assignee.
gh issue view 10View issue #10.
gh issue close 10 --comment "Fixed in #42"Close with a comment.
gh issue edit 10 --add-label "priority"Add a label.
gh issue comment 10 --body "More context."Add a comment.

Repos and workflow

CommandWhat it does
gh repo clone org/repoClone a repo.
gh repo create my-app --public --cloneCreate and clone a new repo.
gh repo forkFork the current repo.
gh repo view --webOpen repo in browser.
gh workflow listList workflows.
gh workflow run ci.ymlTrigger a workflow manually.
gh run listList recent workflow runs.
gh run view 123456789View a specific run.
gh run watchStream the current run’s output.
gh release listList releases.
gh release create v1.2.0 --notes "Changelog..."Create a release.
gh release upload v1.2.0 dist/app.tar.gzAttach an asset to a release.

API and scripting with —jq

gh api exposes the GitHub REST and GraphQL APIs; --jq pipes the response through jq before output.

CommandWhat it does
gh api repos/{owner}/{repo}Get repo metadata.
gh api repos/{owner}/{repo}/pulls --jq '.[].number'List PR numbers.
gh api repos/{owner}/{repo}/actions/runs --jq '.workflow_runs[0].conclusion'Last run conclusion.
gh api graphql -f query='{ viewer { login } }'GraphQL query.
gh pr list --json number,title --jq '.[] | "\(.number)\t\(.title)"'TSV of open PRs.
gh issue list --json title,labels --jq '.[] | select(.labels[].name == "bug") | .title'Issue titles with “bug” label.
gh run list --json databaseId,status --jq '[.[] | select(.status == "in_progress")] | length'Count in-progress runs.

Use gh api --paginate to fetch all pages and --jq to filter each page:

gh api --paginate repos/org/repo/issues --jq '.[].title'

Common gotchas

  • gh pr create with no flags drops you into an interactive editor. Pass --title and --body to skip interactive mode in scripts.
  • gh pr checkout modifies your local git state. Make sure your working tree is clean first or stash changes.
  • gh api uses {owner} and {repo} as path templates that expand from the current directory’s remote. Outside a git repo, pass the full path: repos/org/name.
  • --jq runs after the full response is received, not per page. For large datasets with --paginate, use --jq to filter early and reduce memory usage.
  • gh workflow run requires on: workflow_dispatch in the workflow YAML. Workflows without this trigger cannot be run manually.
  • Labels passed with --label must already exist in the repo. Create them with gh label create first.