> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/wezterm/wezterm/llms.txt
> Use this file to discover all available pages before exploring further.

# Shell Integration

> Enhanced terminal features with OSC escape sequences for shells

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

<Info>
  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.
</Info>

## Key Features

<Steps>
  <Step title="Working Directory Tracking">
    New tabs and panes automatically inherit the current working directory from the active pane.
  </Step>

  <Step title="Semantic Navigation">
    Jump through scrollback to the start of previous commands or select complete command output.
  </Step>

  <Step title="User Variables">
    Track custom shell state and trigger events based on shell activity.
  </Step>

  <Step title="Prompt Detection">
    Distinguish between prompts, input, and output for better copy/paste and navigation.
  </Step>
</Steps>

## 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:

```bash theme={null}
printf "\033]7;file://HOSTNAME/CURRENT/DIR\033\\"
```

<Tip>
  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.
</Tip>

### Bash Configuration

Add to your `~/.bashrc`:

```bash theme={null}
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`:

```zsh theme={null}
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`:

```lua theme={null}
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:

```powershell theme={null}
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](https://starship.rs/):

```powershell theme={null}
$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

<Accordion title="Navigate by Prompt">
  Jump to previous command prompts:

  ```lua theme={null}
  config.keys = {
    {
      key = 'UpArrow',
      mods = 'CTRL|SHIFT',
      action = wezterm.action.ScrollToPrompt(-1),
    },
    {
      key = 'DownArrow',
      mods = 'CTRL|SHIFT',
      action = wezterm.action.ScrollToPrompt(1),
    },
  }
  ```
</Accordion>

<Accordion title="Select Command Output">
  Instantly select all output from a command:

  ```lua theme={null}
  config.keys = {
    {
      key = 'S',
      mods = 'CTRL|SHIFT',
      action = wezterm.action.SelectTextAtMouseCursor 'SemanticZone',
    },
  }
  ```
</Accordion>

### 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

<Info>
  Learn more about [OSC 133 Semantic Prompts](https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md).
</Info>

## 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_PROG`    | Current command being executed    |
| `WEZTERM_USER`    | Current username (from `id -un`)  |
| `WEZTERM_HOST`    | Hostname (from `hostname`)        |
| `WEZTERM_IN_TMUX` | `1` if inside tmux, `0` otherwise |

<Warning>
  If using tmux, you must add `set -g allow-passthrough on` to your `tmux.conf` for user vars to work.
</Warning>

### Setting Custom Variables

Use the `__wezterm_set_user_var` function provided by shell integration:

```bash theme={null}
# 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:

```lua theme={null}
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:

```lua theme={null}
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](https://github.com/wez/wezterm/tree/main/assets/shell-integration).

### Installing for Bash/Zsh

<Steps>
  <Step title="Download the integration script">
    ```bash theme={null}
    curl -fsSL https://raw.githubusercontent.com/wez/wezterm/main/assets/shell-integration/wezterm.sh -o ~/.wezterm.sh
    ```
  </Step>

  <Step title="Source in your shell config">
    Add to `~/.bashrc` or `~/.zshrc`:

    ```bash theme={null}
    if [[ -f ~/.wezterm.sh ]]; then
      source ~/.wezterm.sh
    fi
    ```
  </Step>

  <Step title="Restart your shell">
    ```bash theme={null}
    exec $SHELL
    ```
  </Step>
</Steps>

### System-wide Installation

On most Unix systems, you can install to `/etc/profile.d/`:

```bash theme={null}
sudo cp wezterm.sh /etc/profile.d/wezterm.sh
```

### Xonsh Support

For Xonsh users, use the [term-integrations plugin](https://github.com/jnoortheen/xontrib-term-integrations):

```bash theme={null}
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:

```lua theme={null}
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:

```bash theme={null}
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`:

```lua theme={null}
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

```bash theme={null}
__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](https://github.com/chrisant996/clink) brings bash-style line editing to Windows cmd.exe.

### Configuration

```lua theme={null}
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

<Accordion title="Working directory not inherited">
  Verify OSC 7 is being emitted:

  ```bash theme={null}
  # In your terminal, after changing directory:
  printf "\033]7;file://%s%s\033\\" "$HOSTNAME" "$PWD"
  ```

  Check that `WEZTERM_PANE` environment variable is set.
</Accordion>

<Accordion title="User vars not working in tmux">
  Ensure your `tmux.conf` includes:

  ```bash theme={null}
  set -g allow-passthrough on
  ```

  Restart tmux after updating the configuration.
</Accordion>

<Accordion title="Shell integration not loaded">
  Verify the integration script is sourced:

  ```bash theme={null}
  type __wezterm_set_user_var
  ```

  If the function is not found, check that your shell config sources the integration file.
</Accordion>

## Best Practices

<Steps>
  <Step title="Use provided integration scripts">
    Start with WezTerm's official shell integration scripts rather than writing your own.
  </Step>

  <Step title="Test incrementally">
    Add features one at a time (OSC 7, then OSC 133, then custom user vars) to isolate issues.
  </Step>

  <Step title="Check for conflicts">
    Some prompt frameworks (like Starship or Oh My Zsh) may conflict. Check their documentation for integration guides.
  </Step>

  <Step title="Update regularly">
    Shell integration improves over time. Periodically update your integration scripts.
  </Step>
</Steps>

## Learn More

* [Terminal Basics](/concepts/terminal-basics) - Understand escape sequences and PTYs
* [Multiplexing](/concepts/multiplexing) - Tabs, panes, and domains
* [Escape Sequences](https://wezfurlong.org/wezterm/escape-sequences.html) - Complete reference
* [Events](https://wezfurlong.org/wezterm/config/lua/window-events/index.html) - Handle user-var-changed and other events
