[!NOTE|label:reference:]
install
# ubuntu/debian
$ (type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
&& out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
&& cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y
# -- or --
$ version=$(curl -fsSL https://api.github.com/repos/cli/cli/releases/latest | jq -r .tag_name)
$ pkg=""gh_${version}_linux_$(pkg --print-architecture).deb""
$ curl -fsSL -O "https://github.com/cli/cli/releases/download/$(echo "${version}" | sed 's/[^0-9.]//g')/${pkg}"
$ sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq -o Dpkg::Use-Pty=0 "./${pkg}"
# yum
$ type -p yum-config-manager >/dev/null || sudo yum install yum-utils
$ sudo yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
$ sudo yum install gh
# dnf5
$ sudo dnf install dnf5-plugins
$ sudo dnf config-manager addrepo --from-repofile=https://cli.github.com/packages/rpm/gh-cli.repo
$ sudo dnf install gh --repo gh-cli
# dnf4
$ sudo dnf install 'dnf-command(config-manager)'
$ sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
$ sudo dnf install gh --repo gh-cli
auto completion
# bash
$ echo 'eval "$(gh completion --shell bash)"' >> ~/.bashrc
# zsh
$ echo 'eval "$(gh completion --shell zsh)"' >> ~/.zshrc
# fish
$ gh completion --shell fish > ~/.config/fish/completions/gh.fish
# powershell
> 'gh completion --shell powershell | Out-String | Invoke-Expression' | Out-File -Append -Encoding utf8 $PROFILE
authentication
[!TIP|label:clear environment variable]
$ unset GITHUB_TOKEN GITHUB_USER
# gh login with web
$ gh auth login --hostname github.com --git-protocol ssh --web
# token
$ gh auth login -h github.com --with-token <<< "${GH_ACCESS_TOKEN}"
# PAT
$ gh auth login --hostname github.com --git-protocol ssh
? Upload your SSH public key to your GitHub account? Skip
? How would you like to authenticate GitHub CLI? Paste an authentication token
Tip: you can generate a Personal Access Token here https://github.com/settings/tokens
The minimum required scopes are 'repo', 'read:org'.
? Paste your authentication token: ****************************************
authentication scopes
# scope: admin:public_key
$ gh auth refresh -h github.com -s admin:public_key
# scope: read:gpg_key
$ gh auth refresh -s read:gpg_key
# add authentication scopes
$ gh auth refresh --scopes <scope>
# i.e.:
$ gh auth refresh -h github.com -s admin:public_key
$ gh auth refresh -s read:gpg_key
# remove authentication scopes
$ gh auth refresh --remove-scopes <scope>
list repos and permissions
$ gh repo list "${OWNER}" --limit 10000 --json nameWithOwner,viewerPermission
# list admin only
$ gh repo list "${OWNER}" --limit 10000 --json nameWithOwner,viewerPermission \
--jq '.[] | select(.viewerPermission=="ADMIN") | .nameWithOwner'
# list all info
$ gh repo list "${OWNER}" --limit 10000 --json nameWithOwner,viewerPermission \
--jq '.[] | .viewerPermission + "\t" + .nameWithOwner'
# list with perm order
$ gh repo list "${OWNER}" --limit 10000 --json nameWithOwner,viewerPermission \
--jq 'sort_by([
-( .viewerPermission as $p | (["READ","TRIAGE","WRITE","MAINTAIN","ADMIN"] | index($p)) ),
.nameWithOwner
])
| .[]
| "\(.viewerPermission)\t\(.nameWithOwner)"' |
column -t
commits
list commit
$ gh api repos/${OWNER}/${REPO}/commits/${REVISION}
# i.e.:
$ gh api repos/${OWNER}/${REPO}/commits/${REVISION} --jq '.commit.committer'
$ gh api repos/${OWNER}/${REPO}/commits/${REVISION} \
--jq '[.sha, "\(.commit.author.name) <\(.commit.author.email)> - \(.commit.author.date)", (.commit.message | split("\n"))]'
$ gh api repos/${OWNER}/${REPO}/commits/${REVISION} \
--jq '[
"revision: \(.sha)",
"author: \(.commit.author.name) <\(.commit.author.email)> - \(.commit.author.date)",
"committer: \(.commit.committer.name) <\(.commit.committer.email)> - \(.commit.committer.date)",
{message: (.commit.message | split("\n")) }
]'
get commit created time
$ REVISION='xxx'
$ gh api repos/${OWNER}/${REPO}/events \
--jq ".[] | select(.payload.head | startswith(\"${REVISION}\")?) | [ .actor.login, .created_at ]"
# or with `jq`
$ gh api repos/${OWNER}/${REPO}/events | \
jq --arg rev "$REVISION" '.[] | select(.payload.head | startswith($rev)?) | [ .actor.login, .created_at ]'
get HEAD of branch
[!TIP]
GET /repos/{owner}/{repo}/git/refs/heads/{branch}
# i.e.:
$ gh api "repos/{owner}/{repo}/git/refs/heads/{branch}"
# or
$ gh api "repos/marslo/ibook/git/refs/heads/marslo" | jq -r .object.sha
tags
list tags
[!TIP]
GET /repos/{owner}/{repo}/git/refs/tags
$ gh api "/repos/${OWNER}/${REPO}/git/refs/tags"
# or
$ gh api "/repos/${OWNER}/${REPO}/git/refs/tags" --jq '.[] | .object.sha + " - " + .ref'
add lightweight tags
[!TIP]
POST /repos/{owner}/{repo}/git/refs -f refs=refs/tags/{TAG_NAME} -f sha="<SHASUM>"
# tag `refs/tags/<TAG_NAME>` on `${REVISION}`
$ gh api -X POST -H "Accept: application/vnd.github+json" "/repos/${OWNER}/${REPO}/git/refs" \
-f ref="refs/tags/<TAG_NAME>" \
-f sha="${REVISION}"
branch protection
[!NOTE|label:references:]
get branch protection
[!TIP|label:API]
GET /repos/{owner}/{repo}/branches/{branch}/protection
$ gh api "repos/${OWNER}/${REPO}/branches/${BRANCH}/protection"
init branch protection
$ lock=true
$ jq -n --argjson lock "${lock}" '{
required_status_checks: null,
required_pull_request_reviews: null,
restrictions: null,
enforce_admins: $lock,
lock_branch: $lock
}' |
gh api -X PUT -H "Accept: application/vnd.github+json" \
"repos/${OWNER}/${REPO}/branches/${BRANCH}/protection" --input -
update lock_branch status
[!TIP|label:jq tricy]
$ jq -n '.var1=true | .var2=false' { "var1": true, "var2": false }
$ lock=true # or false
# read current settings
$ base=$(gh api -H "Accept: application/vnd.github+json" "repos/${OWNER}/${REPO}/branches/${BRANCH}/protection")
# update lock_branch and enforce_admins only, and keep other settings unchanged ( dynamically get keys and values )
$ jq -n --argjson base "$base" --argjson lock "$lock" \
'
(
$base
| del( .url )
| with_entries(
if ( .value | type=="object" and has("enabled") )
then { key: .key, value: (.value.enabled // false) }
else .
end
)
)
| .lock_branch = $lock
| .enforce_admins = $lock
| .required_status_checks = $base.required_status_checks
| .required_pull_request_reviews = $base.required_pull_request_reviews
| .restrictions = $base.restrictions
' |
gh api -X PUT -H "Accept: application/vnd.github+json" \
"repos/${OWNER}/${REPO}/branches/${BRANCH}/protection" --input -
[!TIP|label:jq tricy] $ jq -n '{var1:true, var2:false}' { "var1": true, "var2": false }
$ lock=true # or false
# read current settings
$ base=$(gh api -H "Accept: application/vnd.github+json" "repos/${OWNER}/${REPO}/branches/${BRANCH}/protection")
# update lock_branch and enforce_admins only
$ jq -n \
--argjson base "${base}" \
--argjson lock "${lock}" \
'{
required_status_checks: $base.required_status_checks,
required_pull_request_reviews: $base.required_pull_request_reviews,
restrictions: $base.restrictions,
enforce_admins: $lock,
lock_branch: $lock,
required_linear_history: ( $base.required_linear_history.enabled // false ),
allow_force_pushes: ( $base.allow_force_pushes.enabled // false ),
allow_deletions: ( $base.allow_deletions.enabled // false ),
block_creations: ( $base.block_creations.enabled // false ),
required_conversation_resolution: ( $base.required_conversation_resolution.enabled // false ),
allow_fork_syncing: ( $base.allow_fork_syncing.enabled // false )
}' |
gh api -X PUT \
-H "Accept: application/vnd.github+json" \
"repos/${OWNER}/${REPO}/branches/${BRANCH}/protection" --input -
pr
[!TIP|label:reference:]
json field mapping
[!NOTE|label:references:]
gh api:
- template:
template='"#\(.number) - \(.title)\tAuthor: \(.user.login)\nCreated: \(.created_at)\nUpdated: \(.updated_at)\n\n\(.body)"'- example:
gh api 'repos/:owner/:repo/pulls' | jq -r ".[] | ${template}"orgh api repos/${OWNER}/${REPO}/pulls --jq ".[] | ${template}"gh pr list --json:
- template:
template=template='"#\(.number) - \(.title)\tAuthor: \(.author.login)\nCreated: \(.createdAt)\nUpdated: \(.updatedAt)\n\n\(.body)"'- example:
gh pr list -R ${OWNER}/${REPO} --json 'number,title,author,createdAt,updatedAt,body' --jq ".[] | ${template}"
gh api |
gh pr list --json |
|---|---|
number |
number |
title |
title |
body |
body |
state |
state |
user.login |
author.login |
created_at |
createdAt |
updated_at |
updatedAt |
closed_at |
closedAt |
merged_at |
mergedAt |
html_url |
url |
head.ref |
headRefName |
base.ref |
baseRefName |
draft |
isDraft |
labels[].name |
labels[].name |
assignees[].login |
assignees[].login |
create pr
# .. modify files ..
# create branch and push
$ git commit -am '<COMMENTS HERE>'
$ git push origin HEAD:refs/heads/<NEW_BRANCH_NAME>
# create pr via cli
$ gh pr create \
--base <MAIN_BRANCH> \ # the main branch ( target branch )
--head <NEW_BRANCH_NAME> \ # the HEAD of pr
--title "<the title>" \ # the title
--body "<the body>"
comment on pr
$ gh pr review <PR_NUMBER> --comment -b "<the comment>"
# i.e.:
$ gh pr review 4 --comment -b "interesting"
edit pr
$ gh pr edit <PR_NUMBER> --add-label "<LABEL>"
$ gh pr edit <PR_NUMBER> --remove-label "<LABEL>"
# i.e.:
$ gh pr edit 5 --add-label 'sandbox'
merge pr
[!NOTE|label:options:]
- merge methods:
mergesquashrebase--delete-branch: delete the head branch after merge--admin: merge as admin ( bypassing branch protection rules )
$ gh pr merge <PR_NUMBER> --<merge_method> --delete-branch
# i.e.:
$ gh pr merge 4 --squash --delete-branch
list pr
[!NOTE|label:options:]
--state: open, closed, merged, all--json: specify the fields to output in json format--jq: filter the json output with jq
# --limit : number of PR to fetch
$ gh pr list -R ${OWNER}/${REPO} --state merged --limit 30 \
--json number,title,createdAt,mergedAt \
--jq '.[] | "PR #\(.number) | createAt: \(.createdAt) | mergeAt \(.mergedAt)"'
# filter by date
$ gh pr list -R ${OWNER}/${REPO} --state merged \
--json number,title,createdAt,mergedAt \
--jq '.[] | select(.mergedAt | startswith("2026-02-17")) |
[
"PR : #\(.number)",
"createAt: \(.createdAt)",
"mergeAt: \(.mergedAt)"
] | join("\n")'
''
# with more info
$ gh pr list -R ${OWNER}/${REPO} --state merged \
--json number,title,url,createdAt,mergedAt,author,mergedBy,autoMergeRequest \
--jq '
.[] | select( .mergedAt | startswith("2026-02-17") ) |
[
"PR : #\(.number) - \(.title)",
"URL : \(.url)",
"Author : \(.author.login)",
"MergedBy : \(.mergedBy.login // "No Merged")",
"CreateAt : \(.createdAt) UTC, \(.createdAt | fromdateiso8601 | localtime | strftime("%Y-%m-%d %H:%M:%S")) PST",
"MergeAt : \(.mergedAt) UTC, \(.mergedAt | fromdateiso8601 | localtime | strftime("%Y-%m-%d %H:%M:%S")) PST",
"AutoMerge : \(.autoMergeRequest.mergeMethod // "Manual")",
"---"
] | join("\n")
'
list PR info
$ gh api repos/${OWNER}/${REPO}/pulls/${PR_NUMBER} \
--jq '{
"author": .user.login,
"mergeBy": ( if .merged_by then .merged_by.login else "No Merged" end ),
"isAutoMerge": ( if .auto_merge != null then "Yes" else "No" end ),
"mergeMethod": ( if .auto_merge != null then .auto_merge.merge_method else "manual" end )
}'
# or
$ gh api repos/${OWNER}/${REPO}/pulls/${PR_NUMBER} \
--jq '{
"author": .user.login,
"mergeBy": (.merged_by.login // "No Merged"),
"isAutoMerge": (.auto_merge != null),
"mergeMethod": (.auto_merge.merge_method // "Manual")
}'
get HEAD of PR
$ gh pr view ${PR_ID} --json headRefOid -q .headRefOid
issues
[!NOTE|label:reference:]
list issues
$ gh issue list
# view issue
$ gh issue view 1
create issue
[!NOTE|label:command:]
gh issue create: create issue via command linegh issue new: create issue via command line
$ gh issue create --title "<the title>" --body "<the body>"
comments on issue
$ gh issue comment <ISSUE_NUMBER> --body "<the comment>"
# i.e.:
$ gh issue comment 2 --body 'comment from gh as well'
checkers
list check-runs status
# list all checker status for PR
$ gh pr checks "${PR_ID}"
# list recent 20 `pre-commit` checker status
$ gh run list --workflow=pre-commit.yml --limit 20
# list `pre-commit` for a specific branch
$ gh run list --workflow=pre-commit.yml --branch "${BRANCH}"
list check-runs history in PR
# list recent 10 check-runs for a specific branch
$ gh run list --branch "${BRANCH}" --limit 10 --json databaseId,name,status,workflowName
# list query check-runs for a specific PR
$ gh run list --branch "${BRANCH}" --status queued --json databaseId -q '.[].databaseId'
view, cancel or rerun check-runs
# view
$ gh run view "${RUN_ID}" [--log]
# i.e.:
$ gh run view 33067779843
✓ refs/pull/169459/head CodeQL · 33067779843
Triggered via dynamic about 31 minutes ago
JOBS
✓ Analyze (javascript-typescript) in 1m1s (ID 98502075159)
✓ Analyze (python) in 1m47s (ID 98502075424)
For more information about a job, try: gh run view --job=<job-id>
View this run on GitHub: https://github.com/<OWNER>/<REPO>/actions/runs/33067779843
# cancel
$ gh run cancel "${RUN_ID}"
# force cancel
$ gh api --method POST repos/${OWNER}/${REPO}/actions/runs/${RUN_ID}/force-cancel
# force cancel all queued runs
$ gh run list --branch user/gbhatia/release-calendar-v2 --status queued --json databaseId -q '.[].databaseId' |
while read id; do
echo "force-cancelling ${id}"
gh api --method POST "repos/${OWNER}/${REPO}/actions/runs/${id}/force-cancel"
done
# rerun
$ gh run rerun "${RUN_ID}"
# jobs status in check-run
$ gh api "repos/${OWNER}/${REPO}/actions/runs/${RUN_ID}/jobs"
force set checker status
# force set `pre-commit` status to `success` for a PR, in case the ghost run is stuck
$ gh api --method POST \
"repos/${OWNER}/${REPO}/statuses/$(gh pr view "${PR_ID}" --json headRefOid -q .headRefOid)" \
-f state=success -f context=pre-commit -f description='manual: stuck ghost run'
# or set via check-runs API - requires `checks:write` permission
$ gh api --method POST \
"repos/${OWNER}/${REPO}/check-runs" \
-f name=pre-commit \
-f head_sha=${PR_HEAD_HASH} \
-f status=completed \
-f conclusion=success
get checkers version
# workflow/<name>.yml
jobs:
sync:
name: <NAME>
runs-on: ubuntu-latest
steps:
- name: checkout source
uses: actions/checkout@v6 # get version via following command
$ gh api repos/actions/checkout/releases/latest --jq '.tag_name' 2>/dev/null || echo "GH_API_FAILED"
v7.0.1
# uses: actions/setup-python@v<X>
$ gh api repos/actions/setup-python/releases/latest --jq '.tag_name' 2>/dev/null || echo "GH_API_FAILED"
v7.0.0
# uses: actions/setup-node@v<X>
$ gh api repos/actions/setup-node/releases/latest --jq '.tag_name' 2>/dev/null || echo "GH_API_FAILED"
v7.0.0
# check latest version
$ for a in actions/checkout actions/setup-python actions/setup-node actions/cache; do
latest="$(gh api "repos/$a/releases/latest" --jq '.tag_name + " (" + .published_at + ")"' 2>/dev/null)"
printf '%-24s latest=%s\n' "$a" "${latest:-<none>}"
done
actions/checkout latest=v7.0.1 (2026-07-20T15:10:05Z)
actions/setup-python latest=v7.0.0 (2026-07-20T03:15:01Z)
actions/setup-node latest=v7.0.0 (2026-07-14T02:46:05Z)
actions/cache latest=v6.1.0 (2026-06-26T19:17:06Z)
# -- check node using version --
# $1=repo $2=ref
$ check() {
local using
using="$(gh api "repos/$1/contents/action.yml?ref=$2" --jq '.content' 2>/dev/null | base64 -d 2>/dev/null | command grep -E '^\s*using:' | head -1 | tr -d ' ')"
printf '%-24s %-6s -> %s\n' "$1" "$2" "${using:-unknown}"
}
# for current actions
$ check actions/checkout v6
actions/checkout v6 -> using:node24
$ check actions/setup-python v6
actions/setup-python v6 -> using:'node24'
$ check actions/setup-node v6
actions/setup-node v6 -> using:'node24'
$ check actions/cache v5
actions/cache v5 -> using:'node24'
# for latest actions
$ check actions/checkout v7
actions/checkout v7 -> using:node24
$ check actions/setup-python v7
actions/setup-python v7 -> using:'node24'
$ check actions/setup-node v7
actions/setup-node v7 -> using:'node24'
$ check actions/cache v6
actions/cache v6 -> using:'node24'
rulesets
[!NOTE|label:references:]
list all rulesets
[!TIP|label:URL] the web URL of rulesets: https://github.com/
/ /rules
$ gh api "repos/${OWNER}/${REPO}/rulesets"
# or: list id and name
$ gh api "repos/${OWNER}/${REPO}/rulesets" | jq -r '.[] | (.id|tostring) + ": " + .name'
7288536: BranchDeleteRule
7288533: BranchNamingRule
7288566: PRRuleSet
list ruleset with keywrods
$ keyword='ci/verified'
$ for id in $(gh api "repos/${OWNER}/${REPO}/rulesets" --jq '.[].id'); do
> gh api "repos/${OWNER}/${REPO}/rulesets/${id}" \
> | jq -r --arg id "${id}" --arg keyword "${keyword}" '
> if (tostring | contains($keyword)) then
> ($id|tostring) + ": " + .name
> else empty end
> '
> done
11286108: ProtectedBranchesDevelRelease
11286106: ProtectedBranchesMain
11286110: PRReviewRule
update ruleset
[!NOTE|label:references:]
- this is to add new branch into exclude list of ruleset
- API:
get current rulesets
[!TIP|label:API]
GET /repos/{owner}/{repo}/rulesets/{ruleset_id}$ gh api \ -H 'Accept: application/vnd.github+json' \ -H 'X-GitHub-Api-Version: 2022-11-28' \ "/repos/${OWNER}/${REPO}/rulesets/${RULESET_ID}" > ruleset.org.jsoncreate new ruleset json
$ branch='refs/heads/devel' $ jq --arg ref "${BRANCH}" '{ name, target, enforcement, bypass_actors, rules, conditions: { ref_name: { include: ( .conditions.ref_name.include // ["~ALL"] ), exclude: ( (.conditions.ref_name.exclude // []) + [$ref] | unique ) } } }' "ruleset" > "ruleset.new.json"update ruleset
[!TIP|label:API]
PUT /repos/{owner}/{repo}/rulesets/{ruleset_id}$ gh api -X PUT \ -H 'Accept: application/vnd.github+json' \ -H 'X-GitHub-Api-Version: 2022-11-28' \ "/repos/${OWNER}/${REPO}/rulesets/${RULSET_ID}" \ --input "ruleset.new.json"
rulsets update history
[!NOTE|label:references:]
rule suites
[!NOTE|label:references:]
list failure rule suites
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/${OWNER}/${REPO}/rulesets/rule-suites?ref=refs/heads/${BRANCH}&time_period=week"
# or
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/${OWNER}/${REPO}/rulesets/rule-suites?ref=refs/heads/${BRANCH}&time_period=week" \
--jq '.[] | {id, ref, pushed_at, actor_name, result}'
{
"actor_name": "username",
"id": 1445681219,
"pushed_at": "2025-09-17T16:23:14-07:00",
"ref": "refs/heads/devel",
"result": "pass"
}
{
"actor_name": "username",
"id": 1445649205,
"pushed_at": "2025-09-17T16:10:30-07:00",
"ref": "refs/heads/devel",
"result": "fail"
}
{
"actor_name": "username",
"id": 1445570037,
"pushed_at": "2025-09-17T15:44:01-07:00",
"ref": "refs/heads/devel",
"result": "fail"
}
check failure evaluations
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' "/repos/${OWNER}/${REPO}/rulesets/rule-suites/${RULE_SUITE_ID}"
# or list only failure evaluations
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/${OWNER}/${REPO}/rulesets/rule-suites/${RULE_SUITE_ID}" \
--jq '.rule_evaluations[] | select(.result=="fail")'
# or
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/${OWNER}/${REPO}/rulesets/rule-suites/${RULE_SUITE_ID}" \
--jq '{ref, result, failed_rules: (.rule_evaluations | map(select(.result=="fail")))}'
{
"details": "Cannot create ref due to creations being restricted.",
"enforcement": "active",
"result": "fail",
"rule_source": {
"id": 7288533,
"name": "BranchNamingRule",
"type": "ruleset"
},
"rule_type": "creation"
}
{
"details": "2 of 2 required status checks are expected.",
"enforcement": "active",
"result": "fail",
"rule_source": {
"id": 7288566,
"name": "PRRuleSet",
"type": "ruleset"
},
"rule_type": "required_status_checks"
}
tips
open in web
$ gh repo view --web
$ gh pr view --web
switch accounts
# switch to another account
$ gh auth switch
# check current auth status
$ gh auth status
config setup
| KEY | DESCRIPTION | OPTIONS | DEFAULT VALUE |
|---|---|---|---|
| accessible_colors | Use 4-bit color schemes for better accessibility | enabled, disabled | disabled |
| accessible_prompter | Use an accessibility-friendly prompter for input | enabled, disabled | disabled |
| browser | Web browser to open GitHub URLs | Browser command | system default |
| color_labels | Show labels using their RGB colors in terminals that support truecolor | enabled, disabled | disabled |
| editor | Text editor to use when authoring commit messages, PR descriptions, etc. | Path or name of an editor | system default |
| git_protocol | Protocol to use for Git operations (clone, push, etc.) | https, ssh | https |
| http_unix_socket | Path to a Unix socket for making HTTP connections (used in enterprise environments) | Path to socket file | (unset) |
| pager | Pager program to display long command outputs | Name of pager | system default |
| prefer_editor_prompt | Use the editor instead of inline prompts when asking for input | enabled, disabled | disabled |
| prompt | Enable or disable interactive prompts in the terminal | enabled, disabled | enabled |
| spinner | Show an animated spinner as a progress indicator | enabled, disabled | enabled |
$ gh config set git_protocol ssh
# or
$ gh config set git_protocol https --host github.com
# setup editor
$ gh config set editor vim
$ gh config set editor nvim
$ gh config set editor "code --wait"
# list config
$ gh config list
git_protocol=ssh
editor=nvim
prompt=enabled
prefer_editor_prompt=disabled
pager=
http_unix_socket=
browser=
color_labels=disabled
accessible_colors=disabled
accessible_prompter=disabled
spinner=enabled
alias
create alias
$ gh alias set bugs 'issue list --label="bugs"'list alias
$ gh alias list as: auth switch bugs: issue list --label="bugs" co: pr checkout me: api user --jq ".login" merge-clean: '!gh pr merge "$1" --squash --delete-branch' myissues: issue list --author "@me" --state open open: repo view --web propen: pr view --web repopath: repo view --json nameWithOwner -q .nameWithOwner
list ssh-key
$ gh ssh-key list
TITLE ID KEY TYPE ADDED
marslo@sample 125897633 ssh-ed25519 AAAAC3Nz...luNwnWMQR+wMad11Dpiw authentication about 2 months ago