The Modern Windows Command Line

Rebecca
Programming Go on Windows
9 min readAug 1, 2022

--

A comprehensive guide to command line development on Windows in 2022

Now we’re looking powerful!

Contents

1. Windows Terminal
2. Winget Package Manager
3. PowerShell
4. Git and GitHub CLI
5. Additional customization with OhMyPosh

Introduction

Call it a flash from the past, but the majority of developers use the command-line every day along with their favorite IDE. In this article we will install and configure an opinionated set of tools enabling a modern and effective command line workflow that is thoroughly Microsoft technology centric. By the end of this guide we’ll have installed and configured the following Microsoft technologies :

  • Windows Terminal
  • Winget
  • PowerShell
  • GitHub CLI

There are certainly other terminals, shells, and package managers out there to choose from but the options presented here make the most sense for Windows developers dedicated to the platform.

1. Windows Terminal

Windows Terminal is Microsoft’s modern, feature-rich terminal emulator for command-line users. The primary function of a terminal emulator is to provide access to local and remote operating systems through a powerful, efficient, and most importantly scriptable text-base interface. Compared to Microsoft’s relatively ancient console host interface Windows Terminal is nothing short of revolutionary.

Install Windows Terminal?

If you are on Windows 11 then you are in luck as Windows Terminal is already installed on your system. If you are on Windows 10 the install is still just a click away over at the Microsoft App Store where you can download and install it directly from Microsoft.

2. Winget Package Manager

A package manager is a program you use from the command line to discover, install, and manage applications on your system.

If you are on Windows 11 (or a recent version of Windows 10) winget is already installed on your system. If you aren’t sure you can easily determine whether or not it is already part of your system by launching Windows Terminal and typing winget at the prompt.

In the unlikely event Winget is not already installed just browse on over to its release page on GitHub and download the latest .msixbundle. Be careful and make sure the version you download is marked latest release and isn’t an old or preview release.

Discover, list, and upgrade packages

We will be using Winget to install most everything from here on out so you will have at least some exposure to it by the end of this guide. That said, to get you started on your journey discovering the wonders of command line package management review the following list of commands. These cover the vast majority of a developer’s routine interaction with winget.

winget search <keyword>
searches all available packages for the specified keyword

winget list
lists all packages installed on your system and indicates for each if an upgrade is available

winget list <package>
reports the version of the specified package if it is installed on your system and indicates whether an upgrade is available

winget upgrade <package>
updates the specified package to its latest version

winget upgrade --all
upgrades all packages installed on your system

3. PowerShell

The choice of PowerShell is probably the most controversial of the lot but since we are sticking with Microsoft-centric technologies in this guide we are going to install and configure it as our default shell. Other options available include Microsoft’s Windows Subsystem for Linux (WSL) and the version of the venerable BASH shell installed along with Git. These other options all involve additional setup, however, and come with various limitations and caveats in addition to the advantages they provide in some scenarios.

Install PowerShell

An older version of PowerShell called (confusingly) Windows PowerShell is included by default with Windows but can not be upgraded or uninstalled. It is also locked-down by default as it is intended for system administration. You can use this version if you prefer but to do so and follow along with this guide you will need to loosen these restrictions by executing the command Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

To use the latest release version of PowerShell instead (recommended!) we can install it using Winget like so :

winget install Microsoft.PowerShell 

Make PowerShell the default shell

To load the latest release version of PowerShell by default and configure Windows Terminal as your default terminal application for Windows navigate to the Settings tab in Windows Terminal using the shortcut Ctrl-, and set the following values :

Close Windows Terminal by typing exit and open it again to see the result of these changes.

4. Git and GitHub

Why git?

For developers weaned on Git it is probably hard to imagine how one could develop without it. For the rest of us, especially those with deep roots in industry, Team Foundation Server and Perforce have traditionally been the version control systems of choice because of their excellent support for versioning large binary files.

Conceptually, TFS and Perforce are centralized version control systems in which source code revisions are stored on a server and all source control operations are carried out by the server process. This can make offline work and scaling to large numbers of users difficult unless additional tools and features like proxies, streams, and sandboxes are employed.

Git, on the other hand, is a distributed version control system in which all version control information for each repository also resides on every developer’s workstation. As such, Git prioritizes offline workflows, micro-commits, and other behaviors that are cumbersome to perform when using a traditional non-distributed version control system.

Although there are other significant differences like fine-grained access control to specific files and folders within repositories and the maturity of large file support (as alluded to above), Git’s unchallenged ubiquity as the version control system of choice for modern software development, not to mention its deep integration and support within all five major “big tech” companies (the so-called FAANGs), make it the obvious choice for future-facing software development workflows.

If you are new to Git, consider completing Github’s browser-based version of the ubiquitous hello world example before continuing.

Install git

As a developer, much of your interaction with Github will be via the command line where you will issue git and gh commands to accomplish various tasks. The gh command is specific to Github and requires you to authenticate with it interactively before you can use it. The git command, on the other hand, is a more general tool and will work with any properly configured Git repository or hosting service and requires minimal to no additional configuration to function.

To install Git properly we will use a pre-configured settings file and pass it to winget as an override to its default settings :

Invoke-WebRequest -Uri "https://git.io/JXGyd" -OutFile "git.inf"
winget install Git.Git --override '/SILENT /LOADINF="git.inf"'
# restart shell to reload PATH

While we’re at it let’s configure Git with our name and email address. This information will get appended to each git commit we make.

git config --global user.email "you@somedomain.com"
git config --global user.name "Your Name"

Also, even though we are on Windows our source code should be able to be processed by Linux, macOS, and BSD-based systems as well. To ensure that when we commit a file to source control the appropriate conversion takes place let’s configure git to handle the job for us :

git config --global core.autocrlf input

If you examine the custom settings file referenced above you’ll notice that we specify CRLFOption=LFOnly there as well to similarly enforce the use of the LF end-of-line character as opposed to the CRLF sequence.

Install Github CLI

To install gh, the Github CLI, issue the following command. Don’t forget that you need to restart Windows Terminal so that PowerShell will recognize the update to your path.

winget install GitHub.cli
# restart shell to reload PATH

Next, we will authenticate with Github on behalf of the gh command :

gh auth login

This command will prompt you to interact with the application via the terminal. This happens often with the gh command. We will step-through this interaction in detail to help familiarize you with the general process.

You are first asked if you want to authenticate using a standard Github account or an enterprise account. Choose Github.com using the arrow keys and then press enter.

% gh auth login
? What account do you want to log into?
> GitHub.com
GitHub Enterprise Server

Next you are asked whether you wish to use HTTPS or SSH when interacting with the remote repository. Choose SSH using the arrow keys on your keyboard and again press enter to continue.

% gh auth login
? What account do you want to log into? GitHub.com
? What is your preferred protocol for Git operations?
HTTPS
> SSH

In the next step you are asked if you would like a new SSH key pair to be created and added for you automatically. Respond with Y. You are then asked to optionally provide a passphrase.

% gh auth login
? What account do you want to log into? GitHub.com
? What is your preferred protocol for Git operations? SSH
? Generate a new SSH key to add to your GitHub account? (Y/n)
? Enter a passphrase for your new SSH key (Optional)

If you already have one or more SSH key pairs on your system you will instead be asked which to add to your Github account.

At this point gh will create a .ssh folder in the root of your %USERPROFILE% and add two new files, id_ed25519 and id_ed25519.pub The former contains your new Github SSH private key which only resides on your system and should be closely guarded. The latter contains the matching public key which is both stored locally and uploaded to Github.

“Keep it SECRET, keep it SAFE!”
Anyone with access to your Github private key can modify source code in your name!

Before the gh command can upload your public key to Github, however, we need to authenticate with Github on its behalf. When prompted how you would like to authenticate select Login with a web browser :

% gh auth login
? What account do you want to log into? GitHub.com
? What is your preferred protocol for Git operations? SSH
? Generate a new SSH key to add to your GitHub account? (Y/n)
? Enter a passphrase for your new SSH key (Optional)
? How would you like to authenticate GitHub CLI?
> Login with a web browser
Paste an authentication token

At this point Github CLI will provide you with a one-time code you need to submit to Github. Hit enter to have Github CLI open the browser for you and load the correct page. When you are done the screen should look like the following :

% gh auth login
? What account do you want to log into? GitHub.com
? What is your preferred protocol for Git operations? SSH
? Generate a new SSH key to add to your GitHub account? (Y/n)
? Enter a passphrase for your new SSH key (Optional)
? How would you like to authenticate GitHub CLI? Login with a web browser​
! First copy your one-time code: XXXX-XXXX
- Press Enter to open github.com in your browser...​
✓ Authentication complete. Press Enter to continue...
​- gh config set -h github.com git_protocol ssh
✓ Configured git protocol
✓ Logged in as ghuser

We should note that everything you can do with the gh command can also be done via Github’s website … just less efficiently!

5. Customize the command line with OhMyPosh

PowerShell’s default prompt provides very little context about the current directory such as which git branch is active, whether there are any pending changes that need to be committed, and a host of other information useful to have access to at-a-glance.

To overcome this limitation and enrich our command line experience we will install and configure OhMyPosh like so :

  1. Launch Windows Terminal
  2. Install OhMyPosh using Winget :
    winget install JanDeDobbeleer.OhMyPosh
  3. Create a default PowerShell profile :
    New-Item -Path $PROFILE -Type File -Force
  4. Configure OhMyPosh to load whenever you launch PowerShell :
    Add-Content $PROFILE "`noh-my-posh init pwsh -c $env:POSH_THEMES_PATH\pure.omp.json | Invoke-Expression"
  5. Restart Windows Terminal

Once installed and configured you will notice that the name of the current Git branch, if any, will be displayed immediately after the current path as part of your prompt. Right now there’s not much to see but we’ll explore additional features of OhMyPosh as we encounter them later in this series.

We’re ready to roll

At this point we have everything necessary to integrate the command line into our workflow. In the next section we’ll learn how to use our new command line powers within Microsoft’s Visual Studio Code IDE!

--

--