让并行的多个 opencode 会话直接对话,无需复制粘贴------忠实复刻 Claude Code 的跨会话消息范式。
如果你同时开着好几个终端跑 OpenCode------一个改前端、一个改后端、一个守着长跑的迁移------那 opencode-plugin-peers 就是为这种场景准备的:它让这些相互独立的 OpenCode 会话能在同一台机器上发现彼此、互发纯文本消息,而无需在窗口之间来回复制粘贴。
更关键的是:它的设计完全复刻了 Claude Code 的跨会话消息(cross-session messaging)范式 ------同样的纯文本边界、同样的 ListAgents/SendMessage 式工具、同样的 accept/hold/refuse 入站策略。你可以把它理解为「OpenCode 版的 Claude Code 跨会话消息」。
- npm :www.npmjs.com/package/ope...
- GitHub :github.com/jkrandom-su...
一、它解决什么问题
并行使用多个 AI 编码会话时,最痛的不是算力,而是上下文在不同窗口之间断裂:
- 前端会话改了接口契约:"字段从
userId变成了user_id" - 后端会话跑完了数据库迁移:"迁移完成,可以安全 rebase 到 main 了"
这些结论原本要么靠你手动口述、要么靠复制粘贴。opencode-plugin-peers 做的事情,就是让会话之间直接把结论交给对方。
text
frontend 会话:"API 契约变了,字段现在是 user_id"
backend 会话:"迁移跑完了,可以安全 rebase 到 main"
二、核心定位:忠实复刻 Claude Code 的跨会话消息风格
这是这个插件最值得讲的一点。它并不是凭空设计一套消息协议,而是刻意沿着 Claude Code 已经验证过的跨会话消息范式来构建。从概念到命令名,几乎都能一一对应:
| opencode-plugin-peers | Claude Code 跨会话消息 | 说明 |
|---|---|---|
list_agents 工具 |
ListAgents 工具 |
发现当前可触达的会话 |
send_message 工具 |
SendMessage 工具 |
按名称向某个会话投递消息 |
/peers(别名 /list-agents) |
/list-agents(别名 /peers) |
命令名都几乎一致 |
/peers-name |
/rename / claude --name |
给会话命名以便寻址 |
/peers-inbox、/peers-outbox |
持留(held)消息审批 | 入站消息的人工审核 |
inboundPolicy:accept/auto/hold/refuse |
crossSessionInbound:accept/hold/refuse |
入站策略(多了一个智能的 auto) |
peerPermissions:allow/ask/deny |
权限模式(bypass / prompt) | 跨会话权限边界 |
| 纯文本、不含文件 / 历史 / 命令 | 纯文本、不含文件 / 历史 / 命令 | 完全一致的安全边界 |
它最忠实地继承了 Claude Code 那条刻意的克制设计:
消息只能是纯文本------不传文件、不传对话历史、不传授权、不传可执行的斜杠命令。接收方收到的是一条「合成用户消息」,其中带有发送方的精确端点 ID 和如何回复的说明。所有由该消息触发的动作,依然要经过接收会话自己的权限规则。
这条约束让「默认开启消息互通」变得安全,也正是 Claude Code 跨会话消息能够放心默认开启的核心理由。
三、安装
前置条件:opencode >= 1.18.0。
方式一:CLI 安装
bash
opencode plugin -g opencode-plugin-peers
方式二:写进 opencode.json
json
{
"plugin": ["opencode-plugin-peers"]
}
可选但推荐:单回车立即执行。 该包附带一个 TUI 条目,能让斜杠命令在第一次回车时就执行。因为 opencode 的 TUI 从 ~/.config/opencode/tui.json(与 opencode.json 不同的另一份列表)加载插件,所以建议把插件也加到那里:
json
{
"plugin": ["opencode-plugin-peers"]
}
不加也能用,只是命令会保留 opencode 默认的「第一次回车补全 /name、第二次回车才提交」行为。几个细节:
- 自动补全里每个命令只显示一行
/peers*;立即执行来自 TUI 条目里一个高优先级的回车绑定。 - 带参数的命令 (如
/peers-name frontend)不受影响------回车照常提交,参数原样保留。 - 旧版 opencode 会忽略这个 TUI 条目,保持两段式回车。
本地开发(从 checkout):
bash
npm install && npm run build
ln -sf "$PWD/dist/index.js" ~/.config/opencode/plugins/opencode-plugin-peers.js
# (~/.config/opencode/plugins/*.js 会在启动时自动加载)
四、快速上手:3 分钟跑通
bash
# 终端 1
cd /tmp/proj-a && opencode
/peers-name alpha
# 终端 2
cd /tmp/proj-b && opencode
/peers-name beta
/peers # 应该能看到 alpha
# 在 beta 的会话里,让 agent 发消息:
Use send_message to tell "alpha": the deploy keys rotated, pull again.
# alpha 会立即收到这段文本------即便它正忙,也照样注入;
# 同时,"传输已收"与"最终送达 ACK"是两回事,会被分别跟踪。
关键命令速查
| 命令 | 作用 |
|---|---|
/peers-name <名称> |
给当前会话命名,方便别人按名称找你 |
/peers(别名 /list-agents) |
查看当前在线的 opencode 会话 |
/peers-inbox |
列出被持留(held)的消息 |
/peers-inbox accept 2 |
放行第 2 条持留消息 |
/peers-inbox drop all |
丢弃全部持留消息 |
/peers-outbox |
查看回执与最终 ACK 结果 |
/peers 的输出长这样
text
Other Opencode sessions (2):
[waiting] · frontend · /Users/you/app/frontend · started 9m ago
[idle] · backend · /Users/you/app/backend · started 29m ago
[waiting]:那边正在跑一个 turn,但对端消息仍然会被立即注入;[idle]:那边没在跑 turn;- 若出现「队列中的消息」,表示一次即时注入需要重试(不是要等对方空闲),同时发送方仍持有一个待定的最终 ACK。
让 agent 自己开口
直接用自然语言驱动即可,无需手动调工具:
text
Use send_message to tell "backend" that the login form now posts to /v2/login.
- 接收方会立刻收到一条合成用户消息,含发送方精确端点 ID 与回复方式;
send_message会返回一个追踪 ID;- 用
peer_message_status或/peers-outbox可以区分「传输已收」与「最终送达」。
五、功能特性一览
list_agents/send_message工具------agent 能自己发现 peer 并发消息。- 斜杠命令 ------
/peers(别名/list-agents)、/peers-name、/peers-inbox、/peers-outbox,供用户侧控制。 - 四级入站闸门 :
accept / auto / hold / refuse;其中auto会自动放行同目录 的 peer,对跨目录消息则持留待审------这是个比 Claude Code 更细的策略档位。 - 每个会话一个可独立寻址的端点 (含子会话);名字重复时用精确的端点 ID 消歧。
- 持久化队列 :持留消息、送达结果、发送方发件箱在进程重启后仍然存活。
- 即时注入 :被接受的消息会通过每条一次
promptAsync立即注入,即便目标会话正忙也照注入。 - 纯文本、无文件、无共享历史------和 Claude Code 一模一样的边界。
- 对端触发的 turn 默认无人值守 :由注入消息引发的权限请求会被自动批准(
peerPermissions,对应 Claude Code 的权限模式);你自己手敲的 turn 不受影响。 - 结果与通知内联展示,不弹 toast。
- 显式 TUI 控制:palette 动作使用宿主对话框进行选择与确认;斜杠命令封装保留,方便自动化与兼容。
- 纯本地:一切都在本机(macOS/Linux 用 Unix 域套接字,Windows 用回环 TCP,外加一个兼容 v1 的回环监听器)。
六、配置项
通过 opencode.json 的元组形式传参:
json
{
"plugin": [
["opencode-plugin-peers", { "inboundPolicy": "hold", "name": "frontend" }]
]
}
| 选项 | 默认值 | 说明 |
|---|---|---|
inboundPolicy |
"accept" |
accept 立即送达;auto 仅在收发双方目录相同时放行、否则持留;hold 暂存待审;refuse 拒收 |
peerPermissions |
"allow" |
对端发起的权限请求:allow 自动批准普通请求,ask 保留原生提示,deny 拒绝。即使在 allow 下,权限配置、AGENTS.md、凭证/密钥、权限提权等永不自动批准;已有 deny 规则永远优先 |
name |
目录名 | 别人用来寻址你的显示名 |
storageDir |
$XDG_DATA_HOME/opencode-plugin-peers |
注册表与持留收件箱的存放位置 |
heartbeatMs |
10000 |
注册表心跳间隔 |
staleMs |
30000 |
心跳超过该阈值即判定为离线 |
maxQueue |
50 |
已接受但未送达的消息上限 |
maxHeld |
100 |
持留收件箱上限 |
heldExpiryMs |
300000 |
持留审批的过期时间;过期会产生最终 ACK |
maxMessageBytes |
8192 |
单条消息大小上限 |
sendRatePerMin |
10 |
每个 peer 的出站速率限制 |
recvRatePerMin |
20 |
每个发送方的入站速率限制 |
sweepMs |
15000 |
投递 / ACK 可靠性的兜底扫描间隔 |
七、工作原理
text
OpenCode process A OpenCode process B
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ session A1 → endpoint/spool │ │ session B1 → endpoint/spool │
│ session A2 → endpoint/spool │ │ session B2 → endpoint/spool │
│ durable outbox ◄── final ACK ├───────────┤ local UDS/TCP listener │
│ registry v1 + v2 ────────────┼──────────►│ promptAsync(exact session) │
└──────────────────────────────┘ └──────────────────────────────┘
- 发现(Discovery) :协议 v2 为每个会话端点发布一条
0600注册记录,并为最近活跃的根会话发一条 v1 兼容记录。只有有生命迹象 的会话才被广播(启动时的 busy/重试、随后的会话事件或消息活动、或等待恢复的未投递 spool 记录)。session.list()里的历史会话永不 发布,所以/peers只显示存活会话。 - 传输(Transport) :v2 在 macOS/Linux 用带鉴权的 Unix 域套接字,Windows 用回环 TCP;同时保留一个回环 HTTP 监听器供 v1 发送方使用。peer 永远不会去调用另一个进程的 OpenCode server。
- 投递与恢复(Delivery & recovery) :每条消息都是
spool/<endpoint>/{queued,held,inflight,done}下的一条0600JSON 记录。原子状态迁移、进程锁、确定性的 OpenCode 消息 ID 与持久化去重,让重试与重启都是安全的。 - ACK 语义 :HTTP 接受只是一个回执 。最终的
delivered / refused / expired / dropped / duplicateACK 会被持久化重试给发送方,并存入outbox/。 - 环路保护 :消息携带
via跳转列表;超过 4 跳的链路会被拒绝。
八、安全模型(务必读)
- 同机信任 :任何以你用户身份运行的进程都能读取注册表文件,从而能和你的会话收件箱通信。bearer token 只防其他用户 和误连 ,不防同 UID 的恶意进程------这一点与 Claude Code 本地 IPC 的信任级别一致。
- 提示注入 :一条 peer 消息对模型而言是不可信输入 ,跟你粘贴的文本没有区别。纯文本无法传递文件、历史、授权或可执行斜杠命令。在默认的
peerPermissions: "allow"下,普通工具请求可以无人值守地执行;对敏感项目请改用ask、hold或refuse。 - 受保护类别的护栏是「尽力而为」,不是「硬边界」 :
allow模式下,插件会拒绝 对那些提及 权限配置、AGENTS.md、凭证/密钥、shell 启动文件等敏感路径的请求进行自动批准------但它是按请求文本匹配 的,措辞巧妙的请求仍可能避开命名路径(例如npm config set x y会写~/.npmrc,却从不显式出现该路径)。请把allow当作「完全信任本机上的每一个 peer」 ;在信任不成立时,请设置ask(或inboundPolicy: "hold"/"refuse")。 - 自动批准如何保持有界 :插件监听权限请求事件,只有当发起该 turn 的是它注入的消息时 才自动应答(通过从工具调用的消息向上回溯到原始用户消息、检查其 metadata 来判定)。你自己手敲 turn 发起的权限请求不会被应答,会原样落入 opencode 的正常提示流程。
九、与 Claude Code 的对照
| 能力 | Claude Code | opencode-plugin-peers |
|---|---|---|
| 跨进程与同进程的会话寻址 | 原生 | 有,本地端点注册表 |
| 名字重复时的精确寻址 | 有 | 有,歧义时用端点 ID |
| 目标正忙时仍可投递 | 有 | 有,每条一次即时 promptAsync 注入 |
| 持久化投递 / 重启恢复 | 产品级托管 | 有,文件系统 spool + 持久化 ACK/发件箱 |
| 权限边界 | 原生策略集成 | 基于事件的 allow/ask/deny + 受保护类别护栏 |
| 用户审批 UX | 原生 | 显式宿主 TUI 对话框 + 斜杠封装 |
| 远程控制 / 共享任务 UI | Claude 生态可用 | 超出范围 |
结论:在发现、精确寻址、忙时投递、重启恢复、最终结果追踪 这几个「本地纯文本交接」的效果上,它与 Claude Code 基本等价;但它不是 Claude Code 产品级编排或远程 UI 的即插即用替代。
十、局限
- 仅限同机(暂无跨主机中继)。
- opencode 的
command.execute.beforehook 目前不可取消:斜杠命令因此通过「把提示文本替换成一个无害的已处理标记」来消费;TUI palette 控制会额外加上显式对话框,但 server hook 本身无法阻止后续命令处理。 - 没有共享 transcript、Remote Control、Agent View、跨机中继,也没有 Claude Code 式的 team/task 编排。
十一、典型用法与工作流
下面这些模式都来自 Claude Code 跨会话消息的实践------因为范式一致,它们可以直接平移到 opencode-plugin-peers。
模式 1:监控者把活儿交给一个 worker
让一个会话盯着长跑任务(日志、 soak 测试、迁移)。当它发现问题,不要就地修 ------它的上下文已经被污染。新开一个命名的 worker(/peers-name worker-fix)在干净的 worktree/PR 里干活,让监控者把问题描述过去,等 worker 修完再发消息回来。监控者得以带着干净上下文继续监控。
模式 2:只给目标、不给包袱(隔离式验证)
给第二个会话只发一个目标------不给技能、历史、文件------问它会选什么策略。它的回答「天生独立,而非靠自律」。并行跑几个;当多个新窗口都收敛到你的方案,方案就被印证;当其中某个找到更短的路径,那就是你下一个要修订的点。
模式 3:协调者自己开窗
list_agents 只能触达已存在的会话,插件本身不会替你开窗。但配合终端复用器 CLI,agent 可以自己开 pane、在其中启动命名会话、再发任务过去。一个会话做协调(例如在每个独立 worktree 里 review 一个 PR),把回复一个个收回来。
模式 4:无头(headless)跑批
bash
cd /tmp/proj-a && opencode serve --port 14100 &
cd /tmp/proj-b && opencode serve --port 14101 &
# 然后通过 HTTP API 驱动两者(POST /session、/session/:id/prompt_async)
十二、小结
opencode-plugin-peers 的价值可以用一句话概括:
它把 Claude Code 已经打磨成熟的「跨会话纯文本消息」范式,原汁原味地搬进了 opencode------同样的纯文本安全边界、同样的
ListAgents/SendMessage风格工具与/peers命令、同样的accept/hold/refuse入站闸门,外加一个更细的auto档和持久的重启恢复。
它不追求复刻 Claude Code 的产品级编排或远程 UI,而是把「让并行的多个会话把结论直接交给彼此」这件事,做得安全、本地、可恢复。如果你已经在用 Claude Code 的跨会话消息,迁移心智几乎为零------连命令名都几乎一样。
上手就两步 :装插件、给会话命名。然后,当一个窗口里的结论需要让另一个窗口知道时,直接说出口------agent 会替你写好消息,对端会立刻收到。