Let your agents talk to each other.
agent-bridge lets running AI agent harness sessions push messages to each other across machines — agent-to-agent, not shell-to-shell. Every harness shares the same SSH file transport, while each receiver keeps its own host lifecycle: Claude Code uses an MCP + claude/channel stdio plugin; OpenClaw uses a native gateway plugin; Codex uses a background service that wakes the exact bound persisted task through the public App Server API. No broker, no cloud, no fresh agents spawned on the remote side.
One prompt. Paste it into your agent on each machine.
This is the fast path. It works because your local AI agent can read the README, install the CLI, build the MCP server, and register the right channel plugin for its harness.
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 appropriate Claude Code, OpenClaw, or Codex integration for this harness. Do everything automatically.
sudo systemctl enable --now sshd
Windows 10/11: OpenSSH Server is an optional feature; admin users need keys at C:\ProgramData\ssh\administrators_authorized_keys, not the user’s home dir. See the Windows setup section in the README for the consolidated PowerShell script.
After the agents finish installing, photograph the pairing screen on one machine and send the photo to the agent on the other. That’s the pair step; the agents handle the rest.
Agent-to-agent, not shell-to-shell.
Push, not poll
Messages arrive through the right host path: <channel source="agent-bridge"> events in Claude Code, native OpenClaw channel turns, or an exact persisted Codex task resumed and woken by codex-channel. No fresh agent spawn on the far side.
Running sessions, not new ones
The bridge connects already-existing sessions. Machine A’s bridge_send_message drops an SSH-authenticated envelope into Machine B’s target inbox; the receiving harness injects it into the addressed conversation. No fresh claude --print or codex exec is spawned on the far side.
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 Claude Code channel-owner MCP child is hardened against benign stdin/stderr/SIGTERM closure, exits on real parent/stdout death, and replays undelivered messages on startup. OpenClaw is hosted separately by the gateway plugin. No shadow ~/.agent-bridge/inbox directories, no fresh remote agent processes.
Shared context: fleet-wide learnings
Your fleet develops institutional memory. Any agent on any machine records globally-useful learnings (agent-bridge learnings add / bridge_learnings_add) and searches what every other agent already figured out (learnings search / bridge_learnings_search). Strictly additive to each harness’s own memory — agents keep writing their native memory exactly as before and copy the fleet-wide subset here, never relocate it. Full NDJSON replica per machine, replicated peer-to-peer over the same SSH transport, idempotent by entry id — offline peers reconcile with learnings sync.
Codex tasks become stable endpoints
Run agent-bridge codex bind inside a task. It discovers the thread id, derives a stable title-based codex/<alias>, and starts the background service. Messages queue safely while the task is busy; the task itself never polls.
Manual install, step by step.
Prefer doing it yourself? This is exactly what the quick-start prompt above tells your agent to do. Run these on each machine you want to bridge.
agent-bridge-mcp-server is a legacy 0.1.x artifact; the 4.10.0 channel packages are repository packaging units, not npm-registry products.
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 the agent 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"
# Symptom (OpenClaw logs): # paired machine "MacBookPro.lan" not found in ~/.agent-bridge/config BASE="MacBookPro" ALIAS="MacBookPro.lan" # Check route label + config sections tail -200 ~/.openclaw/logs/gateway.log | grep -E "$ALIAS|paired machine|agent-bridge/v2" grep -nE "^\[$BASE\]$|^\[$ALIAS\]$|^(host|user|port|key|internet_host)=" ~/.agent-bridge/config # If missing, add [MacBookPro.lan] mirroring [MacBookPro]. # Same idea for MagicDNS names, e.g. [macbookpro.tail52aa3c.ts.net]
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.
Routing labels must match config sections. If your sender uses a hostname variant (.lan or MagicDNS), add a mirrored alias section so back-and-forth replies keep working.
Codex and other MCP-capable harnesses
Codex push · generic MCP tools
Codex 0.145.0+ is verified first-class in both directions. A bound task receives pushed turns through the background codex-channel service; Gemini CLI, Aider, and other MCP hosts can call the tools but remain tools-only until their own receive loops are verified. OpenClaw remains a separate native gateway integration.
curl -fsSL https://raw.githubusercontent.com/EthanSK/agent-bridge/main/install.sh | bash agent-bridge codex bind # automatic task id + title-derived alias agent-bridge codex doctor # read-only health check
{
"mcpServers": {
"agent-bridge": {
"command": "node",
"args": ["/absolute/path/to/agent-bridge/mcp-server/build/index.js"],
"env": {}
}
}
}
Codex delivery is documented in codex-channel/README.md. For unverified MCP-only harnesses, bridge_receive_messages is a manual Claude Code-target diagnostic fallback, not proof of a complete receive loop. Companion instruction files ship for Codex, Gemini, generic MCP hosts, and OpenClaw.
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 the agent on the other. The agent 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_messagewith an explicittarget. Claude Code and OpenClaw inject into their running sessions;codex/<alias>wakes the exact bound persisted task through the background Codex service. No fresh agent is spawned.
Push into a running session.
Claude Code advertises the experimental claude/channel capability and the bridge_* tools from one MCP child. OpenClaw uses a separate gateway plugin. Codex uses a singleton background service that scans bound inbox/codex/<alias>/ targets and drives thread/resume plus turn/start for the exact task.
// Machine A's Claude calls: bridge_send_message({ machine: "MacBook-Pro", message: "can you run the e2e suite and paste the failures?", target: "claude-code/default" }) // 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", message: "3 failed, logs attached: ...", target: "claude-code/default" })
Auto-update + stale-runtime recovery. The in-process probe still notifies live harnesses when origin/main is ahead, and receivers still coordinate same-host updates through scripts/auto-update-coord.sh. Recent releases add plugin-registry rewiring (stale Claude/OpenClaw plugin cache paths), harness-independent periodic update scripts for launchd / Windows Scheduled Tasks, and migration-instruction injection into [BRIDGE-UPDATE-AVAILABLE] notices. Runtime caveat remains: disk-fresh code is not always process-fresh code; a full Claude Code session restart is the deterministic way to load a new long-running MCP child.
Thirteen bridge tools. One concept per tool.
Deliver an SSH-authenticated message envelope to an explicit target. Claude Code receives channel events, OpenClaw receives native turns, and codex/<alias> wakes the exact bound task.
Manually inspect/consume the local Claude Code-target inbox. Usually not needed under Claude Code push; useful for diagnostics, tools-only setups, and (3.8.0+) subagent long-poll — pass wait: true, timeout_seconds: 30 to block until a new message arrives. 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?”
Show a native macOS completion banner locally or on a paired Mac. This is a user notification, not an agent message, and never writes an inbox file.
Record a fleet-wide learning locally and replicate it to paired peers. This adds a shared copy; it never replaces repo or harness-native memory.
Search the local full replica of fleet-wide learnings before re-deriving a machine or infrastructure fix.
Bind the current Codex task as a stable address. The alias is optional: task id and title-derived alias are discovered automatically when the host exposes them.
Remove a Codex alias binding after safe session release and settings recovery.
Inspect Codex bindings, queue state, service health, recovery journals, and actionable supervision warnings.
Diagnostic Claude Code plugin status: running version, process ID, uptime, active persona/target, watcher lease, and health snapshot. Useful for spotting stale runtime code or fleet version drift.
Tested & scaffolded harnesses.
bridge_* MCP tools and the claude/channel path in one MCP stdio child, not a separate daemon.openclaw-channel/ native channel plugin registers agent-bridge as a first-class OpenClaw channel (same tier as Telegram) via api.registerChannel(), dispatching inbound messages into the running agent session via dispatchInboundReplyWithBase from openclaw/plugin-sdk/compat. In v3.0+, reply routing is agent-driven: the inbound turn carries a [BRIDGE-CONTEXT] block, bridge replies are implicit when fromTarget is present, and additionalReplyChannels controls any extra user-facing channels.agent-bridge codex bind creates a stable automatic alias for the exact persisted task; the background service queues and injects inbound turns while MCP tools handle sends, replies, binding, and status. The task itself never polls.gemini mcp add agent-bridge .... GEMINI.md in the repo root is picked up for guidance. Polling mode.bridge_* tools. Inbound receive/reply is scaffolded until a harness-specific target and polling loop are tested. See INSTRUCTIONS.md in the repo root.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. -
SFTP delivery over SSH
Message JSON is delivered with the SSH SFTP subsystem: create parent inbox directories, upload to a temporary file, then atomically rename into place. The transport path itself needs no remote shell commands,
$HOMEexpansion,mkdir -p, ormv, so Windows OpenSSH targets work cleanly. -
Pairing grants full local-account SSH authority
The default setup adds an unrestricted key to
authorized_keys. A paired peer can therefore open a shell as that local user, not merely deliver bridge messages. Protect, revoke, and rotate keys accordingly; use a restricted account or forced command if you need message-only trust. -
TTL-bounded delivery
Messages have a default 1-day 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.
-
4.10.0First-class Codex endpoints. Bind the current task with one command; Agent Bridge derives a stable alias, queues safely while busy, resumes the exact persisted thread through the public App Server, and preserves at-most-once delivery with durable recovery. A real Codex → Claude Code → OpenClaw → OpenClaw → Codex chain passed across two Macs.
-
4.9.x / 4.8.0Fleet learnings, endpoint fallback, and native notifications. Shared context remains additive to native memory; replication can fall back between tailnet and LAN endpoints; agents can show native completion banners without waking another agent.
-
4.1.0Compact relay expansion. OpenClaw relay notices now show a short
expand idandagent-bridge relay-expand <id>instead of dumping long bridge message bodies into user-facing chats; the full content stays in a bounded local store. -
4.0.0 breakingClaude Code personas and explicit targets. Claude Code inboxes are now persona-scoped (
claude-code/default,claude-code/<persona>) withAGENT_BRIDGE_PERSONAas the live session identity. Legacytarget="claude-code"is still routed to default for rolling upgrades, but new sends should name the target explicitly. -
openclaw-channel 3.0.0 breakingAgent-driven OpenClaw reply routing. The native OpenClaw channel is verified end-to-end and no longer auto-fans-out via
replyVia. Inbound bridge turns carry a[BRIDGE-CONTEXT]block; the agent chooses bridge replies and anyadditionalReplyChannelsitself. -
4.0.x / 3.14.xRuntime freshness and recovery hardening. Recent commits added plugin-registry rewiring, harness-independent periodic update scripts, migration instructions inside update notices, orphaned-child cleanup, channel recovery observability, and clearer stale-runtime operations docs.
-
3.14.xNamed-target routing and relay docs travel with the repo. Agents are instructed to resolve specific target aliases deliberately instead of silently falling back to default, and every inbound bridge message should be relayed to the user with a concise summary plus the running version.
-
3.8.0 / 3.5.0Subagent long-poll + same-machine delivery.
bridge_receive_messagessupports bounded long-poll waits for subagents that cannot see parent channel pushes, andbridge_send_messagecan deliver directly to local/self/localhost inboxes without an SSH loopback. -
3.4.0+Per-target inboxes and quarantine. Message delivery is target-subdir based; targetless legacy files are routed to
.failed/_unrouted/, malformed files are quarantined under.failed/, and status/stat tools report failed counts for diagnostics. -
docs/siteHighlights refreshed. README + site summaries now match the recent 3.14.x → 4.1.0 work instead of older 3.x-era assumptions.
▸ full history: CHANGELOG.md