WezTerm supports advanced shell integration features that enable enhanced user experiences through special escape sequences. When properly configured, your shell can communicate additional context to WezTerm, enabling features like semantic navigation, smart working directory handling, and custom status information.
What is Shell Integration?
Shell integration uses OSC (Operating System Command) escape sequences to communicate between your shell and WezTerm. These sequences provide metadata about:
Current working directory
Command prompts vs output
User and hostname information
Custom shell state
Shell integration is automatically activated on Fedora, Debian, and Arch Linux packages for Bash and Zsh. On other systems, you’ll need to configure it manually.
Key Features
Working Directory Tracking
New tabs and panes automatically inherit the current working directory from the active pane.
Semantic Navigation
Jump through scrollback to the start of previous commands or select complete command output.
User Variables
Track custom shell state and trigger events based on shell activity.
Prompt Detection
Distinguish between prompts, input, and output for better copy/paste and navigation.
OSC 7: Working Directory
OSC 7 tells WezTerm the current working directory, enabling smart directory inheritance when spawning new tabs or panes.
How it Works
Your shell emits an escape sequence with the current directory as a URL:
printf "\033]7;file://HOSTNAME/CURRENT/DIR\033 \\ "
When the working directory is set via OSC 7, spawning a new tab will use the current working directory of the active tab, saving you from manually changing directories.
Bash Configuration
Add to your ~/.bashrc:
if [[ -n " $WEZTERM_PANE " ]]; then
_wezterm_osc7 () {
printf "\033]7;file://%s%s\033 \\ " \
" $HOSTNAME " \
"$( pwd | sed 's/\\(/\\(\%20/g')"
}
PROMPT_COMMAND = "${ PROMPT_COMMAND : + $PROMPT_COMMAND ; }_wezterm_osc7"
fi
Zsh Configuration
Add to your ~/.zshrc:
if [[ -n " $WEZTERM_PANE " ]]; then
function _wezterm_osc7 () {
printf "\033]7;file://%s%s\033 \\ " \
" $HOST " \
"${ PWD / \/ /% 2F }"
}
precmd_functions += ( _wezterm_osc7 )
fi
Windows cmd.exe
Configure in your .wezterm.lua:
config . set_environment_variables = {
prompt = '$E]7;file://localhost/$P$E \\ $E[32m$T$E[0m $E[35m$P$E[36m$_$G$E[0m ' ,
}
PowerShell
Add to your PowerShell profile:
function prompt {
$p = $executionContext .SessionState.Path.CurrentLocation
$osc7 = ""
if ( $p .Provider.Name -eq "FileSystem" ) {
$ansi_escape = [ char ] 27
$provider_path = $p .ProviderPath -Replace "\\\\" , "/"
$osc7 = " $ansi_escape ]7;file:// ${ env: COMPUTERNAME} / ${provider_path}${ansi_escape} \"
}
" ${osc7} PS $p $( '>' * ( $nestedPromptLevel + 1 ) ) " ;
}
PowerShell with Starship
If using Starship :
$prompt = ""
function Invoke-Starship-PreCommand {
$current_location = $executionContext .SessionState.Path.CurrentLocation
if ( $current_location .Provider.Name -eq "FileSystem" ) {
$ansi_escape = [ char ] 27
$provider_path = $current_location .ProviderPath -replace "\\\\" , "/"
$prompt = " $ansi_escape ]7;file:// ${ env: COMPUTERNAME} / ${provider_path}$ansi_escape \"
}
$host .ui.Write ( $prompt )
}
OSC 133: Semantic Prompt Markup
OSC 133 marks distinct zones in your terminal output:
Prompt - Your shell prompt
Input - Commands you type
Output - Command results
This enables powerful navigation and selection features.
Benefits
Jump to previous command prompts: config . keys = {
{
key = 'UpArrow' ,
mods = 'CTRL|SHIFT' ,
action = wezterm . action . ScrollToPrompt ( - 1 ),
},
{
key = 'DownArrow' ,
mods = 'CTRL|SHIFT' ,
action = wezterm . action . ScrollToPrompt ( 1 ),
},
}
Instantly select all output from a command: config . keys = {
{
key = 'S' ,
mods = 'CTRL|SHIFT' ,
action = wezterm . action . SelectTextAtMouseCursor 'SemanticZone' ,
},
}
Implementation
The complete OSC 133 specification uses these sequences:
OSC 133 ; A ST - Mark start of prompt
OSC 133 ; B ST - Mark start of input (command)
OSC 133 ; C ST - Mark start of output
OSC 133 ; D [; exit_code] ST - Mark end of output
OSC 1337: User Variables
User variables are pane-specific variables (similar to environment variables but scoped to a pane rather than a process).
Built-in Variables
When using WezTerm’s shell integration, these variables are automatically maintained:
Variable Description WEZTERM_PROGCurrent command being executed WEZTERM_USERCurrent username (from id -un) WEZTERM_HOSTHostname (from hostname) WEZTERM_IN_TMUX1 if inside tmux, 0 otherwise
If using tmux, you must add set -g allow-passthrough on to your tmux.conf for user vars to work.
Setting Custom Variables
Use the __wezterm_set_user_var function provided by shell integration:
# Example: Set a project variable
__wezterm_set_user_var PROJECT "my-awesome-app"
Using Variables in Configuration
User variables trigger events that you can handle in your configuration:
wezterm . on ( 'user-var-changed' , function ( window , pane , name , value )
if name == 'PROJECT' then
window : set_right_status ( value )
end
end )
Accessing Variables
Read user variables from Lua:
wezterm . on ( 'update-status' , function ( window , pane )
local vars = pane : get_user_vars ()
local project = vars . PROJECT or 'no-project'
window : set_right_status ( project )
end )
Complete Shell Integration Setup
WezTerm provides shell integration scripts in the wezterm repository .
Installing for Bash/Zsh
Download the integration script
curl -fsSL https://raw.githubusercontent.com/wez/wezterm/main/assets/shell-integration/wezterm.sh -o ~/.wezterm.sh
Source in your shell config
Add to ~/.bashrc or ~/.zshrc: if [[ -f ~ /.wezterm.sh ]]; then
source ~/.wezterm.sh
fi
System-wide Installation
On most Unix systems, you can install to /etc/profile.d/:
sudo cp wezterm.sh /etc/profile.d/wezterm.sh
Xonsh Support
For Xonsh users, use the term-integrations plugin :
xpip install xontrib-term-integrations
xontrib load term_integrations
Advanced Examples
Dynamic Tab Titles with User Vars
Update tab titles based on the current command:
wezterm . on ( 'format-tab-title' , function ( tab , tabs , panes , config , hover , max_width )
local pane = tab . active_pane
local prog = pane . user_vars . WEZTERM_PROG or pane . title
return ' ' .. prog .. ' '
end )
Git Branch in Status Bar
In your shell configuration:
update_git_branch () {
if git rev-parse --is-inside-work-tree > /dev/null 2>&1 ; then
local branch = $( git branch --show-current 2> /dev/null )
__wezterm_set_user_var GIT_BRANCH " $branch "
else
__wezterm_set_user_var GIT_BRANCH ""
fi
}
# Call before each prompt
PROMPT_COMMAND = "update_git_branch; $PROMPT_COMMAND "
In .wezterm.lua:
wezterm . on ( 'update-status' , function ( window , pane )
local git_branch = pane : get_user_vars (). GIT_BRANCH
if git_branch and git_branch ~= '' then
window : set_right_status ( wezterm . format ({
{ Foreground = { Color = '#00ff00' } },
{ Text = ' ' .. git_branch },
}))
else
window : set_right_status ( '' )
end
end )
Command Duration Tracking
__wezterm_cmd_start_time = ""
__wezterm_record_start () {
__wezterm_cmd_start_time = $( date +%s )
}
__wezterm_record_duration () {
if [[ -n " $__wezterm_cmd_start_time " ]]; then
local end_time = $( date +%s )
local duration = $(( end_time - __wezterm_cmd_start_time ))
__wezterm_set_user_var CMD_DURATION " $duration "
__wezterm_cmd_start_time = ""
fi
}
preexec_functions += ( __wezterm_record_start )
precmd_functions += ( __wezterm_record_duration )
Clink Integration (Windows)
Clink brings bash-style line editing to Windows cmd.exe.
Configuration
local wezterm = require 'wezterm'
local config = {}
config . set_environment_variables = {}
if wezterm . target_triple == 'x86_64-pc-windows-msvc' then
-- Use OSC 7
config . set_environment_variables [ 'prompt' ] =
'$E]7;file://localhost/$P$E \\ $E[32m$T$E[0m $E[35m$P$E[36m$_$G$E[0m '
-- Better dir output
config . set_environment_variables [ 'DIRCMD' ] = '/d'
-- Inject clink
config . default_prog =
{ 'cmd.exe' , '/s' , '/k' , 'c:/clink/clink_x64.exe' , 'inject' , '-q' }
end
return config
Troubleshooting
Working directory not inherited
Verify OSC 7 is being emitted: # In your terminal, after changing directory:
printf "\033]7;file://%s%s\033 \\ " " $HOSTNAME " " $PWD "
Check that WEZTERM_PANE environment variable is set.
User vars not working in tmux
Ensure your tmux.conf includes: set -g allow-passthrough on
Restart tmux after updating the configuration.
Shell integration not loaded
Verify the integration script is sourced: type __wezterm_set_user_var
If the function is not found, check that your shell config sources the integration file.
Best Practices
Use provided integration scripts
Start with WezTerm’s official shell integration scripts rather than writing your own.
Test incrementally
Add features one at a time (OSC 7, then OSC 133, then custom user vars) to isolate issues.
Check for conflicts
Some prompt frameworks (like Starship or Oh My Zsh) may conflict. Check their documentation for integration guides.
Update regularly
Shell integration improves over time. Periodically update your integration scripts.
Learn More