GitHub CLI — The Deployment That Succeeded via Wrong Workflow
A developer used the GitHub web UI to trigger a workflow.
20+ years shipping production infrastructure and CI/CD at scale. Notes here come from systems that actually shipped.
- ✓Git installed (v2.30+), GitHub CLI (gh v2.0+), a GitHub account with repository permissions, basic familiarity with Git commands (clone, commit, push), and terminal proficiency.
Install: brew install gh or apt install gh. Authenticate: gh auth login. Key commands: gh pr create, gh pr review, gh run list, gh issue create, gh repo clone.
GitHub CLI is the remote control for GitHub. Instead of clicking buttons on a website, you type commands in your terminal. Create a PR without opening a browser. Merge without leaving the editor. Run a deploy workflow with a single command. It's faster, scriptable, and harder to misclick than the web UI.
The GitHub web UI is designed for casual use. For daily operations — creating PRs, reviewing code, running workflows, managing issues — the CLI is faster and safer. A single gh pr create --fill creates a PR from your current branch without touching the mouse. gh workflow run deploy.yml --ref main triggers a deployment with a specific ref — no risk of clicking the wrong button. This guide covers the essential gh commands, the incident where web UI clicking triggered the wrong workflow, and how to script common operations.
Why GitHub CLI?
GitHub CLI (gh) replaces context-switching between terminal and browser. For DevOps engineers, staying in the terminal means faster workflows, easier scripting, and fewer distractions. gh supports authentication, repo management, issues, PRs, actions, and more. It's not a toy—it's a production tool. If you're still clicking through the GitHub UI for routine tasks, you're wasting time. Install gh, authenticate, and never open a browser for repo management again.
gh auth login before anything else. It supports HTTPS, SSH, and token-based auth. For CI/CD, use GH_TOKEN env var.gh auth status.Creating Repositories from the Terminal
Creating a repo via UI is slow. With gh, you can create a repo, initialize it, and push code in seconds. Use gh repo create with flags for visibility, license, and gitignore. For teams, set defaults in ~/.config/gh/config.yml. This is especially useful for bootstrapping microservices or spinning up ephemeral repos for experiments. Avoid the trap of creating repos manually—automate it.
gh config set -h github.com visibility public to avoid typing flags every time.gh repo create in our service scaffolding tool. One misstep: forgetting --push flag—always verify remote is set.gh repo create and avoid UI overhead.Cloning and Forking Repositories
Cloning a repo is basic, but gh adds convenience: gh repo clone uses the authenticated user by default, supports SSH, and can clone from any org. Forking is a one-liner: gh repo fork. This is critical for open-source contributions or internal forks. gh also sets up the upstream remote automatically. Avoid manual git remote add—let gh handle it.
gh config set git_protocol ssh for a seamless experience.gh repo clone with deploy keys. A common failure: missing SSH keys in the runner—always test clone step first.Managing Repository Settings
Repository settings like description, homepage, topics, and visibility are configurable via gh. Use gh repo edit to update multiple fields. This is essential for automation: when spinning up repos, enforce naming conventions and metadata. You can also enable/disable issues, wiki, and projects. Avoid manual UI edits—script them.
gh repo list to bulk edit repos. For example, add a topic to all repos in an org.gh repo edit --visibility private.gh repo edit to enforce consistency.Listing and Searching Repositories
Finding repos in large orgs is painful. gh repo list filters by owner, language, topic, and visibility. Use --json for machine-readable output. This is invaluable for audits, reporting, or feeding into other tools. Combine with jq for complex queries. Avoid scrolling through the UI—use the terminal.
--limit to control output. For all repos, loop with --page flag. Default limit is 30.gh repo list --json name,visibility to detect unintended public repos. It saved us twice.gh repo list filters.Deleting and Archiving Repositories
Cleanup is part of lifecycle management. gh repo delete removes a repo permanently (requires confirmation). gh repo archive marks it read-only. Use these in automation for ephemeral environments or stale projects. Be careful: deletion is irreversible. Always archive before delete in production workflows.
--yes only in scripts after careful checks.Working with Pull Requests and Issues
gh isn't just for repo management—it handles PRs and issues too. Create, list, review, and merge PRs without leaving the terminal. This speeds up code review workflows. For DevOps, automating PR creation for dependency updates or release branches is a game-changer. Use gh pr create with templates and labels.
gh pr create --fill to auto-fill from commit messages. For complex PRs, use --template with a custom file.gh pr create in CI. One failure: missing labels caused skipped CI checks. Always include required labels.Automating with GitHub Actions and gh
gh integrates seamlessly with GitHub Actions. Use gh workflow run to trigger workflows, gh run list to check status, and gh run watch to monitor in real-time. This enables complex automation: e.g., trigger a deployment workflow after a PR merge. Avoid polling the API—use gh's built-in commands.
workflow_dispatch event with inputs. Use --field to pass parameters.gh run watch in CI to block until deployment completes. A timeout caused a false positive—always set a timeout in your script.Scripting and CI/CD Integration
gh is designed for scripting. Use --json and --jq to parse output in shell scripts. For CI/CD, set GH_TOKEN environment variable for authentication. Common patterns: create release, upload assets, manage environments. Avoid brittle parsing of human-readable output—always use --json.
gh auth token to get the current token securely.gh release list output with awk—it broke when GitHub changed the format. Now we always use --json.--json and --jq for reliable automation.Troubleshooting Common Issues
Even with gh, things go wrong. Common issues: authentication failures, rate limiting, and permission errors. Use gh auth status to verify auth. Check rate limits with gh api rate_limit. For permission issues, verify your token scopes. Always test commands in a dry-run manner first. Avoid assuming everything works—build in error handling.
gh auth status as a first step and alert on failure.gh auth status and gh api rate_limit to diagnose issues quickly.The 'Run Workflow' Button That Deployed Staging to Production
gh run list --workflow=deploy.yml then gh run cancel <id>. 2. Updated the deploy workflow to require a confirmation input: workflow_dispatch: inputs: confirm: description: 'Type PRODUCTION to confirm'. 3. Switched team to CLI-only deploys: gh workflow run deploy.yml --ref main -f env=production. 4. Added environment protection rules on GitHub requiring manual approval for production deployments.- GitHub web UI makes it easy to click the wrong workflow.
- Use CLI for critical operations — it forces explicit parameters.
- Add confirmation inputs to workflow_dispatch workflows.
- Require environment protection rules for production deployments.
gh pr create --fill — auto-fills title and body from commitsgh pr review <number> --approve or --request-changesgh workflow run deploy.yml --ref main — specify exact branchgh repo clone owner/repo| File | Command / Code | Purpose |
|---|---|---|
| install-gh.sh | brew install gh | Why GitHub CLI? |
| create-repo.sh | gh repo create my-new-project --public --add-readme --license mit --gitignore No... | Creating Repositories from the Terminal |
| clone-fork.sh | gh repo clone cli/cli | Cloning and Forking Repositories |
| edit-repo.sh | gh repo edit my-repo --description "A microservice for user auth" --homepage "ht... | Managing Repository Settings |
| list-repos.sh | gh repo list your-org --visibility public --language go --limit 100 | Listing and Searching Repositories |
| delete-archive.sh | gh repo archive your-org/stale-project | Deleting and Archiving Repositories |
| pr-workflow.sh | gh pr create --title "Update dependencies" --body "Automated dependency update" ... | Working with Pull Requests and Issues |
| actions-gh.sh | gh workflow run deploy.yml --ref main --field environment=staging | Automating with GitHub Actions and gh |
| ci-script.sh | VERSION="v1.0.0" | Scripting and CI/CD Integration |
| troubleshoot.sh | gh auth status | Troubleshooting Common Issues |
Key takeaways
gh pr create --fill for auto-filled PRsgh workflow run with explicit parameters for production deploysFrequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Notes here come from systems that actually shipped.
That's Git. Mark it forged?
3 min read · try the examples if you haven't