跳到主要内容
ansicode

OSC 0 / 2 — 设置窗口/图标标题

修改终端窗口的标题栏文本。

字节形式

涵盖所有常见的字符串字面量写法,方便正反查找。

\\x1b[\x1b]0;TITLE\x07
\\033[\033]0;TITLE\007
\\e[\e]0;TITLE\a
ESC [ESC ] 0 ; TITLE BEL
hex1b 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-renameset-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)

示例

bash
printf '\033]0;Hello window\007'
python
import sys; sys.stdout.write('\x1b]0;Hello window\x07')
go
fmt.Print("\x1b]0;Hello window\x07")
javascript
process.stdout.write('\x1b]0;Hello window\x07')
c
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
支持

相关序列

在家族食谱中

OSC 食谱 · 1. 信封 —— `\x1b]` …… `\x07` 或 `\x1b\\`