Claude Code 推出「跨会话消息」功能 不同对话窗口之间可以互相交流对话 组队干活
- 你开的多个 Claude Code 会话现在能互相传话了:一个终端改完的事,Claude 会自己去告诉另一个终端。
- 传过去的只有一段纯文字,不带对话历史也不带文件,想搬整个上下文,那是另一个功能的活。
- 整套设计里最要紧的一条:另一个会话说的话,永远不算你的授权。
多个 Claude Code 会话之间可以互相发消息
如果你习惯同时开好几个终端跑 Claude Code,一个在改前端、一个在跑数据库迁移、一个在另一个 worktree 里干活,那这些会话过去是彼此隔音的。谁也不知道旁边那个在干嘛,要同步点什么,只能你自己在终端之间复制粘贴。
现在这堵墙上开了个口子:一个会话学到的东西,Claude 可以自己递给另一个会话。它甚至不用你开口,刚改完的东西会影响另一个会话正在做的活时,它会主动去打个招呼。
users.name 改成了 users.display_name,一句话让它去告诉 weekly-digest。右边收到的是一行 @user-profiles 开头的消息,它自己判断出「统计查询还在读旧字段」,当场把代码改了。全程没有人在两个终端之间复制粘贴。视频:Anthropic要求是 Claude Code v2.1.224 或更新,跑在 macOS 或 Linux 上。满足条件就自动开着,不需要配置任何东西。
想知道自己这台能不能用,敲一句 /list-agents 就行(这个命令也可以写成 /peers)。认得这个命令,功能就是开的。
本站实测:这台 macOS 机器上 claude --version 返回 2.1.225,刚好过线;环境变量 CLAUDE_CODE_MESSAGING_SOCKET 确实存在,值是 /tmp/cc-socks/27983.sock,文档说的收件箱 socket 是真绑上了。当时只开着一个会话,所以列表返回的是空的:没有别人,自然谁也够不着。
你开一个终端跑起 Claude Code,那就是一个会话;开三个终端就是三个互相独立的会话。
像三个同事各自在自己工位上干活,以前彼此隔音,现在中间开了个传纸条的口子。
每个会话在本机开的一个收信口,别的会话把消息投到这里。
像每户门口挂的信箱,只有同一栋楼(同一台机器、同一个系统用户)的人投得进去。
一条消息只有一段纯文字,不含对话历史和文件
这是最容易误解的一点,得先说清楚。
一条消息就是一个 Claude 写给另一个 Claude 的一段纯文字。不是对话历史,不是文件,不带上下文。接收方看到的只有发送方的名字和那段文字,对方聊过什么、动过哪些文件,它一概看不见。
文档给的示例消息长这样:
数据库迁移做完了,新字段叫 tenant_id,现在 rebase 到 main 是安全的。
官方文档中的示例消息
就这么一句话。
所以边界也清楚了:如果你想搬的是整个对话,比如换台电脑接着聊,或者让新会话继承现在的上下文,那不该用消息,该用恢复会话(resume)把整个会话续过去。
两个工具由 Claude 自己调用,不用你手动发
这件事背后是两个工具:ListAgents 负责发现能够到哪些会话,SendMessage 负责按名字把消息送过去。
这两个工具你都不用管。Claude 自己判断该不该发、发给谁,连措辞也是它自己写的。你要做的只是给一句提示,比如告诉它「问问另一个终端里那个会话,迁移跑完了没有」,或者「把我们刚才干的事告诉那个在做支付接口的会话」,具体发出去的是什么话,由它决定。
想自己看一眼能够到哪些会话,敲 /list-agents。列表里会有三类:
跑在当前会话里面的 Agent。注意 Agent team 的队友不在这个列表里,Claude 通过团队自己的名册去联系它们。
同一台机器上跑着的 Claude Code 会话,包括后台会话。一个会话要绑上了收件箱 socket 才会出现在这里。
连着 Remote Control 时才显示,标着 Remote Control 字样,包括你在别的机器上和网页版里的会话。这一类只能回复,不能主动搭话。
NAMING会话的名字从哪来
消息是按名字投递的,名字有三个来源:你用 /rename 改的、启动时用 --name 指定的,或者都没有的话 Claude Code 自己起一个,拿工作目录的文件夹名派生,像 myapp-3f 这样。
两个会话可能重名。/list-agents 的输出会带上各自的工作目录来区分,Claude 自己那份列表还会给每行加一个短标识,撞名的时候就用它来定位。
消息在工具调用间隙送达,有三种结果
消息到了对面,不会打断人家手上的活。接收方的 Claude 是在两次工具调用的间隙读消息的,所以一个正在执行的命令绝不会被打断。如果那个会话当时正闲着,消息会直接开启新的一轮。
至于能不能送到,有三种结果:
消息一旦送达,就按你自己敲的一条提示词计费。送达之后接收方也能同样回复过来,只有跨机器那种单向情况例外。
另一个会话发来的消息不算用户授权
这是整套设计里最讲究的地方。
当 A 会话给 B 会话发消息时,Claude Code 会明确告诉 B:这条消息来自另一个会话,不是来自你的人类用户。然后限制它能干什么,四条限制,每条挡的都是一种具体的坏情况:
另一个会话发来的消息,永远不算你的授权,不能拿去回答一个正等着你批准的权限提示。挡住的是:A 会话说一句「同意吧」,B 会话就把你没点头的操作放行了。
接收方被明确要求,绝不因为另一个会话说了什么,就去改权限设置、改 CLAUDE.md 或者别的配置。挡住的是:从一条消息开始,一步步把你的安全设置放宽。
消息文字里如果出现斜杠命令,它就是一段普通文本,Claude Code 不会执行。挡住的是:把命令伪装成消息内容送进去。
按消息去干活时如果需要某个权限,你会看到跟平时一模一样的提示。挡住的是:借着「这是别的会话让我干的」绕过日常审批。
发送这一侧同样有约束:Claude 被要求绝不去请另一个会话做那些在自己这边已经被拒绝、被拦下、或者按自己权限设置本来就做不了的事。碰上这种情况,它得把活退回给你,而不是绕道从别的会话干成。
这两侧加起来是同一个意思:跨会话消息是一条传话的通道,不是一条提权的通道。
没配置时按两个会话的权限模式决定送不送
你什么都没设的时候,Claude Code 会看两个会话各自的权限模式来决定。它把会话分成两类:一类会弹提示问你,另一类跳过权限提示直接执行。
(plan 模式在有跳过能力的会话里算「跳过」那一类;auto、acceptEdits、dontAsk 都算「会弹提示」那一类。)
规则是这样的:
| 接收方 | 发送方是「会弹提示」类 | 发送方是「跳过提示」类 |
|---|---|---|
| 会弹提示 | 送达 | 扣住等你批准 |
| 跳过提示 | 扣住等你批准 | 送达 |
乍看有点绕,但背后的逻辑很顺:一个能不问自明就直接执行的会话,最不能随便被外面喂消息,因为它收到什么就会去做什么。所以权限越松的会话,入站反而卡得越严。
一种权限模式,这个模式下 Claude 干活不再逐次问你,直接执行。
像给助理配了一把总钥匙,效率高,但正因为它不再问你,别人递进来的条子就更得先经你过目。
你自己定入站策略的设置项,三个值:accept 全送、hold 全扣住、refuse 全丢掉。
相当于给自家信箱定个规矩:来什么收什么、先攒着等我看、还是干脆封了投信口。
DIALOG被扣住之后会发生什么
消息被扣住时,接收方会弹一个审批框,显示发送方和消息预览。三条出路:
- 批准,这一条送给 Claude
- 拒绝,或者把框关掉,这条就丢了
- 放着不管,超过
dialogExpiry期限(默认五分钟)框会自己关掉,消息丢弃
扣住的消息最多存 100 条,超了丢最老的。如果扣住期间这个会话的权限模式变了,规则会重新过一遍,该放行的放行;要是变成了拒收,扣住的全丢掉,并且给每个够得着的发送方回一个拒绝通知。
发送方那边也看得到动静:消息被扣住时那边会收到通知,后来是送达、拒绝还是过期,也会有个跟进消息。只有一上来就被拒收的,发送方那边没有任何提示。
同机器走本地 socket,跨机器只能回复
消息走哪条路、这边能发什么,全看对方会话在哪儿:
「只能回复」的意思是:必须对方先开口,你这边才能搭话。想主动联系另一台机器上的会话,这条路走不通。
VISIBILITY同机器互通的前提是「看得见同一批文件」
每个会话把自己登记在磁盘上的文件里,并在那儿绑收件箱 socket。Claude 要列出或联系本机会话时,读的就是这些文件,所以两个会话能互相够到的前提,是它们看得见同一批文件。
这条推论很实际:容器有自己的文件系统,所以容器里的会话和宿主机上的会话互相够不着;但同一个容器里的两个会话可以互通,自托管 runner 上也一样。
还有个细节容易踩:跨机器的回复,如果发出时你这边没连着 Remote Control,消息仍然能送到(走对 Anthropic 服务器的直接请求),但不带回信地址,对方没法再回你。Claude 在发的时候会被告知这一点。
想让所有跨出这台机器的消息都要你点头,把 isolatePeerMachines 设成 true。设了之后,哪怕在跳过所有权限提示的模式下,回复要发出本机之前也会问你。任何一个设置层级里写了 true 都算数,所以一个提交进仓库的项目配置能打开这个要求,但关不掉它。同机器之间的消息不受影响。
claude -p 会话也能收消息,socket 给脚本用
无人值守的 claude -p 会话同样会绑收件箱 socket,能收消息,也会出现在列表里,所以一个长跑的 -p 工人可以接收指令。
但这里有个坑:-p 会话弹不出审批框。所以消息一旦被扣住,就一直扣在那儿,除非后来的设置变化把它放行。想让无人值守的工人能自己收消息,得在启动时的 --settings 里把 crossSessionInbound 设成 accept。(设在用户级设置里也行,但那会对你跑的每个会话都生效。)
另外还有一种叫 bare mode 的起法,那种不绑 socket,收不到消息,也不出现在列表里。
SOCKETsocket 在哪,怎么用
两个地方能找到路径:
/status里的Peer address那一行,路径带uds:前缀- 环境变量
CLAUDE_CODE_MESSAGING_SOCKET,hook 和 Bash 命令都拿得到,而且在任何 hook 跑之前就已经导出了(包括 SessionStart)。每个会话导出的都是自己的,不会继承父会话的
这意味着你可以让一个脚本或者 hook 往自己的会话里投消息。本站实测时拿到的值是 /tmp/cc-socks/27983.sock,那串数字就是会话对应的进程号。
这条路上有个平台差异值得记一下。会话自己的子进程(比如一个 hook 或 Bash 命令)回投消息时,如果能验明来路就直接送达:Linux(包括 WSL 2 里的)连已经退出的子进程都能验;macOS 只能在那个进程还活着的时候验;容器里如果 Claude Code 是 1 号进程,完全没法验。验不了的时候按普通消息处理,于是一个跳过权限提示的会话会把它扣住等你批准。
至于沙箱里的 Bash 命令能不能够到 socket,由沙箱的 Unix socket 设置管(sandbox.network.allowAllUnixSockets 和 sandbox.network.allowUnixSockets)。
收和发分别关闭,各有一个副作用
收和发是两个独立的开关,你可以只关一边:
| 你想关的 | 怎么做 |
|---|---|
| 不想收 | crossSessionInbound 设成 refuse,到达的消息全部丢掉不投递。从项目或本地设置里设,优先级压过其他所有来源 |
| 不想发、也不想被列出来 | 加权限拒绝规则,点名 SendMessage 和 ListAgents,两个都写裸工具名、不带参数 |
| 整个组织都关 | 管理员在 managed settings 里把两条拒绝规则和 refuse 一起写上 |
两个副作用得知道:
第一,拒绝 SendMessage 会连带干掉给子代理和团队成员发消息的能力。因为是同一个工具在服务这两件事,你本意可能只是不想让会话之间互相打扰,结果把会话内部的协作也一并关了。
第二,关掉之后从外面完全看不出来。Claude Code 仍然照常绑 socket,只是把到达的消息全丢掉。一个拒收的会话,在它自己的 /status 里和别人的列表里都没有任何标记,想确认,只能去查它的配置。
跟恢复会话、Agent teams 等的分工对照
Claude Code 里能「多开」的机制有好几套,最容易选错。文档专门列了一段对照,值得抄下来:
| 你想干的事 | 该用的 |
|---|---|
| 把同一个对话续到另一个终端,或把上下文带给新会话 | 恢复会话(resume) |
| 要一个由 Claude 自己生出来并统一指挥的团队 | Agent teams(Claude 自己拉起并管理的一队 Agent) |
| 在一个地方盯着并操控很多会话 | Agent view |
| 用手机或别的设备亲自操控某个会话 | Remote Control |
| 把外部事件(CI 结果、聊天消息)推进会话里 | channels |
| 你自己开的、各自独立的会话之间传个话 | 就是本文讲的跨会话消息 |
一句话区分:跨会话消息管的是「你自己开的、各自独立的会话」之间。由 Claude 生出来并指挥的那批,走的是团队自己的名册;要把上下文整个搬走,那是恢复会话的事。
系统版本服务商的限制,以及消息循环节流
| 条件 | 要求 |
|---|---|
| 操作系统 | macOS 和 Linux(包括 WSL 2 里的 Linux)。原生 Windows 上没有这个功能 |
| 版本 | v2.1.224 或更新 |
| 服务商 | Amazon Bedrock、AWS 上的 Claude Platform、Google Cloud 的 Agent Platform、Microsoft Foundry 都不提供 |
| 环境变量 | 为隐私关掉遥测的那几个变量(CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC、DISABLE_TELEMETRY、DO_NOT_TRACK、DISABLE_GROWTHBOOK),会连带把这功能依赖的特性开关判定关掉 |
最后这条最容易漏:你可能压根没想关消息功能,只是当初为了少发点遥测数据设了个环境变量,结果这功能一直是关的。这几个变量可能来自你的 shell、某个设置文件的 env 段,也可能来自管理员配置。
TROUBLESHOOT发不出去时怎么查
敲 /list-agents,两种情况分开看:
命令不认识:这个会话根本没有跨会话消息,照上面那张表一条条对,先从 claude --version 开始。
命令认识,但消息没到:功能是开的,问题在更细的地方,可能是权限拒绝规则把这两个工具摘掉了,可能是接收方的入站控制把消息扣住或丢掉了,也可能对方在另一台机器上(那种只能回不能主动发起)。
LIMITS两条硬限制
只能发纯文本。Agent teams 内部那种结构化的协议消息,出不了团队。
消息循环会被自动掐断。同一个发送方有限流,短时间内到达的完全相同的重复消息会被丢掉,等着 Claude 读的消息每个会话最多堆 50 条。所以两个会话互相刷消息的死循环,会自己停下来,不用你去救。
CLAUDE_CODE_MESSAGING_SOCKET 值为 /tmp/cc-socks/27983.sock、单会话状态下代理列表为空。文档未给出消息长度上限,也未说明「扣住上限 100 条」与「等读上限 50 条」两个队列的关系,以及接收方因消息产生的后续动作如何计费;提到脚本可往 socket 投消息,但未给协议格式。全部图示为本站按文档内容绘制。Claude Code 的多个会话现在能互相说话,但话不能替你点头
官方文档拆解:Claude 怎么找到谁能收话、消息送不送得到看什么、这条通道为什么焊死了不能提权
↓ 一页读完 · 有一张会动的图
会话之间能互相递话了,以前只能你自己复制粘贴
同时开几个终端跑 Claude Code 的人,以前彼此隔音,一个会话发现的事,得自己复制粘贴到另一个窗口才能同步。现在只要版本够新,Claude 会自己把这件事递过去,不用你开口,也不用配置。
传过去的只有一段纯文字
接收方看到的只有发送方的名字和一段话,比如「数据库迁移做完了,新字段叫 tenant_id,现在 rebase 安全」。对方聊过什么、动过哪些文件,一概看不到。
✘ 不传文件
✘ 不带上下文
Claude 自己判断该不该发,你不用去调用工具
这背后是两个工具:一个负责找到能够到哪些会话,一个负责把话送过去。两个都不用你手动点,Claude 自己判断要不要发、发给谁、措辞怎么写,你能做的只是提一句「问问另一个终端里的会话,数据库迁移做完了没有」。
另一个会话说的话,不算你的同意
消息送到时,Claude Code 会把来源标清楚:这是另一个会话说的,不是你说的。然后被框死能干什么、不能干什么。
✘ 不能因为这句话去改权限设置、CLAUDE.md 或别的配置
✘ 消息里出现的斜杠命令只是文字,不会被执行
✘ 该弹的权限提示照样弹,不会被绕过去
会话越敢自己拍板,外面递话进来卡得越严
没配置的情况下,Claude Code 按两边的权限松紧决定送不送:
| 接收方 | 发送方会弹提示 | 发送方跳过提示 |
|---|---|---|
| 会弹提示 | 送达 | 扣住等批准 |
| 跳过提示 | 扣住等批准 | 送达 |
这背后的道理:一个不问自明就直接执行的会话,外面递话进来的风险更大,所以权限越松的会话,入口反而卡得越紧。
不想要这条通道,收和发能分开关:crossSessionInbound 设成 refuse 关掉接收;加一条权限拒绝规则点名 SendMessage 和 ListAgents 关掉发送,但这会连带关掉会话内部叫子代理帮忙的能力。跑在 Bedrock、AWS、Google Cloud、Microsoft Foundry 上的版本目前都还没有这功能。这条通道只管你自己开的、各自独立的会话,恢复会话、Agent teams 那些其他「多开」机制走的是另一套。
前端那边知道吗
粘贴到另一个窗口
能自己说话了
迁移完了没
rebase 安全
- × 没有对话历史
- × 没有文件
- × 没有上下文
能替我点头吗
不是你
- × 不能替你点权限确认
- × 消息里的命令只是文字
啥时候能送到
收信卡得越严
确实自己传过去了
同意还是得自己点