@goldnico/opencode-teams
v0.1.19
Published
Independent multi-agent team orchestration plugin for OpenCode
Readme
opencode-teams
OpenCode 多 Agent 团队编排 — 持久化、可恢复、kitty/tmux 多终端
一个独立的 OpenCode 插件,把 Leader + 成员拆成独立 opencode 进程,通过 Unix socket + 文件 inbox 通信。Fork 自 oh-my-openagent 的 Team Mode,重新设计为独立插件。
特性
- 持久化团队:Leader 进程退出后,团队配置、成员列表、inbox 消息、任务全部留在磁盘;新 Leader 启动可一键接管(
-s+_flags/OPENTEAMS_RESUME)。 - 主动恢复:
teams_recover_member让 leader 把意外退出的成员主动拉起;inbox 兜底确保消息在 member 重启后可达。 - 15 个
teams_*工具:团队 / 任务 / 消息 / 成员管理齐全(见下表)。 - 双终端 UI:成员面板用
tmux或kitty拉起(tmux优先,kitty 后备;macOS 沙盒下用kitty --listen-on+kitten @ --to远程控制)。 - 跨 uniqname 隔离:socket server 拒绝跨队 send_message。
- 背压邮件 + 任务依赖链:inbox 满则反压;任务支持
blockedBy等待。
安装
依赖:OpenCode ≥ 1.0 + Bun(dev 模式)或 Node 18+(npm 模式)。
用户级(npm 包,推荐)
npm install -g @goldnico/opencode-teams
# 或
pnpm add -g @goldnico/opencode-teams~/.config/opencode/opencode.jsonc 的 plugin 数组里加:
{
"plugin": ["@goldnico/opencode-teams"],
}项目级(dev / 本地开发)
项目根 .opencode/plugins/ 下的 plugin 自动加载,opencode.jsonc 不需要 plugin 字段(当前仓库的项目配置就用了这种模式)。本地 dev 构建后链接:
bun install
bun run build
ln -sf ../../dist/index.js .opencode/plugins/opencode-teams.js配置 team_mode(可选)
team_mode 是 plugin 自己的配置(不是 OpenCode schema 字段),由 hooks.ts:config 钩子读取,控制团队规模。完整示例:
{
"plugin": ["@goldnico/opencode-teams"],
"team_mode": { "max_members": 8, "max_parallel_members": 4 },
}声明 team-member agent(必需)
成员进程必须用 team-member agent(或自定义 agent)才能加载 teams_* 工具。该 agent 要:
- 关闭所有工具(
"tools": { "*": false }) - 开启
teams*("tools": { "teams*": true }) - 加载
member.md基础 prompt("prompt": "{file:./member.md}")
项目级 opencode.jsonc 示例(节选):
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"team-member": {
"description": "团队成员 agent,可以是 leader 或 member",
"prompt": "{file:./member.md}",
"tools": { "*": false, "read": true, "teams*": true },
"permission": { "bash": { "sleep *": "allow" } },
},
},
}leader 直接在 TUI 跑(自动 kind=main),member 由 teams_add_member 通过 agent 字段指定。
验证安装
启动 OpenCode 后看 toast:leader 跑出来应该看到 已检测到 kitty UI 或 已检测到 tmux UI;没看到说明 team-member agent 没被识别 / plugin 没加载。
工具(15 个)
| 分类 | 工具 |
| ---- | -------------------------------------------------------------------------------------- |
| 团队 | teams_create、teams_delete、teams_list、teams_status |
| 成员 | teams_add_member、teams_remove_member、teams_recover_member、teams_member_list |
| 任务 | teams_task_create、teams_task_list、teams_task_get、teams_task_update |
| 消息 | teams_send_message |
| 配置 | teams_change、teams_change_member |
快速开始
启动 OpenCode(leader 自动 kind=main)后,在 TUI 给 agent 发中文 prompt:
用 teams_create 创建一个团队 name=demo 你是 leader。告诉我 uniqname。
用 teams_add_member 给 <uniqname> 加一个成员 name=bot, prompt="你是 echo bot。收到消息后 sleep 1 秒用 teams_send_message 把原内容回复给发送者", agent=team-member。
用 teams_send_message 向 <uniqname> 的 bot 发 "hello",等 bot 回复。leader 通过 tmux 或 kitty 拉起成员进程(自动检测,tmux 优先)。消息通过 Unix socket(leader↔bot)+ 文件 inbox 兜底(session.idle 每 10s 拉)双向通信。
更多场景(成员 recover、leader recover、多团队隔离)见 AGENTS.md §端到端验证。
架构
┌──────────────┐ socket (Unix) ┌──────────────┐
│ Leader │◀───────────────▶│ socket │
│ opencode │ │ server │
│ (main) │ │ (server.ts) │
└──────┬───────┘ └──┬─────┬─────┘
│ launch UI │ │
│ (kitty/tmux) │ │
▼ ▼ ▼
┌──────────┐ ┌────────────────┐
│ member-1 │ │ ~/.o_teams/ │
│ opencode │◀─inbox───────│ runtime/<uniqname>/ │
└──────────┘ │ config.json │
│ inboxes/ │
│ tasks/ │
└────────────────┘- Core:
src/core/文件持久化 + socket 协议 + state machine;不依赖 OpenCode SDK - Providers:
src/providers/opencode/适配层;tools.ts15 个teams_*、hooks.ts团队上下文注入 - UI:
src/ui/{tmux,kitty}/+src/ui/factory-selector.ts(tmux优先) - Entry:
src/index.ts默认导 server plugin;src/tui.ts是 TUI plugin(启动 toast)
存储布局
~/.o_teams/ 默认 baseDir
teams/{name}/config.json — 团队规格定义
runtime/{uniqname}/ — 团队运行时
config.json — 成员定义 + socket 路径
inboxes/{member}/ — 每个成员的收件箱
inbox/ — 未读
processed/ — 已读
tasks/ — 共享任务列表
prompts/{name}.md — 成员启动 prompt
.teams/sock/{uniqname} — Unix socket 文件
_flags/OPENTEAMS_RESUME — 触发恢复的 flag
# 项目根 .o_teams/ 优先使用(baseDir 解析时检测 process.cwd()),不存在则自动创建baseDir 解析顺序:config.base_dir → TEAMS_BASE_DIR env → 项目根 .o_teams/teams-config.json → 项目根 .o_teams/(不存在则自动创建)
启动流程
- Leader 调
teams_create→ 写runtime/{uniqname}/config.json+ 启动 socket server - Leader 调
teams_add_member name=X prompt=Y→ 写成员到 config.json → 通过team-memberagent(项目级opencode.jsonc)拉起新 opencode 进程 → kitty/tmux 拉窗口 - 成员进程启动时带 env:
OPENTEAMS_SOCKET=...、OPENTEAMS_RUN_ID=...、OPENTEAMS_MEMBER=...、OPENTEAMS_ROLE=member - 成员连接 socket → 自注册(带 sessionId)→ leader 通过
incoming_message推消息 - session.idle 时成员主动拉 inbox 兜底(10s 间隔)
关键命令
bun install # 装依赖
bun run typecheck # tsc --noEmit
bun run build # bun build ./src/index.ts --outdir dist --target bun
bun test # 全部单测
bun test test/core/locks.test.ts # 单文件
bun test -t "<pattern>" # 按名称
bun run lint # eslint
bun run lint:fix # 自动修
bun run format # prettierCI 只跑 typecheck -> build;本地改业务逻辑时还要跑 bun test。
E2E 验证(手动场景)
行为 / 消息 / 恢复逻辑改动必须真启 OpenCode 跑一遍,单测不覆盖 socket 交互和 agent loop。详见 AGENTS.md 的"端到端验证(手动场景)"章节,必跑 Case 1–6 + 8。
推荐的 E2E 环境(kitty 场景)
kitten @ 在 OpenCode 工具沙盒(bash tool)里跑会因无 /dev/tty 失败。解法:
SOCK="$TMPDIR/kitty-e2e.sock"
rm -f "$SOCK"
/Applications/kitty.app/Contents/MacOS/kitty \
--listen-on "unix:$SOCK" \
--override "allow_remote_control=yes" &
# 然后从沙盒用 kitten @ --to "unix:$SOCK" <subcommand> 控制发送 Enter 触发 TUI 提交:kitten @ send-text --match "id:$WID" $'\r'(不能用 \n)。
进程红线
- 绝对不要
pkill -f "kitty"或kill -9全部 kitty 进程——用户日常使用。 - 绝对不要
kill用户正在用的 opencode 进程——按 PID 精确处理。 - 不要
pkill -f "opencode"——会包括用户当前用的 opencode。
版本
v0.1.x 见 AGENTS.md 的"版本标签"章节;pre-phase1-member-mgmt / pre-cleanup-2026-06-15 是历史快照。
