Tools

GitHub CLI

Master the GitHub CLI (gh) for streamlined repository management, pull requests, issues, and automation

GitHub CLI: Command-Line GitHub Integration

The GitHub CLI (gh) brings GitHub functionality to your terminal, enabling seamless integration between local Git workflows and GitHub features. This comprehensive guide covers installation, configuration, and advanced usage patterns.

Installation and Setup

Installing GitHub CLI

Windows

# Using winget (Windows Package Manager)
winget install --id GitHub.cli

# Using Chocolatey
choco install gh

# Using Scoop
scoop install gh

# Manual installation
# Download from https://github.com/cli/cli/releases

macOS

# Using Homebrew (recommended)
brew install gh

# Using MacPorts
sudo port install gh

# Manual installation
# Download from https://github.com/cli/cli/releases

Linux

# Debian/Ubuntu
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/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

# Red Hat/CentOS/Fedora
sudo dnf install gh

# Arch Linux
sudo pacman -S github-cli

# Manual installation
# Download from https://github.com/cli/cli/releases

Authentication

# Login to GitHub
gh auth login

# Choose authentication method:
# 1. Login with a web browser (recommended)
# 2. Paste an authentication token

# Check authentication status
gh auth status

# Set default Git protocol
gh config set git_protocol https  # or ssh

# View current user
gh api user --jq .login

Repository Management

Repository Operations

# Clone repository
gh repo clone owner/repository
gh repo clone https://github.com/owner/repository.git

# Clone your own repositories  
gh repo clone my-repo  # Automatically uses your username

# Create new repository
gh repo create my-new-repo --public
gh repo create my-new-repo --private --description "My awesome project"

# Create repository from template
gh repo create my-project --template owner/template-repo --public

# Fork repository
gh repo fork owner/repository
gh repo fork owner/repository --clone  # Fork and clone
gh repo fork --remote-name upstream    # Set upstream remote name

Repository Information

# View repository information
gh repo view
gh repo view owner/repository
gh repo view --web  # Open in browser

# List repositories
gh repo list                    # Your repositories
gh repo list owner             # Specific user's repositories
gh repo list --public         # Only public repositories
gh repo list --private        # Only private repositories
gh repo list --fork           # Only forks
gh repo list --source         # Exclude forks

# Search repositories
gh repo search "machine learning" --language=python --stars=">1000"
gh repo search --owner=github --limit=10

Repository Settings

# Edit repository settings
gh repo edit --description "Updated description"
gh repo edit --homepage "https://myproject.com"
gh repo edit --topics "javascript,web,frontend"
gh repo edit --visibility private  # or public

# Enable/disable features
gh repo edit --enable-issues=true
gh repo edit --enable-projects=false
gh repo edit --enable-wiki=true

# Archive repository
gh repo archive owner/repository

# Delete repository (requires confirmation)
gh repo delete owner/repository --confirm

Pull Requests

Creating Pull Requests

# Create pull request from current branch
gh pr create --title "Add user authentication" --body "Implements OAuth2 login system"

# Create with interactive prompts
gh pr create

# Create draft pull request
gh pr create --draft --title "WIP: User dashboard" --body "Work in progress"

# Create pull request with reviewers and assignees
gh pr create \
  --title "Fix login bug" \
  --body "Resolves timeout issue" \
  --reviewer @teammate1,@teammate2 \
  --assignee @me \
  --label bug,priority-high

# Create pull request from different base branch
gh pr create --base develop --head feature-branch --title "Feature update"

# Use template
gh pr create --template .github/pull_request_template.md

Managing Pull Requests

# List pull requests
gh pr list                     # All open PRs
gh pr list --state all        # All PRs (open, closed, merged)
gh pr list --author @me       # Your PRs
gh pr list --assignee @me     # PRs assigned to you
gh pr list --label bug        # PRs with specific label

# View pull request details
gh pr view 123                # PR number
gh pr view --web             # Open current branch's PR in browser

# Check out pull request locally
gh pr checkout 123           # Check out PR #123
gh pr checkout https://github.com/owner/repo/pull/123

# Review pull request
gh pr review 123 --approve --body "LGTM! Great work."
gh pr review 123 --request-changes --body "Please address the security concern"
gh pr review 123 --comment --body "Consider adding tests for edge cases"

Pull Request Operations

# Merge pull request
gh pr merge 123                # Interactive merge
gh pr merge 123 --merge       # Create merge commit
gh pr merge 123 --squash      # Squash and merge
gh pr merge 123 --rebase      # Rebase and merge

# Close pull request without merging
gh pr close 123 --comment "Closing due to change in requirements"

# Reopen pull request
gh pr reopen 123

# Edit pull request
gh pr edit 123 --title "Updated title" --body "New description"
gh pr edit 123 --add-label enhancement --remove-label bug
gh pr edit 123 --add-reviewer @teammate --add-assignee @me

# Ready draft pull request
gh pr ready 123

Pull Request Status

# Check pull request status
gh pr status                  # Summary of your PRs
gh pr checks                  # Status checks for current branch
gh pr checks 123             # Status checks for specific PR

# View pull request diff
gh pr diff 123               # Show diff
gh pr diff 123 --name-only   # Show only file names

# Comments and conversations
gh pr comment 123 --body "Thanks for the review!"
gh pr view 123 --comments    # View all comments

Issues Management

Creating Issues

# Create issue
gh issue create --title "Bug: Login fails on mobile" --body "Detailed description of the bug"

# Create with interactive prompts
gh issue create

# Create with labels and assignees
gh issue create \
  --title "Feature request: Dark mode" \
  --body "Add dark mode support for better UX" \
  --label enhancement,ui \
  --assignee @designer

# Create from template
gh issue create --template .github/ISSUE_TEMPLATE/bug_report.md

Managing Issues

# List issues
gh issue list                 # Open issues
gh issue list --state all    # All issues
gh issue list --author @me   # Issues you created
gh issue list --assignee @me # Issues assigned to you
gh issue list --label bug    # Issues with specific label

# View issue details
gh issue view 456             # Issue number
gh issue view --web         # Open in browser
gh issue view 456 --comments # Include comments

# Edit issue
gh issue edit 456 --title "Updated title" --body "New description"
gh issue edit 456 --add-label bug --remove-label enhancement
gh issue edit 456 --add-assignee @developer

# Close/reopen issue
gh issue close 456 --comment "Fixed in latest release"
gh issue reopen 456

Issue Comments

# Add comment to issue
gh issue comment 456 --body "I'm working on this issue"

# View issue with comments
gh issue view 456 --comments

# React to issues/comments
gh api graphql -f query='
  mutation {
    addReaction(input: {subjectId: "ISSUE_ID", content: THUMBS_UP}) {
      reaction {
        content
      }
    }
  }
'

GitHub Actions

Workflow Management

# List workflows
gh workflow list

# View workflow runs
gh run list                   # Recent runs
gh run list --workflow=ci.yml # Specific workflow
gh run list --status=failure # Failed runs only

# View specific run
gh run view 12345            # Run ID
gh run view --log           # View logs
gh run view --web           # Open in browser

# Re-run workflow
gh run rerun 12345          # Re-run specific run
gh run rerun 12345 --failed # Re-run only failed jobs

Triggering Workflows

# Trigger workflow dispatch
gh workflow run deploy.yml

# Trigger with inputs
gh workflow run deploy.yml \
  --field environment=production \
  --field version=v1.2.3

# Enable/disable workflows
gh workflow enable ci.yml
gh workflow disable deploy.yml

Logs and Artifacts

# Download workflow logs
gh run download 12345        # Download artifacts
gh run download 12345 --name test-results  # Specific artifact

# View live logs
gh run watch 12345           # Watch running workflow

# Cancel running workflow
gh run cancel 12345

Release Management

Creating Releases

# Create release
gh release create v1.0.0 --title "Version 1.0.0" --notes "Initial release"

# Create with release notes from file
gh release create v1.0.0 --notes-file CHANGELOG.md

# Create pre-release
gh release create v2.0.0-beta --prerelease --title "Beta Release" --notes "Beta version for testing"

# Create release with assets
gh release create v1.0.0 \
  --title "Version 1.0.0" \
  --notes "Production ready release" \
  dist/app.zip dist/app.tar.gz

Managing Releases

# List releases
gh release list

# View release details
gh release view v1.0.0
gh release view latest       # Latest release
gh release view --web        # Open in browser

# Download release assets
gh release download v1.0.0   # All assets
gh release download v1.0.0 --pattern "*.zip"  # Specific pattern

# Edit release
gh release edit v1.0.0 --title "Updated title" --notes "Updated notes"

# Delete release
gh release delete v1.0.0 --yes

Release Automation

# Create release from latest tag
gh release create $(git describe --tags --abbrev=0) --generate-notes

# Upload additional assets to existing release
gh release upload v1.0.0 new-asset.zip

# Script for automated releases
#!/bin/bash
# release.sh
VERSION=$1
NOTES_FILE=${2:-CHANGELOG.md}

if [ -z "$VERSION" ]; then
    echo "Usage: ./release.sh <version> [notes-file]"
    exit 1
fi

# Create tag
git tag -a "$VERSION" -m "Release $VERSION"
git push origin "$VERSION"

# Create release
gh release create "$VERSION" \
  --title "Release $VERSION" \
  --notes-file "$NOTES_FILE" \
  dist/*

Advanced Features

GitHub API Integration

# Make API requests
gh api user                  # Get current user
gh api repos/:owner/:repo    # Get repository info
gh api /orgs/github/repos    # List organization repos

# POST requests
gh api repos/:owner/:repo/issues \
  --field title="API created issue" \
  --field body="Created via GitHub CLI"

# Use jq for JSON processing
gh api user --jq .login      # Extract username
gh api repos/:owner/:repo --jq .stargazers_count  # Get star count

# Paginate through results
gh api --paginate repos/:owner/:repo/issues --jq '.[].title'

Aliases and Shortcuts

# Create aliases
gh alias set prc 'pr create --draft --title'
gh alias set prv 'pr view --web'
gh alias set issues-me 'issue list --assignee @me'

# Use aliases
gh prc "WIP: New feature"    # Creates draft PR
gh prv                       # Opens current PR in browser
gh issues-me                 # Lists your assigned issues

# List aliases
gh alias list

# Delete alias
gh alias delete prc

Configuration

# View configuration
gh config list

# Set configuration values
gh config set editor vim
gh config set git_protocol ssh
gh config set prompt enabled

# Repository-specific config
gh config set --host github.com oauth_token YOUR_TOKEN

# Reset configuration
gh config set pager cat      # Disable pager
gh config set browser firefox # Set default browser

Scripts and Automation

Bulk Operations

#!/bin/bash
# bulk-pr-operations.sh

# Approve all PRs from trusted contributor
gh pr list --author trusted-contributor --json number --jq '.[].number' | \
while read pr_number; do
    gh pr review "$pr_number" --approve --body "Auto-approved trusted contributor"
done

# Close stale PRs
gh pr list --json number,updatedAt --jq '.[] | select(.updatedAt < "2023-01-01") | .number' | \
while read pr_number; do
    gh pr close "$pr_number" --comment "Closing stale PR"
done

Repository Automation

#!/bin/bash
# setup-new-repo.sh

REPO_NAME=$1
DESCRIPTION=$2

# Create repository
gh repo create "$REPO_NAME" --public --description "$DESCRIPTION"

# Clone and setup
gh repo clone "$REPO_NAME"
cd "$REPO_NAME"

# Add initial files
echo "# $REPO_NAME" > README.md
echo "$DESCRIPTION" >> README.md

# Setup git hooks
mkdir -p .githooks
echo "#!/bin/sh\nnpm test" > .githooks/pre-commit
chmod +x .githooks/pre-commit
git config core.hooksPath .githooks

# Initial commit
git add .
git commit -m "feat: initial repository setup"
git push origin main

# Setup branch protection
gh api repos/:owner/:repo/branches/main/protection \
  --method PUT \
  --field required_status_checks='{"strict":true,"contexts":[]}' \
  --field enforce_admins=true \
  --field required_pull_request_reviews='{"required_approving_review_count":1}'

Issue Management Scripts

#!/bin/bash
# issue-management.sh

# Triage new issues
gh issue list --label "needs-triage" --json number,title | \
jq -r '.[] | "\(.number): \(.title)"' | \
while IFS=': ' read -r issue_number title; do
    echo "Triaging issue #$issue_number: $title"
    
    # Add to project board
    gh api graphql -f query="
        mutation {
            addProjectCard(input: {
                projectColumnId: \"PROJECT_COLUMN_ID\",
                contentId: \"$(gh api repos/:owner/:repo/issues/$issue_number --jq .node_id)\"
            }) {
                projectCard {
                    id
                }
            }
        }"
    
    # Remove triage label
    gh issue edit "$issue_number" --remove-label "needs-triage"
done

Integration with Git Workflows

Git and GitHub CLI Combined

# Complete feature workflow
#!/bin/bash
# feature-workflow.sh

FEATURE_NAME=$1
if [ -z "$FEATURE_NAME" ]; then
    echo "Usage: ./feature-workflow.sh <feature-name>"
    exit 1
fi

# Start feature branch
git checkout main
git pull origin main
git checkout -b "feature/$FEATURE_NAME"

# Work on feature (placeholder)
echo "# $FEATURE_NAME" > "$FEATURE_NAME.md"
git add .
git commit -m "feat: add $FEATURE_NAME"

# Push and create PR
git push -u origin "feature/$FEATURE_NAME"
gh pr create --title "feat: $FEATURE_NAME" --body "Implements $FEATURE_NAME feature"

# Get PR number for later use
PR_NUMBER=$(gh pr view --json number --jq .number)
echo "Created PR #$PR_NUMBER"

Continuous Integration

# CI status checking
#!/bin/bash
# check-ci.sh

# Wait for CI to complete
PR_NUMBER=$(gh pr view --json number --jq .number)

echo "Waiting for CI checks on PR #$PR_NUMBER..."
while true; do
    STATUS=$(gh pr checks --json state --jq '.[] | select(.state != "COMPLETED") | .state' | wc -l)
    if [ "$STATUS" -eq 0 ]; then
        echo "All checks completed!"
        break
    fi
    echo "Waiting for $STATUS checks to complete..."
    sleep 30
done

# Check if all passed
FAILED=$(gh pr checks --json conclusion --jq '.[] | select(.conclusion == "FAILURE") | .conclusion' | wc -l)
if [ "$FAILED" -eq 0 ]; then
    echo "All checks passed! ✅"
    gh pr merge --squash
else
    echo "Some checks failed! ❌"
    gh pr checks
fi

Best Practices

Efficient Workflows

# Set up useful aliases
gh alias set co 'pr checkout'
gh alias set prs 'pr status'
gh alias set rv 'pr review --approve --body "LGTM"'
gh alias set rc 'pr review --request-changes'

# Useful functions in .bashrc or .zshrc
prc() {
    # Create PR with conventional commit title
    local title="$1"
    local body="${2:-}"
    gh pr create --title "$title" --body "$body"
}

prco() {
    # Checkout PR by number or URL
    gh pr checkout "$1"
}

# Quick status check function
ghstatus() {
    echo "=== Your Pull Requests ==="
    gh pr status
    echo
    echo "=== Your Issues ==="
    gh issue list --assignee @me --limit 5
    echo
    echo "=== Recent Activity ==="
    gh api notifications | jq -r '.[0:5] | .[] | "\(.subject.title) (\(.repository.full_name))"'
}

Security Best Practices

# Use fine-grained tokens when possible
gh auth login --scopes repo,read:org

# Audit token permissions
gh auth status

# Use environment variables for tokens in scripts
export GITHUB_TOKEN="your_token_here"
gh api user --hostname github.com --header "Authorization: token $GITHUB_TOKEN"

# Rotate tokens regularly
# Generate new token in GitHub settings
gh auth login --with-token < new_token.txt

Performance Tips

# Cache API responses for repeated queries
gh config set pager cat  # Disable pager for scripts

# Use specific fields to reduce response size
gh pr list --json number,title,author --jq '.[] | "\(.number): \(.title) by \(.author.login)"'

# Limit results for large repositories
gh issue list --limit 10
gh pr list --limit 5

# Use GraphQL for complex queries
gh api graphql -f query='
  query($owner: String!, $name: String!) {
    repository(owner: $owner, name: $name) {
      issues(first: 10) {
        nodes {
          title
          author {
            login
          }
        }
      }
    }
  }
' -f owner=OWNER -f name=REPO

Troubleshooting

Common Issues

# Authentication problems
gh auth status                    # Check auth status
gh auth logout && gh auth login   # Re-authenticate

# API rate limiting
gh api rate_limit                 # Check rate limit status

# Permission errors
gh repo view --json permissions   # Check repository permissions

# Network issues
gh api --hostname github.com user # Test API connectivity

# Config issues
gh config list                    # View all config
rm ~/.config/gh/config.yml        # Reset config (last resort)

Debugging

# Enable debug output
export GH_DEBUG=1
gh pr list

# Verbose API output
export GH_DEBUG=api
gh api user

# Check version and update
gh version
gh extension upgrade --all

Next Steps

🚀 Congratulations! You now have comprehensive GitHub CLI knowledge.

Enhance your workflow:

  1. Explore Advanced Git Workflows - Integrate CLI with team processes
  2. Learn VS Code Integration - Combine with editor workflows
  3. Master Git Aliases - Create powerful command combinations

Advanced GitHub CLI Topics

  • Create custom GitHub CLI extensions
  • Integrate with CI/CD pipelines
  • Build automated issue management systems
  • Develop repository analytics dashboards
  • Create team productivity tools
  • Implement security scanning workflows