Mike Barkas

Software and DevOps

Mike Barkas

Mike Barkas

Software and DevOps

GitHub from the Command Line

October 6, 2025

When working on projects, I use the terminal a lot. I write code in Vim or VS Code, commit with Git, and run builds from the shell. For a long time the one thing that pulled me out of that flow was GitHub itself. Opening a pull request, checking whether CI passed, or closing an issue all meant switching to a browser, clicking around, then coming back to the terminal.

The GitHub CLI, gh, fixes that. It brings pull requests, issues, and Actions to the command line, so I switch to the browser far less often.

Pull requests

After pushing a branch, I can open a PR without leaving the terminal:

gh pr create --fill

--fill uses my commit messages for the title and body. Add --draft if the work isn’t ready for review yet.

A few others I use every day:

gh pr status         # PRs on my branch, PRs waiting on my review
gh pr list           # open PRs in the repo
gh pr checkout 131   # check out someone else's PR locally
gh pr diff           # review the changes in the terminal
gh pr merge --squash --delete-branch

Setting the base branch

By default, gh pr create targets the repository’s default branch, usually main. On this site I work from feature branches that merge into dev, so I need a different base.

You can pass it each time with --base:

gh pr create --base dev --fill

If you don’t pass --base, gh checks the branch’s gh-merge-base setting in your Git config. If that isn’t set either, it falls back to the repository’s default branch.

You can set it once for a branch:

git config branch.118--bug-fix.gh-merge-base dev

The general form is git config branch.{current}.gh-merge-base {base}. After that, a plain gh pr create on that branch targets dev, and I don’t have to remember the flag.

Issues

I keep a to-do list in GitHub issues, so being able to work with them from the terminal is handy:

gh issue list --assignee @me
gh issue view 118
gh issue create --title "Fix build" --label bug
gh issue close 118 --comment "Fixed in #133"

GitHub Actions

This is where gh saves me the most time. Instead of refreshing the Actions tab, I watch the run from the terminal:

gh pr checks --watch        # wait for the PR's checks to finish
gh run list                 # recent workflow runs
gh run watch                # pick a run and follow it live
gh run view --log-failed    # show only the logs from failed steps
gh run rerun --failed       # rerun just the jobs that failed

gh run view --log-failed is my favorite. It goes straight to the failing step’s output instead of making me dig through every job.

Automating it with a script

Because gh is just another command, it fits into shell scripts. Here are two small scripts I keep in ~/bin.

Git treats any executable named git-something in your $PATH as a subcommand, which I covered in Git Alias with Arguments.

git start creates a branch for an issue and sets its merge base:

#!/usr/bin/env bash
# ~/bin/git-start
# Usage: git start <issue-number> [base-branch]
set -euo pipefail

issue="$1"
base="${2:-dev}"

# Build a branch name like "118--bug-fix" from the issue title
title=$(gh issue view "$issue" --json title --jq .title)
slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | cut -c1-30 | sed 's/^-//; s/-$//')
branch="${issue}--${slug}"

git fetch origin "$base"
git switch -c "$branch" "origin/$base"
git config "branch.${branch}.gh-merge-base" "$base"

echo "On $branch, PRs will target $base"

git ship pushes the branch, opens a PR if there isn’t one yet, and watches the checks:

#!/usr/bin/env bash
# ~/bin/git-ship
set -euo pipefail

git push -u origin "$(git branch --show-current)"

# Only create a PR if this branch doesn't already have one
if ! gh pr view > /dev/null 2>&1; then
  gh pr create --fill
fi

# Give GitHub a few seconds to register the workflow runs
sleep 10
gh pr checks --watch

My workflow is now git start 118, write some code, commit, and git ship. The PR targets the right branch and I can see whether CI passed without opening a browser.

If I do need the browser, gh pr view --web or gh browse opens the right page directly.

Summary

gh has many more commands and options than I covered here. gh help and gh <command> --help are worth reading. You can also call the GitHub API directly with gh api, and most commands accept --json and --jq for scripting.

You don’t need to use all of it. Learning a handful of pr, issue, and run commands lets you do the everyday GitHub tasks without leaving the command line.

Also try telling your AI tool to run your scripts.