Anatomy of a Prompt (PowerShell)

First posted: 20 August 2017
Last updated: 10 March 2019

Table of Contents

History

Introduction

Whenever I post a screen shot of my PowerShell prompt, people ask me how it's put together:

ConEmu ScreenShot

There's a lot going on in this screenshot, so I'm going to put together the pieces. The information here assumes you have general familiarity with customizing your PowerShell environment (for example, editing your profile file). It also assumes you have some pre-requisites installed, like Git for Windows and Visual Studio.

You can copy/paste along as we go, but I have also provided downloadable versions at the end of the blog post.

Important Note: When saving the PowerShell files, make sure they are saved as "UTF-8 with Signature". This will ensure that PowerShell treats your file as UTF-8 and does not accidentally treat it as ANSI. Here is an example using my editor of choice, Notepad2:

Encoding in Notepad2

Fonts and Colors

On Windows, I use a console program called ConEmu. and I've chosen it because its configuration allows me to get exactly what I want, in a portable executable. (I keep most of my utilities like this in the cloud, so that I can just sync them down to a new machine with no installation.)

The most critical feature that I'm leveraging here is the ability of ConEmu to create a slightly compressed font display without needing an actual condensed font. Speaking of fonts, I use a font from the awesome Nerd Fonts project to provide several of the custom symbols in my prompt. It joins together icons from several projects (including Powerline, Font Awesome, and Octicons), and creates pre-merged versions of their font based on several free, fixed pitch fonts (my prompt is using Ubuntu Mono).

ConEmu Font Settings

I get the slightly condensed look with the "Width" setting (width of 9 against font size of 20).

Lastly, I use a custom color set (based heavily on the Ubuntu default terminal colors). The colors I've chosen for many of the prompt elements are based on the mix of these custom colors; if you choose to stick with the default color values, you may wish to adjust some of my color choices for better legibility.

ConEmu Colors

Important note: Because there are use of Unicode characters in many of the samples, please make sure your text editor is capable of editing files in UTF-8 mode. If you see ? characters where you expect to see custom symbols, make sure that your file is in UTF-8 mode, and that your text editor is using your custom Nerd Font.

posh-git

The blue portion of the prompt is Git project information, powered by posh-git. This is a PowerShell plugin that supports printing information about the Git repository referenced by the current directory. The great thing about posh-git is that it comes with a tremendous amount of flexibility when formatting the prompt output. Here is what it looks like by default:

Default posh-git Prompt

You configure the prompt by overriding the default values in a configuration object that posh-git sets. Here are the overrides which convert that default prompt into the blue prompt you've seen above:

To use these overrides, place these lines after the Import-Module statement that posh-git added to your PowerShell profile. Once you restart your shell, you should see your new customizations in place (don't worry about the path; we'll be re-styling that later on):

post-git Customized Prompt

If you want to customize the symbols used in the prompt, the easiest way to find them is by using the Character Map application built into Windows. Just select the Nerd Font you're using while browsing characters, and you can copy them directly from this app into your profile:

Windows Character Map application

prompt Function

When PowerShell wants to display your prompt, it executes the command prompt. By default, this command is provided by a "PowerShell function". Adding this to your Profile will override the default prompt with our custom prompt (I'll break down each meaningful section afterward):

Let's break this down into the individual parts of the prompt.

Showing errors Error display

The first section of the prompt (red background) is where we optionally show errors that have occurred:

There are two categories of errors that might happen in PowerShell: internal errors (for example, you try to run a command that doesn't exit), and external errors (when you run an executable, and the return code is something other than zero). We have separate code for each kind. We reset the $Error array and the $LASTEXITCODE values here when we're done.

Showing custom prompt environments Custom prompt environment

Next you'll see us printing out custom prompt environments:

This is used by things like the vs2017.ps1 script that we will discuss later. The assumption is that any text you place into $PromptEnvironment will be shown here as-is (in White on DarkMagenta).

Showing the Kubernetes (kubectl) current context Kubernetes (kubectl) context

The gray box in my prompt shows your current kubectl context:

Showing Azure CLI current subscription Azure CLI current subscription

I find it useful to know which Azure subscription is my current subscription when running commands via az, so I print out the name of the subscription in my prompt:

One thing to note here is that I used sed for the string parsing, mostly because I wrote this parser for Bash on Linux before I wrote it for PowerShell. There is no built-in way to parse INI files (in either shell), so sed ends up filling this role. You'll need a version of Gnu sed somewhere on your path; I pull mine from the Git for Windows installation (by putting ...\usr\bin folder on my PATH).

Showing Git information Git information

As we previously saw, posh-git does all the heavy lifting for figuring out the current Git status: it shows the current branch name as well as the state of the filesystem (modified files, un-tracked files, etc.). All we need to do is print the info:

Showing current path Current path

The last element of the prompt is the current directory:

The location is normalized to replace your home folder with

Printing directory stack depth

At the end of the prompt, we print one cyan + symbol for every level deep you are in the directory stack (that is, for every un-popped directory you pushed using Push-Location, aka pushd):

Conditional prompt text & color

I like to know when I'm running as admin or not, and whether my current window is using PowerShell or PowerShell Core.

There is a little bit of Windows vs. Unix-ism here to determine whether you're an admin. On Windows, we ask the current user identity whether it's in the Administrators group or not; on Unix-like environments, we test the user ID against 0 (meaning, you're root). Then when we print the prompt, we use green for (safe) non-admin users, and red for (unsafe) administrators.

The prompt text itself is either PS> for PowerShell, or pwsh> for PowerShell Core (regardless of the OS that you're running on).

Prompt Environment

The final piece of the puzzle is printing the prompt environment. I have several commands which place the shell into a special mode to be used for specific environments. For example, I have a command called vs2017 which adds Visual Studio environment variables just as though you'd run the Visual Studio Command Prompt, and then adds that information to the printed prompt environment.

I use a single script which can be used for any version of Visual Studio 2017 (or later):

And then I use a few simpler commands to invoke it:

vs.ps1 is a little complex because Visual Studio 2017+ now allows you to install multiple editions side by side. It looks to see which edition you have installed and uses the VsDevCmd.bat to get the updated environment variables. If you have multiple editions installed, you can use the -edition switch to specify which environment you want.

The final line of the script sets the global PromptEnvironment variable, which we use in our custom prompt function (as shown previously).

Downloadable Files

You can download profile.ps1 and vs.ps1 (and friends) from my GitHub gist.

Conclusion

I hope this quick tour through my custom prompt inspires you to make customizations of your own, based on your needs. Being able to carefully craft your prompt to be succinct and quickly glanceable can be very handy when spending significant time in your command window of choice.

Here is the prompt from one of my Pop!_OS 18.10 Linux machines, running in PowerShell Core:

PowerShell Core on Linux

Happy hacking!