tmux + Claude Code 多 Agent 并行开发:终端会话管理实战指南
在终端里同时开着四五个 Claude Code 会话每个都在跑不同的开发任务切来切去经常分不清哪个窗口在改哪个项目偶尔还会在两个会话里同时对同一份配置动手脚改完才发现互相覆盖。这种混乱我经历过太多次了。后来我花了一个周末给 Claude Code 配了个“总管”用 tmux 做多会话管理再加一层自己的调度脚本把“同时管理多个 AI Agent”这件事从手忙脚乱变成了有章可循。这篇文章就是把整套方案、配置、踩坑记录完整分享出来。如果你也在终端里同时跑多个 Agent、或者正打算把 Claude Code 接入日常工作流这篇应该能帮你少走不少弯路。1. 先搞清楚为什么要在终端里同时跑多个 Agent1.1 单会话的瓶颈在哪很多人一上来就问“怎么同时管理多个 Agent”其实背后的真实需求往往不是“我要炫技式地开一堆会话”而是“一个 Claude Code 会话根本不够用”。这不是 Claude Code 本身弱而是单会话的工作模式有天然瓶颈。先说上下文窗口。Claude Code 在终端里交互式干活时每一轮都会带着会话历史上下文越积越长响应速度会明显变慢到了后半程它甚至会“忘掉”前面讨论过的关键约束。我试过让一个会话从需求讨论一路做到代码实现大概 40 分钟之后它就变得非常迟钝经常答非所问。更现实的做法是把任务拆成多个阶段每个阶段用独立会话处理上下文短、目标明确、输出质量明显更高。再说任务并行。实际做一个项目常常是“这边改接口文档那边写单元测试中间还要调一个样式 bug”。这些任务彼此独立完全可以并行。但单个终端会话只能串行处理你只能等它做完 A 再做 B。如果每个任务开一个独立 Agent 会话多个任务同时推进效率完全是两个量级。我自己的实测感受是代码迁移、批量重构、多文件文档编写这类任务并行之后整体耗时能压缩到原来的三分之一左右关键不是“墙上的时间”变短了而是“等待时间”被填满了。1.2 多 Agent 并行到底解决什么问题多 Agent 并行的核心价值不是“同时问多个问题”而是把一条阻塞式的任务流水线变成多条并行的任务支线。举个例子我最近重构一个老项目的日志模块同时开了三个会话会话 A 负责梳理现有日志埋点和输出格式会话 B 负责设计新的日志分级方案和接口定义会话 C 负责写迁移脚本和兼容层。三个会话各改各的文件我在旁边做 code review 和最终整合一天就把原本预估三天的活干完了。还有一个容易被忽略的价值隔离实验风险。单会话里你让 Agent 试一个新方案如果跑偏了会污染整个对话上下文后面所有任务都会带上这次试错的“惯性”。但如果你开一个专门做实验的会话方案不行直接关掉会话重来主任务会话完全不受影响。这种“坏会话随手丢好会话继续用”的体验只有在多会话管理做好的前提下才成立。不过多会话也带来新问题怎么快速知道哪个会话在干什么怎么避免多个会话同时改同一个文件怎么让一个会话的输出变成另一个会话的输入这些就是“总管”要解决的事。单纯开多个终端窗口是最原始的做法但窗口一多就乱命名混乱、误关、找不到历史都是坑所以我最终选了一套更结构化的方案。2. 方案选型对比三个思路我为什么选了 tmux 脚本2.1 多开几个终端标签页最直接但最乱最开始我就是这么干的终端模拟器比如 iTerm2、Windows Terminal本身支持多标签页每个标签页开一个 Claude Code看起来挺简单实际用起来问题一堆。第一个问题是标签页和项目没有强绑定关系。你开四个标签页每个都叫“claude”过了十分钟你自己都忘了哪个对应哪个项目只能挨个点开看。第二个问题是会话生命周期不好管。标签页关了就全没了想恢复上一次的工作现场得手动重来。第三个问题是没法做更细的自动化——比如我想一键同时拉起三个会话标签页模式做不到。但标签页模式有一个好处零学习成本。如果你只是偶尔需要同时用两个 Agent开两个标签页完全够用。如果你要日常并行处理多个任务那标签页模式很快就到瓶颈。2.2 Claude Code 自带会话管理够用但不彻底Claude Code 本身有会话恢复机制可以用claude --resume回到之前的会话也可以用claude --continue接着上次的对话继续。这在单会话场景下是挺好用的我也一直在用但它解决不了“同时管理多个活跃会话”的问题因为它本质是“串行恢复”不是“并行共存”。什么意思就是你虽然可以在多个会话之间切换但每次切换都要敲命令、查会话 ID、确认恢复哪个。会话一多这个过程的摩擦成本非常高。而且 Claude Code 自带的会话列表只是个扁平列表里面没什么“项目标签”或“任务状态”的概念纯靠会话标题和 ID 去识别用久了就成负担。另外--resume和--continue过程中有时候要确认几个交互选项一旦你记错了会话 ID恢复错了上下文后面的对话全跑偏整个工作流就断了。所以我把“自带会话管理”定位成辅助手段——适合单个任务的续接不适合多 Agent 的统一调度。2.3 tmux 打底 统一调度脚本我最终的选择我最终定下来的方案是tmux 做多会话底座配合自定义脚本做统一入口。tmux 本身就是“终端复用器”它能在一个终端窗口里管理多个会话、多个窗口、多个面板会话还能在后台持续运行即使你把终端模拟器关了tmux 里的 Claude Code 进程也不会断。这个方案有几个非常契合多 Agent 管理的特点。第一每个 Agent 可以放在独立的 tmux 窗口里窗口命名直接标注“任务名/项目名”一眼就能看出哪个窗口在干什么。第二会话和终端窗口解耦窗口误关了 Agent 进程也不受影响随时可以重新附着回来。第三可以在 tmux 之上做一层脚本封装把“创建会话、打开 Claude Code、切到指定项目目录、注入初始提示词”这一整套动作变成一条命令。我自己的“总管”脚本就是干这个的一条agent new fix-log-module命令自动创建一个以fix-log-module命名的 tmux 窗口自动进入指定项目目录自动启动 Claude Code并且带上预置的初始 prompt整个过程完全不用手动敲重复命令。从使用体验上说这就从“管理多个终端窗口”升级成了“管理一组有名字、有状态、有分工的 Agent 任务”。方案上手难度并行能力会话恢复自动化扩展适合场景多标签页极低一般弱几乎不可扩展偶尔两三个会话Claude Code 自带 resume低串行支持有限单任务续接tmux 脚本中等强强完全可编程日常多 Agent 并行开发3. 动手搭建“总管”从安装到第一套完整工作流3.1 准备基础环境先说 tmux。macOS 上推荐用 Homebrew 安装brew install tmuxUbuntu/Debian 系用 aptsudo apt install tmux装完输入tmux -V能输出版本号就算成功。tmux 本身配置不多但对多 Agent 管理来说有几个关键设置我建议改一下开启鼠标支持方便用鼠标直接点窗口、降低快捷键前缀延迟、把窗口列表显示在屏幕下方方便看当前窗口名。我把一份极简配置放在~/.tmux.conf里# 开启鼠标支持 set -g mouse on # 前缀快捷键响应延迟调低 set -sg escape-time 10 # 窗口列表常驻底部实时显示每个窗口名 set -g status-justify left # 新窗口默认在当前目录打开 bind c new-window -c #{pane_current_path} # 使用 Ctrla 作为前缀键默认是 Ctrlb个人习惯 set -g prefix C-a unbind C-b bind C-a send-prefix这里重点说下bind c new-window -c #{pane_current_path}这一行它的作用是新开窗口时自动继承当前窗口所在目录。这个配置对多 Agent 工作流非常有用因为你的 Agent 通常按项目目录区分新窗口直接打开在项目目录下少输一次cd。然后是 Claude Code 的安装。官方推荐的安装方式是通过 npm前提是你已经有 Node.js 环境建议装 Node 18 以上版本npm install -g anthropic-ai/claude-code装完在终端里敲claude就能进入交互界面。第一次启动会进入认证流程需要登录你的账号完成授权。这里有个小技巧如果是在远程开发机上想接入自己已有的访问权限可以直接把本地已经认证好的配置目录同步过去或者通过环境变量指定 API Key 方式完成认证具体要看你的使用场景选哪种。对我这种主要在个人电脑上用的情况直接走官方登录流程最省事只需要操作一次后续claude命令都复用同一份凭据。3.2 用 tmux 配置出“任务窗口”管理底座tmux 安装好、基本配置放好之后先别急着直接在里面开 Claude Code。我建议先把 tmux 的窗口命名习惯建立起来。多 Agent 工作流里窗口名就是你的任务索引没起好名字后面全是混乱。手动场景下起名操作是这样的在一个 tmux 会话里按Ctrla然后按c新建窗口再按Ctrla然后按,给当前窗口重命名。比如输入fix-log-module窗口列表里就能看到这个名字。这一步做完你开的每个 Claude Code 窗口都有了对应的任务标识。但手动操作还是太慢了。既然都是资深终端用户了能脚本化的事情就不要用手敲。我在自己家目录下建了bin目录里面放了一个agent脚本核心功能就三个新建 Agent 任务窗口、列出当前所有 Agent 窗口、关闭指定 Agent 窗口。先看新建。这个功能要解决的痛点是一条命令完成“开窗口 进目录 起 Claude Code 注入初始提示词”。核心实现长这样#!/bin/bash # agent new task-name [project-dir] [initial-prompt] ROOT_DIR$HOME/work if [ $1 new ]; then TASK_NAME$2 PROJECT_DIR${3:-$ROOT_DIR} # 新开一个 tmux 窗口命名任务名默认进入项目目录 tmux new-window -n $TASK_NAME -c $PROJECT_DIR # 在新窗口里发送启动命令 if [ -n $4 ]; then tmux send-keys -t $TASK_NAME claude --prompt \$4\ C-m else tmux send-keys -t $TASK_NAME claude C-m fi fi这里有个细节值得说一下tmux new-window -c指定的是这个窗口启动时的工作目录。由于 Claude Code 在启动时会读取当前目录下的项目上下文比如 CLAUDE.md、文件结构等所以“先切到项目目录再启动 Claude Code”这个顺序非常重要。直接在一个杂乱的目录里启动 Claude Code它一开始对项目的理解就是错的后面所有任务都容易跑偏。列出当前所有 Agent 窗口也很有用。我绑定了agent ls命令它做的事情很简单就是打印出当前 tmux 会话里每个窗口的名字和当前活动任务if [ $1 ls ]; then tmux list-windows -F #{window_index}: #{window_name} (#{window_active}) fi这样我随时可以知道现在同时在跑哪几个 Agent哪些窗口处于活跃状态。比起在一堆终端标签页里来回切这个效率提升太明显了。3.3 日常操作流程怎么切、怎么关、怎么恢复搭建完成之后实际操作流程是这样走的。早上一到工位我先跑tmux attach回到之前的会话然后agent ls看一眼昨天开了哪些 Agent 窗口。如果任务还在进行中直接切到对应窗口就能看到 Claude Code 的输出如果某个 Agent 等了我一个晚上比如跑了一个长时间的重构任务我切过去直接看结果不用重新拉起任何进程。切换窗口是 tmux 的基础操作。Ctrla加窗口数字直接跳到对应窗口或者Ctrla加n/p在相邻窗口之间切换。如果你开了鼠标支持直接点底部状态栏的窗口名也行。我自己的习惯是给每个窗口编号和任务名一起看比如1: fix-log-module、2: write-unit-test、3: review-pr谁在干什么一目了然。关闭 Agent 窗口也分两种情况。如果任务是自然完成的我一般会先看一眼 Agent 的最终输出确认没问题后直接在 Claude Code 里输入/exit退出然后按Ctrld关闭窗口。如果任务已经失控上下文乱套了、Agent 开始重复犯同一个错误我倾向于直接tmux kill-window -t 窗口名杀进程不留任何让它继续纠结的机会。杀完之后如果想重来一条agent new task-name就又能拉起一个全新的干净会话。这一点比“继续硬聊”要靠谱得多因为 Agent 一旦陷进错误的上下文里继续对话只会加深错误而不是纠正错误。会话恢复是 tmux 最值钱的功能之一。终端模拟器崩了、电脑重启了、SSH 断开了都不影响 tmux 里的 Claude Code 继续在后台跑。reconnect 之后只要tmux attach所有窗口、所有进度都原封不动。我有一次在服务器上跑一个耗时的 Agent 任务笔记本合盖带回家第二天打开重新连上Claude Code 的输出还挂在窗口里跟没断过一样。这种“任务不随终端一起死亡”的体验用普通多标签页是根本做不到的。3.4 给每个 Agent 加“入场说明”多 Agent 并行的最大风险之一是 Agent 会“自作主张”地扩大任务边界。你让它改日志模块它顺手把 README 也改了把两个无关文件的格式都动了一遍code review 时你根本分不清哪些改动是必要的。解决办法是在启动 Agent 之前给它一份明确的“入场说明”。Claude Code 本身对项目级说明文件 CLAUDE.md 有很好的支持启动后 Agent 会自动读取这个文件作为项目背景。但多 Agent 场景下每个任务的边界可能不一样所以我更习惯给每个具体任务注入单独的初始 prompt。在我的agent new脚本里第四个参数就是初始 prompt例如agent new fix-log-module ~/work/myapp 只修改 src/logging 目录下的代码不要改动其他任何文件。完成后列出所有改动清单。这样拉起的新窗口里Claude Code 启动后第一眼看到的就是这条约束。实测下来带明确边界的 Agent 任务和没带边界的最终提交上来的代码差异非常大。后者经常“好心办坏事”前者基本指哪打哪。4. 多 Agent 并行时的任务分工与结果汇总4.1 给每个 Agent 划清“地界”会话管理只是总管的第一个层次第二个层次是任务编排。多个 Agent 同时干活最大的雷是“两个 Agent 改同一份文件”。它们各自基于自己对代码的理解做修改但它们的修改彼此不知道你合并的时候会看到两份完全冲突的 diff。所以我的铁律是并行任务之间文件级隔离是底线。具体到操作上我会在给每个 Agent 下任务之前先自己看一眼这个任务会碰哪些文件确保任务 A 改的文件和任务 B 改的文件没有交集。如果实在没法避免比如两个任务都要改同一个配置文件那就排成串行让 A 先干完手动处理完冲突点再让 B 接手。举一个我最近的真实例子。我把一个项目的认证模块改造拆成两个并行任务任务 A 负责重构 token 刷新逻辑只允许动src/auth/目录任务 B 负责更新所有调用认证接口的页面代码只允许动src/pages/目录。两个任务在文件层面完全没有交集我可以放心让它们同时跑最后合并的时候没有任何冲突。这里还要提醒一句文件级隔离不只是“让 Agent 别乱改”更要“让 Agent 能看到它需要看的东西”。比如任务 B 虽然只改页面但它需要理解认证接口的调用方式所以我会在初始 prompt 里明确告诉它“接口定义文档在docs/auth-api.md只读不允许修改”。Agent 能感知的上下文边界决定了它干活的质量这也是总管脚本里 prompt 参数存在的意义——不只是约束更是引导。4.2 用“任务清单文件”做 Agent 之间的交接两个并行 Agent 各自干完了活怎么把结果汇总起来这是多 Agent 工作流里另一个经常被忽视的问题。我的做法是给每个任务配一个独立的“工作日志文件”Agent 在任务过程中必须持续往这个文件里写进展。任务进行中我会时不时切到对应窗口看一眼日志任务结束后我把所有日志汇总成一个整体报告再决定下一步怎么走。比如在前面说的认证模块改造例子里我给任务 A 配了docs/task-auth-refactor.md给任务 B 配了docs/task-page-update.md然后要求它们在完成任务时把修改了哪些文件、踩了什么坑、有哪些遗留问题都写进去。最终我拿着这两份文档做汇总整个过程非常清晰。这里的关键是Agent 的输出不能只在终端窗口里滚动它需要落盘成可供人阅读、可供其他 Agent 引用的文档。文件系统就是 Agent 之间的“共享黑板”。交叉引用也很有价值。比如一个 Agent 需要调用另一个 Agent 产出但尚未合并的代码我可以直接在新任务的 prompt 里告诉它“参考docs/task-auth-refactor.md里定义的 token 刷新接口规范按这个规范改你的页面代码”。这样任务之间虽然代码没有物理交集但逻辑上是衔接的最终整合的时候不需要我再做一次大翻译。4.3 注意资源消耗和 API 成本问题多 Agent 并行必然带来更高的资源开销和 API 调用成本。API 账单这一块我用几次之后就长记性了并行开三个 Agent 跑一天的 token 消耗远大于一个 Agent 串行跑三天。这不是说不让你并行而是要有成本意识。我的经验是给每个 Agent 任务设定明确的“结束条件”。有些任务的结束条件是“跑完测试套件”有些是“生成完代码就停下来不许继续优化”。如果没有这个约束Agent 会在任务完成后继续“善后”不断检查、微调、重构每一轮都在消耗 token。我会在初始 prompt 里直接写清楚任务完成后立即停止输出结果并退出。这是一个非常省钱的习惯。资源消耗方面Claude Code 本身是网络 API 调用为主本地 CPU 占用不算夸张但如果你同时在跑多个 Agent 并且每个都带着大项目上下文内存占用还是会上去的。我在 16GB 内存的 MacBook 上同时开过四个 Agent系统整体感受还行但偶尔会有明显卡顿。如果电脑配置一般建议同时运行的 Agent 控制在两个到三个够用就好。5. 问题排查实录与避坑指南5.1 tmux 操作翻车现场tmux 学习曲线最陡的地方是快捷键很多人在第一步就被劝退了。我自己刚开始用的时候也总是记不住前缀键经常在普通终端里按Ctrla然后什么都没发生还以为命令没生效。实际上一旦进入 tmux前缀键的组合方式就是在普通模式先按前缀、再按功能键这个“两段式按键”需要一点时间适应。还有一个我踩过的坑tmux 里的窗口滚动。Claude Code 的输出很长的时候你可能会想看前面的输出但鼠标滚动默认只会滚动终端模拟器的缓冲区tmux 里的历史输出根本滚不动。后来我在~/.tmux.conf里加了这样一段配置才解决# 进入复制模式 bind [ copy-mode # 退出复制模式 bind ] paste-buffer具体的日常操作就是按Ctrla再按[进入复制模式然后用方向键或PageUp/PageDown翻页按q退出。这个功能在多 Agent 工作流里几乎是刚需——Claude Code 写了一大段代码你要回头确认几个关键行不进入复制模式根本看不到。另外tmux 会话多了以后自己也容易混乱。tmux 本身是“会话-窗口-面板”三层结构我目前的用法只用到了“会话”和“窗口”两层面板pane我基本不用。原因很简单面板分割之后每个格子太小Claude Code 的交互界面非常吃宽度挤在半个屏幕里体验很差。如果你也有同感建议老老实实一个 Agent 一个窗口别学某些教程把面板切得跟俄罗斯方块一样。5.2 Claude Code 安装与启动的典型问题安装这一步最容易出问题的就是 Node.js 版本。Claude Code 对 Node 版本有一定要求版本太老会直接报错。如果你用系统自带的旧版 Nodenpm install -g大概率会失败或者装上之后运行时报语法错误。我的建议是先用node -v确认版本如果低于 18赶紧通过 nvm 或直接装最新 LTS 版别在这一步纠结。启动过程中的一个常见问题是首次认证。claude命令第一次运行会要求登录如果你的终端环境是远程服务器没有本地的浏览器环境登录流程会卡住。我在远程开发机上遇到过这个问题最终的解法是在本地浏览器完成认证流程之后把对应的配置目录同步到服务器上具体到 Claude Code 就是用户目录下的.claude配置目录。同步之后服务器上的claude命令直接就走已验证的身份不用再走一次登录。另外提醒一下claude --prompt这种方式适合快速启动并注入初始指令但它不是交互式会话。如果你预期后续要和这个 Agent 来回沟通比如让它在同一个会话里改完再改、跑完测试再修 bug你应该进入交互模式再粘贴初始需求而不是用--prompt一次性投喂。我的脚本里默认是进入交互模式边缘情况下才用--prompt这个细节对后续任务体验影响还是挺大的。5.3 多 Agent 任务互相污染的心得最后一个大坑是“会话污染”和“文件污染”。先说会话污染指的是 Claude Code 的上下文里残留了之前任务的信息导致它在执行新任务时被误导。我遇到的典型场景是同一个窗口里先让 Agent 分析了一个 bug它给出了一整套修复建议然后我又让它去写新功能的单元测试结果它写的测试用例里全是针对刚才那个 bug 的。这个不是 Claude Code 笨而是你把两个不相关任务硬塞进了同一个对话上下文里。解决办法就是“一个任务一个会话”任务做完了就关窗需要新任务就新开窗口不要贪图方便在同一会话里连续下达不同指令。文件污染更隐蔽。两个 Agent 并行时如果一个 Agent 的测试脚本或临时文件写到了公共目录另一个 Agent 在扫描项目结构时会看到这些半成品文件从而误判项目当前状态。我后来统一的约定是所有 Agent 的临时输出、中间产物、调试文件一律写到项目根目录下的tmp/文件夹里这个名字一看就知道是临时目录Agent 扫描时即使看到了也大概率会忽略。如果在真实项目里跑多 Agent建议在 CLAUDE.md 里加一行“所有临时文件放 tmp/ 目录勿以 tmp/ 下的内容判断项目状态”能有效减少误判。关于多 Agent 任务的最终汇总我现在的流程已经稳定成一套“四步走”打开总管脚本拉起所有并行 Agent 窗口、用初始 prompt 给每个 Agent 划清边界和交付物、任务完成后让 Agent 把结果写进各自的日志文件、我统合日志做 code review 和整合。这套流程跑了几周之后我再也没有怀念过以前那种“十个终端标签页乱跳”的日子。最后分享一个我个人的小习惯不管并行跑多少个 Agent我始终保留一个“干净窗口”里面不跑任何 Agent 任务只用来敲 git 命令、做文件操作、看测试结果。这个窗口相当于我的“操作台”Agent 们在我的“车间”里干活我坐在操作台前统揽全局。听起来很玄学但实际用起来非常有效——人的注意力本来就是单线程的给自己留一个不被 Agent 输出刷屏的窗口多 Agent 工作流的掌控感会提升一个档次。