跳到主要内容

tmux 终端工作流完整指南:会话、分屏、自定义快捷键与 iTerm2 配合

Rainy
雨落无声,代码成诗 —— 致力于技术与艺术的极致平衡
Rainy
25 MIN READ... VIEWS

如果你经常在终端里写代码、跑服务、看日志、连远程机器,tmux 基本是绕不开的工具。它解决的不是“终端不够漂亮”,而是一个更工程化的问题:终端会话应该像项目状态一样可恢复、可组织、可迁移。

iTerm2 已经是 macOS 上非常强的终端应用,支持标签页、分屏、Hotkey Window、Profile、Trigger、字体主题和快捷键。但 iTerm2 的窗口状态主要活在本机 GUI 里;一旦 SSH 断开、终端关闭、机器重启,很多运行中的上下文就消失了。tmux 则运行在 shell 里面,可以把一个项目的 editor、server、test、log、AI CLI 都放进同一个持久会话。

最推荐的分工是:

iTerm2 = macOS 原生窗口、字体、主题、全局唤起、Profile
tmux = 项目会话、窗口、pane、远程保活、布局恢复
Shell = 命令入口、目录跳转、项目启动脚本
Neovim = 编辑器 split、LSP、搜索、Git、代码修改

这篇文章会按“先能用,再顺手,最后可定制”的顺序介绍 tmux。


一、tmux 到底是什么

tmux 是 terminal multiplexer。直译是“终端复用器”,但更贴近日常使用的理解是:它在一个真实终端里创建多个可持久化的虚拟终端工作区。

它有三层核心对象:

对象类比用来做什么
session一个项目工作区frontendapiblogprod-ssh
window工作区里的标签页editorservertestlogs
panewindow 里的分屏左边编辑器,右上跑服务,右下看日志

用 iTerm2 类比,大概是:

iTerm2 window/tab ≈ 外层项目入口
tmux session ≈ 项目持久工作区
tmux window ≈ 项目内任务标签
tmux pane ≈ 同一任务里的终端分屏

tmux 最关键的能力有四个:

  1. 断线不丢进程:SSH 断了,tmux 里的服务、日志、编辑器还在。
  2. 关闭终端不丢现场:detach 后可以随时 attach 回去。
  3. 统一项目布局:一个 session 里固定 editor/server/test/logs。
  4. 键盘驱动:通过 prefix 和快捷键快速分屏、切换、复制、重命名。

如果你只在本地写一点脚本,iTerm2 分屏已经够用;如果你有长期项目、远程机器、后台服务、AI CLI、Neovim、日志观察,tmux 的价值会很明显。


二、安装与启动

macOS 推荐用 Homebrew:

brew install tmux
tmux -V

Ubuntu/Debian:

sudo apt update
sudo apt install tmux
tmux -V

Fedora:

sudo dnf install tmux
tmux -V

Arch Linux:

sudo pacman -S tmux
tmux -V

第一次启动:

tmux

这会创建一个匿名 session。更推荐直接给项目命名:

tmux new-session -s idea_visual

常用简写:

tmux new -s idea_visual
tmux ls
tmux attach -t idea_visual
tmux a -t idea_visual

如果 session 不存在就创建,存在就进入:

tmux new-session -A -s idea_visual

这条命令很适合放进 iTerm2 Profile、shell alias 或项目启动脚本。


三、先掌握默认快捷键

tmux 的默认 prefix 是 Ctrl+b。多数操作都不是直接按,而是:

先按 Ctrl+b,松开,再按目标键

常用默认键:

操作默认快捷键
detach,离开当前 sessionCtrl+b d
新建 windowCtrl+b c
下一个 windowCtrl+b n
上一个 windowCtrl+b p
按编号切 windowCtrl+b 0Ctrl+b 9
重命名 windowCtrl+b ,
关闭当前 pane/windowexitCtrl+d
左右分屏Ctrl+b %
上下分屏Ctrl+b "
在 pane 间切换Ctrl+b o
显示 pane 编号并跳转Ctrl+b q 后按编号
当前 pane 全屏/还原Ctrl+b z
进入复制模式Ctrl+b [
粘贴 tmux bufferCtrl+b ]
命令行模式Ctrl+b :

刚开始不需要记全。先记住这几个就能工作:

Ctrl+b d 离开但不关闭
tmux a 回来
Ctrl+b c 新建 window
Ctrl+b % 左右分屏
Ctrl+b " 上下分屏
Ctrl+b z 当前 pane 全屏
Ctrl+b [ 复制模式

四、session:把项目工作区保留下来

1. 创建、进入、离开

创建一个项目 session:

tmux new -s blog

离开 session:

Ctrl+b d

列出所有 session:

tmux ls

重新进入:

tmux attach -t blog

创建或进入同名 session:

tmux new -A -s blog

2. 重命名与删除

重命名当前 session:

Ctrl+b $

从外部重命名:

tmux rename-session -t old-name new-name

删除一个 session:

tmux kill-session -t blog

删除所有 session:

tmux kill-server

kill-server 会终止 tmux 管理的全部会话,谨慎使用。

3. 推荐命名策略

session 名字不要太抽象。建议直接用项目名或机器名:

idea_visual
api-server
web-console
prod-bastion
staging-k8s

如果你同时做多个分支实验,可以把分支或任务加进去:

blog-main
blog-tmux-post
api-auth-refactor

五、window:给项目任务分层

tmux window 适合放“同一项目里的不同任务”。例如:

0 editor
1 server
2 test
3 logs
4 git

常用操作:

操作默认键
新建 windowCtrl+b c
重命名 windowCtrl+b ,
下一个 windowCtrl+b n
上一个 windowCtrl+b p
按编号切换Ctrl+b 0..9
显示 window 列表Ctrl+b w
关闭当前 window退出所有 pane 或 Ctrl+b &

从命令行创建具名 window:

tmux new-window -n server
tmux new-window -n test
tmux new-window -n logs

在脚本里创建一个简单布局:

tmux new-session -d -s blog -n editor -c "$PWD"
tmux send-keys -t blog:editor "nvim" C-m
tmux new-window -t blog -n server -c "$PWD"
tmux send-keys -t blog:server "npm run start" C-m
tmux new-window -t blog -n git -c "$PWD"
tmux attach -t blog

这里的 -d 表示后台创建,-c "$PWD" 表示窗口从当前目录启动。


六、pane:把同一个任务拆成可观察区域

pane 是 tmux 里最常用的能力。典型布局:

┌─────────────────────────────┬──────────────────────┐
│ │ npm run start │
│ nvim ├──────────────────────┤
│ │ npm run typecheck │
└─────────────────────────────┴──────────────────────┘

默认分屏:

Ctrl+b % 左右分屏
Ctrl+b " 上下分屏
Ctrl+b z 当前 pane 全屏/还原
Ctrl+b x 关闭当前 pane
Ctrl+b q 显示 pane 编号

这里有一个容易误解的地方:tmux 文档里的 split-window -hsplit-window -v 是按拆分方向命名的。-h 表示 horizontal split,结果是生成左右两个 pane;-v 表示 vertical split,结果是生成上下两个 pane。很多 GUI 终端会按分隔线方向描述“垂直/水平分屏”,所以看起来像是反的。日常记忆可以更直接:

split-window -h 左右分屏
split-window -v 上下分屏

调整布局:

Ctrl+b Space 在内置布局间切换
Ctrl+b { 当前 pane 向前交换
Ctrl+b } 当前 pane 向后交换
Ctrl+b ! 把当前 pane 拆成独立 window

默认 pane 切换是 prefix 后再按方向键。很多人会改成 Vim 风格:

Ctrl+h 左
Ctrl+j 下
Ctrl+k 上
Ctrl+l 右

这组键也是 tmux 与 Neovim 配合的关键,后面会给完整配置。


七、复制模式:不用鼠标也能翻历史、复制文本

tmux 每个 pane 都有自己的 scrollback。默认进入复制模式:

Ctrl+b [

如果配置了 Vi 模式,就可以用:

h/j/k/l 移动
Ctrl+u 上翻半页
Ctrl+d 下翻半页
g 到顶部
G 到底部
/ 搜索
n 下一个匹配
N 上一个匹配
Space 开始选择
Enter 复制选中内容
q 退出复制模式

推荐把复制模式改成 Vi 风格,并用 v 开始选择、y 复制:

setw -g mode-keys vi

bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel
bind-key -T copy-mode-vi Escape send-keys -X cancel

macOS 上如果想复制到系统剪贴板,可以用 reattach-to-user-namespace 或更现代的 OSC 52。简单起步可以先交给终端鼠标复制;等习惯 tmux 后再加 tmux-yank 插件。


八、.tmux.conf:把默认配置改成顺手的配置

tmux 配置文件通常是:

~/.tmux.conf

修改后在 tmux 里执行:

Ctrl+b :source-file ~/.tmux.conf

更常见的做法是绑定一个 reload 快捷键:

bind r source-file ~/.tmux.conf \; display-message "tmux config reloaded"

以后按:

Ctrl+b r

就能重新加载配置。

1. 一份可直接使用的基础配置

下面这份配置适合 macOS + iTerm2 + Neovim 用户作为起点:

# Use 256 colors and truecolor when terminal supports it.
set -g default-terminal "screen-256color"
set -ga terminal-overrides ",xterm-256color:RGB"

# Make tmux feel more responsive.
set -sg escape-time 10
set -g focus-events on

# History.
set -g history-limit 50000

# Start window and pane numbering at 1.
set -g base-index 1
setw -g pane-base-index 1
set -g renumber-windows on

# Mouse support: select pane/window, resize pane, scroll history.
set -g mouse on

# Vi-style copy mode.
setw -g mode-keys vi
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel
bind-key -T copy-mode-vi Escape send-keys -X cancel

# Reload config.
bind r source-file ~/.tmux.conf \; display-message "tmux config reloaded"

# Easier splits. Keep the current path when splitting.
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
unbind '"'
unbind %

# Create windows in the current path.
bind c new-window -c "#{pane_current_path}"

# Vim-style pane movement with prefix.
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# Resize panes with repeated prefix bindings.
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

# Quickly maximize the current pane.
bind m resize-pane -Z

# Clear scrollback and screen.
bind C-l send-keys C-l \; clear-history

# A readable status line.
set -g status-position bottom
set -g status-interval 5
set -g status-left-length 40
set -g status-right-length 120
set -g status-left "#[bold] #S #[default]"
set -g status-right "#{pane_current_path} | %Y-%m-%d %H:%M "
set -g window-status-current-format "#[bold] #I:#W "
set -g window-status-format " #I:#W "

这份配置做了几件重要的事:

  • mouse on 让滚动、选择 pane、调整大小更自然;
  • base-index 1 让 window 编号从 1 开始,更贴近键盘数字;
  • split-window -c "#{pane_current_path}" 让新 pane 继承当前目录;
  • |- 比默认的 %" 更容易记;
  • h/j/k/lH/J/K/L 形成移动与 resize 的对应关系;
  • status line 保持克制,只显示 session、window、路径和时间。

2. 是否要把 prefix 从 Ctrl+b 改成 Ctrl+a

很多人会把 prefix 改成 Ctrl+a

unbind C-b
set -g prefix C-a
bind C-a send-prefix

优点:

  • Ctrl+a 更靠近左手小指,按起来更快;
  • 如果你以前用过 GNU screen,会更熟悉;
  • tmux 高频使用时手感更轻。

代价:

  • shell 里 Ctrl+a 默认是移动到行首;
  • Readline、Zsh、Bash、Emacs 用户可能会觉得冲突;
  • 远程机器和默认环境不一致时容易按错。

我的建议:

刚开始:保留 Ctrl+b
高频使用后:再考虑 Ctrl+a
已经习惯 shell 的 Ctrl+a 行首跳转:不要改

如果改成 Ctrl+a,最好给 shell 行首动作留一个替代键,例如在 Zsh/Bash 里继续使用 HomeCtrl+x Ctrl+a,否则你会把终端编辑体验弄乱。


九、快捷键绑定的设计原则

tmux 的快捷键不要只是“能绑定就绑定”。更好的做法是按层级设计。

1. 保留三层边界

Neovim 内部移动: Ctrl+h/j/k/l
tmux 项目内移动: Ctrl+h/j/k/l 或 prefix + h/j/k/l
iTerm2 外层切换: Cmd+Number、Cmd+Option+Number、Cmd+Arrow

不要把 iTerm2、tmux、Neovim 全部改成同一套 prefix。短期看统一,长期会混乱。更稳定的模型是:

层级负责范围推荐键
Neovim编辑器 split/windowCtrl+h/j/k/l
tmux同一项目内的 pane/windowCtrl+h/j/k/l、prefix
iTerm2不同项目、不同机器、临时终端Cmd 系列
macOS应用切换Cmd+Tab

2. 常用操作直接绑定,危险操作保留 prefix

适合无 prefix 直接绑定:

pane 方向切换
少量 resize
复制模式里的 v/y

不建议无 prefix 直接绑定:

kill-pane
kill-session
rename-window
new-session
source-file

原因很简单:移动是高频、低风险;关闭和重命名是低频、高风险。

3. 把键位设计成可推理

推荐:

h/j/k/l 移动 pane
H/J/K/L 调整 pane 大小
| 左右分屏
- 上下分屏
r reload
m maximize

不推荐:

a 打开日志
g resize
u reload
x 新建 window

快捷键不是越短越好,而是要看半年后你还能不能猜出来。


十、Neovim 与 tmux:统一 pane/split 移动

如果你在 Neovim 里也使用 split,最烦的是边界切换:

Neovim split 内部:Ctrl+w h/j/k/l
tmux pane 之间: prefix h/j/k/l

更好的方案是用 vim-tmux-navigator,让 Ctrl+h/j/k/l 同时理解 Neovim split 和 tmux pane。

Neovim lazy.nvim 配置:

return {
{
"christoomey/vim-tmux-navigator",
cmd = {
"TmuxNavigateLeft",
"TmuxNavigateDown",
"TmuxNavigateUp",
"TmuxNavigateRight",
"TmuxNavigatePrevious",
},
keys = {
{ "<C-h>", "<cmd><C-U>TmuxNavigateLeft<cr>", desc = "Move left across nvim/tmux" },
{ "<C-j>", "<cmd><C-U>TmuxNavigateDown<cr>", desc = "Move down across nvim/tmux" },
{ "<C-k>", "<cmd><C-U>TmuxNavigateUp<cr>", desc = "Move up across nvim/tmux" },
{ "<C-l>", "<cmd><C-U>TmuxNavigateRight<cr>", desc = "Move right across nvim/tmux" },
{ "<C-\\>", "<cmd><C-U>TmuxNavigatePrevious<cr>", desc = "Move to previous nvim/tmux pane" },
},
},
}

对应 .tmux.conf

# Smart pane switching with awareness of Vim/Neovim splits.
vim_pattern='(\S+/)?g?\.?(view|l?n?vim?x?|fzf)(diff)?(-wrapped)?'
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
| grep -iqE '^[^TXZ ]+ +${vim_pattern}$'"

bind-key -n C-h if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'
bind-key -n C-j if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'
bind-key -n C-k if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'
bind-key -n C-l if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
bind-key -n C-\\ if-shell "$is_vim" 'send-keys C-\\' 'select-pane -l'

bind-key -T copy-mode-vi C-h select-pane -L
bind-key -T copy-mode-vi C-j select-pane -D
bind-key -T copy-mode-vi C-k select-pane -U
bind-key -T copy-mode-vi C-l select-pane -R
bind-key -T copy-mode-vi C-\\ select-pane -l

这样以后:

Ctrl+h/j/k/l

在 Neovim split 内会移动 Neovim window;到达边界后会继续移动到 tmux pane。这个体验非常接近一个统一 IDE。

注意:如果使用 vim-tmux-navigator,不要再同时保留普通的 Neovim Ctrl+h/j/k/l window 映射,否则同一组按键会互相覆盖。


十一、iTerm2 怎么和 tmux 配合更方便

iTerm2 和 tmux 不是二选一。关键是不要让它们抢同一层职责。

1. iTerm2 负责外层项目入口

iTerm2 保留原生快捷键:

场景推荐 iTerm2 快捷键
新建 tabCmd+T
关闭 tab/windowCmd+W
tab 间切换Cmd+Left/RightCmd+Number
window 间切换Cmd+Option+Number
临时 iTerm2 垂直分屏Cmd+D
临时 iTerm2 水平分屏Cmd+Shift+D
iTerm2 pane 间切换Cmd+Option+ArrowCmd+[ / Cmd+]
最大化当前 iTerm2 paneCmd+Shift+Enter
全局唤起终端Hotkey Window

tmux 负责项目内部:

一个项目里的 editor/server/test/logs:tmux pane/window
不同项目或不同机器:iTerm2 tab/window
临时一次性命令:iTerm2 split 或新 tab

这样最稳定:

  • Ctrl 系列交给 shell/tmux/Neovim;
  • Cmd 系列交给 iTerm2/macOS;
  • 不要让 iTerm2 抢 Ctrl+h/j/k/l
  • 不要把 tmux prefix 绑定成 Cmd 组合键。

2. 用 Profile 自动进入 tmux

在 iTerm2 里可以为常用项目创建 Profile:

iTerm2 Preferences
-> Profiles
-> +
-> General
-> Command: Command

填入:

cd ~/project/ai_project/idea_visual && tmux new-session -A -s idea_visual

以后从这个 Profile 打开的 tab 会自动进入项目目录并 attach 到同名 tmux session。

也可以创建一个通用 shell 函数:

workon() {
if [ -z "$1" ]; then
echo "usage: workon <project-dir-name>"
return 1
fi

local dir="$HOME/project/$1"
if [ ! -d "$dir" ]; then
echo "directory not found: $dir"
return 1
fi

cd "$dir" || return
tmux new-session -A -s "$1"
}

使用:

workon idea_visual
workon api-server
workon frontend-app

如果你的项目路径不统一,可以用更直接的函数:

tmux_here() {
local name
name="$(basename "$PWD" | tr '.:' '__')"
tmux new-session -A -s "$name"
}

进入项目目录后:

tmux_here

3. Hotkey Window + tmux 是一个很舒服的组合

iTerm2 的 Hotkey Window 适合做“随叫随到”的终端入口。建议设置成:

Profile: hotkey
Command: tmux new-session -A -s scratch
Window: floating / full width / top or center

这样你可以随时唤起一个 scratch tmux session:

  • 临时跑命令;
  • 记录短任务;
  • SSH 到机器检查状态;
  • 打开一个长期保留的 REPL;
  • 放一个常驻 AI CLI。

注意:Hotkey Window 里的 tmux session 不要和长期项目 session 混在一起。scratch 就做临时任务,项目仍然用项目名 session。

4. iTerm2 的外观层:Nerd Font + Oh My Posh

iTerm2 的外观不要只理解成配色。真正影响日常可读性的,是字体、图标、prompt 信息密度和 tmux status line 是否协调。

如果你想把 shell prompt 做得更现代,可以用 Oh My Posh themes 作为主题选择入口。Oh My Posh 官方提供了大量内置主题,完整列表可以从主题页跳到 GitHub 查看;带 minimal 的主题通常不依赖 Nerd Font,其他大量主题会使用图标,所以更推荐先配置 Nerd Font。

macOS + iTerm2 的基础步骤:

brew install jandedobbeleer/oh-my-posh/oh-my-posh
oh-my-posh font install meslo

然后到 iTerm2 里把 Profile 字体改成安装好的 Nerd Font:

iTerm2 Preferences
-> Profiles
-> Text
-> Font

如果你更喜欢和我的 dotfiles 保持一致,可以用 Hack Nerd Font Mono。我的 dotfiles 里也提供了修复终端字体的脚本,目标字体名是 HackNFM-Regular 12,用于解决 NvChad 图标或终端图标显示成 ? 的问题。

Zsh 中启用 Oh My Posh 的方式是把 init 放到 ~/.zshrc 末尾:

eval "$(oh-my-posh init zsh)"

如果要指定主题,可以先从主题页挑一个名字,例如 catppuccintokyopowerlevel10k_modernpure,再写成:

eval "$(oh-my-posh init zsh --config catppuccin)"

更稳的做法是把主题导出成本地配置,避免每次 shell 启动时依赖远端主题解析:

mkdir -p ~/.config/oh-my-posh
oh-my-posh config export --config catppuccin --output ~/.config/oh-my-posh/catppuccin.omp.json

eval "$(oh-my-posh init zsh --config ~/.config/oh-my-posh/catppuccin.omp.json)"

如果你已经在用 Oh My Zsh,建议把 ZSH_THEME 设为空或保留一个很轻的主题,然后让 Oh My Posh 作为最后的 prompt 渲染层:

ZSH_THEME=""
source $ZSH/oh-my-zsh.sh
eval "$(oh-my-posh init zsh --config ~/.config/oh-my-posh/catppuccin.omp.json)"

在 iTerm2 + tmux 组合里,我建议把信息分成两层:

层级放什么信息不建议放什么
Oh My Posh prompt当前目录、Git branch、Git dirty 状态、语言版本、命令耗时太长的 Kubernetes/context 信息
tmux status linesession、window、pane path、时间、少量运行状态和 prompt 重复的 Git branch

也就是说,prompt 关注“当前命令上下文”,tmux status line 关注“当前工作区上下文”。两边都显示同一组信息,会浪费横向空间。

5. 用我的 dotfiles 复现这套工作流

我的个人配置放在 RainLib/dotfiles。这个仓库用 chezmoi 管理 dotfiles,覆盖 zsh、Neovim、tmux、WezTerm、Kitty、Ghostty、Alacritty 等终端和编辑器配置。

新机器上可以这样初始化:

brew install chezmoi
chezmoi init https://github.com/RainLib/dotfiles.git
chezmoi apply -v

也可以一步完成:

chezmoi init --apply https://github.com/RainLib/dotfiles.git

这个 dotfiles 里和 iTerm2/tmux 最相关的点是:

  • macOS 脚本会安装 iTerm2、tmux、TPM、Nerd Fonts 等依赖;
  • tmux 主配置来自 dot_tmux.conf,实际落地为 ~/.tmux.conf
  • tmux prefix 使用 Ctrl+s,不是默认的 Ctrl+b
  • tmux 插件包含 tmux-plugins/tpmcatppuccin/tmuxchristoomey/vim-tmux-navigator
  • Neovim 和 tmux 都使用 vim-tmux-navigator,所以 Ctrl+h/j/k/l 可以跨 Neovim split 和 tmux pane 移动;
  • scripts/fix-terminal-fonts.sh 可以修复 iTerm2 字体,避免 Nerd Font 图标显示异常。

如果只想应用 tmux 和 Neovim 的相关配置,可以从 dotfiles 仓库根目录执行:

sh scripts/apply.sh ~/.tmux.conf ~/.config/nvim
tmux source-file ~/.tmux.conf

然后检查 tmux prefix 和跨 pane 绑定:

tmux show -g prefix
tmux list-keys -T root C-h

期望结果是:

prefix C-s
C-h 绑定到 if-shell ... select-pane -L

当前 dot_zshrc 使用的是 Oh My Zsh 主题 mgutz,并保留了 starship 初始化的注释。如果你想切到 Oh My Posh,就把上面 Oh My Posh 初始化放到 dot_zshrc 末尾,再通过 chezmoi apply 下发:

chezmoi cd
# 编辑 dot_zshrc
chezmoi apply -v ~/.zshrc
exec zsh

这样做的好处是:iTerm2 的字体、tmux 的 pane 导航、Neovim 的 split 导航、Zsh prompt 主题都放回 dotfiles 管理,不会散落在不同机器的手工设置里。

6. iTerm2 的 tmux Integration:什么时候用 tmux -CC

iTerm2 支持 tmux Control Mode,可以用原生 iTerm2 tab/window/pane 显示 tmux 会话:

tmux -CC new -A -s idea_visual

或进入已有 session:

tmux -CC attach -t idea_visual

优点:

  • tmux window 可以映射成 iTerm2 tab/window;
  • 可以用更多 iTerm2 原生 UI;
  • 对喜欢 GUI tab 的用户更自然。

代价:

  • 行为和普通 tmux 有差异;
  • 跨机器、跨终端迁移时不如普通 tmux 直观;
  • 排查问题时要区分普通 tmux 与 iTerm2 Control Mode;
  • 部分 tmux 插件、状态栏、复制体验可能需要额外适配。

我的建议:

刚建立稳定工作流:用普通 tmux
已经熟悉 tmux 后:再试 tmux -CC
经常 SSH 到 Linux 服务器:优先普通 tmux
主要本机 macOS 开发,喜欢 iTerm2 原生 tab:可以试 tmux -CC

普通 tmux 的迁移性更好,tmux -CC 更像 iTerm2 用户的增强模式。


十二、插件:少装,但装对

tmux 不需要一上来装很多插件。先把原生能力用顺,再考虑插件。

常见插件:

插件作用是否推荐
tmux-plugins/tpmtmux plugin manager需要插件时再装
tmux-plugins/tmux-sensible一组合理默认值可选
tmux-plugins/tmux-yank复制到系统剪贴板macOS 常用
tmux-plugins/tmux-resurrect保存/恢复 session 布局长期工作区推荐
tmux-plugins/tmux-continuum自动保存/恢复谨慎使用
christoomey/vim-tmux-navigatorNeovim/tmux pane 无缝切换Neovim 用户强烈推荐

TPM 安装方式:

git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm

.tmux.conf 中加入:

set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-yank'
set -g @plugin 'tmux-plugins/tmux-resurrect'

run '~/.tmux/plugins/tpm/tpm'

重新加载配置后,在 tmux 里按:

Ctrl+b I

安装插件。

我的取舍建议:

只想稳定工作:不装插件也可以
需要系统剪贴板:tmux-yank
需要恢复布局:tmux-resurrect
Neovim 重度用户:vim-tmux-navigator
不想维护复杂状态:暂时别上 continuum

十三、推荐工作区布局

1. 普通 Web 项目

session: idea_visual

window 1: editor
pane 1: nvim
pane 2: npm run start
pane 3: npm run typecheck

window 2: git
pane 1: git status / lazygit

window 3: logs
pane 1: server logs

可以用命令创建:

session="idea_visual"

tmux new-session -d -s "$session" -n editor -c "$PWD"
editor_pane="$(tmux display-message -p -t "$session:editor" "#{pane_id}")"
tmux send-keys -t "$editor_pane" "nvim" C-m

server_pane="$(tmux split-window -h -t "$editor_pane" -c "$PWD" -P -F "#{pane_id}")"
tmux send-keys -t "$server_pane" "npm run start" C-m

test_pane="$(tmux split-window -v -t "$server_pane" -c "$PWD" -P -F "#{pane_id}")"
tmux send-keys -t "$test_pane" "npm run typecheck" C-m

tmux select-pane -t "$editor_pane"
tmux new-window -t "$session" -n git -c "$PWD"
tmux send-keys -t "$session:git" "git status" C-m
tmux attach -t "$session"

这里用 #{pane_id} 捕获真实 pane ID,而不是写死 editor.1editor.2editor.3。这样无论你的 pane-base-index 是默认的 0,还是前面配置里的 1,脚本都能正常运行。

2. AI Coding 工作区

如果你用 Codex CLI、Claude Code CLI 或其他终端 Agent,建议给它独立 pane:

┌──────────────────────────────┬──────────────────────────────┐
│ │ codex / claude │
│ nvim │ │
│ ├──────────────────────────────┤
│ │ npm test / npm run build │
└──────────────────────────────┴──────────────────────────────┘

原因:

  • AI CLI 输出很长,独立 pane 更容易观察;
  • 修改文件后可以立刻在 Neovim 里 review;
  • 测试 pane 可以持续跑验证命令;
  • tmux session 可以保留 AI CLI 的上下文和日志。

3. 远程服务器工作区

远程机器上尤其适合 tmux:

ssh user@server
tmux new -A -s ops

建议在远程 session 里分 window:

1 shell
2 logs
3 docker
4 k8s
5 db

远程机器上不要太依赖 iTerm2 专有能力,因为你可能从不同终端进入。tmux 原生命令和 .tmux.conf 才是最可迁移的部分。


十四、常见问题

1. 为什么 tmux 里颜色不对

先检查外层终端:

echo $TERM

iTerm2 通常是 xterm-256color。tmux 里可以配置:

set -g default-terminal "screen-256color"
set -ga terminal-overrides ",xterm-256color:RGB"

如果你的 Neovim 主题需要 truecolor,再确认:

:set termguicolors?

2. 为什么 Esc 或 Vim 模式有延迟

加入:

set -sg escape-time 10

默认 escape-time 偏保守,会让 Vim/Neovim 用户感觉 Esc 反应慢。

3. 为什么新 pane 没有在当前目录打开

split 绑定里要加 -c "#{pane_current_path}"

bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
bind c new-window -c "#{pane_current_path}"

4. 鼠标滚动进入了 shell 历史而不是 tmux 历史

开启 mouse:

set -g mouse on

然后滚动时 tmux 会进入 pane 的 scrollback。需要复制时,可以用 tmux copy mode,也可以按住 Option 绕过 tmux 让 iTerm2 直接选择文本。

5. SSH 断开后怎么恢复

重新 SSH,再 attach:

ssh user@server
tmux ls
tmux attach -t ops

如果你之前只是 detach 或网络断开,进程仍然在 session 里。

6. 什么时候不用 tmux

下面这些场景 iTerm2 原生能力就够:

  • 只是临时跑一条命令;
  • 只需要本机短期 split;
  • 不需要保留工作现场;
  • 不使用 SSH;
  • 项目没有长期运行的服务、日志、测试。

tmux 的价值来自“持久工作区”。如果没有持久化需求,不必强行套一层。


十五、最终推荐配置

如果你想快速落地,可以按这个顺序:

  1. 安装 tmux。
  2. 使用 tmux new -A -s project-name 管理每个项目。
  3. 保留 iTerm2 的 Cmd 系列快捷键,别让它抢 tmux/Neovim 的 Ctrl 系列。
  4. .tmux.conf 开启 mouse、Vi copy mode、当前目录分屏。
  5. 把分屏改成 |-
  6. h/j/k/l 做 pane 移动,H/J/K/L 做 resize。
  7. 如果用 Neovim,安装 vim-tmux-navigator,统一 Ctrl+h/j/k/l
  8. 高频项目用 iTerm2 Profile 自动执行 cd project && tmux new -A -s project
  9. 给 iTerm2 配好 Nerd Font,再按需接入 Oh My Posh themes。
  10. 用 dotfiles/chezmoi 管理 ~/.zshrc~/.tmux.conf~/.config/nvim,避免多台机器配置漂移。
  11. 需要恢复布局时再引入 tmux-resurrect

最小可用命令只有三条:

tmux new -A -s idea_visual
tmux ls
tmux attach -t idea_visual

最核心的心智模型也只有一句:

iTerm2 管外层入口,tmux 管项目现场,Neovim 管代码编辑。

把这条边界守住,终端工作流会稳定很多。

Logo
RainLib

探索技术、设计与分布式系统的边界。构建面向未来的开发者工具。

留言与建议

© 2026 RainLib. 为未来构建。(Built for the Future)
版权所有。
系统正常