The Friction of the ‘Browser Tax’

As a developer, I’ve always hated the “browser tax.” You know the feeling: you’ve just finished a feature, you’ve committed your code, and now you have to leave your focused terminal environment, open a heavy browser tab, navigate to the PR page, and manually fill out templates. It’s a context-switch that kills momentum. This is why I shifted my entire process toward gh cli workflow automation.

The GitHub CLI (gh) isn’t just a wrapper for API calls; it’s a programmable interface that allows us to treat our project management as code. By integrating gh into shell scripts and CI/CD pipelines, I’ve managed to reduce the time spent on administrative overhead by nearly 40%.

The Challenge: Why Standard Git Isn’t Enough

Standard Git handles the versioning, but the collaboration happens on GitHub. This gap is where productivity dies. When I was managing multiple open-source projects, I found myself repeating the same sequence: check for stale issues, create a branch, push, and then manually create a PR. Using a tool like best cli tools for productivity helps, but without a dedicated GitHub interface in the terminal, you’re still tethered to the UI.

Solution Overview: The Power of gh

The gh CLI bridges the gap between your local filesystem and the GitHub cloud. The magic happens when you combine its output (which supports JSON) with other terminal power tools. For instance, combining gh with fzf command line tutorial techniques allows you to fuzzily search through your open PRs and checkout the corresponding branch in milliseconds.

Core Automation Commands

Before we dive into complex scripts, here are the primitives I use daily:

Advanced Techniques: Scripting Your Workflow

The real power of gh cli workflow automation lies in the --json flag. By outputting data in JSON format and piping it into jq, you can build highly specific triggers.

Example: The “Clean-Up” Script

I wrote a script to find all PRs that have been merged and are now stale, then automatically delete the associated branches. Here is how I implemented it:

# Find merged PRs and extract the head branch name
merged_branches=$(gh pr list --state merged --json headRefName --jq '.[].headRefName')

for branch in $merged_branches; do
  echo "Deleting merged branch: $branch"
  git push origin --delete "$branch"
done
Technical flowchart showing the data flow from gh CLI to jq for branch cleanup
Technical flowchart showing the data flow from gh CLI to jq for branch cleanup

In my experience, this prevents the “branch clutter” that usually plagues large teams. As shown in the technical diagram below, this replaces a manual 10-minute audit with a 2-second command execution.

Implementation: Creating a ‘Feature Start’ Alias

I don’t just run commands; I create aliases. In my .zshrc, I’ve implemented a function that automates the start of a new feature based on an issue number.

# Usage: start_feat 123
function start_feat() {
  local issue_num=$1
  local title=$(gh issue view $issue_num --json title -q '.title' | tr ' ' '-'))
  
  git checkout -b "feat/issue-${issue_num}-${title}"
  echo "Started work on issue #$issue_num: $title"
}

This ensures naming consistency across the team and links the branch directly to the task, removing all guesswork.

Case Study: Automating a Release Cycle

Last year, I automated the release process for a library. Instead of manual tagging, I created a workflow that:
1. Checks if all CI tests passed using gh run list.
2. Extracts the next semantic version from a file.
3. Creates a GitHub Release with a generated changelog using gh release create.

This turned a 30-minute anxious process into a single command: ./release.sh. The reliability increased because the script validates the state of the repo before proceeding.

Pitfalls to Avoid

Automation is a double-edged sword. Here are a few things I learned the hard way:

Final Verdict

Switching to a gh-centric workflow fundamentally changed how I interact with my code. It moves the “management” of the project into the same space as the “creation” of the project. If you spend more than 30 minutes a day in the GitHub UI, you are losing time that could be spent coding.