The Pragmatic Programmer’s Guide to Github CLI

June 18, 2024
header, create a new issue in github

As an engineer, do you find yourself spending a significant amount of time navigating Github, Gitlab, or another Git provider? Whether you’re reviewing pull requests, reading through code, or submitting issues to a public repository, it can be quite the time investment. What if there was a way to streamline this process and stay focused? In this blog post, we will cover how the Github CLI can reduce the amount of time spent on the browser, where countless distractions compete for your attention. By minimizing context switching from your coding tools (terminal and IDE) to Github’s website, you can gain more time for meaningful work.

This concept is well articulated in the Pragmatic Programmer book, where Andy Hunt and Dave Thomas discuss thinking about how we work rather than just doing the work.

“Tools amplify your talent. The better your tools, and the better you know how to use them, the more productive you can be.”

Focusing on how we work can slow us down initially, but often it will provide an awareness of productivity-draining tasks. For instance, are there any manual tasks involved in your current developer workflow that are really tedious or repetitive? With a little creativity and initiative, you might be able to make it easier! By introducing CLIs, providing basic time-saving commands, and demonstrating how you can create shortcuts for your favorite commands, and save you time. If you’re already familiar with CLIs, this article will likely seem introductory. If not, I hope it brings awareness to a new type of tool that should be added to your developer toolbox.

What is a CLI?

If you’re already familiar with CLI tools, feel free to skip this section and head into Basic Commands below.

A command line interface (CLI) is textual-based software that provides a set of commands you can use from a Command Line line such as bash, PowerShell, iTerm, or XCode. Many CLIs come pre-installed with your Command Line, but other useful tools need to be installed. Some notable CLIs which you’ve likely used are git, aws, curl, grep or npm. Some are simple commands such as cd which aid in setting the “current directory” and others are a whole toolbox of helpful utilities.

Here, we will focus on the Github CLI. Installing Github CLI is easy and well documented. If you want to follow along, installation instructions can be found here. Once installed, you will also need to authenticate with Github CLI. I suggest using the gh auth login command for initial authentication, as it will allow you to easily authenticate from the website.

Basic commands and use cases

Once Github CLI has been installed, we are ready to start test-driving it to see what it can do to help us out. We will start with some simple items first.

Getting help with gh and the --help flag

help icon

The gh command is how we will access the CLI. But, how do we actually do things with gh? Any respectable CLI will provide you with guidance on how to use it if you know how to ask.

Help is typically retrieved by passing in a --help or -h flag after the CLI command. When beginning to use a CLI, it is a good idea to run —-help to see what features are available. In many situations, the CLI offers more functionality than you’d expect.

Let’s go ahead and run our first command to learn what gh prints:

$ gh --help Work seamlessly with GitHub from the command line. USAGE gh <command> <subcommand> [flags] CORE COMMANDS auth: Authenticate gh and git with GitHub browse: Open the repository in the browser codespace: Connect to and manage codespaces gist: Manage gists issue: Manage issues org: Manage organizations pr: Manage pull requests project: Work with GitHub Projects. release: Manage releases repo: Manage repositories GITHUB ACTIONS COMMANDS cache: Manage Github Actions caches run: View details about workflow runs workflow: View details about GitHub Actions workflows ALIAS COMMANDS co: Alias for "pr checkout" ADDITIONAL COMMANDS alias: Create command shortcuts api: Make an authenticated GitHub API request completion: Generate shell completion scripts config: Manage configuration for gh extension: Manage gh extensions gpg-key: Manage GPG keys label: Manage labels ruleset: View info about repo rulesets search: Search for repositories, issues, and pull requests secret: Manage GitHub secrets ssh-key: Manage SSH keys status: Print information about relevant issues, pull requests, and notifications across repositories variable: Manage GitHub Actions variables HELP TOPICS actions: Learn about working with GitHub Actions environment: Environment variables that can be used with gh exit-codes: Exit codes used by gh formatting: Formatting options for JSON data exported from gh mintty: Information about using gh with MinTTY reference: A comprehensive reference of all gh commands FLAGS --help Show help for command --version Show gh version EXAMPLES $ gh issue create $ gh repo clone cli/cli $ gh pr checkout 321 LEARN MORE Use `gh <command> <subcommand> --help` for more information about a command. Read the manual at https://cli.github.com/manual

Wow, that’s a lot of text! The output lists the different commands and flags the CLI supports. For the scope of this blog, we will cover a few of the more common commands that software engineers are likely to find useful. To get more specific help on a command, we can use the --help flag on a sub-command. For instance, if we want to learn how to use auth, we can type:

$ gh auth --help Authenticate gh and git with GitHub USAGE gh auth <command> [flags] AVAILABLE COMMANDS login: Log in to a GitHub account logout: Log out of a GitHub account refresh: Refresh stored authentication credentials setup-git: Setup git with GitHub CLI status: View authentication status switch: Switch active GitHub account token: Print the authentication token gh uses for a hostname and account INHERITED FLAGS --help Show help for command LEARN MORE Use `gh <command> <subcommand> --help` for more information about a command. Read the manual at https://cli.github.com/manual

If you’re following along, you may have already used auth to authenticate. If we want to log in for instance, we could then figure out how to do so by continuing to request help from the CLI.

In the future, if an error is returned when running a command, it will be useful to go back and pass in the help flag to make sure your usage is correct. We now know how to find information on running commands, so let’s dig in and start using that keyboard!

Cloning a Repository with gh repo clone

Although cloning repos is trivial, it is even easier from the command line if you already know the name of the repository and the owner / organization.

Let’s try and check out one of Nearform_Commerce’s most popular Open-source libraries, Victory. Since we are not the owner of the repository, we need to use the OWNER/REPO syntax for this to work correctly. If you are cloning a repository you own, the OWNER piece can be omitted.

$ gh repo clone FormidableLabs/Victory Cloning into 'victory'... remote: Enumerating objects: 73527, done. remote: Counting objects: 100% (9119/9119), done. remote: Compressing objects: 100% (2981/2981), done. remote: Total 73527 (delta 6808), reused 7814 (delta 6050), pack-reused 64408 Receiving objects: 100% (73527/73527), 58.76 MiB | 11.81 MiB/s, done. Resolving deltas: 100% (47985/47985), done.

Great that worked! The nice thing about cloning in this way is that it will use your preferred cloning method (SSH or HTTPS) which was set when authenticating. One less thing to remember and we don’t have to go searching for that Clone button on the Github repository page.

Creating a Repository with gh repo create

clone command

For testing the rest of the CLI commands, we will create a blank repository to test with. Feel free to check the --help parameters if you get stuck. The goal here is to create a repository called gh-cli-test. Note: in the output below <OWNER> will state the userid you’re currently authenticated as.

$ gh repo create gh-cli-test --public --add-readme ✓ Created repository <OWNER>/gh-cli-test on GitHub https://github.com/<OWNER>/gh-cli-test

Awesome, we created a blank repository which we can use as a sandbox for further CLI practice. Notice that we passed in the --public and --add-readme flags. Let’s clone down the repository using the gh repo clone command and then set it as our current directory.

$ gh repo clone gh-cli-test $ cd gh-cli-test

Creating an Issue using gh issue create

issue icon

Many repositories use Github issues as a way to track work that needs to be done. Before we dive into more complicated commands, let’s try this one. Our empty repository has no information other than a blank readme, so let’s create an issue for that and then fix it.

Most Github CLI commands will allow you to interactively use them if inputs aren’t provided, but for this one, we will use a couple of flags so it runs immediately. We will create an issue in our repository mentioning how the readme needs to be updated.

$ gh issue create --title "readme is empty" --label "documentation" --body "please add content to readme" Creating issue in <OWNER>/gh-cli-test https://github.com/<OWNER>/gh-cli-test/issues/2

Take note of the issue number, we will use it later.

Creating a Pull Request using gh pr create

pull request

Creating a pull request can be tedious and require a lot of clicks using the UI. That is why this is probably my favorite command. When my code is pushed and ready for a pull request, I can immediately create a pull request from the command line using the pr command.

Now that we’ve got a fresh new repo cloned and an open issue, let’s get to work resolving it. To do that, we can create a pull request with code changes to fix the issue. Let’s create a branch off of main to do our work, update the readme with some content, commit our changes, and push them up to our remote.

$ git checkout -b update-readme; $ echo "- testing out github cli" >> README.md # adds to readme file $ git commit .; $ git commit -m "updating readme"; $ git push;

Now we’ve got enough content to create a PR. We have the original code in main branch, and our updated readme in update-readme branch. We’re now ready to create a pull request. You can accept all the default options for now.

$ gh pr create --title "update readme" --body "fixes #<issue number>" Creating pull request for update-readme into main in <OWNER>/gh-cli-test https://github.com/<OWNER>/gh-cli-test/pull/2

Wow, look at that! The pull request is already created. The CLI provides you with the URL so you can copy it and share it with coworkers for reviews. Later on, I will show you how to update this flow to be even more helpful.

To close out the issue, let’s use gh pr merge command to merge it into main and resolve our issue. We will also do this interactively so we can choose our merge options thoughtfully.

$ gh pr merge Merging pull request #3 (update readme) ? What merge method would you like to use? Squash and merge ? Delete the branch locally and on GitHub? Yes ? What's next? Submit ✓ Squashed and merged pull request #3 (update readme) remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Total 3 (delta 0), reused 2 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), 970 bytes | 485.00 KiB/s, done. From https://github.com/Burnett2k/gh-cli-test * branch main -> FETCH_HEAD 1f12a8a..5790745 main -> origin/main Updating 1f12a8a..5790745 Fast-forward README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) ✓ Deleted local branch update-readme and switched to branch main ✓ Deleted remote branch update-readme

If the issue was referenced correctly in the Pull Request, you should now see that the issue is closed within Github. You’re on your way to becoming a CLI expert!

$ gh issue list no open issues in <OWNER>/gh-cli-test

Getting workflow information using gh workflow

workflow icon

Many repositories take advantage of Github actions to run workflows such as building projects, running unit tests, and deployments. Instead of constantly checking the actions tab of Github, you can use the CLI to figure out the status of workflows or pull request checks. Note: for this command, we will be using the FormidableLabs/Victory repository since our previously created repository doesn’t have any workflows.

To list all possible workflows for a repository you can use:

$ gh workflow list NAME STATE ID Chromatic active 7923605 CI active 7918779 Close inactive issues active 87107184 Issue Triage active 87107185 Release active 31132377 (END)

If you happen to create a pull request with checks on it, you can use an alternate command (gh pr checks) to get real-time feedback on how the checks are progressing. In this case, we are pulling the checks for pull request 2809 rather than the current branch. Passing in the --watch flag will leave the output in the terminal and update their progress at regular intervals.

$ gh pr checks 2809 --watch Refreshing checks status every 10 seconds. Press Ctrl+C to quit. Some checks are still pending 0 cancelled, 0 failing, 8 successful, 0 skipped, and 1 pending checks NAME DESCRIPTION ELAPSED URL ✓ Chromatic/Storybook Publish (pull_request) 2m23s https://github.com/FormidableLabs/victory/actions/runs/8015215921... ✓ Vercel Preview Comments https://vercel.com/github ✓ CI/build (pull_request) 5m2s https://github.com/FormidableLabs/victory/actions/runs/8015215920... ✓ CI/format (pull_request) 26s https://github.com/FormidableLabs/victory/actions/runs/8015215920... ✓ CI/lint (pull_request) 2m59s https://github.com/FormidableLabs/victory/actions/runs/8015215920... ✓ CI/test (pull_request) 2m54s https://github.com/FormidableLabs/victory/actions/runs/8015215920... * UI Tests 2 changes must be accepted as baselines. https://www.chromatic.com/build?appId=5b4acf7c54c0490024d5980b&nu... ✓ Storybook Publish 216 stories published. https://5b4acf7c54c0490024d5980b-jizcnjkjos.chromatic.com/ ✓ Vercel Deployment has completed https://vercel.com/formidable-labs/victory/GZFDyvZunSfzvMcAhLuLyd...

This command can be useful if you pushed up a change and want to ensure it passes all CI checks. Or need to quickly find the URL for a workflow run to check the logs on it.

While we could continue covering more basic commands, it’s time to shift gears a bit and show how we can create shortcuts for some of the commands above to make them even quicker to use. To do that, we will use a concept called aliasing.

Creating Aliases using gh alias

alias icon

Have you noticed some commands or workflows consistently need the same input and are tiresome to type out? We want to use the keyboard more, but not create repetitive strain injuries! One way to mitigate this spurious typing is by utilizing aliases to shorten the command. You can think of an alias as a shortcut or custom command which ‘wraps’ a more complicated one.

For instance, I often close out of my open pull request in the browser and get annoyed trying to find it again. Instead of searching in Chrome history, I can run a CLI command to open it back up in the browser. However, the command for that is a bit annoying to fully type.

Instead, I created an alias called viewpr which maps to that command. To set this up, use the gh alias command. The first argument is what you want to call the command (alias), and the second is the command(s) you want the alias to run. The neat thing about aliases is you can choose the name, so if you wanted to shorten it even more to vp, that’s also possible. Note: when creating aliases using this command you omit the gh portion from the full command since it is implied. Let’s set up that alias:

$ gh alias set viewpr "pr view --web" - Creating alias for viewpr: pr view --web ✓ Added alias viewpr

We can verify alias creation using gh alias list

$ gh alias list co: pr checkout viewpr: pr view --web

Try out the new alias. Note: the output below assumes there’s an open Pull Request associated to your currently checked out branch.

$ viewpr Opening github.com/FormidableLabs/victory/pull/2809 in your browser.

Neato! This is just one example of how you can create aliases for common commands. The possibilities are endless in how you can customize them.

Wrapping Up

Keep in mind we have only covered the Github CLI here. There are countless other CLIs to explore and use. For instance, Gitlab also provides a comparable CLI to Github. Any time you use a web-based SaaS, it’s worth it to see if they offer a CLI. Although there are countless CLI possibilities, sadly we cannot cover them all. In this post, we have covered common commands and empowered you to build your own time-saving commands with aliases.

If you remember to take time each day to think about how you work you’ll find these commands helpful. As authors Andy Hunt and Dave Thomas eloquently state in Pragmatic Programmer:

“Every day, work to refine the skills you have and to add new tools to your repertoire.”

Github CLI can significantly streamline your workflow by reducing time spent switching between your coding environment and Github’s website. By mastering a few key commands, you can stay focused and boost your productivity.

If you're interested in learning more about how our team implements the Github CLI, feel free to reach out commerce@nearform.com or follow us on X for more engineer insights.

Related Posts

When and Why to Use Micro Frontend Architecture

November 12, 2024
As businesses grow and their technical stacks evolve, micro frontends have emerged as a practical architectural strategy for managing complexity and improving scalability. Deciding when and why to adopt micro frontends isn't just an engineering conversation; it’s one that should involve product and business stakeholders as well. Is it the right choice for your organization? What benefits, risks, and tradeoffs should you weigh before committing?

Serverless Event-Driven APIs with AWS Kinesis

October 24, 2024
Everything that happens in an application or a software system is triggered by something. Whether it’s a user action, a sensor output, a periodic trigger, an event loop, an API call, or something else entirely — our software is governed by events. Sometimes those events are implicit, like a server that handles an HTTP request and updates a database row without ever explicitly defining it as an “entity updated” event or recording the details.

Generics in Go and Effective Abstraction

October 16, 2024
In the quest for better performance and easier concurrency, many backend server engineering teams are turning to Go to power their APIs and build tools. According to the Stack Overflow 2024 Developer Survey, Go is the 12th most popular language used extensively by professional developers — behind the heavy-hitters like JavaScript and Python, slightly ahead of Rust, and well ahead of languages like Ruby, Scala, or Elixir.