This final chapter puts everything together with real-world automation patterns, CI/CD integration, and productivity tips.
Full Feature Development Workflow
A complete workflow from issue to merged PR, entirely from the terminal:
# 1. Find or create the issue
gh issue create --title "Add dark mode" --label enhancement --assignee @me
# 2. Create a linked development branch
gh issue develop 42 --name feature/dark-mode --base main
# 3. Make changes, commit
# ... edit code ...
git add . && git commit -m "Implement dark mode"
# 4. Create the PR (auto-pushes the branch)
gh pr create --title "Add dark mode" --body "Closes #42" --reviewer teammate
# 5. Watch CI
gh pr checks --watch
# 6. Merge when ready
gh pr merge --squash --delete-branch
# 7. Verify the issue was closed
gh issue view 42 --json state --jq '.state'Fork-Based Contribution Workflow
Contributing to an open source project:
# 1. Fork and clone in one step
gh repo fork upstream-org/project --clone
cd project
# 2. Create a feature branch
git checkout -b fix-typo
# 3. Make changes and commit
git add . && git commit -m "Fix typo in README"
# 4. Create the cross-fork PR
gh pr create --title "Fix typo in README" --body "Small typo fix"
# 5. Monitor CI checks
gh pr checks --watch
# 6. Respond to review feedback
git add . && git commit -m "Address review feedback"
git push
# 7. If the base branch has moved ahead
gh pr update-branchRelease Automation
Script a release process:
#!/bin/bash
set -e
VERSION=$1
if [ -z "$VERSION" ]; then
echo "Usage: ./release.sh v1.2.3"
exit 1
fi
# Ensure we're on main and up to date
git checkout main && git pull
# Tag
git tag "$VERSION"
git push origin "$VERSION"
# Build (hypothetical)
make build-all
# Create release with auto-generated notes
gh release create "$VERSION" \
--title "$VERSION" \
--generate-notes \
./dist/*
echo "Release $VERSION published!"
gh release view "$VERSION" --webCI/CD Integration
Using gh in GitHub Actions
name: Auto-merge Dependabot PRs
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: write
pull-requests: write
jobs:
auto-merge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- name: Enable auto-merge
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh pr merge --auto --squash "${{ github.event.pull_request.number }}" -R "${{ github.repository }}"Automated Issue Triage
name: Triage new issues
on:
issues:
types: [opened]
jobs:
triage:
runs-on: ubuntu-latest
steps:
- name: Add triage label
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh issue edit ${{ github.event.issue.number }} \
--add-label "needs-triage" \
-R "${{ github.repository }}"Scheduled Stale Issue Cleanup
name: Close stale issues
on:
schedule:
- cron: '0 9 * * 1' # Every Monday at 9am
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Close old issues
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh issue list \
--label "stale" \
--state open \
--json number \
--jq '.[].number' \
-R "${{ github.repository }}" | \
xargs -I {} gh issue close {} \
--comment "Closing as stale. Reopen if still relevant." \
--reason "not planned" \
-R "${{ github.repository }}"GitHub Enterprise Server
All gh commands work with GitHub Enterprise Server (2.20+). There are several ways to configure it.
Authenticate with Enterprise
# Interactive login
gh auth login --hostname github.mycompany.com
# Token-based login (for CI/automation)
echo $MY_ENTERPRISE_TOKEN | gh auth login --hostname github.mycompany.com --with-tokenSet a Default Host
# Environment variable (recommended for scripts)
export GH_HOST=github.mycompany.com
export GH_ENTERPRISE_TOKEN=ghp_xxxxx
# Now all commands target the enterprise instance
gh repo list my-org
gh issue list -R my-org/my-repoPer-Command Host Override
gh repo list --hostname github.mycompany.comMultiple Hosts
You can be authenticated to both github.com and an enterprise instance simultaneously. gh determines the host from:
- The
--hostnameflag (if provided) - The
GH_HOSTenvironment variable - The git remote of the current repository
- Default:
github.com
Enterprise-Specific Considerations
- Token scopes may differ on Enterprise. Verify with
gh auth status --hostname github.mycompany.com - API endpoints are auto-prefixed:
gh api repos/org/repobecomeshttps://github.mycompany.com/api/v3/repos/org/repo - Config is stored per-host in
~/.config/gh/hosts.yml
Productivity Tips
1. Set Up a Dashboard Alias
gh alias set --shell dashboard '
echo "=== My PRs ==="
gh search prs --author @me --state open --json repository,title,number --jq ".[] | \" \(.repository.nameWithOwner)#\(.number) \(.title)\""
echo ""
echo "=== Review Requests ==="
gh search prs --review-requested @me --state open --json repository,title,number --jq ".[] | \" \(.repository.nameWithOwner)#\(.number) \(.title)\""
echo ""
echo "=== My Issues ==="
gh search issues --assignee @me --state open --json repository,title,number --jq ".[] | \" \(.repository.nameWithOwner)#\(.number) \(.title)\"" | head -10
'2. Quick PR Review Cycle
gh alias set review 'pr checkout'
gh alias set approve 'pr review --approve'
gh alias set lgtm 'pr review --approve --body "LGTM!"'3. Batch Operations
# Add a label to all open issues matching a search
gh search issues "memory leak" --repo myorg/myrepo --state open --json number --jq '.[].number' | \
xargs -I {} gh issue edit {} --add-label "priority: high" -R myorg/myrepo
# Close all draft PRs older than 30 days
gh pr list --draft --json number,createdAt --jq \
'[.[] | select((.createdAt | fromdateiso8601) < (now - 2592000))] | .[].number' | \
xargs -I {} gh pr close {} --delete-branch4. Sync Multiple Forks
#!/bin/bash
for repo in project1 project2 project3; do
echo "Syncing $repo..."
gh repo sync myuser/$repo --source upstream-org/$repo
done5. Environment-Based Defaults
Add to your .bashrc / .zshrc:
# Default repo for personal projects
export GH_REPO="myuser/my-main-project"
# Preferred editor
export GH_EDITOR="code --wait"
# Better pager
export GH_PAGER="less -SRXF"
# Enable debug mode when needed
alias ghdebug="GH_DEBUG=api gh"6. Dotfile Synchronization
Keep your gh config in your dotfiles:
# Symlink config
ln -sf ~/dotfiles/gh/config.yml ~/.config/gh/config.ymlThis syncs your aliases, editor, protocol, and pager preferences across machines.
Complete Command Reference
| Command | Alias | Purpose |
|---|---|---|
gh auth | Authentication management | |
gh browse | Open pages in browser | |
gh codespace | gh cs | Cloud dev environments |
gh gist | Code snippet management | |
gh issue | Issue management | |
gh org | Organization management | |
gh pr | Pull request management | |
gh project | Project board management | |
gh release | Release management | |
gh repo | Repository management | |
gh alias | Command shortcuts | |
gh api | Raw API requests | |
gh attestation | Artifact verification | |
gh cache | Actions cache management | |
gh completion | Shell completions | |
gh config | CLI configuration | |
gh extension | gh ext | Extension management |
gh gpg-key | GPG key management | |
gh label | Label management | |
gh ruleset | Ruleset management | |
gh run | Actions run management | |
gh search | GitHub-wide search | |
gh secret | Secret management | |
gh ssh-key | SSH key management | |
gh status | Activity dashboard | |
gh variable | Variable management | |
gh workflow | Actions workflow management |
Where to Go from Here
- Official docs: cli.github.com/manual
- Source code: github.com/cli/cli
- Extensions: github.com/topics/gh-extension
- Release notes: github.com/cli/cli/releases
- File an issue: github.com/cli/cli/issues