about_PSReadLine
Short Description
PSReadLine provides an improved command-line editing experience in the PowerShell console.
There have been many updates to PSReadLine since the version that ships in Windows PowerShell 5.1.
- v2.3.5 first shipped in PowerShell 7.4.2 and 7.5.0-preview.3
- v2.3.4 first shipped in PowerShell 7.4.0-rc.1
- v2.2.6 first shipped in PowerShell 7.3.0
- v2.1.0 first shipped in PowerShell 7.2.5
- v2.0.4 first shipped in PowerShell 7.0.11
- v2.0.0 ships in Windows PowerShell 5.1
For more information about version differences, see about_PSReadLine_Release_Notes.
Long Description
The current version of PSReadLine can be installed and used on Windows PowerShell 5.1 and newer. For some features, you need to be running PowerShell 7.2 or higher.
PSReadLine provides a powerful command-line editing experience for the PowerShell console. It provides:
- Syntax coloring of the command line
- A visual indication of syntax errors
- A better multi-line experience (both editing and history)
- Customizable key bindings
- Cmd and Emacs modes
- Many configuration options
- Bash style completion (optional in Cmd mode, default in Emacs mode)
- Emacs yank/kill-ring
- PowerShell token based "word" movement and deletion
PSReadLine requires PowerShell 5.1, or newer. PSReadLine works with the default Windows console host, Windows Terminal, and Visual Studio Code. It doesn't work in the Windows PowerShell ISE.
PSReadLine can be installed from the PowerShell Gallery. To install PSReadLine in a supported version of PowerShell run the following command.
Install-Module -Name PSReadLine -AllowClobber -Force
Custom Key Bindings
PSReadLine supports custom key bindings using the Set-PSReadLineKeyHandler
cmdlet. Most custom key bindings call one of the bindable functions, for
example
Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
You can bind a ScriptBlock to a key. The ScriptBlock can do pretty much anything you want. Some useful examples include
- edit the command line
- opening a new window (for example, help)
- change directories without changing the command line
The ScriptBlock receives two arguments:
$key
- A [ConsoleKeyInfo] object that is the key that triggered the custom binding. If you bind the same ScriptBlock to multiple keys and need to perform different actions depending on the key, you can check$key
. Many custom bindings ignore this argument.$arg
- An arbitrary argument. Most often, this would be an integer argument that the user passes from the key bindings DigitArgument. If your binding doesn't accept arguments, it's reasonable to ignore this argument.
Let's take a look at an example that adds a command line to history without executing it. This is useful when you realize you forgot to do something, but don't want to re-enter the command line you've already entered.
$parameters = @{
Key = 'Alt+w'
BriefDescription = 'SaveInHistory'
LongDescription = 'Save current line in history but do not execute'
ScriptBlock = {
param($key, $arg) # The arguments are ignored in this example
# GetBufferState gives us the command line (with the cursor position)
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line,
[ref]$cursor)
# AddToHistory saves the line in history, but does not execute it.
[Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($line)
# RevertLine is like pressing Escape.
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
}
}
Set-PSReadLineKeyHandler @parameters
You can see many more examples in the file SamplePSReadLineProfile.ps1
, which
is installed in the PSReadLine module folder.
Most key bindings use some helper functions for editing the command line. Those APIs are documented in about_PSReadLine_Functions.
Notes
Command History
PSReadLine maintains a history file containing all the commands and data you've
entered from the command line. The history files are a file named
$($host.Name)_history.txt
. On Windows systems the history file is stored at
$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine
.
The history can contain sensitive data including passwords. PSReadLine attempts to filter out sensitive information. Any command lines containing the following strings aren't written to the history file.
password
asplaintext
token
apikey
secret
PSReadLine 2.2.0 improves the filtering of sensitive data
- Uses the PowerShell Abstract Syntax Tree (AST) of the parsed command line to look for sensitive data.
- Uses an allowlist of safe cmdlets from the SecretManagement module to
allow those commands to be added to the history. The allowlist contains:
Get-Secret
Get-SecretInfo
Get-SecretVault
Register-SecretVault
Remove-Secret
Set-SecretInfo
Set-SecretVaultDefault
Test-SecretVault
Unlock-SecretVault
Unregister-SecretVault
For example, the following commands are allowed to be written to the history file:
Get-Secret PSGalleryApiKey -AsPlainText # Get-Secret is in the allowlist
$token = Get-Secret -Name github-token -Vault MySecret
[MyType]::CallRestAPI($token, $url, $args)
$template -f $token
The following commands aren't being written to the history file:
$token = 'abcd' # Assign expr-value to sensitive variable name.
Set-Secret abc $mySecret # Set-Secret is not in the allowlist.
ConvertTo-SecureString stringValue -AsPlainText # '-AsPlainText' is an alert.
Invoke-WebRequest -Token xxx # Expr-value as argument to '-Token'.
Get-ResultFromTwo -Secret1 (Get-Secret -Name blah -AsPlainText) -Secret2 sdv87ysdfayf798hfasd8f7ha # '-Secret2' has expr-value argument.
If there are other commands you don't want written to the history files, you
can use the AddToHistoryHandler parameter of the Set-PSReadLineOption
cmdlet. For an example of how to use AddToHistoryHandler, see Example 7 of
Set-PSReadLineOption.
PSReadLine 2.3.4 improves the filtering of sensitive data
Improved the default sensitive history scrubbing to allow the history to contain safe property access.
When the sensitive string is part of a property access:
- If this member access operation isn't part of an assignment, then we consider it safe
- Otherwise, if the right-hand side is a pipeline or a variable, we also consider it safe
For example, the following use cases are considered safe and can be saved to the history.
$a.Secret = Get-Secret -Name github-token -Vault MySecret
$a.Secret = $secret
$a.Password.Secret | Set-Value
$token = (Get-AzAccessToken -ResourceUrl 'https://app.contoso.com').Token
The release also improved the sensitive history scrubbing to allow retrieving
token using the az
, gcloud
, and kubectl
command-line tools.
For example, the following use cases are considered safe and can be saved to the history.
kubectl get secrets
kubectl get secret db-user-pass -o jsonpath='{.data.password}' | base64 --decode
kubectl describe secret db-user-pass
az account get-access-token --resource=https://app.contoso.com --query accessToken --output tsv
$env:PGPASS = gcloud auth print-access-token
Feedback & contributing to PSReadLine
Feel free to submit a pull request or submit feedback on the GitHub page.
See Also
- PSReadLine is heavily influenced by the GNU readline library.