Skip to content

Customizing Your PowerShell Prompt

Marc Kassay edited this page Jun 16, 2022 · 20 revisions

PowerShell allows you to customize your prompt to show whatever information you want. In PowerShell, the "prompt" text is provided by a function named prompt. PowerShell provides you with a default prompt function that is defined as:

# Built-in, default PowerShell prompt
function prompt {
    "PS $($ExecutionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "
}

When you run Import-Module posh-git, posh-git checks to see if the PowerShell default prompt is the current prompt. If it is, then posh-git will install a posh-git default prompt that looks like this in v0.x:

C:\Users\Keith\GitHub\posh-git [master ≡]>

And looks like this in v1:

C:\Users\Keith\GitHub\posh-git [master ≡]>

v0.x - Customizing the posh-git prompt

You can tweak the posh-git prompt with the settings in $GitPromptSettings. For example, you can make the posh-git default prompt span two lines with the following setting:

$GitPromptSettings.AfterText += "`n"

This results in the following prompt that provides plenty of room to type commands without wrapping e.g.:

C:\Users\Keith\GitHub\posh-git [master ≡]
>

You can also customize the default prompt prefix text e.g.:

$GitPromptSettings.DefaultPromptPrefix = '$(Get-Date -f "MM-dd HH:mm:ss") '

This will change the prompt to:

02-18 21:17:07 C:\Users\Keith\GitHub\posh-git [master ≡]>

And if you would prefer to have any path under your home directory abbreviated with ~, you can change this setting:

$GitPromptSettings.DefaultPromptAbbreviateHomeDirectory = $true

This will change the prompt to the one shown below:

~\GitHub\posh-git [master ≡]>

v1.x - Customizing the posh-git prompt

In v1.x, $GitPromptSettings has been updated to a strongly typed object consisting primarily of fields which encapsulate text and color. $GitPromptSettings has also been enhanced to support more flexibility in customizing the posh-git prompt.

For instance, you can customize the default prompt prefix to display a colored timestamp with these settings:

$GitPromptSettings.DefaultPromptPrefix.Text = '$(Get-Date -f "MM-dd HH:mm:ss") '
$GitPromptSettings.DefaultPromptPrefix.ForegroundColor = [ConsoleColor]::Magenta

This will change the prompt to:

02-18 13:45:19 ~\GitHub\posh-git [master ≡]>

If you would prefer not to have any path under your home directory abbreviated with ~, use the following setting:

$GitPromptSettings.DefaultPromptAbbreviateHomeDirectory = $false

This will change the prompt to:

C:\Users\Keith\GitHub\posh-git [master ≡]>

If you would like to change the color of the path, you can use the following setting on Windows:

$GitPromptSettings.DefaultPromptPath.ForegroundColor = 'Orange'

Note: Setting the ForegroundColor to a color name, other than one of the standard ConsoleColor names, only works on Windows. On Windows, posh-git uses the System.Drawing.ColorTranslator.FromHtml() method to parse a color name as an HTML color. For a complete list of HTML colors, see this [W3Schools page][w3c-colors].

If you are on Linux or macOS and desire an Orange path, you will need to specify the RGB value for Orange e.g.:

$GitPromptSettings.DefaultPromptPath.ForegroundColor = 0xFFA500

This will change the prompt to:

~\GitHub\posh-git [master ≡]>

If you would like to make your prompt span two lines, with a newline after the Git status summary, use this setting:

$GitPromptSettings.DefaultPromptBeforeSuffix.Text = '`n'

This will change the prompt to:

~\GitHub\posh-git [master ≡]
>

You can swap the order of the path and the Git status summary with the following setting:

$GitPromptSettings.DefaultPromptWriteStatusFirst = $true

This will change the prompt to:

[master ≡] ~\GitHub\posh-git>

Finally, you can combine these settings to customize the posh-git prompt fairly significantly. In the DefaultPromptSuffix field below, we are prepending the PowerShell history id number before the prompt char > e.g.:

$GitPromptSettings.DefaultPromptWriteStatusFirst = $true
$GitPromptSettings.DefaultPromptBeforeSuffix.Text = '`n$([DateTime]::now.ToString("MM-dd HH:mm:ss"))'
$GitPromptSettings.DefaultPromptBeforeSuffix.ForegroundColor = 0x808080
$GitPromptSettings.DefaultPromptSuffix = ' $((Get-History -Count 1).id + 1)$(">" * ($nestedPromptLevel + 1)) '

This will change the prompt to:

[master ≡] ~\GitHub\posh-git
02-18 14:04:35 38>

If you'd like to make any of these changes permanent i.e. available whenever you start PowerShell, put the corresponding setting(s) in one of your profile scripts after the line that imports posh-git.

For reference, the following layouts show the relative position of the various parts of the posh-git prompt. Note that <> denotes parts of the prompt that may not appear depending on the status of settings and whether or not the current dir is in a Git repository. To simplify the layout, DP is being used as an abbreviation for DefaultPrompt settings.

Default prompt layout:

{DPPrefix}{DPPath}{PathStatusSeparator}<{BeforeStatus}{Status}{AfterStatus}>{DPMiddle}<{DPDebug}><{DPTimingFormat}>{DPSuffix}

Prompt layout when DefaultPromptWriteStatusFirst is set to $true:

{DPPrefix}<{BeforeStatus}{Status}{AfterStatus}>{PathStatusSeparator}{DPPath}{DPMiddle}<{DPDebug}><{DPTimingFormat}>{DPSuffix}

This is the complete list of settings that can be configured with $GitPromptSettings:

GitPromptSettings display

Creating your own prompt function

If you need a custom prompt only to perform some non-prompt logic, you can still use posh-git's prompt function to write out a prompt string. This can be done with the $GitPromptScriptBlock variable available in v1.x as shown below e.g.:

# my profile.ps1
function prompt {
    # Your non-prompt logic here

    # Have posh-git display its default prompt
    & $GitPromptScriptBlock
}

If you'd like to write prompt text before and/or after the posh-git prompt, you can use posh-git's Write-Prompt command as shown below:

# my profile.ps1
function prompt {
    # Your non-prompt logic here
    $prompt = Write-Prompt "Text before posh-git prompt " -ForegroundColor Green
    $prompt += & $GitPromptScriptBlock
    $prompt += Write-Prompt "Text after posh-git prompt " -ForegroundColor Magenta
    if ($prompt) {$prompt} else {" "}
}

If such tweaks aren't sufficient for your needs, you can override both the built-in PowerShell prompt and the posh-git prompt functions by defining a function named prompt in your PowerShell profile script. This profile script is located at $Home\Documents\WindowsPowerShell\profile.ps1 for Windows PowerShell and in $Home\Documents\PowerShell\profile.ps1 for PowerShell Core. If the file doesn't exist, then create it. Then place the following function in the profile script:

function prompt {
    Write-Host $ExecutionContext.SessionState.Path.CurrentLocation -ForegroundColor Cyan
    "$('>' * ($nestedPromptLevel + 1)) "
}

This prompt function illustrates a few features of the PowerShell prompt functions. First, on Windows 7 and 8.1 a string cannot indicate a color to use for parts of the string. Therefore, you have to use Write-Host on these versions of Windows to get colored text in your prompt. Second, your prompt function should always return a string with at least a single space in it. More on that later.

On Windows 10, Linux and macOS, PowerShell can utilize ANSI sequences to color parts of the prompt string. But for the example prompt function above, let's assume we're running on Windows 7. We're using Write-Host to display the path in Cyan. Write-Host also outputs a newline by default, so the > prompt will appear on the line below. The resulting prompt, after starting a new PowerShell console, is shown below:

C:\Users
>

You might be wondering why the previous function didn't simply write everything using the Write-Host command like this:

function prompt {
    Write-Host $ExecutionContext.SessionState.Path.CurrentLocation -ForegroundColor Cyan
    Write-Host "$('>' * ($nestedPromptLevel + 1)) " -NoNewline
}

As mentioned above, you always want to return a string with at least a single space even though you've written your entire prompt using Write-Host. If you don't, as the example above does not, this is what the resulting prompt will look like:

C:\Users\Keith
> PS>

Notice the extra PS>. PowerShell expects the prompt function to return a string which PowerShell will output. If there is no output from the prompt function or the output is an empty string, PowerShell apparently assumes your prompt function did not fulfill its obligation and outputs PS> as a minimal prompt. So while using Write-Host allows you to write colored text in versions of Windows that don't support ANSI escape sequeces, you still need to return at least a single space to suppress PS> from being output as part of the prompt.

Let's look at several ways to integrate posh-git's Git status summary information into your prompt. Here is a typical boiler plate pattern for a prompt function:

function prompt {
    $origLastExitCode = $LASTEXITCODE

    # Generate prompt text to appear before the > char

    $LASTEXITCODE = $origLastExitCode
    "$(if ($PsDebugContext) {'[DBG]: '} else {''})$('>' * ($nestedPromptLevel + 1)) "
}

This boiler plate saves and restores the $LASTEXITCODE at the end of the function prompt. If you're sure you will never invoke a native application in the prompt function then this is unnecessary. However, most of the commands exported by the posh-git module use the git application.

When using posh-git commands, the boiler plate needs to be tweaked a little to accomodate for the fact that a posh-git command that writes prompt information may either write directly to the host or it may return a string. If the host supports ANSI escape sequences then posh-git commands that write prompt information will return strings that may contain ANSI sequences. Otherwise these same commands simply write directly to the host.

In order to support both of these scenarios, append the potential output from each posh-git "write" command to a prompt string. At the end of the prompt function, output this string. In the example below, $prompt will always contain at least > so even if the other commands write directly to the host, the prompt function will always return a non-empty string. This example also shows how to use posh-git's Write-Prompt command to write colored text.

function prompt {
    $origLastExitCode = $LASTEXITCODE

    $prompt = ""

    $prompt += Write-Prompt "$($ExecutionContext.SessionState.Path.CurrentLocation)" -ForegroundColor Cyan
    $prompt += Write-VcsStatus
    $prompt += Write-Prompt "$(if ($PsDebugContext) {' [DBG]: '} else {''})" -ForegroundColor Magenta
    $prompt += "$('>' * ($nestedPromptLevel + 1)) "

    $LASTEXITCODE = $origLastExitCode
    $prompt
}

This results in a PowerShell prompt with both the current path and Git status summary information on a single line:

C:\Users\Keith\GitHub\posh-git [master ≡]>

NOTE: If you are relying entirely on posh-git commands to build up the prompt string, then before outputting the prompt string make sure it is not empty. If it is then output a single space to prevent PS> from being output e.g. if ($prompt) {$prompt} else {" "}

So far these prompts aren't really much different than what you get with posh-git's prompt function. This next prompt function demonstrates how to use various posh-git "write" commands to reverse the order of the Git status and branch name display.

function prompt {
    $origLastExitCode = $LASTEXITCODE

    $prompt = "$($ExecutionContext.SessionState.Path.CurrentLocation)"

    if ($status = Get-GitStatus -Force) {
        $prompt += " ["
        if ($status.HasWorking) {
            $prompt += (Write-GitWorkingDirStatusSummary $status -NoLeadingSpace) +
                       "$(Write-GitWorkingDirStatus $status) "
        }
        if ($status.HasWorking -and $status.HasIndex) {
            $prompt += "| "
        }
        if ($status.HasIndex) {
            $prompt += "$(Write-GitIndexStatus $status -NoLeadingSpace) "
        }
        $prompt += "$(Write-GitBranchStatus $status -NoLeadingSpace)$(Write-GitBranchName $status)]"
    }

    $prompt += "$(if ($PsDebugContext) {' [DBG]:'} else {''})$('>' * ($nestedPromptLevel + 1)) "

    $LASTEXITCODE = $origLastExitCode
    $prompt
}

This results in the following prompt with the Git status summary presented in reverse order:

C:\Users\Keith\GitHub\rkeithhill\PowerShell [! +1 ~0 -0 | +1 ~0 -0 ↓68 master]>

Hopefully, this has provided you with ideas on the various ways you can customize your prompt to your liking. For more in-depth information on PowerShell prompts, see the online PowerShell help topic about_prompts.