Overview

gh is the official GitHub CLI. It removes the context switch to the browser for the most common operations: opening PRs, triaging issues, triggering workflows, and cutting releases. The rules below cover authentication, the command groups worth learning, --jq for scriptable output, and one-liners that save repeated clicks. Read shell for the shell scripting patterns that pair with gh.

Authenticate once; use tokens for non-interactive environments

gh auth login          # interactive: browser or PAT
gh auth status         # verify which account and scopes are active
gh auth token          # print the current token for piping

For CI and automation, set GH_TOKEN in the environment or in github-secrets. The CLI picks up GH_TOKEN before prompting for interactive auth. Use a fine-grained PAT scoped to the repositories and permissions the script needs. Avoid classic PATs with broad scopes.

gh pr covers the full PR lifecycle

gh pr create --title "feat(tooling): add CLI page" --body "$(cat body.md)" --draft
gh pr list --state open --assignee "@me"
gh pr view 42
gh pr checkout 42        # switches to the branch locally
gh pr merge 42 --squash --delete-branch
gh pr review 42 --approve --body "LGTM"
gh pr merge --auto --squash   # enable auto-merge on the current branch's PR

gh pr create without arguments infers the title from the last commit and opens an editor for the body. Pass --web to open the creation form in the browser when the body is complex. See github-pr-workflow for the title and body conventions these commands must follow.

gh issue replaces the issues tab

gh issue create --title "Bug: deploy fails on Saturday" --label "bug"
gh issue list --label "bug" --state open
gh issue view 17
gh issue close 17 --comment "Fixed in #42"
gh issue edit 17 --add-label "priority:high"

Link issues to PRs in the PR body with Closes #17; do not close issues manually when a PR will do it at merge.

gh workflow triggers and monitors Actions runs

gh workflow list
gh workflow run deploy.yml --ref main
gh run list --workflow ci.yml --limit 5
gh run view 123456789
gh run watch 123456789      # stream logs in real time
gh run rerun 123456789 --failed   # retry only failed jobs

gh run watch is useful for deploy workflows where you want to confirm success before notifying a stakeholder. gh run rerun --failed retries flaky checks without re-running jobs that already passed. See github-actions for the workflow files these commands operate on.

Use --jq for scriptable JSON output

Most gh commands accept --json to emit structured output and --jq to filter it with a jq expression in one step.

# List open PR numbers and titles
gh pr list --json number,title --jq '.[] | "\(.number): \(.title)"'
 
# Get the SHA of the last commit on main
gh api repos/:owner/:repo/commits/main --jq '.sha'
 
# Find all issues labeled "bug" opened in the last 7 days
gh issue list --label bug --json number,createdAt,title \
  --jq '[.[] | select(.createdAt > (now - 604800 | todate))]'
 
# Print the run IDs of all failed CI runs
gh run list --workflow ci.yml --json databaseId,conclusion \
  --jq '.[] | select(.conclusion=="failure") | .databaseId'

--jq eliminates a separate jq invocation and keeps the pipeline readable. For complex transformations, pipe to jq directly.

gh repo manages repository-level operations

gh repo clone org/repo
gh repo fork org/repo --clone
gh repo view --web                    # open in browser
gh repo create my-new-repo --public --clone
gh repo set-default org/repo         # set default for ambiguous commands in a monorepo checkout

gh repo set-default is useful in a checkout that contains multiple remotes. After setting the default, commands like gh pr list target the right repository without a --repo flag.

Script common multi-step operations as shell functions

# Open a draft PR for the current branch
draft-pr() {
  local title="${1:?usage: draft-pr <title>}"
  gh pr create --title "$title" --body "" --draft
}
 
# Approve and auto-merge a PR by number
ship() {
  local num="${1:?usage: ship <pr-number>}"
  gh pr review "$num" --approve
  gh pr merge "$num" --auto --squash --delete-branch
}

Store these in ~/.zshrc or ~/.bashrc. They turn a four-command sequence into a single call and reduce typos in the flags that vary by repo policy. See shell for shell function conventions.