‹ 指南

我们自己在用的 tmux 配置

本站截图背后那份 ~/.tmux.conf:为小屏幕、代码助手,以及手机和电脑同时挂着的场景调过。

撰写于

为什么要配

tmux 默认是给台式机用的:只挂一个客户端,键盘上的修饰键随手就够,程序也只输出文字。放到手机上,这几条没有一条成立:屏幕小,往往还有一台笔记本同时挂着,而里面跑的越来越多是代码助手,它讲的是颜色、图片和 Shift+Enter,这些在原装 tmux 下都活不下来。

这就是我们真正在跑的那份文件,不是入门模板:本站所有 tmux 截图都是透过它拍的。整份拷走,或者只挑你要的部分,每一行都带注释说明它换来了什么,下面几节则解释那些不太显然的取舍。

~/.tmux.conf
##### 终端能力 #####

# 终端类型 + 24 位真彩色:没有 RGB,渐变会有色带
set  -g default-terminal "tmux-256color"
set -as terminal-features ",*:RGB"

# RGB 告诉的是 tmux:外层终端支持真彩色;里面的程序(nvim、bat、fzf、
# delta)要不要发 24 位色,看的是 COLORTERM。tmux 自己从不把这个变量
# 传进去,所以把它钉死
set-environment -g COLORTERM truecolor

# 内嵌图片(sixel、kitty、imgcat),否则会被 tmux 丢掉
set  -g allow-passthrough on
set -as terminal-features ",*:sixel"

# 在 tmux 里复制,直接进手机剪贴板(OSC 52)
set  -g set-clipboard on

# ……走 mosh 时也一样。tmux 发这条 OSC 52 时不填目标,发出来是 52;;,
# 而 mosh 只转发 52;c;,所以没有这一行,在 tmux 里复制的内容只会进
# tmux 自己的粘贴缓冲区,根本出不了服务器。%p1 一定要留着:跳过它
# 直接写 %p2 的写法能正常加载,然后什么都不发
set -ag terminal-overrides ',*:Ms=\E]52;%p1%sc;%p2%s\a'

# 让 Ctrl+Shift+…、Shift+Enter 之类以 CSI u 形式穿过 tmux
# (Claude Code 靠这个来实现 Shift+Enter 换行)
set  -s extended-keys on
set -as terminal-features ",*:extkeys"
set  -g extended-keys-format csi-u

# 别在 Esc 上等:默认那 500ms 会毁掉 Alt 组合键
set -sg escape-time 10

# 焦点事件和鼠标(在终端里按住 Shift 可以本地选中)
set  -g focus-events on
set  -g mouse on

# 把窗口标题转发出来,终端 App 才能给标签页命名
set  -g set-titles on
set  -g set-titles-string "tmux · #{pane_title}"

# 回滚行数:代码助手输出很多,给它留够
set  -g history-limit 100000

##### 手机 / 同时挂着多个客户端 #####

# 窗口大小跟着「最近活动」的客户端走:手机和电脑同时挂着时,
# 谁在打字就按谁的屏幕来;小屏幕不会把布局锁死
set  -g window-size latest
setw -g aggressive-resize on

# 窗口和窗格从 1 开始编号,关掉后自动补号:手机键盘上 1 比 0 好按
set  -g base-index 1
setw -g pane-base-index 1
set  -g renumber-windows on

# 关掉当前会话时跳到下一个,而不是直接 detach:
# 从手机上重连很麻烦
set  -g detach-on-destroy off

# 提示消息多留一会儿,小屏幕上才来得及看
set  -g display-time 2000
set  -g display-panes-time 2000

##### 代码助手提醒 #####

# Claude Code 这类工具干完活会响铃:不要闪屏,
# 只在状态栏那个窗口名上加一个粗体的 !
set  -g bell-action any
set  -g visual-bell off
setw -g monitor-bell on

# 后台窗口有新输出 -> 状态栏出现 # 标记,
# 一眼就能看出哪个代码助手还在跑、哪个已经停了
setw -g monitor-activity on
set  -g visual-activity off

##### 配色 #####

# bg=default 让终端自己的背景透过来,点缀色(会话名、前缀提示、活动标记)
# 取自终端的调色板。凡是必须在每个挂着的客户端上都看得清的部分,改用
# 固定的 256 色,它们在任何主题下都长一个样

# 状态栏放在顶部,避开底部 Claude Code 的输入框
set  -g status-position top
set  -g status-interval 5
set  -g status-style "bg=default,fg=default"

# 左边显示会话名;右边只在按住前缀键时显示 ^B 提示
set  -g status-left "#[fg=colour5,bold] #S #[default]"
set  -g status-left-length 20
set  -g status-right "#{?client_prefix,#[fg=colour3 bold]^B ,}"
set  -g status-right-length 20

# 窗口列表:当前窗口是一块自带白字的蓝底(任何主题下对比度都是 5.8:1),
# 其它窗口用中灰;响铃(!)红色,有活动(#)黄色
setw -g window-status-format " #I #W#{?window_flags,#{window_flags}, } "
setw -g window-status-style "fg=colour245"
setw -g window-status-current-format " #I #W "
setw -g window-status-current-style "bg=colour26,fg=colour231,bold"
setw -g window-status-bell-style "fg=colour203,bold"
setw -g window-status-activity-style "fg=colour3"

# 窗格边框、消息、复制模式的选中样式:一种灰,一种蓝
set  -g pane-border-style "fg=colour243"
set  -g pane-active-border-style "fg=colour32"
set  -g message-style "fg=colour32,bold,bg=default"
# tmux 自己的命令提示符是一条不透明的黑条:让它和消息一个样
set  -g message-command-style "fg=colour32,bold,bg=default"
set  -g mode-style "bg=colour26,fg=colour231"
set  -g display-panes-colour colour243
set  -g display-panes-active-colour colour32
setw -g clock-mode-colour colour32

##### 快捷键 #####

setw -g mode-keys vi

# 分屏和新建窗口都继承当前目录:不用再 cd 回代码助手干活的地方
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
bind c new-window   -c "#{pane_current_path}"

# Alt+数字直接跳窗口,不用按前缀键:手机上少按一次组合键
bind -n M-1 select-window -t 1
bind -n M-2 select-window -t 2
bind -n M-3 select-window -t 3
bind -n M-4 select-window -t 4
bind -n M-5 select-window -t 5

# 前缀键 + hjkl 在窗格之间移动
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

##### 复制与粘贴 #####

# 前缀键 + v 也能进复制模式(比 [ 好记)
bind v copy-mode

# 复制模式:v 开始选择,y 复制(经 OSC 52 送到手机/本机剪贴板),
# Y 复制整行,Ctrl+v 切换矩形选择
bind -T copy-mode-vi v send -X begin-selection
bind -T copy-mode-vi y send -X copy-selection-and-cancel
bind -T copy-mode-vi Y send -X copy-line-and-cancel
bind -T copy-mode-vi C-v send -X rectangle-toggle

# 鼠标拖选即复制,但留在复制模式的原位:不会跳回底部,
# 可以接着看代码助手的回滚输出;按 q 退出
bind -T copy-mode-vi MouseDragEnd1Pane send -X copy-selection

# 双击复制一个词,三击复制一整行。词的边界只算空格,
# 所以双击就能从代码助手的输出里一次拿到完整的文件路径或 URL
set -g word-separators " "
# 那个 `run -d0.3` 要留着:进复制模式和复制放在同一条命令里,
# tmux 的缓冲区有了内容,却不发 OSC 52,剪贴板里什么都没有。
# 用 -H 而不是 -M:-M 会把这次点击继续传下去,选区会越过这个词
bind -n DoubleClick1Pane copy-mode -H \; send -X select-word \; run -d0.3 \; send -X copy-selection-and-cancel
bind -n TripleClick1Pane copy-mode -H \; send -X select-line \; run -d0.3 \; send -X copy-selection-and-cancel
bind -T copy-mode-vi DoubleClick1Pane send -X select-word \; send -X copy-selection-and-cancel
bind -T copy-mode-vi TripleClick1Pane send -X select-line \; send -X copy-selection-and-cancel

# 前缀键 + ] 粘贴最近一次复制(tmux 默认);前缀键 + P 打开缓冲区列表,
# 粘贴更早复制的内容
bind P choose-buffer

# 前缀键 + t:弹出一个小终端跑一次性命令,不打乱代码助手的布局;
# exit 就关
bind t display-popup -E -w 80% -h 75% -d "#{pane_current_path}"

# 前缀键 + r:重载配置
bind r source-file ~/.tmux.conf \; display "已重载 ~/.tmux.conf"

tmux 挡住了终端的哪些能力

复用器夹在程序和 Term 之间,而原装的它对「放什么过去」相当保守。allow-passthrough on 才能让内嵌图片显示出来:sixel、kitty graphics 和 imgcat 都是以转义序列送达的,否则会被 tmux 吞掉。terminal-features ",*:RGB" 恢复24 位色,没有它,TUI 里的渐变全是色带。而 set-clipboard on 才让复制模式里按 y 直接进手机剪贴板,走 OSC 52,服务器上不用装任何辅助程序。

RGB 只是告诉 tmux 自己:Term 能画 24 位色。里面的程序要自己判断,看的是 COLORTERM,而 tmux 从不把这个变量传进去:从普通 shell 启动的服务端,会让 nvim、bat、delta 退回 256 色,看起来只是主题发灰,不像出了错。set-environment -g COLORTERM truecolor 把它钉给之后开的每一个窗格。Term 连上时也会给正在运行的 tmux 服务端设上它;这一行让这份配置从任何终端连过去都一样对。

三行 extended-keys 是这组里最新、也最容易漏掉的。它让 Ctrl+Shift+…、Shift+Enter 这类按键以 CSI u 形式穿过去,而不是被压扁成普通按键。Claude Code 用 Shift+Enter 在提示词里换行;少了这几行,这一下会变成普通 Enter,把写到一半的提示词直接提交。

set-clipboard 下面那行 terminal-overrides 只为一种组合而存在:在 mosh 会话里跑 tmux。一条 OSC 52 要写明它指的是哪个剪贴板,而 tmux 把这个名字留空,发出来是 52;;;mosh 按字面只认 52;c;,于是一条都不转发,你在 tmux 里复制的内容落进 tmux 自己的粘贴缓冲区就到头了。这一行把名字钉成 c。格式里的 %p1 即使取值被丢掉也必须留着:跳过它直接写 %p2 的版本能正常加载,然后一个字节都不发。

手机和电脑同时挂着

挂两个客户端时,原装 tmux 会把每个窗口缩到最小的那个客户端,手机一连上,200 列的笔记本就被压到 56 列,而且一直保持。window-size latest 改成按最近活动的客户端来:在笔记本上打字就用笔记本的屏幕,拿起手机就为手机重排。aggressive-resize 对单个窗口做同样的事。

detach-on-destroy off 也是同一个道理。关掉会话的最后一个窗格,原装 tmux 会把你丢回对端的 shell:在手机上,这意味着你刚花二十秒建起来的那条连接。跳到下一个会话,人就还在里面。

哪个代码助手还在干活

代码助手干完一轮会响铃。monitor-bell 开、visual-bell 关,这一下就变成状态栏里那个窗口名旁边一个粗体的红色 !,而不是在你正在看的屏幕上闪一下;monitor-activity 则给任何有输出的窗口加一个黄色的 #。手机上同一时间只看得见一个窗口,状态栏是唯一能让你分辨四个 agent 里谁还在想、谁在等你的地方。

在任何主题下都看得清的状态栏

bg=default 让 Term 自己的背景透过状态栏,点缀色(会话名、^B 提示、活动标记)都是调色板里的颜色,会跟着 Term 一起换主题。但跟着调色板走,不等于看得清。调色板里的颜色保留的是它的角色,不是亮度:colour8 在每个主题里都是「亮黑」,在深色主题上就是一片暗灰。当前窗口原来用的 reverse 更是把对比度变成了抽奖:黑底的调色板上只有 2.2:1,粉彩系的调色板上又没问题。手机和电脑同时挂着时,两边的调色板甚至都不一样。

所以凡是要读的部分,都改用固定的 256 色,它们在每个终端里画出来都一样。当前窗口是一块自带白字的蓝底(colour26 底、colour231 字,任何主题下都是 5.8:1);其它窗口名用一种浅色深色都看得清的中灰;边框、消息、命令提示符和时钟共用一种蓝。tmux 3.7 能分辨客户端是浅色还是深色(#{client_theme}),但前提是终端上报,而走 mosh 时这份上报永远到不了,所以这里没有任何东西依赖它。

适合拇指的按键

这里每一条绑定都在省掉一次组合键或一次跨键盘的移动。| 和 - 按它们长的样子分屏。前缀键 + hjkl 在窗格间移动,完全不用碰方向键。前缀键 + t 在当前窗格上弹出一个临时小终端(这是手机上对「我要跑一条命令,但不想打乱代码助手的布局」的答案),exit 就关。

Alt+1 … Alt+5,不用前缀键

切窗口是 tmux 里最频繁的操作,在手机上也最贵:前缀键再加一个数字,是两层组合。bind -n 把前缀键整个去掉,而 Term 的按键栏有一个粘滞 alt,于是它就变成两次点击。

就地开出来的分屏

分屏和新建窗口那几条绑定上的 -c "#{pane_current_path}",让新窗格开在你已经在的那个目录里。没有它,每次分屏都从 $HOME 开始,而你在手机键盘上要打的第一样东西就是一长串 cd。

复制代码助手的输出

复制相关的绑定是为了从代码助手打印的东西里挑内容而调的。双击复制一个词,而 word-separators 只算空格,所以一个「词」就是一整条文件路径或 URL:点一下,不用小心翼翼地拖。三击拿整行。鼠标拖选会复制,并且留在复制模式的原位,不会弹回底部,你可以接着往回看回滚输出;按 q 离开。前缀键 + P 打开之前复制过的内容列表。

双击和三击那两条绑定里的 run -d0.3 要留着。进复制模式和复制放在同一条命令里,tmux 的粘贴缓冲区有了内容,却不发 OSC 52,于是复制的东西到不了剪贴板,不管走哪种连接都一样。这点延迟让模式切换先落定,tmux 自带的默认绑定里也有它,就是这个原因。

怎么装上

  1. 把上面这份文件拷走,存成服务器上的 ~/.tmux.conf:不是手机上。tmux 在会话运行的那一端读它。
  2. 在 shell 提示符下用下面这条命令加载一次。
  3. 之后每次改完,用 前缀键 + r 重载即可。
第一次加载,在 shell 里
tmux source-file ~/.tmux.conf

中间那步看着和重载绑定重复,其实不是:前缀键 + r 没法完成第一次加载。这个绑定要等文件被读过才存在,而 tmux 服务端是在启动时读配置的,第一次的时候,那还早于文件存在。于是唯一不能用快捷键完成的重载,恰恰是把这个快捷键装上的那一次。另外注意 source-file 是 tmux 的命令而不是 shell 的:所以在这里要在前面加 tmux,而在配置文件里则不用。

还有两件事得先确认,否则怎么改都不生效:这份配置需要 tmux 3.5 或更新的版本,更老的版本启动时只会报一句「unknown option」,那条设置就静默失效了,用 tmux -V 看一下你装的是哪个。另外在 Debian 与 Ubuntu 上,第一行选用的 tmux-256color 这条 terminfo 描述并不随 tmux 一起装,而是在 ncurses-term 包里,记得一并装上。

延伸阅读: 在手机上用 tmux · SSH 自动恢复 · 常见问题