Pi 在 tmux 中的键位扩展配置指南:extended-keys 与 csi-u 格式详解
Pi 是一个以 TUI(终端用户界面)为核心的 coding agent,其交互体验高度依赖终端能否准确上报带修饰键(Shift/Ctrl/Alt)的按键事件。当 Pi 运行在 tmux 内时,tmux 默认会剥离这些修饰信息,导致 Shift+Enter、Ctrl+Enter 与裸 Enter 无法区分,进而影响提交与换行等默认键位。本文基于 Pi 仓库中的 tmux 配置文档 展开,讲解推荐的 tmux 配置、csi-u 格式背后的键序列原理,并结合 Pi 源码中的键盘协议协商逻辑,说明这套配置是如何被 Pi 请求、解析和验证的。读完本文,你将能够为 tmux 环境配置一套完整的扩展键上报方案,并理解 Pi 在不同终端协议下的键位回退机制。
问题背景:为什么 tmux 默认会"吞掉"修饰键
Pi 的 TUI 编辑器默认键位是:Enter 提交输入、Shift+Enter 插入换行。这一点可以从键位文档 keybindings.md 中的默认绑定表得到印证:tui.input.submit 默认绑定 enter,tui.input.newLine 默认绑定 shift+enter 和 ctrl+j。
问题在于 tmux 本身是一个终端复用器,它在客户端终端与前台程序之间做键序列的中转。默认配置下,tmux 不具备"扩展键"(extended keys)转发能力:一旦应用请求了扩展键上报,tmux 仍会把修饰过的 Enter 折叠回传统序列——Shift+Enter、Ctrl+Enter、Alt+Enter 全部塌缩为 \r 或 \x1b\r。Pi 收到的就是一个普通的回车,于是"换行"变成了"提交"。
Pi 官方文档给出的修复方案只有两行 tmux 配置,效果却直接决定 TUI 的多行输入体验。
推荐配置:两行 tmux 设置加一次完整重启
在 ~/.tmux.conf 中加入:
set -g extended-keys on
set -g extended-keys-format csi-u
然后完全重启 tmux(注意不是 source ~/.tmux.conf,扩展键选项要求服务端重启才生效):
tmux kill-server
tmux
配置生效后,Pi 在 Kitty 键盘协议不可用时会自动请求扩展键上报(extended key reporting),tmux 则以 csi-u 格式转发修饰键序列。csi-u 是目前最可靠的组合;其中 extended-keys-format 选项要求 tmux 3.5 或更高版本。
为什么推荐 csi-u:两种转发格式对照
只写 set -g extended-keys on 而不指定格式时,tmux 默认使用 xterm 的 modifyOtherKeys 格式。当应用请求扩展键上报后,修饰键会以如下序列转发:
Ctrl+C→\x1b[27;5;99~Ctrl+D→\x1b[27;5;100~Ctrl+Enter→\x1b[27;5;13~
而加上 set -g extended-keys-format csi-u 后,同样的按键会以统一的 CSI-u 格式转发:
Ctrl+C→\x1b[99;5uCtrl+D→\x1b[100;5uCtrl+Enter→\x1b[13;5u
Pi 的键位解析层对两种格式都有实现,因此二者都能工作,但官方推荐 csi-u。从 keys.ts 的源码结构看,这个推荐是有实现层依据的:
parseKittySequence()用正则^\x1b\[(\d+)(?::(\d*))?(?::(\d+))?(?:;(\d+))?(?::(\d+))?u$解析 CSI-u 序列,能同时提取码点(codepoint)、shifted key、base layout key、修饰键位值(modifier)和事件类型(press/repeat/release),信息维度比 modifyOtherKeys 更丰富;parseModifyOtherKeysSequence()解析的是^\x1b\[27;(\d+);(\d+)~$这一更窄的格式,只有修饰键和码点两个字段。
换句话说,CSI-u 是 Kitty 键盘协议与 tmux 扩展键的公共格式,一条解析链路同时覆盖了 Kitty 协议终端、tmux csi-u 模式以及其他支持该格式的终端;而 modifyOtherKeys 只作为回退路径存在。
修复效果对照表
官方文档给出了不带扩展键与启用 csi-u 后各 Enter 变体的原始序列对照:
| 按键 | 未启用 extkeys | 启用 csi-u 后 |
|---|---|---|
| Enter | \r |
\r |
| Shift+Enter | \r |
\x1b[13;2u |
| Ctrl+Enter | \r |
\x1b[13;5u |
| Alt/Option+Enter | \x1b\r |
\x1b[13;3u |
注意修饰键位值的编码规则:CSI-u 中 modifier 从 1 开始计数,1 = 无修饰、2 = Shift、3 = Alt、4 = Super、5 = Ctrl(多修饰键按位或叠加,如 Ctrl+Shift = 7)。这与 keys.ts 中 modValue - 1 归一化为内部位掩码的解析逻辑一致。
这个折叠问题不仅影响默认键位(Enter 提交、Shift+Enter 换行),也会影响任何自定义键位中使用的"修饰版 Enter"。如果你通过 ~/.pi/agent/keybindings.json 自定义了 shift+enter 相关的绑定,同样需要先修复 tmux 侧的序列塌缩,否则 Pi 根本收不到对应事件。
源码印证:Pi 如何请求扩展键并验证 tmux 配置
键盘协议协商:先试 Kitty,再落 modifyOtherKeys
Pi 的 TUI 层在启动时并不是被动等待按键序列,而是主动向终端发起协议协商。从 terminal.ts 的源码结构看,这条协商链如下:
- 发送查询序列。常量
KITTY_KEYBOARD_PROTOCOL_QUERY为\x1b[>7u\x1b[?u\x1b[c,即"以 flag 7 请求 Kitty 键盘协议 → 查询当前协议状态 → 追加一个 DA 设备属性查询作为哨兵"。注释中说明了 flag 7 的构成:- 1 = disambiguate escape codes(消除转义序列歧义)
- 2 = report event types(上报 press/repeat/release 事件类型)
- 4 = report alternate keys(上报 shifted key 与 base layout key,支持非拉丁键盘布局)
- 渐进式检测。Pi 采用 Kitty 官方推荐的 progressive enhancement 方式:请求先于查询发出,这样不懂 Kitty 协议的终端不会报错。如果收到的 Kitty 协议响应中 flags 非 0,Pi 就激活 Kitty 协议并关闭 modifyOtherKeys;如果先收到 DA 哨兵响应(说明终端不识别 Kitty 协议),则立即回退到 modifyOtherKeys 模式。
- 回退即 tmux 的场景。
enableModifyOtherKeys()会向终端写入\x1b[>4;2m(xterm 的 modifyOtherKeys 模式 2,即"对所有修饰键组合都发扩展序列")。在 tmux 内,正是这条回退请求让 tmux 开始按extended-keys配置转发修饰键——这就是文档所说"Pi 在 Kitty 协议不可用时自动请求扩展键上报"的源码位置。
也就是说,文档中"Pi requests extended key reporting automatically"这句话,对应的实现就是 Kitty 协商失败后的 modifyOtherKeys 回退路径,而不是 Pi 额外发送 tmux 专用指令。
启动时的 tmux 配置体检
除了被动收键,Pi 的交互模式还会主动"体检" tmux 配置。interactive-mode.ts 中有一段异步检查逻辑:通过 tmux show -gv extended-keys 和 tmux show -gv extended-keys-format 查询当前服务端配置,并据此给出两条针对性提示:
- 若
extended-keys为 off:提示"modified Enter keys may not work",建议在~/.tmux.conf中加入set -g extended-keys on并重启 tmux; - 若
extended-keys-format为 xterm:提示"Pi works best with csi-u",建议追加set -g extended-keys-format csi-u并重启 tmux。
如果查询失败(超时、沙箱限制等),Pi 不会误报警告。这个自检机制意味着你不需要靠手动测试按键来发现配置缺失——Pi 启动时就会把 tmux 侧的配置问题直接告诉你。
版本与终端要求
- tmux 3.5 及以上:
extended-keys-format csi-u需要 3.5+,可用tmux -V确认版本; - 终端模拟器需支持扩展键上报:文档列出的可用终端为 Ghostty、Kitty、iTerm2、WezTerm、Windows Terminal。tmux 只能转发它收到和它能生成的序列,如果最外层的终端本身不支持扩展键上报,tmux 内再怎么配置也拿不到修饰键信息;
- tmux 3.2 至 3.4:省略
extended-keys-format csi-u一行即可。这些版本只有extended-keys on(默认 xtermmodifyOtherKeys格式),Pi 的parseModifyOtherKeysSequence()回退路径完整支持该格式,功能不受影响,只是序列样式为\x1b[27;5;13~这类。
小结与验证路径
在 tmux 中使用 Pi 的完整配置路径可以归纳为:
- 确认
tmux -V版本;3.5+ 使用完整两行配置,3.2–3.4 只保留set -g extended-keys on; tmux kill-server后重新进入,确保服务端加载新配置;- 启动 Pi,观察其 tmux 体检是否还有 extended-keys 相关提示;
- 在 Pi 输入框中试按
Shift+Enter,应插入换行而非提交,即csi-u序列(如\x1b[13;2u)已正确贯通"终端 → tmux → Pi"整条链路。
除 tmux 键位外,Pi 对各类终端(Kitty、iTerm2、Apple Terminal、Ghostty 等)的能力差异与覆盖方式,可继续参考 terminal-setup.md;键位本身的可定制范围则见 keybindings.md。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00