Skip to content

第 6 章 · 会话后端:tmux 参考后端

本章目标:理解会话后端(runtime backend)在舰队体系中的角色,掌握 tmux 作为 verified reference backend 的安装、窗口拓扑、监督操作与存活探测机制。

6.1 会话后端是什么

每个 crewmate 都是一个自主运行的 agent 进程,而 agent 进程需要一个可见、可观察、可介入的会话端点(session endpoint)。会话后端就是承载这些端点的终端基础设施:

text
                    ┌─ backend = tmux   ──► tmux window  (参考实现)
firstmate 派生任务 ──┼─ backend = herdr  ──► herdr tab    (实验)
                    ├─ backend = zellij ──► zellij tab    (实验)
                    ├─ backend = orca   ──► Orca terminal (实验, macOS)
                    └─ backend = cmux   ──► cmux workspace(实验, macOS)

后端决定三件事:任务端点落在哪里、captain 如何观看(watch)、以及 firstmate 如何投递指令与读取状态。下一章我们会逐一认识四个实验性后端;本章先吃透参考实现——tmux。

6.2 后端选择链

FirstMate 按以下优先级决定使用哪个后端:

text
1. config/backend 文件显式指定        ← 最高优先级(本地 gitignored 配置)
2. FM_BACKEND=<name> 环境变量          ← 仅本次启动生效
3. runtime auto-detection             ← 自动检测(仅部分后端参与,见第 7 章)
4. tmux                               ← hard default 兜底

也就是说:什么都不配置时,tmux 就是默认答案。反过来,在 config/backend 里写入 tmux 或用 FM_BACKEND=tmux 显式选择,同时也是退出 Herdr/cmux 自动检测的开关——这一点在混合环境里非常实用。

bash
# 方式一:持久选择(写入本地配置,gitignored)
echo "tmux" > config/backend

# 方式二:一次性选择
FM_BACKEND=tmux claude

# 方式三:直接用自然语言要求 firstmate 使用 tmux
> 请用 tmux 作为会话后端

6.3 安装与前置条件

tmux 本体一行命令即可安装:

bash
brew install tmux          # macOS
# 或使用你平台的包管理器,如 apt install tmux

除 tmux 外还需满足通用工具链要求(configuration.md 的 toolchain 一节统一约定):

  • 一个已验证的主 harness CLI:Claude Code、Grok、Pi(或 pi-signed)、Codex、OpenCode、Cursor Agent CLI 之一;
  • Git 与 GitHub CLI,且已通过 gh auth login 完成认证;
  • 所选后端的依赖(tmux 场景即 tmux 自身)。

tmux 后端的一大优点是零预备步骤:官方文档明确写着 "No provisioning is required before the first task",装好就能跑。

6.4 窗口拓扑:任务即窗口

tmux 后端推荐的体验是把主 harness 启动在一个 tmux session 里:

bash
tmux new -s firstmate     # 创建并进入名为 firstmate 的 session
claude                     # 在其中启动主 harness(也可用 grok --trust / pi 等)

此后每个 crew 任务都成为这个 session 里的一个窗口,命名格式为 fm-<id>

bash
# 查看舰队当前的所有任务窗口
tmux list-windows -t firstmate

# 输出示意:
# 0: main*    1: fm-a1b2-   2: fm-c3d4

如果主 harness 运行在 tmux 之外也没关系——FirstMate 会自动创建或复用一个名为 firstmate 的 detached session:

bash
tmux attach -t firstmate   # 随时附着查看舰队

6.5 监督而不附着

日常监督不需要逐个 attach 进窗口。FirstMate 提供两个轻量入口:

bash
# 偷看某个任务的最近输出(有界 tail,不刷屏)
bin/fm-peek.sh <task-id>

# 向任务端点投递一条转向指令(需显式 FM_HOME)
FM_HOME=<home> bin/fm-send.sh <task-id> '改用方案 B,注意保留现有测试'

这里有一条与第 4 章硬规则呼应的红线:如果你亲自 attach 到任务窗口里打字,那属于 authoritative direct intervention(权威的直接介入)——你的输入立即生效,但 firstmate 会在下一次监督评审时 reconcile 这次场外指挥。日常还是走 fm-send.sh,让通信保持单一联络人模型。

6.6 Agent 存活探测(liveness probe)

"窗口还在"不等于"agent 还活着"。tmux 后端的存活探测分两层:

text
第一层:目标存在性检查 —— pane 还在吗?
第二层:进程名身份识别 —— pane 里跑的是 harness 还是裸 shell?

第二层是关键。探测器组合多个独立来源读取进程名:#{pane_current_command}、pane tty 前台进程组的内核 comm 值、甚至 argv[0] 的安装路径成分。之所以要多源交叉验证,是因为不同平台上哪个字段保留可执行文件真实名字并不确定。

探测结果分为五类判定:

判定含义是否触发恢复
alive识别出已知 harness 进程(Claude/Codex/OpenCode/Pi/pi-signed/Grok/Kimi/Cursor/Muse)
dead前台只是普通 shell✅ 是
missing窗口权威性地不存在✅ 是
unreadable状态不可读
ambiguous其他未知进程

注意一个精妙的设计约束:只有 deadmissing 授权恢复。因为一次误判的 "dead" 可能导致在同一个 worktree 上再拉起一个重复 agent——这比漏掉恢复严重得多。所以任何单一来源都无法单独给出负面结论,必须前台进程组可读且证据一致才行。

还有一个反直觉的细节:探测器把范围限定在前台进程组而非 pane 的全部后代进程。这是刻意的——一个残留在后台的 harness 同名进程,不应让一个其实空闲的 pane 被误读成"agent 还活着"。

6.7 当前行为与限制小结

官方文档为 tmux 后端记录了完整的回归测试入口,包括冒烟测试、存活探测测试、composer 幽灵文本测试等:

bash
tests/fm-backend-tmux-smoke.test.sh      # 后端冒烟
tests/fm-tmux-agent-liveness.test.sh     # 存活探测
tests/fm-composer-ghost.test.sh          # composer 判定
tests/fm-tmux-submit-busy.test.sh        # 提交与忙碌状态

需要记住的限制与定位:

  • tmux 是 reference path,也是唯一完整支持 secondmate homes 的基线
  • 忙碌状态不从渲染文本猜测,而是走语义 busy-state 契约(bin/fm-busy-lib.sh);
  • 投递确认采用严格标准:只有被证明为空的 composer 才算投递成功,模糊状态一律保守处理,绝不重打文本。

6.8 验证安装

一切就绪后,用最小任务验证整条链路:派生一个小任务,确认它的 fm-<id> 窗口出现在预期的 session 中即可。

bash
$ tmux list-windows -t firstmate
0: bash  1: fm-e5f6*

看到新窗口出现、fm-peek.sh <id> 能读到 agent 输出,说明 tmux 后端工作正常。

本章小结

  • 会话后端决定 crewmate 端点的位置与监督方式;tmux 是 verified reference backend 与 hard default;
  • 选择链为:config/backend 显式 > FM_BACKEND 一次性 > 自动检测 > tmux 兜底,显式选 tmux 同时退出自动检测;
  • 推荐把主 harness 跑在 tmux new -s firstmate 内,任务窗口命名为 fm-<id>;主 harness 不在 tmux 内时会创建/复用同名 detached session;
  • 日常监督用 bin/fm-peek.shbin/fm-send.sh,不必 attach;attach 后打字属于权威介入,将在下次监督评审时 reconcile;
  • 存活探测输出 alive/dead/missing/unreadable/ambiguous 五类判定,只有 dead 与 missing 触发恢复,以避免重复 agent 风险。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. 什么都没配置时,FirstMate 使用哪个会话后端?

2. 主 harness 未运行在 tmux 内时,FirstMate 如何处理?

3. 存活探测的五类判定中,哪些会触发恢复动作?

4. 为什么存活探测要把进程名来源限定在前台进程组而非 pane 的所有后代?

🛠️ 动手实践

  1. 安装 tmux 并执行 tmux new -s firstmate,在其中启动你最常用的 harness,然后另开一个终端用 tmux list-windows -t firstmate 观察 session 结构。
  2. 通过 firstmate 派生一个极小的 scout 任务(例如"调查某仓库的 LICENSE 类型"),用 bin/fm-peek.sh <id> 跟踪它,记录窗口名 fm-<id> 的出现时机。
  3. 阅读 docs/tmux-backend.md 的 Agent liveness probe 一节,画出五类判定的决策流程图,并解释为什么 ambiguous 不授权恢复。