Tutorial: Opening a tab or pane in the same directory in Windows Terminal
Typically, the "new tab" and "split pane" actions will always open a new tab/pane in whatever the startingDirectory
is for that profile. However, on other platforms, it's common for new tabs to automatically use the working directory of the current tab as the starting directory for a new tab. This allows the user to quickly multitask in a single directory.
Unfortunately, on Windows, it's tricky to determine what the current working directory ("CWD") for a process is. Even if we were able to look it up, not all applications actually set their CWD as they navigate. Notably, Windows PowerShell doesn't change its CWD as you cd
around the file system! Duplicating the CWD of PowerShell automatically would almost always be wrong.
Fortunately, there's a workaround. Applications can emit a special escape sequence (specifically the "OSC 9;9" format) to manually tell the Terminal what the CWD should be.
In this tutorial, you learn how to:
- Configure the shell to tell the Terminal about its current working directory
- Use the
duplicateTab
action to open a tab with the same CWD - Use the
splitPane
action to open a pane with the same CWD - Using the tab context menu to open tabs or panes with the same CWD
Configure your shell
To tell the Terminal what the CWD is, you'll need to modify your shell to emit an escape sequence as you navigate the OS. Fortunately, most shells have a mechanism for configuring the "prompt", which is run after every command. This is the perfect place to add such output.
Windows
Command Prompt: cmd.exe
cmd
uses the %PROMPT%
environment variable to configure the prompt. You can easily prepend the prompt with the command to set the CWD with the following command:
set PROMPT=$e]9;9;$P$e\%PROMPT%
This will append $e]9;9;$P$e\
to your current prompt. When cmd evaluates this prompt, it'll replace
- the
$e
with the escape character - the
$p
with the current working directory
Note that the above command will only work for the current cmd.exe
session. To set the value permanently, AFTER running the above command, you'll want to run
setx PROMPT "%PROMPT%"
PowerShell: powershell.exe
or pwsh.exe
If you've never changed your PowerShell prompt before, you should check out about_Prompts first.
Add the following to your PowerShell profile:
function prompt {
$loc = $executionContext.SessionState.Path.CurrentLocation;
$out = ""
if ($loc.Provider.Name -eq "FileSystem") {
$out += "$([char]27)]9;9;`"$($loc.ProviderPath)`"$([char]27)\"
}
$out += "PS $loc$('>' * ($nestedPromptLevel + 1)) ";
return $out
}
PowerShell with posh-git
If you're using posh-git, then that will already modify your prompt. In that case, you'll want to only add the necessary output to the already modified prompt. The following example is a lightly modified version of this example from the ConEmu docs:
function prompt
{
$loc = Get-Location
$prompt = & $GitPromptScriptBlock
$prompt += "$([char]27)]9;12$([char]7)"
if ($loc.Provider.Name -eq "FileSystem")
{
$prompt += "$([char]27)]9;9;`"$($loc.ProviderPath)`"$([char]27)\"
}
$prompt
}
PowerShell with Starship
If you're using Starship, then that will already modify your prompt. In that case, you'll want to only add the necessary output to the already modified prompt.
function Invoke-Starship-PreCommand {
$loc = $executionContext.SessionState.Path.CurrentLocation;
$prompt = "$([char]27)]9;12$([char]7)"
if ($loc.Provider.Name -eq "FileSystem")
{
$prompt += "$([char]27)]9;9;`"$($loc.ProviderPath)`"$([char]27)\"
}
$host.ui.Write($prompt)
}
WSL
Windows Subsystem for Linux distributions primarily use BASH as the command line shell.
bash
Add the following line to the end of your .bash_profile
config file:
PROMPT_COMMAND=${PROMPT_COMMAND:+"$PROMPT_COMMAND "}'printf "\e]9;9;%s\e\\" "$(wslpath -w "$PWD")"'
The PROMPT_COMMAND
variable in bash tells bash what command to run before displaying the prompt. The printf
statement is what we're using to append the sequence for setting the working directory with the Terminal. The $(wslpath -w "$PWD")
bit will invoke the wslpath
executable to convert the current directory into its Windows-like path. The ${PROMPT_COMMAND:+"$PROMPT_COMMAND; "}
bit is some bash magic to make sure we append this command to any existing command (if you've already set PROMPT_COMMAND
somewhere else.)
zsh
Add the following lines to the end of your .zshrc
file:
keep_current_path() {
printf "\e]9;9;%s\e\\" "$(wslpath -w "$PWD")"
}
precmd_functions+=(keep_current_path)
The precmd_functions
hook tells zsh what commands to run before displaying the prompt. The printf
statement is what we're using to append the sequence for setting the working directory with the Terminal. The $(wslpath -w "$PWD")
bit will invoke the wslpath
executable to convert the current directory into its Windows-like path. Using precmd_functions+=
make sure we append the keep_current_path
function to any existing function already defined for this hook.
Fish
If you're using Fish shell, add the following lines to the end of your config file located at ~/.config/fish/config.fish
:
function storePathForWindowsTerminal --on-variable PWD
if test -n "$WT_SESSION"
printf "\e]9;9;%s\e\\" (wslpath -w "$PWD")
end
end
This function will be called whenever the current path is changed to confirm the current session is opened by Windows Terminal (verifying $WT_SESSION) and sending Operating System Command (OSC 9;9;), with the Windows equivalent path (wslpath -w
) of current path.
MINGW
For MINGW, Git Bash and Cygwin, you need to modify the PROMPT_COMMAND
for WSL: replace wslpath
with cygpath
.
Add the following line to the end of your .bashrc
file:
PROMPT_COMMAND=${PROMPT_COMMAND:+"$PROMPT_COMMAND; "}'printf "\e]9;9;%s\e\\" "`cygpath -w "$PWD" -C ANSI`"'
Note
Don't see your favorite shell here? If you figure it out, feel free to open a PR to contribute a solution for your preferred shell!
Using actions to duplicate the path
Once you've got the shell configured to tell the Terminal what the current directory is, opening a new tab or pane with that path is easy.
Open a new tab with duplicateTab
To open a new tab with the same path (and profile) as the currently active terminal, use the "Duplicate Tab" action. This is bound by default to Ctrl+Shift+D, as follows:
{ "command": "duplicateTab", "keys": "ctrl+shift+d" },
(see duplicateTab
) for more details.
Open a new pane with splitPane
To open a new pane with the same path (and profile) as the currently active terminal, use the "Duplicate Pane" action. This is NOT bound by default. The simplest form of this action is:
{ "command": { "action": "splitPane", "splitMode": "duplicate" } },
(see splitPane
) for more details.
Using the menu to duplicate the path
the above actions are also available on the tab context menu, under the entries "Duplicate Tab" and "Split Pane".
Windows Terminal