Files
dev/third_party/pi/packages/coding-agent/docs/terminal-setup.md
alexion 6081e3e325 chore(vendor): import pi 1.3.0
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
2026-10-15 17:58:48 -04:00

234 lines
8.9 KiB
Markdown

# Configure your terminal
Most modern terminals work with Pi without additional setup. Use this page when modified keys, scrolling, links, images, colors, or input-method editor (IME) positioning do not behave as expected.
Pi uses extended-key protocols so terminals can distinguish combinations such as `Shift+Enter` and `Alt+Enter` from plain `Enter`. Terminal proxies, multiplexers, and built-in IDE terminals can change or discard that information.
## Troubleshooting
| Symptom | Start here |
|---|---|
| `Shift+Enter` submits instead of inserting a line | Your terminal's section below; for tmux, see [Run Pi in tmux](tmux.md) |
| `Alt+Enter` does not queue a follow-up | [WezTerm](#wezterm), [Alacritty](#alacritty), or [Windows Terminal](#windows-terminal) |
| Fullscreen scrolling is unusually slow | [iTerm2](#iterm2) |
| Links work but show no hover preview | [Ghostty](#ghostty) |
| Inline images or colors are not detected | [Override detected capabilities](#override-detected-capabilities) |
| An IME candidate window appears in the wrong place | [WezTerm](#wezterm) or [IntelliJ IDEA](#intellij-idea-integrated-terminal) |
| Modified keys fail only inside tmux | [Run Pi in tmux](tmux.md) |
Use `/hotkeys` to inspect Pi's active shortcuts. See [Keybindings](keybindings.md) to change them.
## Kitty
Kitty supports the required keyboard protocol without additional configuration.
## iTerm2
Regular terminal mode works without additional configuration.
### Fix slow fullscreen scrolling
In fullscreen mode, Pi owns the viewport, so iTerm2 sends mouse-wheel reports instead of scrolling native terminal history. Fast trackpad gestures can then move only about one line at a time.
To change this behavior:
1. Open **iTerm2 > Settings > Advanced**.
2. Search for **Trackpad scrolls fast?**.
3. Set it to **No**.
This is an iTerm2-wide setting and can also change native trackpad scrolling. The underlying behavior is tracked in [iTerm2 issue 9619](https://gitlab.com/gnachman/iterm2/-/work_items/9619).
## Apple Terminal
Pi enables enhanced key reporting when available. If Terminal.app still sends plain Return for `Shift+Enter`, Pi uses a local macOS modifier fallback and treats it as `Shift+Enter`.
The fallback works only when Pi runs on the same Mac as Terminal.app. It cannot inspect the local modifier state when Pi runs on another machine over SSH.
## Ghostty
Add this mapping to Ghostty's configuration if `Alt+Backspace` does not work:
```text
keybind = alt+backspace=text:\x1b\x7f
```
The configuration file is `~/Library/Application Support/com.mitchellh.ghostty/config` on macOS and `~/.config/ghostty/config` on Linux.
Older Claude Code configurations may contain:
```text
keybind = shift+enter=text:\n
```
This sends a raw linefeed, which Pi cannot distinguish from `Ctrl+J`. Remove the mapping if an older Claude Code installation is the only reason you added it. Pi already binds `Ctrl+J` as a newline alternative, so the mapping may appear to work while still preventing Pi and tmux from receiving a real `Shift+Enter` event.
### Open links in fullscreen mode
Links remain clickable in fullscreen mode, but Ghostty does not show its normal hover underline or URL preview while Pi captures mouse input. Hold `Shift+Command` on macOS or `Shift+Ctrl` on Linux to use Ghostty's native link handling.
## WezTerm
WezTerm normally reports `Shift+Enter` through xterm extended keys. To enable the Kitty keyboard protocol explicitly, create `~/.wezterm.lua`:
```lua
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
config.enable_kitty_keyboard = true
return config
```
### Forward Alt+Enter on macOS
WezTerm binds `Option+Enter` to fullscreen by default on macOS. To use it for Pi's follow-up queue, add this entry to your `config.keys` table:
```lua
{
key = 'Enter',
mods = 'ALT',
action = wezterm.action.SendString('\x1b[13;3u'),
}
```
A complete minimal configuration is:
```lua
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
config.keys = {
{
key = 'Enter',
mods = 'ALT',
action = wezterm.action.SendString('\x1b[13;3u'),
},
}
return config
```
### Position an IME candidate window in WSL
If CJK IME candidates do not follow Pi's text cursor in WSL, show the hardware cursor:
```bash
export PI_HARDWARE_CURSOR=1
pi
```
You can instead set `showHardwareCursor` to `true` in Pi settings.
## Alacritty
Alacritty normally reports `Shift+Enter`. On macOS, `Option+Enter` can arrive as plain `Enter`. Add this to `~/.config/alacritty/alacritty.toml` to forward it to Pi:
```toml
[[keyboard.bindings]]
key = "Enter"
mods = "Alt"
chars = "\u001b[13;3u"
```
Restart Alacritty after changing the file.
## VS Code integrated terminal
VS Code 1.109.5 and newer enable the Kitty keyboard protocol in the integrated terminal by default.
For an older version, add a `Shift+Enter` terminal binding to `keybindings.json`:
```json
{
"key": "shift+enter",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001b[13;2u" },
"when": "terminalFocus"
}
```
The user `keybindings.json` file is normally located at:
- macOS: `~/Library/Application Support/Code/User/keybindings.json`
- Linux: `~/.config/Code/User/keybindings.json`
- Windows: `%APPDATA%\\Code\\User\\keybindings.json`
## Zed integrated terminal
Add these bindings to Zed's `keymap.json`:
```json
{
"context": "Terminal",
"bindings": {
"shift-enter": ["terminal::SendText", "\u001b[13;2u"],
"ctrl--": ["terminal::SendText", "\u001b[45;5u"],
"ctrl-alt-]": ["terminal::SendText", "\u001b[93;7u"]
}
}
```
## Windows Terminal
Windows Terminal uses Pi's Windows and WSL shortcut defaults. See [Keybindings](keybindings.md) for the complete list.
### Forward Shift+Enter
Open Windows Terminal's `settings.json` with `Ctrl+Shift+,` or **Settings > Open JSON file**. Add this object to its `actions` array:
```json
{
"command": { "action": "sendInput", "input": "\u001b[13;2u" },
"keys": "shift+enter"
}
```
Fully close and reopen Windows Terminal, then verify that `Shift+Enter` inserts a new line in Pi.
### Use Alt+Enter for follow-ups
Windows Terminal binds `Alt+Enter` to fullscreen by default. Pi therefore uses `Ctrl+Q` for follow-ups on Windows and WSL.
To use `Alt+Enter` instead, configure Windows Terminal to forward the key and bind `app.message.followUp` to `alt+enter` in Pi's `keybindings.json`. See [Keybindings](keybindings.md#assign-keybindings).
## xfce4-terminal and Terminator
These terminals cannot reliably distinguish modified Enter keys from plain `Enter`. Custom bindings such as `Ctrl+Enter` or `Shift+Enter` therefore may not work.
Use a terminal with modern extended-key support when you need those shortcuts, such as Kitty, Ghostty, WezTerm, iTerm2, Windows Terminal, or a compatible Alacritty build.
## IntelliJ IDEA integrated terminal
IntelliJ IDEA's built-in terminal cannot reliably distinguish `Shift+Enter` from plain `Enter`. Use `Ctrl+J` for a newline or run Pi in a terminal with modern extended-key support.
If an IME candidate window does not follow the text cursor, show the hardware cursor:
```bash
export PI_HARDWARE_CURSOR=1
pi
```
## Override detected capabilities
Pi automatically detects OSC 8 hyperlinks, inline image protocols, and truecolor support. A terminal proxy or multiplexer can make that detection inaccurate.
| Capability | Environment variable | Setting |
|---|---|---|
| Hyperlinks | `PI_HYPERLINKS=1\|0\|auto` | `terminal.hyperlinks: true\|false\|"auto"` |
| Inline images | `PI_IMAGE_PROTOCOL=kitty\|iterm2\|none\|auto` | `terminal.images: "kitty"\|"iterm2"\|false\|"auto"` |
| Truecolor | `PI_TRUE_COLOR=1\|0\|auto` | `terminal.trueColor: true\|false\|"auto"` |
Settings take precedence over environment variables. An unset value or `auto` preserves automatic detection.
Only force a capability supported by the complete terminal path. Unsupported escape sequences can corrupt rendering. See [Environment Variables](environment-variables.md#pi-process-configuration) and [Settings](settings.md) for the canonical value definitions.
## Program status
Pi reports its state with the [Program Status Protocol (OSC 7501)](https://www.superlogical.com/rex/docs/build/program-status), so terminals and agent dashboards can show whether it is working, waiting for you, done, or failed:
| State | When |
|---|---|
| `working` | An agent run or compaction is in progress. The message is the session name. |
| `blocked` | An extension dialog or login waits for you. The message is the dialog title. |
| `done` | A run finished. The message is the session name. |
| `error` | A run ended with an error that is not retried. The message is the first line of the error. |
| `idle` | Pi started, or you cancelled the run. |
Reports never contain prompts or model output. Pi sends them only after the terminal answers the protocol's support query; tmux and screen do not forward them. Set `PI_PROGRAM_STATUS=1` to send reports without asking, or `PI_PROGRAM_STATUS=0` to turn them off.