Advanced GitHub CLI Tips: Scripts, Authentication, and AliasesThe GitHub CLI (gh) brings GitHub’s features to your terminal, allowing you to create issues, review pull requests, manage releases, and interact with GitHub Actions without leaving the command line. For many developers, the real productivity gains come from treating gh as a programmable tool: scripting repeated tasks, automating authentication flows in CI, and creating aliases that surface complex operations as single, memorable commands. This article covers advanced techniques and practical examples for scripting, secure authentication, and crafting powerful aliases to streamline your workflow.
Why go beyond basic gh usage?
Basic gh commands are great for occasional tasks, but repetitive workflows and cross-environment automation benefit from:
- Reduced context switching between terminal and browser.
- Consistent, auditable scripts for team operations.
- Secure, CI-friendly authentication methods.
- Short, discoverable aliases that encapsulate complexity.
Scripts: Automating GitHub tasks
Scripting with gh lets you orchestrate multi-step operations — like opening a release, creating branches, running queries, or batching issue management — reliably and repeatably. Below are patterns and examples in Bash, PowerShell, and Node.js.
Best practices for scripting
- Use non-interactive flags (e.g., –json, –jq, –template) to parse output reliably.
- Prefer JSON output and parse with jq (Unix), ConvertFrom-Json (PowerShell), or native parsers in Node/Python.
- Check exit codes and handle errors explicitly.
- Avoid embedding long-lived tokens in scripts; use session-based authentication or environment variables injected securely by your CI/CD.
- Rate-limit awareness: batch operations and include small delays if processing many resources.
Example: Create a release and upload assets (Bash)
#!/usr/bin/env bash set -euo pipefail REPO="owner/repo" TAG="$1" TITLE="${2:-Release $TAG}" BODY_FILE="${3:-release-notes.md}" ASSETS_DIR="${4:-dist}" # Create or update tag gh release create "$TAG" -t "$TITLE" -F "$BODY_FILE" --repo "$REPO" || true # Upload assets for f in "$ASSETS_DIR"/*; do [ -f "$f" ] || continue gh release upload "$TAG" "$f" --repo "$REPO" || echo "Failed to upload $f" done
Notes:
- Use set -euo pipefail for safer scripts.
- The script attempts to create a release and uploads assets; adjust behavior (overwrite checks, retries) for production.
Example: List stale issues and add a label (Bash + jq)
#!/usr/bin/env bash set -euo pipefail REPO="owner/repo" STALE_DAYS=90 LABEL="stale" gh issue list --repo "$REPO" --state open --json number,updatedAt | jq -r --argjson days "$STALE_DAYS" '.[] | select((now - ( .updatedAt | fromdateiso8601)) > ($days*86400)) | .number' | while read -r num; do gh issue edit "$num" --add-label "$LABEL" --repo "$REPO" done
Node.js example: Create issues from CSV
// npm install csv-parse node-fetch const fs = require('fs'); const parse = require('csv-parse/lib/sync'); const {execSync} = require('child_process'); const csv = fs.readFileSync('issues.csv', 'utf8'); const records = parse(csv, {columns: true, skip_empty_lines: true}); for (const row of records) { const title = row.title; const body = row.body || ''; const cmd = `gh issue create --title ${JSON.stringify(title)} --body ${JSON.stringify(body)}`; console.log('Running:', cmd); execSync(cmd, {stdio: 'inherit'}); }
Authentication: Secure, CI-friendly approaches
Authentication is central for automation. gh supports several methods; choosing the right one depends on environment, security needs, and tooling.
Local developer machines
- Use gh auth login to authenticate interactively.
- For scripted local flows, prefer device authorization (gh auth login –web) or use a personal access token (PAT) stored in your OS keychain (not plain files).
CI/CD systems
- Use GitHub Actions native authentication via the GITHUB_TOKEN secret; many gh commands work out of the box in Actions when GITHUB_TOKEN is present.
- For other CI systems (CircleCI, GitLab CI, Jenkins):
- Create a short-lived GitHub App or a fine-scoped PAT.
- Inject the token into CI as an environment variable (e.g., GH_TOKEN).
- Authenticate non-interactively in CI: gh auth login –with-token < <(echo “$GH_TOKEN”)
- Prefer GitHub App installations for finer permissions and auditability when you need organization-level automation.
Example GitLab CI snippet:
script: - echo "$GH_TOKEN" | gh auth login --with-token - gh pr create --title "CI build" --body "Automated PR" --base main
Managing scopes and least privilege
- Limit tokens to specific scopes needed (repo, workflow, issues).
- Rotate tokens regularly and revoke unused tokens.
- For organization-level automation, use GitHub Apps with granular permissions.
Aliases: Shortcuts that encapsulate complexity
gh supports aliases via gh alias set. Aliases can call multiple gh commands, shell out to scripts, or accept parameters. They let you expose complex workflows as ergonomic single-line commands.
Creating simple aliases
- One-line alias example: gh alias set wip ‘issue create –label wip –assignee @me’
- Use placeholders: gh alias set pr-draft ‘pr create –draft –title “\(1" –body "\)2”’
Note: Quotes and parameter handling can be tricky; test aliases thoroughly.
Advanced alias patterns
- Chain commands and use shell execution by prefixing with !: gh alias set rc ‘!f() { git checkout -b release/\(1 && gh pr create –fill –base main –head release/\)1; }; f’
- Use aliases to surface organization-specific policies (labels, templates).
- Keep aliases in a shared dotfiles repo or distribute via a script for team consistency.
Example alias library
Alias | What it does |
---|---|
pr-draft | Create a draft pull request from current branch with a template |
release | Tag, create release, and upload built assets |
stale-label | Detect stale issues and add a “stale” label |
Combining scripts, auth, and aliases: Practical workflows
- Automated release pipeline (CI):
- CI builds artifacts, creates a draft release via gh (authenticated with GH_TOKEN), uploads assets, and optionally publishes after tests pass.
- Team onboarding alias bundle:
- Provide a setup script that installs gh, authenticates via device flow, and adds a set of team aliases and templates.
- Daily triage helper:
- Alias that runs a script to list PRs needing review, assigns reviewers, and posts a standard comment.
Example: release automation (Bash, CI):
# authenticate echo "$GH_TOKEN" | gh auth login --with-token # build ./build.sh # create release TAG="v$(date +%Y%m%d%H%M)" gh release create "$TAG" -t "Release $TAG" -F CHANGELOG.md # upload for f in dist/*; do gh release upload "$TAG" "$f"; done # optionally publish gh release edit "$TAG" --draft=false
Troubleshooting & tips
- gh api is your escape hatch: call REST endpoints directly when a command lacks an option.
- Use –json with –jq to avoid brittle text parsing.
- Inspect alias definitions: gh alias list –format json | jq .
- For scripts in cross-platform environments, prefer Node/Python over Bash if Windows support is needed.
- Monitor rate limits: gh api rate_limit or check headers when using gh api directly.
Security checklist for automation
- Store tokens in secret managers (GitHub Secrets, Vault, CI provider secrets).
- Use minimal scopes and rotate credentials.
- Use GitHub Apps where possible for organization automation.
- Log only necessary information; avoid printing tokens or PII.
- Limit who can modify automation scripts and CI jobs.
Further reading and resources
- gh help and gh
–help for command-specific options. - gh api for custom REST interactions.
- GitHub Apps docs for advanced authentication and permissions.
- jq, yq, and common scripting references for parsing JSON/YAML.
Advanced usage of GitHub CLI turns repetitive GitHub interactions into reliable, repeatable automation. Scripts provide orchestration, secure authentication enables safe CI/CD, and aliases surface complex behaviors as simple commands—together they make gh a force multiplier for developer productivity.
Leave a Reply