---
title: "GitHub CLI (gh) Cheatsheet"
slug: "gh-cli"
category: "cheatsheets"
tags: ["cheatsheets", "gh", "github", "cli", "reference", "devops"]
status: "stable"
last_updated: 2026-05-14
summary: "gh pr/issue/repo/workflow commands with auth, common API patterns, and --jq scripting for automating GitHub workflows from the terminal."
related:
  [
    "[[tooling/github]]",
    "[[cheatsheets/git-commands]]",
    "[[cheatsheets/jq-syntax]]",
    "[[cheatsheets/curl-flags]]",
    "[[cheatsheets/bash-one-liners]]",
    "[[cheatsheets/index|Cheatsheets]]",
  ]
---

## 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 [[cheatsheets/jq-syntax]] and [[cheatsheets/bash-one-liners]]. All commands require authentication via `gh auth login`.

## Auth

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

| Command | What it does |
| --- | --- |
| `gh auth login` | Interactive login via browser or token. |
| `gh auth login --with-token <<< $GITHUB_TOKEN` | Login with a token from stdin; useful in CI. |
| `gh auth status` | Show current auth status and scopes. |
| `gh auth logout` | Remove stored credentials. |
| `gh auth refresh -s repo,workflow` | Request 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.

| Command | What it does |
| --- | --- |
| `gh pr create --title "feat: ..." --body "..."` | Open a PR on the current branch. |
| `gh pr create --draft` | Open a draft PR. |
| `gh pr create --base main --head feature-x` | Specify base and head branches explicitly. |
| `gh pr list` | List open PRs in the current repo. |
| `gh pr list --state all` | All PRs (open, closed, merged). |
| `gh pr view 42` | View PR #42. |
| `gh pr view --web` | Open current branch's PR in the browser. |
| `gh pr checkout 42` | Check out a PR branch locally. |
| `gh pr merge 42 --squash --delete-branch` | Squash-merge and delete the branch. |
| `gh pr review --approve` | Approve the current PR. |
| `gh pr review --request-changes -b "Needs tests."` | Request changes. |
| `gh pr close 42` | Close without merging. |
| `gh pr diff` | Show the diff for the current PR. |
| `gh pr status` | Summary of open, requested, and authored PRs. |

## Issues

| Command | What it does |
| --- | --- |
| `gh issue create --title "Bug: ..."` | Create an issue interactively. |
| `gh issue create --title "Bug" --body "Steps..." --label bug` | Create with a label. |
| `gh issue list` | List open issues. |
| `gh issue list --label bug --assignee @me` | Filter by label and assignee. |
| `gh issue view 10` | View 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

| Command | What it does |
| --- | --- |
| `gh repo clone org/repo` | Clone a repo. |
| `gh repo create my-app --public --clone` | Create and clone a new repo. |
| `gh repo fork` | Fork the current repo. |
| `gh repo view --web` | Open repo in browser. |
| `gh workflow list` | List workflows. |
| `gh workflow run ci.yml` | Trigger a workflow manually. |
| `gh run list` | List recent workflow runs. |
| `gh run view 123456789` | View a specific run. |
| `gh run watch` | Stream the current run's output. |
| `gh release list` | List releases. |
| `gh release create v1.2.0 --notes "Changelog..."` | Create a release. |
| `gh release upload v1.2.0 dist/app.tar.gz` | Attach 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.

| Command | What 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:
```bash
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.

## Related

- [[tooling/github]]
- [[cheatsheets/git-commands]]
- [[cheatsheets/jq-syntax]]
- [[cheatsheets/curl-flags]]
- [[cheatsheets/bash-one-liners]]
- [[cheatsheets/index|Cheatsheets]]
