当 AI 替你写代码之后,你需要一个好的终端管理工具
一个正在发生的变化
AI agent 的编程能力到了一个临界点。越来越多开发者的日常变成了:在终端里打开 Claude Code,用自然语言告诉它要做什么,它自己去读代码、改代码、跑测试、修 bug。描述需求、看它做、追问、确认、下一个任务——编辑器几乎不碰,文件树几乎不翻。
IDE 那个大窗口开始闲置了。真正在用的就是终端,里面跑着和 AI 的对话。
当一整天都在终端里工作,同时跑着 3-5 个项目的 AI 对话,“管理终端窗口”就变成了一个真实的需求。
tmux 就是干这个的——终端多路复用器,在一个终端里管理多个会话、多个窗口、多个分屏。下面是用下来觉得最有用的几段配置,按实际遇到问题的顺序来聊。
开了 5 个项目的对话,切来切去找不到哪个是哪个
这是我切到终端工作流之后最先遇到的问题。
我通常同时开着 engineering、creation、research、skills 等十来个 session,每个对应一个工作台。但 tmux 默认状态栏只显示当前 session——[engineering] 0:ai-brain*。其他 session 在哪、在干什么,一概看不到。
pane 也一样——开了 3 个 pane,一个跑着 Claude Code,一个跑着 dev server,一个是空 shell,外表上分不清。
解法是把状态栏改成一排”session 标签页”,鼠标点哪个切哪个,当前 session 金色高亮。pane 顶部边框显示当前在跑什么命令、在哪个目录:

核心是两个小脚本 + 状态栏配置。脚本放在 ~/.config/tmux/scripts/ 下,chmod +x:
session_list.sh — 生成状态栏 session 标签:
#!/bin/bash
SLOT_WIDTH=14
NAME_WIDTH=$((SLOT_WIDTH - 2))
current=$(tmux display-message -p '#S' 2>/dev/null)
tmux list-sessions -F "#{session_name}" 2>/dev/null | while IFS= read -r name; do
short="${name:0:$NAME_WIDTH}"
if [ "$name" = "$current" ]; then
printf "#[bold,fg=colour235,bg=colour220] %-${NAME_WIDTH}s #[default]" "$short"
else
printf "#[fg=colour245,bg=colour235] %-${NAME_WIDTH}s #[default]" "$short"
fi
done
session_click.sh — 鼠标点击切换 session:
#!/bin/bash
# 整除计算假设 status-left 从终端最左端 x=0 开始
# 如果状态栏有额外左侧 padding,可能偏移一个 session
MOUSE_X="$1"
SLOT_WIDTH=14
index=$((MOUSE_X / SLOT_WIDTH))
session=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | awk "NR==$((index + 1))")
[ -n "$session" ] && tmux switch-client -t "$session"
tmux.conf:
set -g status-interval 2
set -g status-left-length 200
set -g status-left "#(~/.config/tmux/scripts/session_list.sh)"
set -g status-right "#{?client_prefix,#[bold,fg=colour235,bg=colour220] PREFIX #[default] ,} %H:%M "
setw -g window-status-current-format '#[bold,fg=colour220] #I:#W #[default]'
setw -g window-status-format ' #I:#W '
set -g pane-border-status top
set -g pane-border-format ' #{pane_current_command} #{b:pane_current_path} '
set -g pane-active-border-style 'fg=colour220'
set -g pane-border-style 'fg=colour240'
bind -n MouseDown1StatusLeft run-shell "~/.config/tmux/scripts/session_click.sh #{mouse_x}"
还有一个小问题:Claude Code 在后台跑任务时你切去了别的 window,跑完了你不知道。所以我在 window 状态栏上加了红点通知——任务完成时对应 window 名前会亮一个 ●,切过去红点自动消:
# Claude Code 完成通知:window 名前显示红点
setw -g window-status-format '#{?#{==:#{@claude_notify},1},#[fg=colour196]● #[fg=colour245], }#I:#W '
# 切到对应 window 时自动清除
set-hook -g after-select-window 'set-option -w @claude_notify 0'
set-hook -g client-session-changed 'set-option -w @claude_notify 0'
改完之后,一眼就能看到所有 session、当前在哪、每个 pane 在跑什么、哪个 AI 任务刚跑完。
tmux 默认配置的一堆历史遗留问题
状态栏搞定之后,接下来就是被 tmux 的默认行为反复绊。
没有鼠标支持——不能点击切 pane,不能拖拽调大小。回滚缓冲区只有 2000 行——Claude Code 跑一个复杂任务的输出轻松超过这个数。ESC 延迟 500ms——在终端里用 Vim 编辑什么东西时按 ESC 要等半秒。窗口编号从 0 开始——键盘最左边是 1 不是 0。不支持真彩色——Vim 主题颜色偏移。
这组设置基本是”装完 tmux 第一件事”,一次性解决:
set -g mouse on # 开鼠标
set -g history-limit 200000 # 回滚 20 万行(AI 输出很长,这个很有必要)
set -s escape-time 5 # ESC 延迟降到 5ms
set -s focus-events on # 让 Vim 感知焦点变化
set -g base-index 1 # window 从 1 编号
setw -g pane-base-index 1 # pane 也从 1
set -g renumber-windows on # 关窗口后重编号
setw -g automatic-rename on # window 名跟随进程
set -g set-titles on
set -g display-time 2000
set -g default-terminal "tmux-256color"
# RGB 真彩色——如果不生效,检查 echo $TERM 是否匹配 *256col*
# 不匹配的话改成具体值如 ",xterm-256color:RGB"
set -as terminal-features ",*256col*:RGB"
# 个人偏好:复制模式 vim 键位,命令行 emacs 键位
# 不用 vim 的删掉 mode-keys 这行
set -g mode-keys vi
set -g status-keys emacs
改完之后这些绊脚石就没了。
Prefix 键跟 Vim 抢键
tmux 默认 Prefix 是 Ctrl+b。问题是 Vim 里 Ctrl+b 是翻页。在 tmux 内的 Vim 里按 Ctrl+b,tmux 会先拦截这个键作为 Prefix——Vim 收不到,什么都没发生。
我换成了 Ctrl+\:
unbind C-b
set -g prefix 'C-\'
bind 'C-\' send-prefix
这个键 Vim 和 Bash 都不用,在键盘右手区单手就能按。顺便加个 bind r 重载配置,改完不用重启 tmux:
bind r source-file ~/.tmux.conf \; display '✓ 配置已重载'
一个细节
Ctrl+\在终端里默认是 SIGQUIT 信号。绑定为 Prefix 后 tmux 会拦截它,SIGQUIT 不再生效。日常几乎用不到 SIGQUIT,但如果你的工作流依赖这个信号,需要换一个 Prefix。
最常用的操作每次要两步,太慢了
tmux 的默认设计是所有操作先按 Prefix。切窗口 Prefix + 1,分屏 Prefix + %,新建窗口 Prefix + c。
当你一天的工作就是在几个 AI 对话之间切来切去,这个”每次多按一步 Prefix”的成本很快就累积起来了。更烦的是 Prefix + % 是左右分割、Prefix + " 是上下分割——谁能记得住。
我把高频操作全部绑到 Alt+X,一键直达:
macOS 用户注意
macOS 终端默认不发送 Alt 键。需要在终端设置里把 Option 改为 Meta/Alt(iTerm2: Profiles → Keys → Left Option → Esc+),否则以下快捷键全部不生效。
# ── Session ──
bind -n M-s choose-session # Alt+s session 列表
bind -n M-n command-prompt -p "新建 session:" "new-session -s '%%'" # Alt+n 新建
bind -n M-, switch-client -p # Alt+, 上一个
bind -n M-. switch-client -n # Alt+. 下一个
# ── Window ──
# Alt+1~9 直接跳到对应窗口(下面只列 1~5,6~9 同理)
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
bind -n M-'{' previous-window # Alt+{ / } 前后切
bind -n M-'}' next-window
bind -n M-o new-window -c "#{pane_current_path}" # Alt+o 新建(继承路径)
# ── Pane ──
bind -n M-f resize-pane -Z # Alt+f 缩放/还原
bind -n 'M-\' split-window -h -c "#{pane_current_path}" # Alt+\ 左右分(\ 像竖线)
bind -n M-- split-window -v -c "#{pane_current_path}" # Alt+- 上下分(- 像横线)
Alt+1 直接跳窗口 1,Alt+\ 左右分割,Alt+- 上下分割。键位本身就是助记符——竖线分左右,横线分上下。
偶尔要做管理操作,但记不住命令
有些操作不常用但用到时很头疼:关 pane 没有确认提示(误按直接杀)、想把 pane 拆成独立窗口得 Google break-pane、想同时向多个 pane 发命令得 Google synchronize-panes。
这些放在 Prefix 后面,低频操作不需要一键直达:
bind q confirm-before -p "关闭 pane?(y/n)" kill-pane
bind '\' command-prompt -p "重命名 window:" "rename-window '%%'"
bind / command-prompt -p "重命名 session:" "rename-session '%%'"
bind Space next-layout
bind w choose-tree -Z
bind ! break-pane # pane 拆成独立 window
bind @ command-prompt -p "合并到 window:" "join-pane -t ':%%'"
bind m command-prompt -p "移动到 session:" "move-window -t '%%'"
# 同步输入:同时向所有 pane 发命令,开启时边框变红提醒
bind g if-shell '[[ $(tmux showw synchronize-panes | cut -d\ -f2) == "on" ]]' \
'setw synchronize-panes off; set -g pane-active-border-style fg=colour220; display "同步输入:关闭"' \
'setw synchronize-panes on; set -g pane-active-border-style fg=red; display "同步输入:开启(边框变红)"'
Prefix + g 开启同步输入后,你在一个 pane 里打的字会同时发到所有 pane。边框变红提醒你别忘了关。
电脑重启后所有对话窗口全丢
这是最痛的一个。
你花了一个小时精心布好了 5 个 session 的窗口布局——每个项目的 Claude Code 对话在哪个 window、dev server 在哪个 pane、日志在哪个 pane。然后电脑更新重启了,或者 tmux server 意外退出。
打开 tmux——空的。所有布局消失,得从头重建。
# 先装 TPM(只需要一次):
# git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @continuum-save-interval '15' # 每 15 分钟自动保存
set -g @continuum-restore 'on' # 启动时自动恢复
set -g @resurrect-capture-pane-contents 'on' # 保存 pane 输出快照
run '~/.tmux/plugins/tpm/tpm'
# 安装插件:tmux 内按 Prefix + I(大写 i)
一个重要限制
resurrect 恢复的是布局、路径和输出快照,但正在运行的进程不会恢复。比如之前跑着
npm run dev,重启后目录对了但进程需要手动重启。这是终端进程的本质限制,不是 bug。
最耗时的”建 session、开 window、分 pane、cd 到正确目录”全自动了,剩下的”重启几个命令”很快。
一个锦上添花的小功能
有时候想临时跑个 git log 或 ls 看一眼什么东西,但不想为此新建一个 pane 打乱现有布局。
bind -n M-e display-popup -w 80% -h 40% -d "#{pane_current_path}" -E
Alt+e 弹出一个浮动终端,继承当前路径,exit 后自动消失。用完即走,零残留。