Let your Claude sessions talk to each other.
agent-bridge lets a Claude Code session on one Mac push messages straight into a Claude Code session on another — agent-to-agent, not shell-to-shell. One plugin per machine. Messages land as live <channel source="agent-bridge"> events inside the already-running conversation. No broker, no cloud, no fresh agents spawned on the remote side.
One prompt. Paste it into Claude on each Mac.
This is the fast path. It works because Claude Code can read the README, install the CLI, build the MCP server, and register the plugin for you.
Read the README at https://github.com/EthanSK/agent-bridge and follow the setup instructions for this computer. Install agent-bridge, run the setup command, and install the Claude Code plugin. Do everything automatically -- don't ask me questions.
sudo systemctl enable --now sshd
After the agents finish installing, photograph the pairing screen on one machine and send the photo to Claude on the other. That’s the pair step; the agents handle the rest.
Agent-to-agent, not shell-to-shell.
Push, not poll
Messages from a remote machine arrive as real-time <channel source="agent-bridge"> events inside your running Claude session. No timers, no busy loops, no stale inbox.
Running sessions, not new ones
The plugin connects already-running Claude sessions. Machine A’s bridge_send_message drops a signed file into Machine B’s inbox; Machine B’s watcher pushes it into the live conversation. No fresh claude --print spawned on the far side — that whole shape was removed in 3.0.0.
Peer-to-peer over SSH
Direct machine-to-machine SSH on the ports you already allow. No relay, no broker, no vendor. Tailscale is the recommended off-LAN path (stable 100.x.y.z IPs); plain LAN works great too.
Hardened against zombies
The MCP server exits cleanly on parent death, handles EPIPE, detects stdin close, watchdogs its own ppid, and expands remote tildes correctly. No shadow ~/.agent-bridge/inbox directories, no orphaned Node processes chewing CPU after Claude quits.
Manual install, step by step.
Prefer doing it yourself? This is exactly what the quick-start prompt above tells Claude to do. Run these on each machine you want to bridge.
Claude Code
Tested end-to-end
Installs as a single Claude Code plugin that bundles the bridge_* MCP tools and the incoming channel. One install, both halves.
curl -fsSL https://raw.githubusercontent.com/EthanSK/agent-bridge/main/install.sh | bash
git clone https://github.com/EthanSK/agent-bridge.git ~/Projects/agent-bridge cd ~/Projects/agent-bridge/mcp-server && npm install && npm run build
claude plugin marketplace add ~/Projects/agent-bridge claude plugin install agent-bridge@agent-bridge
alias claude-bridge='claude --dangerously-skip-permissions \ --dangerously-load-development-channels plugin:agent-bridge@agent-bridge'
--dangerously-load-development-channels. The flag takes a tagged argument (plugin:<name>@<marketplace>) and does two jobs at once: activates the channel and marks it as allowlist-exempt. Don’t also add --channels plugin:agent-bridge@agent-bridge — that creates a second dev:false entry that fails the allowlist check. Passing the flag bare with no tag also errors.
Pair the two machines
Bash CLI
The bash agent-bridge CLI handles setup, pairing, and SSH-level diagnostics. It coexists with the plugin — the plugin drives agent-to-agent messages, the CLI drives the transport.
# On each machine: enable SSH, generate keys, show pairing screen agent-bridge setup # Off-LAN? Install Tailscale on each machine and use its 100.x.y.z IP as internet_host. # Recommended: no-sudo userspace LaunchAgent. See README "Internet connectivity (Tailscale)" # for the plist template, ~/.ssh/config SOCKS5 block, and --socket CLI pattern. brew install tailscale launchctl load ~/Library/LaunchAgents/com.USERNAME.tailscaled.plist tailscale --socket="$HOME/.local/share/tailscale/tailscaled.sock" up --accept-dns=false --hostname=MY-MACHINE agent-bridge config <other-machine> --internet-host 100.x.y.z # Then photograph the pairing screen on one machine # and send the photo to Claude on the other. It runs `agent-bridge pair` for you. # Verify agent-bridge list agent-bridge status MacBook-Pro # Plain remote shell on a paired machine (diagnostics only) agent-bridge run MacBook-Pro "cd ~/Projects/myapp && git status"
Note. agent-bridge run is a plain SSH remote-shell utility — it does NOT invoke an agent. To talk to the running agent on the other machine, use the plugin’s bridge_send_message MCP tool. The old --claude / --codex / --agent flags that spawned a fresh non-interactive agent session on the remote machine were removed in 3.0.0.
Other MCP-capable harnesses
Scaffolded · not exercised
Codex CLI, Gemini CLI, OpenClaw, Aider, and anything else that speaks the Model Context Protocol can in principle call the bridge_* tools. The server is harness-agnostic by design — but as of v3.0.0, only Claude Code is confirmed end-to-end. If you try one of these and it works (or doesn’t), please open an issue.
{
"mcpServers": {
"agent-bridge": {
"command": "node",
"args": ["/absolute/path/to/agent-bridge/mcp-server/build/index.js"]
}
}
}
Without the Claude Code channel, harnesses run in polling mode: the agent calls bridge_receive_messages at natural breakpoints to drain the inbox. Companion instruction files ship in the repo: AGENTS.md (Codex), GEMINI.md (Gemini), INSTRUCTIONS.md (generic), and an openclaw-channel/ native channel plugin for OpenClaw push delivery.
Three steps. Then it’s invisible.
No fixed client/server roles — both peers are equal. After the handshake, bi-directional messaging just works.
-
Setup
On each machine, run
agent-bridge setup. It enables SSH if needed, generates an ED25519 key pair under~/.agent-bridge/keys/, and prints a pairing screen with the machine name, user, IPs, port, one-time token, and public key. -
Pair
Photograph the pairing screen on one machine and send the image to Claude Code on the other. Claude reads the photo, extracts the fields, and runs
agent-bridge pair --name ... --host ... --token ... --pubkey .... No password, no manual typing. -
Use
Once paired, either side calls
bridge_send_messagefrom inside its Claude session. The message lands in the remote inbox over SSH and is pushed into the running remote Claude’s context as a<channel source="agent-bridge">event. No fresh agent is ever spawned on either side.
Push into a running session.
The plugin registers a single MCP server that advertises the experimental claude/channel capability and the bridge_* tools. A file watcher on ~/.agent-bridge/inbox/ detects new message files and emits notifications/claude/channel into the Claude session — no polling, no manual bridge_receive_messages call needed.
// Machine A's Claude calls: bridge_send_message({ machine: "MacBook-Pro", content: "can you run the e2e suite and paste the failures?" }) // A few hundred ms later, Machine B's Claude sees: <channel source="agent-bridge" from="Mac-Mini" message_id="msg-91c..." ts="2026-04-14T22:11:03Z"> can you run the e2e suite and paste the failures? </channel> // ...and responds the same way: bridge_send_message({ machine: "Mac-Mini", content: "3 failed, logs attached: ..." })
Seven MCP tools. One concept per tool.
Deliver a message to a running agent on a paired machine. Writes a signed JSON message file to the remote inbox over SSH. Under Claude Code, the remote session receives it as a <channel> event; under polling harnesses it waits in the inbox until drained.
Manually drain the local inbox. Usually not needed under Claude Code (the channel pushes for you), but the primary entry point for polling-mode harnesses. Supports peek for non-destructive reads.
Show the local machine name and every paired peer with its user, host, port, and pairing date.
Probe a paired machine over SSH and report reachability. Pass a name to check one, or omit it to check all. Short timeout — safe to call on hot paths.
Run a plain shell command on a remote paired machine via SSH. Returns stdout, stderr, and exit code. Diagnostic utility only — do NOT use it to invoke an agent CLI on the far side. That path was removed in 3.0.0.
Nuke every message in the local inbox. Handy for a clean slate between sessions or tests.
Report pending count, oldest message age, total size, watcher health, processed-ID count, and failed-message count. Useful for diagnosing “did my message arrive?”
Tested & scaffolded harnesses.
bridge_* MCP tools and the channel in one Node process.openclaw-channel/ native channel plugin registers agent-bridge as a first-class OpenClaw channel (same tier as Telegram) via api.registerChannel(), pushing inbound messages into the running agent session via enqueueSystemEvent.codex mcp add agent-bridge .... AGENTS.md in the repo root is auto-picked-up by Codex as instructions. Polling mode — call bridge_receive_messages at breakpoints.gemini mcp add agent-bridge .... GEMINI.md in the repo root is picked up for guidance. Polling mode.bridge_* tools. See INSTRUCTIONS.md in the repo root for plain-English guidance a generic agent can follow.SSH-authenticated. TTL-bounded. No cloud.
-
ED25519 keypairs per machine
Each machine generates its own key under
~/.agent-bridge/keys/duringagent-bridge setup. Authorized keys are installed only on paired peers. No passwords, no shared secrets. -
Base64 transport over SSH
Message content is base64-encoded before SSH delivery to sidestep shell-quoting hazards. The remote-side path is tilde-expanded to
$HOMEso files land in the real inbox, not a literal~directory. -
TTL-bounded delivery
Messages have a default 1-hour TTL. A background prune runs every 5 minutes; expired files are auto-deleted so the inbox never grows unbounded. Malformed files are quarantined to
inbox/.failed/. -
Never touches a third-party server
Everything is direct machine-to-machine SSH on the ports you already allow. No broker, no relay, no vendor. Tailscale is strongly recommended for off-LAN links (stable 100.x.y.z IPs with zero port-forwarding).
What’s new.
-
3.0.0 breakingFresh-spawn wrappers removed. The
--claude,--codex, and--agentflags onagent-bridge runare gone. They spawned a new non-interactive agent on the remote machine — the exact opposite of this project’s purpose. Agent-to-agent is now exclusively channel mode (bridge_send_message→ inbox drop → running remote agent’s context). Plainagent-bridge run <machine> "<cmd>"is kept as a diagnostics utility. Versions aligned across CLI, MCP server, and plugin manifest to3.0.0. -
2.3.2Tilde expansion fix. Messages were landing in a literal
~/.agent-bridge/inboxshadow directory on the remote machine instead of the real$HOME/.agent-bridge/inbox. Fixed insshWriteFileby substituting leading~/with$HOME/before quoting. -
2.3.1OpenClaw companion parity pass. Confirmed the OpenClaw side matches the v2.3.0 plugin-ification: zombie-proof, no hardcoded user paths, identical signal handling.
-
2.3.0Plugin-ification. agent-bridge became a single Claude Code plugin that bundles both the
bridge_*MCP tools and the incoming channel. One install, both halves. No more hand-editing.mcp.jsonfor the Claude Code path.
▸ full history: CHANGELOG.md