gh 29 (github.com/cli/cli (https://github.com/cli/cli 46,430 ), MIT, written in Go) is GitHub 29 's official command-line client; it wraps the REST and GraphQL APIs, and gh api reaches any endpoint directly. Install it from the project's own apt repository, as its install guide shows (winget 26,463 install --id GitHub.cli and brew 6,457 install gh cover Windows and macOS). On this machine, which already had gh, a rerun changed nothing:
KEYRING=/etc/apt/keyrings/githubcli-archive-keyring.gpg
LIST=/etc/apt/sources.list.d/github-cli.list
sudo mkdir -p -m 755 /etc/apt/keyrings
wget -nv -O- https://cli.github.com/packages/githubcli-archive-keyring.gpg \
| sudo tee $KEYRING > /dev/null
sudo chmod go+r $KEYRING
echo "deb [arch=$(dpkg --print-architecture) signed-by=$KEYRING]" \
"https://cli.github.com/packages stable main" | sudo tee $LIST > /dev/null
sudo apt update && sudo apt install gh -yPlain gh auth login asks a few questions and signs you in through the browser with a one-time device code. On a server, pipe a token in instead, and let gh become Git 1,932 's credential helper for github.com:
gh --version
gh auth login --with-token < ~/github-token.txt
gh auth status
gh auth setup-git
git config --global --get-regexp '^credential.https://github.com'gh version 2.101.0 (2026-09-15) https://github.com/cli/cli/releases/tag/v2.101.0 github.com ✓ Logged in to github.com account binarybehemoth (/home/dev/.config/gh/hosts.yml) - Active account: true - Git operations protocol: https - Token: github_pat_*********************... credential.https://github.com.helper credential.https://github.com.helper !/usr/bin/gh auth git-credential
gh masks the token in its status. The path in parentheses matters: this WSL 6 distribution has no desktop keyring, so gh stored the token in plain text in ~/.config/gh/hosts.yml (mode 600); on a desktop it uses the system keyring instead. Delete github-token.txt once gh has it. The empty helper line resets inherited helpers. For scripts and CI, skip gh auth login and export GH_TOKEN, which gh reads on every call without storing anything; that is how the rest of this chapter runs. gh auth logout deletes the stored token.