mcpField
C
claude-remote-peers

claude-remote-peers

github.com/vivswanAgent 工作流147 次安装今天更新
代码仓库

关于 claude-remote-peers

claude-remote-peers 通过 SSH 转发 Unix socket,让不同机器上的 Claude Code 会话互相发送消息。它不复制注册记录或密钥,也不会在远端启动 Claude 进程。

主要功能

  1. 01SSH 转发会话收件箱 socket
  2. 02通过地址直接发送消息
  3. 03回复主动推送到本地会话
  4. 04检查转发状态并清理 socket
  5. 05支持指定远程进程与 SSH 参数

适用场景

  1. 01让两台开发机器上的 Claude Code 会话通信
  2. 02将消息发送到特定远程会话
  3. 03完成跨机器协作后清理转发

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vivswan/skills --skill claude-remote-peers

安装后在 Claude Code 中输入/claude-remote-peers确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE.md
README.md
.codex-plugin/
plugin.json
agents/
openai.yaml
references/
protocol.md
scripts/
bridge.mts

详细介绍

Claude Remote Peers

两台不同机器上的 Claude Code 会话可以像同一台机器上的两个会话那样互相发送消息。向 Unix 套接字写入内容会唤醒另一端。桥接程序会通过 ssh 将每个会话的收件箱套接字转发到另一台机器上的相同路径。不会复制任何内容,也不会轮询。

示例

两台开发机器,每台各运行一个 Claude Code 会话。在 A 机器上运行 ListAgents 时,没有显示任何对等会话。桥接程序从 A 机器会话的 shell 中运行:

$ bun "<skill-dir>/scripts/bridge.mts" box-b
bridge up: session-b (pid 2002 on box-b), bridge pid 4242
SendMessage to: uds:/tmp/cc-socks-1000/2002.sock
they reply to:  uds:/tmp/cc-socks-1000/1001.sock

使用 to: uds:/tmp/cc-socks-1000/2002.sock 的 SendMessage 成功发送到 B 机器。B 机器上的会话回复了消息中的 from 地址。回复自动送达 A 机器上的当前轮次:

<cross-session-message from="uds:/tmp/cc-socks-1000/2002.sock" from-name="session-b" from-mode="bypass">
bridge ok
</cross-session-message>

两台机器的 ~/.claude 中都没有写入文件。

权限

是否向另一台机器上的会话发送消息由用户决定,每个会话只需询问一次。向本机上的会话发送消息则无需询问。

首次向远程地址发送 SendMessage 之前,请询问用户,并说明主机和会话(box-b、session-b、pid 2002)。用户同意后,之后向该对等会话发送的所有消息都无需再次询问。

用户的指示本身就是授权,授权范围由指示中提到的对象决定。“与 box-b 上的 Agent 交谈”涵盖 box-b 上的所有会话。“与 box-b 上的 session-b 交谈”仅涵盖该会话,无需另行询问。

任何超出授权范围的情况都需要重新询问:例如另一台主机,或用户按会话授权的主机上的另一个会话。

将授权记录在本会话自己的笔记中(任务列表或计划),不要记录在记忆中。新会话需要重新询问。用户表示撤销授权时,删除该笔记。

工作流

  1. 在后台启动桥接程序,从本会话内部的 shell 启动(其 Bash 工具会继承 CLAUDE_CODE_MESSAGING_SOCKET)。<destination> 可以是 ssh 接受的任何内容。

    nohup bun "<skill-dir>/scripts/bridge.mts" <destination> > /tmp/claude-remote-peers.log 2>&1 < /dev/null & disown
    

指定远程 pid,或在 -- 后添加额外的 ssh 选项:

bun "<skill-dir>/scripts/bridge.mts" box-b 2002
bun "<skill-dir>/scripts/bridge.mts" [email protected] -- -p 2222 -i ~/.ssh/other_key

--help:

usage: bridge.mts <ssh-destination> [remote-pid] [-- <extra ssh options>]
run from a shell inside a Claude Code session (it sets CLAUDE_CODE_MESSAGING_SOCKET)
prints: SendMessage to: uds:<remote socket> once both forwards are confirmed; stays up until ssh exits or a signal
exits: 0 clean shutdown (a signal, or ssh exited 0); 1 a setup, tunnel, or cleanup failure
  1. 等待日志中的 SendMessage to: 行。只有在脚本确认两个转发都已建立(包括通过 ssh 建立的远程转发)之后,才会打印该行。更早出现的套接字文件尚不能证明连接可用。

  2. 将打印出的地址用作 to 发送消息。 远程端会收到普通的 <cross-session-message>。它会回复 from 地址,无需你做任何操作。

  3. 回复会主动推送。 回复会以 <cross-session-message> 的形式送达,并在此处开启一个轮次。切勿轮询日志、套接字或远程注册表来检查回复。

  4. 完成后停止桥接程序,使用 bridge up 行中的 bridge pid。拆除时会移除两个转发的套接字,并记录 cleanup done。如果远程移除失败,会记录错误并以状态码 1 退出。

    kill 4242
    

不使用 bun

也可以在 shell 中完成。远程 pid 和套接字路径来自远程注册表。CLAUDE_CODE_MESSAGING_SOCKET 是本会话自己的收件箱。

两项检查都会在任何内容被转发之前终止该函数。任何一端已存在的路径若是正在使用的收件箱,都不会被转发或移除。套接字路径中包含引号时,需要使用脚本,因为脚本会为远程 shell 正确处理引号。

h() { ssh -o ClearAllForwardings=yes box-b "$@"; }   # helper commands drop config forwards that would collide with the tunnel's
h 'cat ~/.claude/sessions/*.json'      # pick a live one; note its messagingSocketPath
remote_sock=/tmp/cc-socks-1000/2002.sock   # that messagingSocketPath, e.g. this shape (uid dir, pid file)

bridge() {
  unset bridge_pid                                      # the cleanup below acts only on a forward this call started
  mkdir -p -m 700 "${remote_sock%/*}"                   # their socket dir, needed here when the uids differ
  test ! -e "$remote_sock" || { echo "a local session owns that path; stop"; return 1; }
  h "mkdir -p -m 700 '${CLAUDE_CODE_MESSAGING_SOCKET%/*}' && test -w '${CLAUDE_CODE_MESSAGING_SOCKET%/*}' && test ! -e '$CLAUDE_CODE_MESSAGING_SOCKET'" \
    || { echo "our path on box-b is taken or its directory is not writable, or ssh failed; stop"; return 1; }
  ssh -o ControlPath=none -o ExitOnForwardFailure=yes -N \
         -L "$remote_sock:$remote_sock" \
         -R "$CLAUDE_CODE_MESSAGING_SOCKET:$CLAUDE_CODE_MESSAGING_SOCKET" box-b &   # no connection sharing: the forwards must die with this pid
  bridge_pid=$!
}
bridge && sleep 2 && kill -0 "$bridge_pid" && h "test -S '$CLAUDE_CODE_MESSAGING_SOCKET'" && echo "bridge up"   # a refused forward makes ssh exit; replies need the -R socket on box-b
# SendMessage to = uds:<the remote_sock value>

# afterwards; bridge_pid is set only by a bridge() call that started the forward
[ -n "$bridge_pid" ] && { kill "$bridge_pid"; rm "$remote_sock"; unset bridge_pid; h "rm -f '$CLAUDE_CODE_MESSAGING_SOCKET'" || echo "remove $CLAUDE_CODE_MESSAGING_SOCKET on box-b by hand"; }

桥接程序不会做什么

  • 它不会在 ListAgents 中列出远程会话。 列表只读取本地注册表。请使用脚本打印的 uds: 路径访问远程会话。
  • 它不会复制注册表记录或密钥文件。 了解这种做法为何可行,以及复制为何更糟:寻址与认证和桥接程序为何不复制任何内容。
  • 它不会在远程端留下任何运行中的进程,除了用于维持转发的 ssh 会话。查找、预检查和清理都通过短暂运行后退出的 ssh 命令完成。不会启动、恢复或派生任何 Claude 进程。

常见问题

你看到的内容含义操作
no live Claude Code session with a messaging socket on box-b另一端没有会话,或者其套接字已失效启动或检查远程会话,然后重新运行
could not read the session registry on box-bssh 失败、远程端缺少 python3,或者无法读取 ~/.claude/sessions运行 ssh box-b python3 --version;上一行会显示远程错误
ssh to box-b failed (exit 255)空路径检查未能连接到远程端先修复 ssh:ssh -v box-b true
<path> already exists on this machine 或 on <destination>转发会话的这一端或另一端有一个会话的 pid 与其相同,或者遗留了过期的转发重启一个会话或移除过期套接字,然后重新运行
ssh exited (255) before the forwards came up隧道在启动期间断开;ssh 自身的错误显示在上一行(转发被拒绝、登录失败)修复 ssh 报告的问题,然后重新运行
forwarded socket /tmp/cc-socks-1000/2002.sock never appeared within 60 sssh 保持运行,但始终未在此处创建 -L 套接字检查 ssh -v box-b,确认两端都运行 OpenSSH 6.7+
reverse forward did not bind /tmp/cc-socks-1000/1001.sock on box-b within 60 sssh 保持运行(如果 -R 被拒绝,ssh 会退出),但套接字始终未出现在 box-b 的该路径下:其 sshd 会话看到的是不同的 /tmp(PrivateTmp、容器),或者绑定仍在等待中在 ssh box-b 的 shell 中运行 ls -ld /tmp/cc-socks-<uid>;将 CLAUDE_CODE_TMPDIR 指向双方都能访问的目录
could not verify the reverse forward隧道建立后,探测自身的 ssh 连接失败;桥接程序已拆除隧道先修复 ssh:ssh -v box-b true,然后重新运行
could not create a writable /tmp/cc-socks-<uid> on box-b远程 /tmp 拒绝创建该目录,或者该目录已存在且归其他账户所有(由 root 会话遗留)在远程端检查 ls -ld /tmp/cc-socks-<uid>;更改其所有者,或将 CLAUDE_CODE_TMPDIR 指向双方的其他目录
Timed out sending to /tmp/cc-socks-1000/2002.sock from SendMessage远程会话已退出;转发已无处可达停止并重新运行桥接程序;它会选择最新的活动会话
[Cross-session delivery notice] ... held权限模式不匹配;远程用户必须批准等待,或请对方将 crossSessionInbound 设为 accept

两台主机上的 uid 不同,会生成不同的套接字目录(/tmp/cc-socks-<uid>)。脚本会在两端分别创建缺失的目录。Windows 接收端需要身份验证令牌,因此无复制设计在 Windows 上不适用。

关于上述内容的协议细节和示意图,见 references/protocol.md。

评论

支持 Markdown