OSC 0 / 2 — 设置窗口/图标标题
修改终端窗口的标题栏文本。
字节形式
涵盖所有常见的字符串字面量写法,方便正反查找。
\x1b]0;TITLE\x07\033]0;TITLE\007\e]0;TITLE\aESC ] 0 ; TITLE BEL1b 5d 30 3b ... 07说明
OSC(Operating System Command)序列以 ESC ](\x1b])开头,以 BEL(\x07,xterm 事实标准)或 ST(\x1b\\,ESC \\,源自 ECMA-48 §5.2.2 的规范标准)结尾。\x1b]0;TITLE\x07 同时设置窗口与图标标题;\x1b]1;TITLE\x07 仅图标;\x1b]2;TITLE\x07 仅窗口。; 与结束符之间的载荷是新标题文本 —— 现代模拟器普遍接受 UTF-8。常用于 shell 的 PROMPT_COMMAND / precmd 钩子、tmux 的 automatic-rename 与 set-window-option allow-rename、终端复用器的窗口列表显示、以及标签页重命名工具。
可移植性上两个坑反复出现在 Stack Overflow。其一,结束符选择:xterm 与多数现代模拟器同时接受 BEL 与 ST,但 osc-terminator pitfall 记录了某些版本的 screen / tmux 只有在结束符是 ST 时才会转发标题(xterm-ctlseqs 严格态),而 Linux console / fbcon 完全不处理 OSC 标题(上面矩阵标 no)。稳妥代码用 ST:\x1b]0;TITLE\x1b\\。其二,完全忘记结束符 —— 常见于被截断的代码 —— 会让 OSC 解析器一直挂着,直到下一个恰好是结束符的字节出现(往往是下次提示符重绘的第一个 BEL),导致 bug 间歇且难复现。其三,tmux:.tmux.conf 必须设 set -g allow-rename on 才会让面板内的 OSC 0/2 更新 tmux 窗口名;否则 tmux 直接剥离 OSC,宿主终端永远收不到。Apple Terminal.app 支持标题,但其 AppleScript 层级的标签页标题接口可以按窗口覆盖 OSC。
标题没有「关闭」语义 —— 发新的 OSC 0/2 就替换前一个,空载荷 \x1b]0;\x07 把标题清空到模拟器默认值(通常是当前运行的进程名)。bash 中的规范提示符模式是 PS1='\[\e]0;\u@\h: \w\a\]\u@\h:\w\$ ' —— \[…\] 把转义标记为不可打印,使 PS1 的列数统计保持正确,否则 readline 会误判行长并破坏换行行为。zsh 等价写法是 precmd() { print -Pn "\e]0;%n@%m: %~\a" }。设标题的 terminfo cap 是 tsl(to_status_line)+ fsl(from_status_line);如今 xterm-256color 普及后很少有脚本去走这条路径。相关:osc-hyperlink(OSC 8 内联超链接)、osc-cwd(OSC 7 工作目录通告,iTerm2 / Windows Terminal 据此「在同目录新建标签」)、osc-clipboard(OSC 52 设置系统剪贴板)。
规范出处: xterm-ctlseqs (OSC 0/1/2)
示例
printf '\033]0;Hello window\007'import sys; sys.stdout.write('\x1b]0;Hello window\x07')fmt.Print("\x1b]0;Hello window\x07")process.stdout.write('\x1b]0;Hello window\x07')printf("\x1b]0;Hello window\x07");在哪里用到
实际会发出该序列的工具——把抽象字节锚定到你已经用过的命令上。
- bash, zshPROMPT_COMMAND / precmd 钩子写 `\x1b]0;…\x07`,每次提示符更新窗口标题
- tmux开启 set-titles 后会把 window-name 转发给外层终端
- vim, neovim`set title` 会把缓冲区名(`filename - VIM`)写成窗口标题
- ssh client许多发行版给 ssh 打补丁,使其在连接时把标题设为 `user@host`
- starship, oh-my-zsh window-title plugins
常见问题
针对这条序列,开发者真正会去搜索的问题的简短回答。
- 为什么我
ssh到远程主机后终端标题就回退了? - 远端主机上的 shell 在每次提示符前自己发了 OSC 0 / OSC 2——bash 的
PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'模式最常见,zsh 的precmd钩子同理。要么在远端关掉该钩子,要么在 ssh 结束之后再设本地标题(用trap … EXIT或 shell 包装函数)。 - OSC 0、OSC 1、OSC 2 有什么区别?
- OSC 0 同时设置图标名与窗口标题。OSC 1 只设置图标名(dock / 任务栏条目显示)。OSC 2 只设置窗口标题(操作系统级窗口装饰)。在 macOS Terminal.app 与多数 Linux 终端上,图标名区分是空操作——OSC 0 与 OSC 2 行为一致。iTerm2 与 gnome-terminal 在桌面查询图标名时会区别对待。
终端支持
- xterm
- 支持
- Linux console (fbcon)
- 不支持
- macOS Terminal.app
- 支持
- iTerm2
- 支持
- Windows Terminal
- 支持
- cmd.exe / ConPTY
- 支持
- kitty
- 支持
- alacritty
- 支持
- WezTerm
- 支持
- Ghostty
- 支持
- GNOME Terminal
- 支持
- Konsole
- 支持
- tmux
- 支持
- GNU screen
- 支持
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 支持 | 不支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |