基于 tmux 的多智能体编排工具,多个 AI agent 可在不同 git worktree 中协作,共享角色提示和消息传递。
不要在 bankrbot SWARM 代币上花任何钱。
一个基于 tmux 的严格智能体编排平台,将成群的 AI 智能体转化为可靠、专业的软件工程师。
本分支(main)是文档性质的:它解释系统并携带共享的运维脚本和默认章程条款。可运行的工作流分支携带面向项目的配置、角色提示词,以及定义特定工作流的本地章程条款。
SwarmForge 是一个智能体协调系统,促进在不同 git worktree 中工作的智能体之间的通信。
它提供了一种共享结构,用于角色特定提示词、worktree 分配、tmux 会话和消息传递,使多个智能体能够在同一项目上协作而不会互相干扰。
可运行的 SwarmForge 配置位于专属分支上。每个分支包含 swarmforge/swarmforge.conf、本地章程条款和定义一个工作流的角色提示词。启动时,其 ./swarm 包装器在内容尚未存在时从 main 复制共享的运维脚本和共享章程条款,然后启动该分支的本地配置。
two-pack 是快速后端工作流。适用于从小任务中受益的快速编码,无需 Gherkin 和验收测试的开销,同时保留后端重构和硬化。
coder 以 TDD 和单元测试实现请求的行为。
cleaner 批量处理 coder 的交接,执行清理、CRAP 和 DRY 审查、架构审查、封装和关注点分离修复,以及语言变异加固。
正常流程是 coder -> cleaner -> coder。当你需要一个紧凑的实现/精化循环且无规范、QA、属性测试或验收测试角色时,使用此分支。
four-pack 是紧凑规范工作流。适用于需要 Gherkin 规范和一些架构考虑的中型项目,而无需将每个质量关卡拆分到各自的智能体:
specifier 将用户意图转化为精确的 Gherkin 验收规范,并在交接前请求批准。
coder 以 TDD、单元测试和生成的验收测试实现已批准的行为切片。
refactorer 执行保持行为的清理、覆盖率改进、CRAP 和 DRY 审查、变异点扫描,以及属性测试支持。
architect 拥有高层结构、依赖方向、变异加固、DRY 审查、软 Gherkin 变异,以及最终完成通知。
正常流程是 specifier -> coder -> refactorer -> architect -> specifier。当你需要严格开发且不将清理、架构、加固和 QA 拆分为独立智能体时,使用此分支。
six-pack 是完整工作流。适用于需要完整规范、前置 QA、后端验证和重大架构考虑的大型项目。它将每个主要质量关卡拆分到独立的角色:
specifier 将用户意图转化为已接受的 Gherkin 规范和端到端 QA 程序。
coder 以 TDD、单元测试和生成的验收测试实现已批准的行为切片。
cleaner 执行本地保持行为的清理、覆盖率改进、CRAP 和 DRY 审查,以及变异点扫描。
architect 审查模块结构、边界、依赖方向和属性测试覆盖率。
hardender 执行变异加固、语言变异、CRAP 和 DRY 验证,以及软 Gherkin 变异。
QA 将 specifier 的 QA 程序转换为可执行脚本,运行最终用户界面验证,检查交接一致性,并发送完成通知。
正常流程是 specifier -> coder -> cleaner -> architect -> hardender -> QA -> 完成。当你需要每个审查和验证关注点由独立智能体拥有时,使用此分支。
SwarmForge 在本地运行。在启动可运行分支之前,确保目标机器已有:
至少一个已配置的智能体后端,如 codex、claude、copilot 或 grok
在你想要使用 SwarmForge 的目录中,选择一个可运行分支并拉取其内容而不创建 Git remote:
BRANCH=four-pack
curl -L "https://github.com/unclebob/swarm-forge/archive/refs/heads/${BRANCH}.tar.gz" | tar -xz --strip-components=1
使用 BRANCH=two-pack 获取双智能体快速工作流,BRANCH=four-pack 获取紧凑规范工作流,或 BRANCH=six-pack 获取完整六智能体工作流。不要对此命令使用 main 分支;main 是文档性质的,存储共享的运维脚本,而可运行分支提供面向项目的配置和提示词。
复制可运行分支后,从目标项目启动 swarm:
./swarm
./swarm 包装器保持可运行分支精简。第一次使用时,如果 swarmforge/scripts/ 缺失,它会下载 main 分支归档,从 swarmforge/scripts/ 复制共享运维脚本,从 swarmforge/constitution/articles/ 暂存共享章程条款,然后启动 swarmforge/scripts/swarmforge.sh。后续运行重用现有的本地脚本目录而不是覆盖它。
窗口会自动打开。
要停止 swarm,关闭 swarmforge/swarmforge.conf 中列出的第一个窗口。那个清理窗口会关闭 tmux 会话并关闭其余跟踪的窗口。
当 swarm 处于活跃状态时,SwarmForge 会尝试阻止主机进入睡眠。在 macOS 上它使用 caffeinate;在 Linux 上在可用时使用 systemd-inhibit。显示器锁定或手动睡眠仍可能根据操作系统中断智能体。在 ./swarm 前设置 SWARMFORGE_PREVENT_SLEEP=0 可以禁用此行为。
SwarmForge 是一个轻量级、基于 tmux 的编排层,它:
从项目本地的 swarmforge/swarmforge.conf 启动配置驱动的 swarm
为每个配置的角色创建一个 tmux 会话,并在支持的后端打开一个终端界面
从项目本地的 swarmforge/roles/<role>.prompt 文件和分层 swarmforge/constitution.prompt 读取行为
支持每个角色的后端,如 claude、codex、copilot 或 grok
将共享的 swarmforge/scripts/ 目录放在每个智能体的 PATH 上,包括用于活跃 swarm 通信的交接辅助工具
在为专用 worktree 名称分配的角色下,在 .worktrees/ 下创建 git worktree
需要时在新工作目录中初始化 git 仓库
将所有 swarm 状态保持在工作目录本地的 .swarmforge/ 中
配置驱动的拓扑结构 —— swarm 形态来自 swarmforge/swarmforge.conf,而非硬编码的 shell 变量。
项目本地的角色 —— 每个角色由被编排的工作树中的 swarmforge/roles/<role>.prompt 定义。
分层章程 —— swarmforge/constitution.prompt 指示智能体读取 swarmforge/constitution/articles/ 下的条款文件。
每个角色的后端选择 —— 一个角色可以启动 claude、codex、copilot 或 grok。
可观察的 Swarm —— 为每个角色打开一个 Terminal 窗口并实时监视会话。
自托管且轻量 —— 在 tmux 和 Terminal 中本地运行,机器极少。
章程结构
每个可运行分支包含一个具有以下一般布局的 swarmforge/ 目录:
swarmforge/
swarmforge.conf
constitution.prompt
constitution/
articles/
project.prompt
local-engineering.prompt
local-workflow.prompt
...
roles/
<role>.prompt
...
constitution.prompt 是入口点。可运行分支通常用它来告知智能体读取 swarmforge/constitution/articles/ 中的每个文件。
共享的默认条款位于 main 上的:
swarmforge/constitution/articles/
engineering.prompt
handoffs.prompt
workflow.prompt
在创建角色 worktree 之前,SwarmForge 在启动时将缺失的共享条款安装到可运行分支的 swarmforge/constitution/articles/ 目录中。它还在脚本同步期间将缺失的共享条款安装到每个角色 worktree 中。现有本地文件会被跳过,因此可运行分支可以通过提交同名条款文件来覆盖共享条款。
Pack 特定的补充和例外应使用明确的本地文件名,而不是编辑共享条款。当前的约定是:
project.prompt 用于工作流的项目形态和本地拓扑。
local-engineering.prompt 用于特定工作流的工程规则。
local-workflow.prompt 用于特定工作流的工作流规则。
local-*.prompt 命名约定意味着"为此可运行分支添加或专门化共享默认条款"。当共享条款仍然有效且分支仅需要额外要求、例外或更窄的指令时使用它。不要将 local-*.prompt 用于完全替换;当分支有意覆盖共享条款时,使用共享文件名。
例如,main 分支可以提供一个共享的 workflow.prompt,而 six-pack 分支可以添加 local-workflow.prompt 来实现 QA 特定的交接行为。如果某个分支需要完全替换共享的工作流文章,它可以提交自己的 workflow.prompt;启动脚本会将该本地文件视为覆盖项,不会再将共享文件复制到其上。
swarmforge/swarmforge.conf 中的每个角色都映射到对应的 swarmforge/roles/<role>.prompt 文件。
在可运行分支中,SwarmForge 会执行以下操作:
SwarmForge 读取 swarmforge/swarmforge.conf。
根目录下的 ./swarm 包装器在共享辅助脚本、终端适配器和共享章程文章尚未存在时,将它们从 main 分支复制过来。
启动脚本将缺失的共享章程文章安装到 swarmforge/constitution/articles/,跳过已存在的本地文章文件。
启动脚本验证配置的角色的提示词、辅助脚本和终端适配器。
如果目标目录还不是 git 仓库,启动脚本会初始化一个并创建第一个提交。
启动脚本在 .worktrees/ 下为每个已配置的角色创建一个 git worktree,除非该角色被分配到 master 或未指定。
启动脚本将 swarmforge/scripts/ 和缺失的共享章程文章同步到每个角色 worktree,并将本地脚本目录放到每个 agent 的 PATH 上,这样 agent 使用本地交接辅助脚本,而不会回读到 master 检出目录。
SwarmForge 创建 tmux 会话,打开终端窗口,并在每个已配置的后端分配到的 worktree 中启动它们。
启动脚本在有 OS 相关睡眠抑制程序可用时启动它,清理脚本在 swarm 结束时停止它。
角色之间通过守护进程投递的交接文件进行通信。Agent 用 swarm_handoff.sh 创建经验证的草稿,用 ready_for_next.sh 接受工作,用 done_with_current.sh 完成工作。
启动脚本将共享辅助脚本同步到每个角色 worktree 下的 swarmforge/scripts/,并将该本地目录放到 agent 的 PATH 上。Agent 不直接发送 tmux 消息。启动器启动 handoffd.bb,它拥有 tmux socket 访问权限,监视每个 agent 的发件箱,将经验证的交接文件复制到接收者的收件箱,并只发送通用的唤醒通知。
Agent 通过三个辅助脚本与交接进行交互:
swarm_handoff.sh <draft-file> 验证并排队待发出的交接。
ready_for_next.sh 使用角色配置的接收模式接受工作。
done_with_current.sh 使用角色配置的接收模式完成当前任务或批次。
发出的草稿使用两种消息类型之一。git 交接指向接收者一个已提交的状态。提交缩写法必须是恰好 10 个十六进制字符;swarm_handoff.sh 验证它解析为单个提交,并在排队交接前将其规范化。
type: git_handoff
to: <role>[,<role>...]
priority: NN
task: <short-stable-task-name>
commit: <10-character-commit-abbrev>
便笺是一条简短的自由格式消息:
type: note
to: <role>[,<role>...]
priority: NN
message: <one line, max 80 chars>
辅助脚本生成投递的有效载荷。Agent 不写入长的交接正文、分支名、队列文件名或 tmux 命令。
接收方 agent 在收到通知或重启后运行 ready_for_next.sh。它分派到为该角色配置的任务或批次辅助脚本。如果它打印 NO_TASK,它们停止等待工作。如果它打印 TASK: <path>,它们将打印的 TASK_NAME 和 PAYLOAD 视为任务。如果它打印 BATCH: <path>,它们按辅助脚本投递的顺序处理打印的 BATCH_ITEM 条目。如果在 agent 已经在工作时收到唤醒通知,它可以忽略该唤醒;done_with_current.sh 在完成当前工作后检查下一个任务或批次。
持久的交接文件和生命周期头信息取代了旧的日志本和重发队列。运行时交接状态存在于每个 worktree 下的 .swarmforge/handoffs/ 中,包含 outbox、sent、failed 和 inbox 子目录。Agent 不应手动编辑、合并、暂存或提交交接的运行时状态。完整的协议参见 swarmforge/handoff-protocol.md。
swarmforge/swarmforge.conf 定义了 swarm 中每个窗口的角色。每一行的格式如下:
window <role> <agent> <worktree> [task|batch] [extra-cli-args...]
可选的接收模式默认为 task。对于应该将所有当前排队的同等优先级交接作为一个批次来消费的角色,使用 batch。
接收模式之后的任何字段都直接作为额外参数传递给 agent CLI。如果你省略了接收模式,额外参数可能从第五个字段开始:
window coder copilot wt-coder --yolo
window architect claude wt-arch task --dangerously-skip-permissions
你可以根据项目需要定义任意数量的窗口。每个角色映射到 swarmforge/roles/<role>.prompt 下对应的提示词文件,因此包含 architect、coder、reviewer、research 和 release 窗口的配置会期望存在:
swarmforge/roles/architect.prompt
swarmforge/roles/coder.prompt
swarmforge/roles/reviewer.prompt
swarmforge/roles/research.prompt
swarmforge/roles/release.prompt
这样每个项目可以选择自己的 swarm 形态,而不是被锁定在一组固定的角色中。
window coordinator codex master
window coder codex coder
window refactorer codex refactorer
window architect codex architect
在上面的例子中,agent 运行在以下 worktree 中:
coordinator -> master 上的主工作目录,并且是清理窗口,因为它被列在第一位coder -> .worktrees/coderrefactorer -> .worktrees/refactorerarchitect -> .worktrees/architect如果某个窗口使用 master 作为其 worktree 名称,SwarmForge 不会创建 .worktrees/master;该角色在 master 分支上的主工作目录中运行。
SwarmForge 使用记录在 .swarmforge/tmux-socket 中的项目特定 tmux socket,这样每个项目 swarm 都与其他 tmux 会话隔离。它还尊重 tmux 的 base-index 和 pane-base-index 设置,在启动 agent 和发送通知时使用,因此从 1 开始编号窗口或窗格的用户无需更改他们的 tmux 偏好。
SwarmForge 通过一个小型终端后端适配器打开可追踪的终端窗口或标签页。
如果有 AppleScript 可用,SwarmForge 打开 macOS Terminal.app 窗口。
否则,如果 wt.exe 可用,SwarmForge 打开 Windows Terminal 窗口。
否则,SwarmForge 在当前 shell 中附加清理 tmux 会话。
在复制可运行分支后,设置 SWARMFORGE_TERMINAL 来覆盖自动检测:
SWARMFORGE_TERMINAL=ghostty ./swarm
SWARMFORGE_TERMINAL=terminal-app ./swarm
SWARMFORGE_TERMINAL=windows-terminal ./swarm
SWARMFORGE_TERMINAL=none ./swarm
当你希望 SwarmForge 打开 Ghostty 标签而不是默认的 Terminal.app 窗口时使用 ghostty。当你希望 SwarmForge 从 WSL 打开 Windows Terminal 窗口时使用 windows-terminal。当你希望 SwarmForge 跳过终端自动化并在当前 shell 中附加清理 tmux 会话时使用 none。
共享的终端后端作为 main 分支上的 swarmforge/scripts/terminal-adapters/ 下的文件携带。可运行分支在启动时复制这些脚本。添加新后端时,通过创建以下命名的文件来更新 main:
swarmforge/scripts/terminal-adapters/wezterm.sh
该文件必须定义这个小合约:
terminal_backend_label() {
echo "WezTerm"
}
terminal_backend_can_open_sessions() {
return 0
}
terminal_backend_tracks_windows() {
return 0
}
terminal_open_session() {
local session="$1"
local title="$2"
local sibling_id="${3:-}"
# 打开一个终端界面,运行:
# cd "$WORKING_DIR" && exec tmux -S "$TMUX_SOCKET" attach-session -t "$session"
#
# 向 stdout 打印一个稳定的窗口/标签 id。
}
terminal_window_exists() {
local window_id="$1"
# 如果 terminal_open_session 返回的 id 仍然存在,返回 0。
# 否则返回非零值。
}
terminal_close_window() {
local window_id="$1"
# 关闭 terminal_open_session 返回的 id。
}
如果终端可以打开会话但无法返回稳定的 id 来进行存在检查/关闭,将 terminal_backend_can_open_sessions 保持为 return 0,并将 terminal_backend_tracks_windows 设置为 return 1。SwarmForge 将为每个会话打开一个界面,并跳过该后端的看门狗程序。swarmforge/scripts/terminal-adapters/windows-terminal.sh 是这种仅启动风格的示例。
如果后端根本无法打开会话,将两个能力函数都设置为 return 1;SwarmForge 将在当前 shell 中附加清理 tmux 会话。只有在添加别名或更改默认自动检测时才编辑 swarmforge/scripts/swarm-terminal-adapter.sh。
每个可见的 agent 窗口都附加到一个 tmux 会话。这意味着终端选择、复制和粘贴可能遵循 tmux 和终端模拟器的规则,而不是普通的文本字段行为。如果复制或粘贴感觉异常,请先检查 tmux 复制模式是否处于活动状态,再判断 agent 是否卡住了。
swarmforge.conf 中的第一个窗口是清理窗口。关闭这个顶部配置的窗口是预设的关机路径:SwarmForge 会拆除 tmux 会话、关闭其余已跟踪的窗口,并关闭整个集群。
关闭任何其他已跟踪的窗口都不会造成破坏。看门狗会重新打开该窗口,并将其重新附加到同一个 tmux 会话中,因此智能体状态和终端历史记录都会完整保留。这通常是恢复陷入陌生 tmux 模式或其他卡顿状态的窗口的最简单方法。