ghexposes GitHub platform operations in a command-line interface.
Git already has a command line, and gh is not a replacement for it. The two cover different halves
of the boundary this pillar keeps returning to: Git manages the repository; gh manages
everything GitHub adds around it.
You commit with git. You open the pull request with gh. You push with git. You check whether CI
passed with gh. Neither replaces the other, and the split is exactly the Git/GitHub division.
Why a CLI matters more than it sounds
Section titled “Why a CLI matters more than it sounds”The obvious benefit is avoiding a context switch — no reaching for a browser to check a pull request. That is real and it is the smaller half.
The larger half is that gh makes GitHub scriptable without writing an HTTP client. It handles
authentication, pagination, error handling and response parsing, and it emits structured JSON on
request. That turns operations which would be a hundred lines of API code into one line of shell.
This is the third rung of the automation ladder from the pillar overview: the point where GitHub stops being something you operate and becomes something you program.
What this cluster covers
Section titled “What this cluster covers”Setup — installing gh on the platforms you actually use, and authenticating properly, including
multiple accounts and non-interactive use in CI.
The command families — repo, pr, issue, workflow and run. These cover the great
majority of daily use, and each lesson works through the operations worth knowing rather than
enumerating every flag.
The escape hatch — gh api, which gives you the entire REST and GraphQL surface with gh’s
authentication and pagination already handled. This is the bridge to the
API cluster.
Automation — writing shell around gh that is safe to run unattended, and then the harder
material: structured output, error handling, exit codes, and scripts that behave correctly when they
run a thousand times instead of once.
Prerequisites
Section titled “Prerequisites”| You should be able to | Covered in |
|---|---|
| Work comfortably at a shell prompt | — |
| Commit, branch and push | Git Fundamentals |
| Explain what a pull request is | Pull Requests Explained |
| Have a GitHub account with 2FA | GitHub Account Setup |
Familiarity with jq is useful for the later lessons but is taught where it is needed.
Learning objectives
Section titled “Learning objectives”By the end of this cluster you should be able to:
- Install and upgrade
ghfrom the correct source on Linux, macOS and Windows. - Authenticate for interactive use, for multiple accounts, and for CI — and explain why those need different approaches.
- Perform the common repository, pull request and Issue operations without leaving the terminal.
- Inspect and trigger workflow runs, and diagnose a failing one from the command line.
- Use
gh apifor anything the porcelain commands do not cover, including GraphQL. - Write shell automation that uses structured output, checks exit codes, and fails safely.
- Explain when to reach for
ghand when to use the API directly.
The learning path
Section titled “The learning path”- Lesson 1: 01. Install GitHub CLIInstall gh from the correct source on each platform, verify the version, enable shell completion, and avoid the packaging traps that install an outdated build.
- Lesson 2: 02. gh authLog in interactively or with a token, manage multiple accounts and hosts, choose the Git protocol, and authenticate gh safely in CI without leaking credentials.
- Lesson 3: 03. gh repoCreate, clone, fork, view, rename, sync, archive and delete GitHub repositories from the terminal with gh repo — including JSON output for scripts.
- Lesson 4: 04. gh prThe pull request lifecycle from the terminal with gh pr: create, list, check out, review, watch checks and merge — with JSON output for scripts and the flags that matter.
- Lesson 5: 05. gh issueCreate, list, view, edit, close and comment on Issues with gh — plus linked branches with gh issue develop, search qualifiers and structured output for triage.
- Lesson 6: 06. gh workflowList, view, enable, disable and trigger GitHub Actions workflows from the terminal with gh workflow — workflow_dispatch inputs, choosing a ref, and reading run results.
- Lesson 7: 07. gh runList, view, watch, rerun and cancel workflow runs, read failed job logs, download artifacts, and build CI troubleshooting into scripts with JSON output.
- Lesson 8: 08. gh apiCall any GitHub REST or GraphQL endpoint with gh api — auth handled, --paginate for every page, --slurp and --jq for filtering, and the combinations that silently return the wrong answer.
- Lesson 9: 09. Automating with BashBuild real automation around gh — exit codes, quoting, JSON with jq, loops, error handling, rate-limit awareness and idempotency — without unsafe bulk operations.
- Lesson 10: 10. GitHub CLI ScriptingStructured output, templates, environment configuration, multi-repository operations, error handling, exit codes, CI authentication and reusable functions built on gh.
How the commands are organised
Section titled “How the commands are organised”gh groups its commands, and knowing the groups makes the surface far less intimidating than a flat
list of forty verbs.
| Group | Commands | Covers |
|---|---|---|
| Core | auth, repo, pr, issue, release, org, gist, browse | Everyday collaboration |
| Actions | run, workflow, cache | CI: inspecting, triggering, debugging |
| Additional | api, label, ruleset, search, secret, variable, ssh-key, gpg-key, alias, config, extension | Configuration, policy and the raw API |
Most commands follow the same shape:
gh <noun> <verb> [target] [flags]gh pr list, gh issue create, gh repo view, gh run watch. Once you know the noun, the verbs are
guessable — and gh <noun> --help confirms them for your installed version.
Several commands infer the repository from the current directory’s Git remotes, so gh pr list inside
a checkout needs no arguments. Outside one, or when targeting somewhere else, --repo OWNER/REPO
makes it explicit. In scripts, always be explicit: a command that infers its target from the working
directory behaves differently depending on where it runs, which is exactly the kind of surprise
automation should not have.
Two things gh will not do
Section titled “Two things gh will not do”It is not a Git client. There is no gh commit, no gh push, no gh merge that operates on your
local repository. gh pr merge asks GitHub to merge; it does not run git merge. When you need to
manipulate history, branches or the working tree, that is Git’s job.
It does not replace the API for applications. gh is a tool for humans and shell scripts. It
shells out, it depends on a binary being installed at a particular version, and its interface is
tuned for interactive use. A service that needs to call GitHub should use the
API directly with a proper HTTP client.
The dividing line is roughly: if a person or a shell script is the consumer, use gh; if a program
is, use the API.
Extensions
Section titled “Extensions”gh supports extensions — third-party commands installed with gh extension install and invoked as
gh <name>. They are ordinary executables that gh discovers, and they can be written in any
language.
They are genuinely useful for team-specific workflows, and they carry the caveat that applies to any
third-party code you run with your credentials: an extension runs with your authenticated gh
session. Install them the way you would install anything else that can act as you.
The one habit that matters
Section titled “The one habit that matters”If this cluster teaches you a single thing, it should be this: never parse human-readable output.
# Fragile — breaks when a column width, colour or icon changesgh pr list | awk '{print $1}'
# Robust — a documented field, extracted structurallygh pr list --json number --jq '.[].number'gh’s default output is designed for humans: aligned columns, colour, truncation, symbols. All of
that is presentation and none of it is a contract. It changes between releases, and it changes based
on whether output is a terminal.
--json selects fields, --jq filters them, and --template formats them. Together they are the
difference between automation that survives a CLI upgrade and automation that silently produces
wrong results after one.
What gh is actually doing
Section titled “What gh is actually doing”gh is an HTTP client. Every command becomes one or more requests to GitHub’s API, authenticated
with the credential from gh auth.
Knowing that explains several behaviours that otherwise seem arbitrary:
- Commands need network access. There is no offline mode, because there is no local state to read.
- Rate limits apply. A loop over five hundred repositories is five hundred API requests.
- Some commands are slower than they look.
gh pr list --jsonwith many fields may make several requests. gh apiis not a special case. It is the same client with the curation removed.
You can watch this directly:
GH_DEBUG=api gh pr list --limit 3That prints the actual HTTP requests and responses. It is the fastest way to learn which endpoint a command uses — and therefore how to reproduce it in a language that is not shell, which is what the API cluster covers.
Configuration
Section titled “Configuration”gh keeps configuration in ~/.config/gh/ — or %APPDATA%\GitHub CLI on Windows — and exposes it
through gh config:
gh config listgh config set editor vimgh config set git_protocol sshgh config set prompt disabledprompt disabled is worth knowing for automation: it stops gh asking interactive questions and
makes it fail with a clear error instead of hanging waiting for input that will never arrive. A CI
job that mysteriously times out is often a gh command waiting at a prompt.
Aliases cover the commands you run constantly:
gh alias set prs 'pr list --author "@me"'gh alias set review 'pr list --search "review-requested:@me"'gh alias set --shell failing 'gh pr checks "$1" --json name,state --jq ".[] | select(.state==\"FAILURE\") | .name"'--shell aliases run through the shell, so they can take arguments and pipe. They are the same idea
as Git aliases, applied to the hosted half.
A note on versions and previews
Section titled “A note on versions and previews”gh releases frequently and gains commands regularly. Some ship marked (preview), which means
their flags and output can change between releases.
Two consequences worth internalising now. First, gh <command> --help on your installed version is
more authoritative than any tutorial, including this one — where a lesson and your help output
disagree, believe the help output. Second, preview commands are a poor foundation for durable
automation; for anything you intend to leave running, prefer stable commands or the API directly.
Then what?
Section titled “Then what?”The API cluster follows, and the boundary between them is worth stating.
gh is excellent for humans, shell scripts, developer workstations and CI glue. The
REST and GraphQL APIs are better when you are building an application, need control
over requests, or are writing a service rather than a script.
gh api sits deliberately between the two, and is where this cluster hands over.