2.5 第一条跨机消息
对话全景
你发跨机消息的方式跟单机一样:在自己的会话里说一句话——组装命令是 agent 的事,不是你的事。这一节用三步走完第一次跨机对话,全程你不需要记任何命令。
第一步 · 两头会话就位
你这一头:你本来就在一个会话里(比如 crosschat claude -n boss 起的那个)——你在里面说话,它替你发消息。对端那一头:yangwsl 机器上有个命名会话——让对端在自己的会话里 /rename beta2,再随便发一条激活即可(机器怎么配上 ssh 的,2.4 SSH 部署与配置已经做完,这里不再重讲)。
第二步 · 查对方会话
跨机的名单在对端机器上,本机 status 看不见——发之前看一眼,别赌名字:
> ssh yangwsl crosschat status
本机会话: claude 1 · codex 1
claude beta2 3 分钟前
codex workteam 12 分钟前
(全量: --claude|--codex|--name)
tcp: 无
ssh: 无
(明细: --conversations --via ssh)
第三步 · 一句话下令
👤 你在 boss 的会话里说:
用 crosschat 走 ssh 跨机给 yangwsl 机器的会话「beta2」问好,要求对方回复。
🤖 boss 自己组装命令、自己发(那条命令长什么样,在下一节——那是 agent 的语言,你不用记)。然后整段对话自己走完(真实实测实录,📨 是 agent 收到的外来消息):
🤖 beta2 收到 📨 来自另一会话的消息:
<cross-session-message from-name="claude/boss" turn="1" from-machine="win">
<crosschat-reply-hint reply-as="beta2">回复请运行: crosschat send --conversation c3 --body "<你的回复>"(长正文/含敏感字符可省 --body 改管道喂 stdin)</crosschat-reply-hint>
你好 beta2,这是跨机问候
</cross-session-message>
🤖 beta2 (照 hint 抄了一条回信命令——一个地址都没写)
🤖 boss 收到 📨 收到!跨机闭环成立(turn 2,自动经 ssh 回到 win)
win · boss yangwsl · beta2
│ │
│ ① send --via ssh:yangwsl --to beta2 │
│ ────────────── ssh 管道 ─────────────► │ ② 收到信封(from-machine="win",
│ │ 回信命令不带 --via)
│ │
│ │ ③ 照抄 hint 回信 --conversation c3
│ ◄────── 回程按 ref 自动选路走 ssh ───── │
│ ④ 收到回复(turn 2) │
与单机的全部差别只有四个字:题词里多了「走 ssh 跨机」。命令由 boss 组装,beta2 照信封回信,双方谁都没敲过一次完整地址。
下面几节把 agent 用的(或你想直接敲的)命令形态逐一拆开——每条都是:用途 → 完整实录 → 隐式发生什么。
发起跨机消息
全景第三步里,boss 替你组装的就是这条;你想自己直接敲,形态也一样:
> crosschat send --via ssh:yangwsl --to beta2 --body "你好 beta2,这是跨机问候,收到请回"
delivered to beta2@yangwsl(9f8e7d6c) (turn 1) · 续话 c1
隐式发生什么,一段讲完:这条命令没有在本机投递——crosschat 组装了一条固定的远端命令,经 ssh 送到 yangwsl 执行,等价于有人在那台机器上敲了 send --to beta2。名字 beta2 在对端名单里解析,本机同名会话与此无关。回执从对端传回后按本机格式重渲染,所以输出跟单机几乎一样,只有收件人多了机器段 @yangwsl(9f8e7d6c)——名字加对端指纹(2.2 机器指纹 mid)。忙时三态照单机语义:
queued to beta2@yangwsl(9f8e7d6c) (turn 2; 对方正忙,已入队,本轮结束即处理) · 续话 c1
已寄存给 beta2@yangwsl(9f8e7d6c)(对方忙,未送达)。队列共 1 条,看门狗每 0.5–5 分钟自动重试,无需手动 status。
人工随时可读滞留内容: ~/.crosschat/mailbox/<线程ID>.md(位于 yangwsl)
续话: c1
delivered / queued 都无需重发;parked 是旧版守护的异常态,已暂存、看门狗自动重投,同样无需手动干预。行尾「续话 c1」是本机配的会话短柄,续话照抄。
❌ 再把别名敲错一次,看看跨机报错长什么样(传输层不通时):
> crosschat send --via ssh:yangsl --to beta2 --body "…" # 别名手滑少了个 w
crosschat: SSH_TRANSPORT_FAILED: ssh 无法到达 yangsl(不通/密钥/known_hosts)。自证: ssh yangsl crosschat --version(顺带核对版本);检查 ~/.ssh/config 与网络。
错误自带头诊断命令——照抄跑一遍就知道断在哪一层。
还有一条纪律在此立住:跨机轮次纪律。防乒乓限流器是各机各自记账的,跨机没有全局限流——turn 轮次是唯一防线。接近预算就总结收尾,别无限往返。
回信不写地址
对端的 beta2 要回复时,它也只是照抄信封里的命令——一个地址都不用写,你的视角里依然是零命令:
> crosschat send --conversation c3 --body "收到!跨机闭环成立"
delivered to claude/boss@win(3f2a81b0) (turn 2) · 续话 c3
隐式发生什么:回信命令里没有 --via,也不需要——发起方机器名已经坐在 c3 背后的对话引用(ref)里,执行侧按它自动补路由:本机 ssh config 里有 win 这个别名,就走 ssh;没有别名但本机入了 tcp 星(第3课),就换 tcp 腿;都没有就照旧试 ssh 并在失败时报错指路。这就是 2.2 别名与 hostname 那句“别名 = hostname 是软依赖“的落点:win 在 yangwsl 侧的别名恰好叫 win,回程自动成立。
信封括注里那句“长正文/含敏感字符可省 –body 改管道喂 stdin“对跨机同样成立——正文走 stdin 管道,不进任何一层的命令行,$、反引号、引号逐字到达(第1课 单机通信的管道手法原样可用,这也是 2.6 通信机制会展开的一条设计)。
查对端名单
全景第二步那条命令的门道与名单的细节:
这就是一次普通的 ssh 远程命令,跑的是对端自己的 status——你看到的是对端那张名单,过滤参数照常可用(ssh yangwsl crosschat status --claude)。
名单上的会话也不问出身,TUI 不是收件前提。codex 的投递目标一律是 daemon 里的线程——TUI 只是其中一个窗口(窗口占着线程时反而会挡住投递,报 CODEX_THREAD_LOCKED,关窗或等它释放即恢复),codex exec 这类无头方式拉起的线程同样在名单里,未命名的用 id8 寻址;claude 这边,后台(bg)会话与交互会话同权可投。例外只有 2.4 说过的 win 收件腿:codex 不可达(AF_UNIX 跨登录会话隔离)。唯一不担保的是在命令行里一次性匿名拉起的 claude(比如 claude -p 干一次性活)——它进不进名单取决于自己有没有注册消息通道,crosschat 不做承诺:发之前 status 看一眼,别赌。
反方向看自己:跨机对话发起后,本机的 crosschat status --conversations 会出现这一对(发起侧也记账):
会话:
文档book → ssh专家 9 分钟前 turn 6 delivered c17
一行里双方、最近轮次、投递状态、行尾续话柄都在。注意 status --via tcp:<机器> 那种远程枚举形态是第3课 跨机通信(tcp)的 tcp 通道能力;ssh 对端就用上面这条 ssh 命令。
体检与望诊
三条命令回答三个问题:本机环境能跑吗(doctor)、对端环境能跑吗(远程 doctor)、我的跨机对话都怎么样(status 过滤)。
先立一个边界:doctor 不检查 ssh 联邦。它体检的是所在机器自己的环境——Node 版本(≥22)、claude 可路由会话、codex CLI 与 daemon 版本(≥0.160 才有忙时入队)、双侧 skill 安装、双身份残留;入了 tcp 星的机器另查星条目与 broker 可达。ssh 别名、密钥、连通性这些联邦项不在它的清单里——联邦诊断走 2.4 的自证命令。
> crosschat doctor
环境
✅ Node v22.9.0 (≥22)
✅ claude CLI C:\...\claude.exe;可路由会话 2 个
✅ codex CLI 0.160.0
✅ codex daemon 0.160.0
✅ claude 侧 skill 与安装源一致
✅ codex 侧 skill 与安装源一致
✅ 无双身份残留
结论: 7 项通过,0 项警告,0 项错误
读法两条:只有 ❌ 让退出码非 0(脚本可判);⚠️ 是合法状态的教学提示——codex 没装、daemon 没跑都只警告不判错,“这台机器是纯 claude 机“是合法答案。对端没入 tcp 星时 tcp 段整段不出现,就像上面临录这样干净。
远程望诊就是同一条命令经 ssh 到对端跑——你坐在本机看对端的体检报告:
> ssh yangwsl crosschat doctor
环境
✅ Node v22.11.0 (≥22)
✅ claude CLI /usr/local/bin/claude;可路由会话 1 个
⚠️ codex daemon 未运行;要用 codex 通道时先执行: codex app-server daemon start
结论: 5 项通过,1 项警告,0 项错误
(实录里的 ✅⚠️ 是 doctor 程序自己打的,不是排版装饰——照抄即得同样输出。)最后是 status 的 ssh 专属过滤:
> crosschat status --conversations --via ssh
会话:
文档book → ssh专家 9 分钟前 turn 6 delivered c17
--via ssh 只留 ssh 腿的对话段(tcp 的用 --via tcp)——跨机对话多了以后,这一条就是你的 ssh 联邦台账。
正文超限时
用途:正文超过大小上限时,按报错指的路走 scp 旁路——大内容不过消息通道。
❌ 先看本地直接挡下的样子(默认上限下硬塞 20KB):
> crosschat send --via ssh:yangwsl --to beta2 --body "<20KB 长文>"
crosschat: MESSAGE_TOO_LARGE: Body is 20000 bytes; the limit is 16384. 可提额:--max-body-kb <KiB> 或 CROSSCHAT_MAX_BODY_KIB=<KiB>(claude 端点硬顶 64KiB、codex 端点 1MiB,到顶只能落盘)。跨机大内容(ssh 形态):先 scp <文件> yangwsl:/tmp/<文件名>,再 crosschat send --via ssh:yangwsl … --body "见 /tmp/<文件名>"(scp 与 --via 共用同一份 ssh 配置)
❌ 还有一种更隐蔽的:本机提了额、出发了、在对端被拦下——错误带 [via] 前缀回来,教学也换成接收方视角:
> crosschat send --via ssh:yangwsl --to beta2 --body "<20KB 长文>" --max-body-kb 64
crosschat: MESSAGE_TOO_LARGE: [via yangwsl] Body is 20000 bytes; the limit is 16384 on this machine (a --via remote send). 发送方本机提额无效——上限属接收方(本机)配置。大内容走 scp 旁路:发送方先落盘,scp <文件> <接收方>:/tmp/<文件名>,再 crosschat send --via ssh:<接收方> … --body "见 /tmp/<文件名>"(scp 与 --via 共用同一份 ssh 配置)。确需直发大内容:由接收方(本机)操作者调 CROSSCHAT_MAX_BODY_KIB。
✅ 照报错教的做(scp 与 --via 共用同一份别名和密钥,2.4 SSH 部署与配置配一次全通):
> scp big-analysis.txt yangwsl:/tmp/big-analysis.txt
> crosschat send --via ssh:yangwsl --to beta2 --body "分析 /tmp/big-analysis.txt,结论报过来"
delivered to beta2@yangwsl(9f8e7d6c) (turn 3) · 续话 c1
① 本机落盘 big-analysis.txt ──► ② scp 到对端 /tmp/ ──► ③ send 只发一句话(带对端本地路径)
(超限的大正文留在这里) 与 --via 同一份别名/密钥 消息通道只走路径引用
大结果回传同理反向走一遍(对端 scp 回来,或题词让对端把结果落盘发路径)。
隐式发生什么,把这套数字一段讲完:默认上限 16KiB;--max-body-kb 或环境变量可调高,但 claude 投递管道硬顶 64KiB、codex 硬顶 1MiB,到顶提额无效;ssh 跨机腿在出发前按最宽的 1MiB 预检——超线本地直接挡下,ssh 根本不会发起;过了预检的,到对端还要用对端自己的限额复检一次(上面第二条实录就是)。所以超限的正解从来不是硬塞,而是 scp。要说清楚的是:scp 不是 crosschat 的内建通道——代码负责预检、并在报错里教这三步,真正执行 scp 的是你(或 agent)。win↔WSL 这对还有更省的捷径:文件根本不用过网络,WSL 直写 win 盘(cp result.txt /mnt/c/Users/<你>/AppData/Local/Temp/),用完即删。