fix(tui): add modifyOtherKeys fallback for modified enter keys in tmux
When Kitty keyboard protocol is not available (e.g. inside tmux), fall back to xterm modifyOtherKeys mode 2 so that Shift+Enter, Ctrl+Enter, and other modified keys are distinguishable from plain Enter. tmux users need to add to ~/.tmux.conf: set -g extended-keys on set -g extended-keys-format csi-u closes #1872
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `claude-sonnet-4-6` model for the `google-antigravity` provider ([#1859](https://github.com/badlogic/pi-mono/issues/1859)).
|
- Added `claude-sonnet-4-6` model for the `google-antigravity` provider ([#1859](https://github.com/badlogic/pi-mono/issues/1859)).
|
||||||
|
- Added [tmux setup documentation](docs/tmux.md) for modified enter key support ([#1872](https://github.com/badlogic/pi-mono/issues/1872))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ pi
|
|||||||
|
|
||||||
Then just talk to pi. By default, pi gives the model four tools: `read`, `write`, `edit`, and `bash`. The model uses these to fulfill your requests. Add capabilities via [skills](#skills), [prompt templates](#prompt-templates), [extensions](#extensions), or [pi packages](#pi-packages).
|
Then just talk to pi. By default, pi gives the model four tools: `read`, `write`, `edit`, and `bash`. The model uses these to fulfill your requests. Add capabilities via [skills](#skills), [prompt templates](#prompt-templates), [extensions](#extensions), or [pi packages](#pi-packages).
|
||||||
|
|
||||||
**Platform notes:** [Windows](docs/windows.md) | [Termux (Android)](docs/termux.md) | [Terminal setup](docs/terminal-setup.md) | [Shell aliases](docs/shell-aliases.md)
|
**Platform notes:** [Windows](docs/windows.md) | [Termux (Android)](docs/termux.md) | [tmux](docs/tmux.md) | [Terminal setup](docs/terminal-setup.md) | [Shell aliases](docs/shell-aliases.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
39
packages/coding-agent/docs/tmux.md
Normal file
39
packages/coding-agent/docs/tmux.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# tmux Setup
|
||||||
|
|
||||||
|
Pi works inside tmux, but tmux strips modifier information from certain keys by default. Without configuration, `Shift+Enter` and `Ctrl+Enter` are indistinguishable from plain `Enter`.
|
||||||
|
|
||||||
|
## Required Configuration
|
||||||
|
|
||||||
|
Add to `~/.tmux.conf`:
|
||||||
|
|
||||||
|
```tmux
|
||||||
|
set -g extended-keys on
|
||||||
|
set -g extended-keys-format csi-u
|
||||||
|
```
|
||||||
|
|
||||||
|
Then restart tmux (not just reload):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tmux kill-server
|
||||||
|
tmux
|
||||||
|
```
|
||||||
|
|
||||||
|
This tells tmux to forward modified key sequences in CSI-u format when an application requests extended key reporting. Pi requests this automatically when Kitty keyboard protocol is not available.
|
||||||
|
|
||||||
|
## What This Fixes
|
||||||
|
|
||||||
|
Without this config, tmux collapses modified enter keys to plain `\r`:
|
||||||
|
|
||||||
|
| Key | Without config | With config |
|
||||||
|
|-----|---------------|-------------|
|
||||||
|
| Enter | `\r` | `\r` |
|
||||||
|
| Shift+Enter | `\r` | `\x1b[13;2u` |
|
||||||
|
| Ctrl+Enter | `\r` | `\x1b[13;5u` |
|
||||||
|
| Alt/Option+Enter | `\x1b\r` | `\x1b[13;3u` |
|
||||||
|
|
||||||
|
This affects the default keybindings (`Enter` to submit, `Shift+Enter` for newline) and any custom keybindings using modified enter keys.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- tmux 3.2 or later (run `tmux -V` to check)
|
||||||
|
- A terminal emulator that supports extended keys (Ghostty, Kitty, iTerm2, WezTerm, Windows Terminal)
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added xterm modifyOtherKeys mode 2 fallback when Kitty keyboard protocol is not available, enabling modified enter keys (Shift+Enter, Ctrl+Enter) inside tmux ([#1872](https://github.com/badlogic/pi-mono/issues/1872))
|
||||||
|
|
||||||
## [0.56.2] - 2026-03-05
|
## [0.56.2] - 2026-03-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ export class ProcessTerminal implements Terminal {
|
|||||||
private inputHandler?: (data: string) => void;
|
private inputHandler?: (data: string) => void;
|
||||||
private resizeHandler?: () => void;
|
private resizeHandler?: () => void;
|
||||||
private _kittyProtocolActive = false;
|
private _kittyProtocolActive = false;
|
||||||
|
private _modifyOtherKeysActive = false;
|
||||||
private stdinBuffer?: StdinBuffer;
|
private stdinBuffer?: StdinBuffer;
|
||||||
private stdinDataHandler?: (data: string) => void;
|
private stdinDataHandler?: (data: string) => void;
|
||||||
private writeLogPath = process.env.PI_TUI_WRITE_LOG || "";
|
private writeLogPath = process.env.PI_TUI_WRITE_LOG || "";
|
||||||
@@ -158,6 +159,11 @@ export class ProcessTerminal implements Terminal {
|
|||||||
* Sends CSI ? u to query current flags. If terminal responds with CSI ? <flags> u,
|
* Sends CSI ? u to query current flags. If terminal responds with CSI ? <flags> u,
|
||||||
* it supports the protocol and we enable it with CSI > 1 u.
|
* it supports the protocol and we enable it with CSI > 1 u.
|
||||||
*
|
*
|
||||||
|
* If no Kitty response arrives shortly after startup, fall back to enabling
|
||||||
|
* xterm modifyOtherKeys mode 2. This is needed for tmux, which can forward
|
||||||
|
* modified enter keys as CSI-u when extended-keys is enabled, but may not
|
||||||
|
* answer the Kitty protocol query.
|
||||||
|
*
|
||||||
* The response is detected in setupStdinBuffer's data handler, which properly
|
* The response is detected in setupStdinBuffer's data handler, which properly
|
||||||
* handles the case where the response arrives split across multiple stdin events.
|
* handles the case where the response arrives split across multiple stdin events.
|
||||||
*/
|
*/
|
||||||
@@ -165,6 +171,12 @@ export class ProcessTerminal implements Terminal {
|
|||||||
this.setupStdinBuffer();
|
this.setupStdinBuffer();
|
||||||
process.stdin.on("data", this.stdinDataHandler!);
|
process.stdin.on("data", this.stdinDataHandler!);
|
||||||
process.stdout.write("\x1b[?u");
|
process.stdout.write("\x1b[?u");
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this._kittyProtocolActive && !this._modifyOtherKeysActive) {
|
||||||
|
process.stdout.write("\x1b[>4;2m");
|
||||||
|
this._modifyOtherKeysActive = true;
|
||||||
|
}
|
||||||
|
}, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -204,6 +216,10 @@ export class ProcessTerminal implements Terminal {
|
|||||||
this._kittyProtocolActive = false;
|
this._kittyProtocolActive = false;
|
||||||
setKittyProtocolActive(false);
|
setKittyProtocolActive(false);
|
||||||
}
|
}
|
||||||
|
if (this._modifyOtherKeysActive) {
|
||||||
|
process.stdout.write("\x1b[>4;0m");
|
||||||
|
this._modifyOtherKeysActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
const previousHandler = this.inputHandler;
|
const previousHandler = this.inputHandler;
|
||||||
this.inputHandler = undefined;
|
this.inputHandler = undefined;
|
||||||
@@ -240,6 +256,10 @@ export class ProcessTerminal implements Terminal {
|
|||||||
this._kittyProtocolActive = false;
|
this._kittyProtocolActive = false;
|
||||||
setKittyProtocolActive(false);
|
setKittyProtocolActive(false);
|
||||||
}
|
}
|
||||||
|
if (this._modifyOtherKeysActive) {
|
||||||
|
process.stdout.write("\x1b[>4;0m");
|
||||||
|
this._modifyOtherKeysActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Clean up StdinBuffer
|
// Clean up StdinBuffer
|
||||||
if (this.stdinBuffer) {
|
if (this.stdinBuffer) {
|
||||||
|
|||||||
Reference in New Issue
Block a user