git worktree + CLI Agent 并行工作模式
用 git worktree 跑多个并行 CLI Agent,避免分支切换打断上下文,含 worktree 管理、Agent 隔离与合并策略
用 tmux 把多个 Agent 会话排在一个终端里,session/window/pane 三层抽象的实操,附常用快捷键速查
内容摘要
**tmux**(terminal multiplexer,终端复用器)是一款 2007 年由 Nicholas Marriott 发起、用 C 写的开源工具,运行在几乎所有 Unix-like 系统上。它干的事一句话能说清:**让你在一个终端窗口里塞下任意多个 shell 会话,并且这些会话即使你关掉终端、断了 SSH,也会继续在后台跑**。
tmux(terminal multiplexer,终端复用器)是一款 2007 年由 Nicholas Marriott 发起、用 C 写的开源工具,运行在几乎所有 Unix-like 系统上。它干的事一句话能说清:让你在一个终端窗口里塞下任意多个 shell 会话,并且这些会话即使你关掉终端、断了 SSH,也会继续在后台跑。
为什么这件事和 CLI Agent 这么相关?因为 2026 年起主流的终端 Agent(Claude Code、Codex CLI、Gemini CLI)几乎都是长跑型进程:一次任务可能要跑十几分钟到几个小时,期间不停拉模型、跑工具、读日志。如果没有 tmux,你会面临三个非常具体的痛点:
npm test --watch + 再开一个 Agent 审 PR」就得开三个终端窗口,注意力来回切。tmux 用三层抽象把这些问题一次解决:session(会话) → window(窗口) → pane(窗格)。
| 要素 | 作用 | 类比 |
|---|---|---|
| Session(会话) | 一组 window 的集合,是 detach/attach 的最小单位;tmux 服务进程内可以有多个 session 同时活着 | 浏览器的「窗口」 |
| Window(窗口) | 一个 session 内的一个标签页,每个 window 占满整个终端区域 | 浏览器里的「标签页」 |
| Pane(窗格) | window 内的一块矩形区域,每个 pane 是一个独立 shell | 标签页里的「分屏」 |
| Prefix Key(前缀键) | 默认 Ctrl-b,所有 tmux 快捷键都要先按 prefix 再按动作键 | Vim 的 : 命令模式触发器 |
| detach / attach | 把 session 从当前终端「摘下来」放进后台,下次再「贴回」任意终端 | 把电脑屏幕拔掉,进程仍在主机里跑 |
记一个口诀就够:一个 tmux server 里有多个 session,一个 session 里有多个 window,一个 window 里有多个 pane。三层从大到小,越往下越细。
下面这张图是最常见的「主控 Agent + 监控 + 副 Agent」三 pane 布局,也是后面代码示例的目标:
关键点:Agent 跑在 pane 里,pane 归属 window,window 归属 session,session 归属后台 server。你 detach 之后,整个 server 还在跑,所有 Agent 一行不停;你下次从家里的 Mac SSH 过来,tmux attach 一下,画面原样回来。
下面这套是最小工作流:装包 → 开 session → 切分 pane → 启动 Agent → detach → 再 attach。
# 1. 安装(按系统选一条)
sudo apt install tmux # Debian / Ubuntu
brew install tmux # macOS
sudo dnf install tmux # Fedora / RHEL
# 2. 开一个命名 session 并直接 attach
tmux new -s project-foo
# 3. 进入 session 后,所有快捷键都要先按 prefix(默认 Ctrl-b)
# Ctrl-b " → 当前 pane 上下分屏
# Ctrl-b % → 当前 pane 左右分屏
# Ctrl-b o → 在 pane 之间循环切换
# Ctrl-b 方向键 → 按方向跳到相邻 pane
# 4. 在第一个 pane 里启动主力 Agent
claude
# 5. 切到第二个 pane 启动测试监控
npm run test:watch
# 6. 切到第三个 pane 跟日志
tail -f logs/server.log
# 7. 想离开但 Agent 别停?detach 即可
# Ctrl-b d
# 回到普通 shell,session 仍在后台跑
# 8. 下次再贴回来
tmux ls # 看后台有哪些 session
tmux attach -t project-foo # 贴回指定 session
预期行为:执行 tmux ls 时,即使你关掉过终端、重启过 SSH,只要 tmux server 没被杀,输出会类似:
project-foo: 1 windows (created Wed Apr 22 10:14:08 2026)
side-task: 1 windows (created Wed Apr 22 11:02:31 2026)
下面这张表是日常 80% 的操作,背完它 tmux 就够用了。所有动作都要先按 prefix(默认 Ctrl-b):
| 类别 | 快捷键 | 作用 |
|---|---|---|
| Session | Ctrl-b d | detach 当前 session(最常用) |
| Session | Ctrl-b s | 弹出 session 列表,可视化切换 |
| Session | Ctrl-b $ | 重命名当前 session |
| Window | Ctrl-b c | 新建 window |
| Window | Ctrl-b n / p | 下一个 / 上一个 window |
| Window | Ctrl-b 0…9 | 跳到编号窗口 |
| Window | Ctrl-b , | 重命名当前 window |
| Window | Ctrl-b w | 弹出 window 列表 |
| Pane | Ctrl-b " | 上下切分当前 pane |
| Pane | Ctrl-b % | 左右切分当前 pane |
| Pane | Ctrl-b o / 方向键 | 在 pane 间切换 |
| Pane | Ctrl-b z | 把当前 pane 临时全屏 / 还原 |
| Pane | Ctrl-b x | 关闭当前 pane(会问 y/n) |
| Pane | Ctrl-b { / } | 把 pane 在 window 内位置左移 / 右移 |
| Pane | Ctrl-b Ctrl-方向键 | 调整 pane 大小(按住 Ctrl) |
| 复制 | Ctrl-b [ | 进入 copy 模式(方向键移动,空格选中,回车复制) |
| 复制 | Ctrl-b ] | 把 tmux 缓冲区粘贴到当前 pane |
| 命令 | Ctrl-b : | 进入命令行模式(输入 kill-session 等) |
| 帮助 | Ctrl-b ? | 列出所有快捷键 |
小贴士:
Ctrl-b在终端里要双手按,长期用很累,多数人会把 prefix 改成Ctrl-a(screen 沿用习惯)或Ctrl-Space,下面的配置示例里就这么改。
把以下内容存到 ~/.tmux.conf,再执行 tmux source ~/.tmux.conf(或重启 tmux):
# ---- 基础体验 ----
# 把 prefix 从 Ctrl-b 改为 Ctrl-a,单手好按
unbind C-b
set -g prefix C-a
bind C-a send-prefix
# 鼠标模式:可以用鼠标点 pane、拖边框调大小、滚轮翻屏
set -g mouse on
# 256 色 + 24-bit 真彩,避免 Claude Code 的高亮色变怪
set -g default-terminal "tmux-256color"
set -ga terminal-overrides ",xterm-256color:Tc"
# Vim 用户必加:把 Esc 键的延迟降到 10ms,避免按 Esc 后卡顿
set -s escape-time 10
# 历史滚屏从 2000 行加到 50000 行(看长 Agent 输出很有用)
set -g history-limit 50000
# window / pane 编号从 1 开始,键盘上更顺手
set -g base-index 1
setw -g pane-base-index 1
# ---- 更顺手的分屏键 ----
# 用 | 和 - 直观地竖切 / 横切,新 pane 默认进当前目录
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
# 用 hjkl 在 pane 间切换(Vim 风)
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
把下面这段存成 agents.sh,chmod +x agents.sh && ./agents.sh,三秒钟摆好「主 Agent + 测试 + 日志」三 pane 布局:
#!/usr/bin/env bash
# agents.sh —— 在一个 tmux session 里同时拉起 Claude Code、测试 watcher、日志 tail
set -euo pipefail
SESSION="agents"
PROJECT_DIR="${1:-$PWD}"
# 如果 session 已经在了,直接 attach,不要重复建
if tmux has-session -t "$SESSION" 2>/dev/null; then
exec tmux attach -t "$SESSION"
fi
# 1. 创建后台 session,第一个 pane 进项目目录
tmux new-session -d -s "$SESSION" -c "$PROJECT_DIR" -n dev
# 2. 在 pane 0 启动 Claude Code
# 用 split-window -- 直接跑命令,比 send-keys 更稳,没有 shell 还没起来就发命令的时机问题
tmux send-keys -t "$SESSION":dev.0 "claude" C-m
# 3. 右边切一个 pane 跑 npm test --watch
tmux split-window -h -t "$SESSION":dev -c "$PROJECT_DIR"
tmux send-keys -t "$SESSION":dev.1 "npm run test:watch" C-m
# 4. 右下再切一个 pane 跟日志
tmux split-window -v -t "$SESSION":dev.1 -c "$PROJECT_DIR"
tmux send-keys -t "$SESSION":dev.2 "tail -f logs/server.log" C-m
# 5. 焦点回到主 Agent,方便上来就敲提示词
tmux select-pane -t "$SESSION":dev.0
# 6. attach 进去
exec tmux attach -t "$SESSION"
实战注意:Agent 启动命令通过
send-keys发送时,如果 shell 还没初始化完,命令文本可能只「贴」进 pane 但不执行。Anthropic 在 2026-03 的 Agent Teams 实践里就遇到过这个 bug(claude-code#40168)。规避办法是优先用tmux split-window -- <command>直接拉起进程,或者在 send-keys 之前 sleep 200ms。
tmux 不是唯一的终端复用器,2026 年的局面已经演化成「老将 + 新锐 + 编辑器内置」三种路线:
| 维度 | tmux | GNU screen | Zellij | WezTerm 内置 split |
|---|---|---|---|---|
| 首发 / 当前活跃度 | 2007,长期活跃维护 | 1987,几乎冻结 | 2021,Rust 写的,2026 年 0.41+ 活跃迭代 | 终端 emulator 自带 |
| 安装 | 几乎所有 Linux/macOS 自带或一行装 | 同左 | 需独立安装,部分发行版还没包 | 装 WezTerm 即获得 |
| 默认 prefix | Ctrl-b | Ctrl-a | 模式切换式(Ctrl-p 进 pane 模式等) | 终端原生快捷键 |
| 学习曲线 | 高,靠记快捷键 | 高 | 低,屏幕底部有持续提示 | 低 |
| 配置文件 | ~/.tmux.conf 命令式 | ~/.screenrc | ~/.config/zellij/config.kdl 声明式 | ~/.wezterm.lua |
| 脚本化(建 session、send-keys) | 极强,CLI 子命令完整 | 一般 | 中(有 zellij action) | 弱 |
| 远程 / SSH detach | ✅ 核心场景 | ✅ | ✅ | ❌ 终端本地,断开 SSH 就没 |
| 内存占用 | 极小 | 极小 | 略高(Rust + WASM 插件) | 由终端决定 |
| 插件生态 | 巨大(tpm、catppuccin、resurrect 等) | 几乎无 | 中等,WASM 插件机制 | N/A |
| 适合人群 | 重度 SSH、服务器侧 Agent、追求可脚本化 | 仅维护老系统 | 想要现代 UX、不想啃配置 | 本地开发为主,不下服务器 |
核心区别用一句话说:
简单的选型规则:本地 + 想要好看的 UX 选 Zellij;要 SSH 上服务器跑 Agent / 要写脚本拉起一堆 pane 选 tmux。
| 误区 | 准确理解 |
|---|---|
以为 Ctrl-b d 是「关闭」 | d 是 detach,session 和里面的 Agent 都还在后台跑;真的要杀要用 tmux kill-session -t <name> |
| 以为 SSH 断了 Agent 就死了 | 只要进程是在 tmux session 里启动的,SSH 断开 tmux server 还在,Agent 继续跑;这是 tmux 的核心价值 |
| 把 prefix key 当成普通快捷键直接按 | 所有 tmux 快捷键都是「先按 prefix,松手,再按动作键」两段式;连按或同时按都不行 |
| 在 pane 里用鼠标选中以为复制成功了 | 不开 mouse on 时鼠标无效;开了之后用鼠标拖选只是把内容放进 tmux 缓冲区,要粘到系统剪贴板需要再配 yank 之类插件,或者按住 Shift 用终端原生选择跳过 tmux |
以为 tmux 命令每次都开新 server | 同一台机器只有一个 tmux server,所有 session 共享它;tmux ls 看到的就是这个 server 内的全部 session |
把脚本里 send-keys 当成原子操作 | send-keys 发完立刻返回,不等命令执行完;启动 Agent 时如果新 pane 的 shell 还没起来,命令会丢失。优先用 split-window -- "claude" 这种直接拉进程的写法 |
| 以为 window 和 pane 是一回事 | window 是占满终端的「标签页」,pane 是 window 内部的「分屏」;杀掉一个 pane 不会影响同 window 其他 pane,但杀掉 window 内最后一个 pane 等于关 window |
| 优势 | 劣势 |
|---|---|
| 断网保命:SSH 一断 Agent 全死的痛苦永远再见,长任务可以放心晚上跑 | 快捷键密度高:第一次用要面对 Ctrl-b + 几十个动作键,没有屏幕提示,纯靠记 |
| 三层模型干净:session/window/pane 清晰对应「项目/任务/视图」,自然适配 Agent 多任务并行 | 复制粘贴反人类:默认配置下选中、复制、粘贴和系统剪贴板的对接需要额外配置,新手最容易劝退的一点 |
脚本化能力极强:new-session、split-window、send-keys、select-pane 一整套子命令,可以一行命令拉起完整工作区 | 配置文件命令式:.tmux.conf 是一行一行 set -g xxx,不像 Zellij 的 KDL 一目了然,diff 起来也累 |
| 几乎全平台:Linux/macOS/WSL/服务器全都能装,云上 IaaS 镜像基本自带 | 默认外观寒酸:开箱即用的状态栏、配色、边框线都很丑,要花时间美化(或装 tpm + 主题) |
| 生态成熟:tpm 插件管理器、resurrect 持久化、catppuccin 配色、agent-teams 等大量项目基于它构建 | windows 体验差:原生不支持 Windows,要走 WSL 或 Cygwin;纯 Windows 用户更适合 Windows Terminal 自带分屏 + Zellij |
| 资源占用极低:一个 tmux server 内存通常只占几十 MB,挂十几个 session 也不感觉 | 多 server 容易混淆:socket 路径不同会起多个 server,tmux ls 各看各的,初学者偶尔会以为 session 「丢了」 |
参考答案:
Ctrl-b d 是把 session 从「当前终端的显示面板」上摘下来,并不会向 session 内任何进程发信号。Claude Code 进程的父进程是 tmux server,而 tmux server 又是个独立的后台 daemon,所以 detach 之后:
要找回它的标准动作两步:
tmux ls # 列出所有 session,看到 project-foo: ...
tmux attach -t project-foo # 贴回去,画面瞬间还原
如果你忘了 session 名字,tmux ls 不带参数就够;如果机器上只有一个 session,连参数都可以省略,直接 tmux a 就行。这就是「断网保命」的根本机制:tmux server 替你把进程的「显示」和「执行」彻底解耦了。
参考答案:
经验上的判断准则是「按上下文相关性分组」:
一句口诀:项目 → session,任务 → window,并排对照 → pane。一开始可能会过度切分(什么都开新 session),用一段时间后会自然收敛到「一个项目一个 session」的节奏。
另一个实用建议:给 session 起和项目目录同名的名字,配合 tmux attach -t <name> 形成肌肉记忆,比死记编号舒服得多。
参考答案:
至少有四条工程层面的硬理由:
可脚本化的 CLI 子命令最完整。tmux 的 new-session / split-window / send-keys / select-pane / display-message 等命令支持 -t 精准定位、-F 自定义输出格式、-P 返回新建 pane id,可以让上层程序按 pane id 精准控制每个 sub-agent。Zellij 的 zellij action 也能做类似事,但 API 完整度、稳定性、文档化程度都差一截。
服务器端零依赖。Agent Teams 的目标场景包括 SSH 到远端服务器跑长任务,几乎所有 Linux 镜像出厂自带 tmux 或 apt install tmux 即可;Zellij 需要手动装、要装 Rust 工具链或下二进制,团队场景里这是负担。
detach / 远程 attach 是核心需求。Sub-agent 跑半小时是常态,必须能在用户合上电脑后继续跑、明天换台机器接回来——tmux 把这件事打磨了快二十年,Zellij 同样能做但稳定性、跨平台一致性更不可知。
生态可组合。tmux 周围有 tpm(插件管理)、tmux-resurrect(持久化 session)、tmux-continuum(自动保存)等成熟工具,Agent Teams 可以直接复用而不必自己实现 session 持久化逻辑。
补充一个反向的考虑:Anthropic 也明确知道 tmux 在 send-keys 时机上有 race condition(claude-code#40168),但他们选择「靠 split-window -- 直接传命令、或加 sleep 兜底」绕过去,而不是放弃 tmux。换句话说:tmux 的脚本化能力 + 服务器端普及度 + 长跑稳定性,目前还没有对手能同时打平。这就是基础设施的护城河。
send-keys 的边界):https://tao-of-tmux.readthedocs.io/en/latest/manuscript/10-scripting.html优先展示同分类且标签更接近的内容,方便继续串联学习。
用 git worktree 跑多个并行 CLI Agent,避免分支切换打断上下文,含 worktree 管理、Agent 隔离与合并策略
在 CLI Agent 里接入第三方工具的决策框架 —— 何时直接 Bash 调外部 CLI,何时走 MCP server,含主流工具速查表
Obsidian v1.12.4 起官方 CLI 全量上线,让 Agent 通过 Bash 直接调 obsidian 命令毫秒级读写 vault,附 Agent 提示词模板与对比 MCP 路径的取舍