{
  "markdown": "<p align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"assets/banner-dark.png\">\n    <img src=\"assets/banner.png\" alt=\"Covalent Bond: two agents sharing an encrypted channel\" width=\"100%\">\n  </picture>\n</p>\n\n<h1 align=\"center\">Covalent Bond</h1>\n\n<p align=\"center\">\n  <b>A secure channel that lets two AI coding agents on different machines work as one.</b>\n</p>\n\n<p align=\"center\">\n  <a href=\"#quick-start\">Quick start</a> ·\n  <a href=\"#how-it-works\">How it works</a> ·\n  <a href=\"#tools\">Tools</a> ·\n  <a href=\"#security\">Security</a> ·\n  <a href=\"docs/ARCHITECTURE.md\">Architecture</a> ·\n  <a href=\"CONTRIBUTING.md\">Contributing</a>\n</p>\n\n<p align=\"center\">\n  <img src=\"https://img.shields.io/badge/MCP-compatible-8A2BE2.svg\" alt=\"MCP compatible\">\n  <img src=\"https://img.shields.io/badge/Node.js-%E2%89%A518-brightgreen.svg\" alt=\"Node.js >= 18\">\n  <img src=\"https://img.shields.io/badge/E2EE-AES--256--GCM%20%2B%20X25519-1f6feb.svg\" alt=\"E2EE: AES-256-GCM + X25519\">\n  <img src=\"https://img.shields.io/badge/relay-Cloudflare%20Workers-f38020.svg\" alt=\"Relay: Cloudflare Workers\">\n  <a href=\"LICENSE\"><img src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License: MIT\"></a>\n</p>\n\n---\n\nA *covalent bond* is two atoms sharing a pair of electrons. Covalent Bond is two coding agents on different machines sharing something just as fundamental: a private, authenticated channel, and through it, a way of working.\n\nPicture two developers pairing across a distance. One has their agent dialed in (organized skills, sharp conventions, the right context loaded) and it produces excellent work. The other is more ad-hoc, and their agent turns out something that's just *okay*. Covalent Bond is the channel that closes that gap: the well-tuned side can hand over the files, context, and conventions that make its agent good, so **both agents converge on the same high-quality way of working**. It bonds not just two agents, but two ways of working, pulling the weaker setup up to the level of the stronger, as equal peers.\n\nIt's peer-to-peer and end-to-end encrypted: the two agents pair up and exchange messages and files through a relay that **can never read the traffic**. It works with **any MCP-compatible agent** (Claude Code, Cursor, Codex, Windsurf, Cline, and others), exposing `bond_*` tools over the Model Context Protocol. And it keeps a human in the loop: every incoming file waits for explicit consent before it touches disk.\n\n- 🤝 **Bonds two ways of working**: share files, context, and conventions so both agents level up together\n- 🔒 **Authenticated E2EE**: a malicious relay can't read *or* MITM the channel\n- 🌐 **Cross-machine**: pair agents anywhere, through a dumb relay (no inbound ports)\n- 🙋 **Human-in-the-loop**: consent before any file is written; full audit log\n- 🔌 **Agent-agnostic**: any MCP client, not tied to one vendor\n\n> It doesn't magically clone one setup onto another. It's the secure, consent-gated channel that makes deliberately sharing your working style *possible* between two machines that otherwise can't reach each other.\n\n## Quick start\n\n**Shortcut: let your agent set everything up.** Paste [docs/AGENT-SETUP.md](docs/AGENT-SETUP.md) to any coding agent and say \"set up Covalent Bond\". It walks the agent through install, relay config, MCP registration, and pairing, with clear stops for the parts only a human may do.\n\nOr do it yourself on **both machines** (steps 1–2), then pair (step 3).\n\n1. **Register the MCP server** with your agent — no install needed, `npx` fetches [the npm package](https://www.npmjs.com/package/covalent-bond). For Claude Code:\n   ```bash\n   claude mcp add --scope user --env COVALENT_RELAY_URL=https://covalent-bond-relay.gopalrajsuresh.workers.dev covalent -- npx -y covalent-bond\n   ```\n   (`--scope user` makes the `bond_*` tools available in every project. The env var points at the public relay; to self-host instead, see [Pick a relay](#pick-a-relay).)\n\n   For other MCP clients (Cursor, Codex, Windsurf, …), this standard stdio-server config works in most of them; paste it into the client's MCP settings JSON (the top-level key is usually `mcpServers` or `servers`):\n\n   ```json\n   {\n     \"mcpServers\": {\n       \"covalent\": {\n         \"command\": \"npx\",\n         \"args\": [\"-y\", \"covalent-bond\"],\n         \"env\": {\n           \"COVALENT_RELAY_URL\": \"https://covalent-bond-relay.gopalrajsuresh.workers.dev\"\n         }\n       }\n     }\n   }\n   ```\n\n   <details>\n   <summary>Windows and local-testing notes</summary>\n\n   On **Windows**, if your client struggles to spawn `npx` directly, wrap it: `\"command\": \"cmd\", \"args\": [\"/c\", \"npx\", \"-y\", \"covalent-bond\"]`. For local testing without a deployed relay, run the mock relay from a source checkout (`npm run relay:dev`) and point `COVALENT_RELAY_URL` at `http://localhost:8787`.\n   </details>\n\n   <details>\n   <summary>Prefer running from source?</summary>\n\n   ```bash\n   git clone https://github.com/gopalrajsuresh/covalent-bond.git covalent-bond\n   cd covalent-bond\n   npm install\n   npm test                    # optional but recommended; all suites run offline\n   cp .env.example .env        # PowerShell: Copy-Item .env.example .env\n   ```\n   The `.env` already contains the public relay URL. Then register with `command: node`, args `/absolute/path/to/covalent-bond/bin/cli.js` (Claude Code: `claude mcp add --scope user covalent -- node /absolute/path/to/covalent-bond/bin/cli.js`), no env var needed.\n   </details>\n2. **Restart your agent session**, then verify: ask the agent to run `bond_status`. It should reply \"No active session\", which means the tools are live.\n3. **Pair and share**\n   - Machine A: *\"Create a Covalent Bond session\"* → agent runs `bond_connect` → you get a code like `AbCd-1234-XyZw`.\n   - Tell the code to the other human **out-of-band** (chat or voice, never through the relay).\n   - Machine B: *\"Join Covalent Bond session AbCd-1234-XyZw\"* → agent runs `bond_join`.\n   - Either side: `bond_status` → **Secure channel established** → send files (`bond_send`) and messages (`bond_message`). Incoming files wait for the human to `bond_accept`.\n   - Done? `bond_end` on both sides.\n\n## How it works\n\nBoth agents meet at a relay that is **untrusted by design** — it forwards ciphertext it can never decrypt. The session code travels human-to-human, never through the relay, and that out-of-band secret is what authenticates the channel:\n\n```mermaid\nsequenceDiagram\n    participant A as Agent A (host)\n    participant H as Humans (out-of-band)\n    participant R as Relay (untrusted)\n    participant B as Agent B (guest)\n\n    A->>A: bond_connect → session code\n    A-->>H: code shared by chat / voice\n    H-->>B: code entered on the other side\n    B->>B: bond_join(code)\n    A->>R: ephemeral public key (routing ID only)\n    B->>R: ephemeral public key (routing ID only)\n    Note over A,B: key = X25519 ⊕ session code → AES-256-GCM\n    A->>R: ciphertext\n    R->>B: ciphertext (relay sees nothing else)\n    B->>B: file held until human runs bond_accept\n```\n\nIf anything in the middle tampers with the key exchange, key confirmation fails and the session aborts before any data flows — a malicious relay can't read *or* impersonate either side.\n\n## Pick a relay\n\nThe relay is a dumb pipe and **untrusted by design**: it sees only a random routing ID and ciphertext, never the session code, keys, or plaintext, and a malicious relay still can't read or forge anything (that's covered by the test suite's MITM scenario). So either option below is equally secure; it's purely a convenience choice.\n\n**Option 1: use the public relay (fastest)**\n\n```\nCOVALENT_RELAY_URL=https://covalent-bond-relay.gopalrajsuresh.workers.dev\n```\n\nSessions expire after 30 minutes of inactivity and nothing is retained. Best-effort availability, rate-limited.\n\n<details>\n<summary><b>Where to set <code>COVALENT_RELAY_URL</code></b> (either place works; a real environment variable wins over <code>.env</code>)</summary>\n\n- **`.env` file (simplest)**: copy [`.env.example`](.env.example) to `.env` in the covalent-bond folder and edit the value. The MCP server reads it at startup, so it applies no matter which project you use the agent from.\n- **MCP client config**: pass it when registering the server, e.g. for Claude Code:\n\n  ```bash\n  claude mcp add --scope user --env COVALENT_RELAY_URL=https://... covalent -- node /absolute/path/to/covalent-bond/bin/cli.js\n  ```\n\n  For other MCP clients, add it to the server's `env` block in their JSON config.\n\nAfter changing either, restart your agent session so the MCP server relaunches.\n</details>\n\n**Option 2: deploy your own in ~2 minutes (free Cloudflare account)**\n\n```bash\nnpm install -g wrangler\nwrangler login          # opens the browser; create a free account if you don't have one\ncd cloudflare-worker\nwrangler deploy         # prints your relay URL: https://covalent-bond-relay.<your-subdomain>.workers.dev\n```\n\nThen set `COVALENT_RELAY_URL` to that URL on **both** machines. Full details (Durable Object migration, optional per-IP throttle, local `wrangler dev`) are in [cloudflare-worker/README.md](cloudflare-worker/README.md).\n\n<details>\n<summary><b>Or let your agent do it</b></summary>\n\nPaste this to any coding agent running in this repo:\n\n> Deploy my own Covalent Bond relay: install wrangler if missing, run `wrangler login` and wait for me to finish authenticating in the browser, then `wrangler deploy` from `cloudflare-worker/`, and tell me the URL to set as `COVALENT_RELAY_URL` on both machines. Follow `cloudflare-worker/README.md`.\n\nThe only manual step is the browser login; the agent handles the rest.\n</details>\n\n## Pair two agents\n\n1. **Machine A**: *\"Create a Covalent Bond session.\"* → the agent calls `bond_connect` and returns a code like `AbCd-1234-XyZw`.\n2. **Share that code with Machine B out-of-band** (chat, voice, in person). It's the secret that secures the link. Never paste it into the relay.\n3. **Machine B**: *\"Join Covalent Bond session `AbCd-1234-XyZw`.\"* → the agent calls `bond_join`.\n4. When `bond_status` shows **Secure channel established**, start sharing: *\"Send `src/auth.js` to my peer,\"* or hand over the pieces that make your agent good: a skill file, a conventions doc, the context that shapes how it works. The peer sees a consent prompt and accepts before anything is written, and the received content arrives wrapped as untrusted data for the other agent to read and adopt.\n\n## Tools\n\n- `bond_connect` — Create a session and get a shareable session code\n- `bond_join` — Join a session using a code shared out-of-band\n- `bond_status` — Connection status, pending transfers, and new events\n- `bond_send` — Send a file to the connected peer, encrypted end to end\n- `bond_message` — Send a short encrypted text message to the peer\n- `bond_wait` — Long-poll for the next peer event\n- `bond_accept` — Accept a pending file transfer after human consent\n- `bond_decline` — Decline a pending file transfer\n- `bond_end` — End the session and disconnect from the relay\n\nFull reference:\n\n| Tool | Parameters | What it does | Requires |\n|------|------------|--------------|----------|\n| `bond_connect` | — | Create a session as host; returns the code to share out-of-band | — |\n| `bond_join` | `sessionCode` | Join a session with a code (`XXXX-XXXX-XXXX`, Base58) | — |\n| `bond_status` | — | Handshake state, pending transfers, unread-event count, and events since the last call | — |\n| `bond_send` | `filepath`, `message?` | Send a file (type whitelist, size cap, 10 s rate limit) with an optional context message | confirmed channel |\n| `bond_message` | `content` | Send a short encrypted text message, max 4000 chars (agent-to-agent conversation) | confirmed channel |\n| `bond_wait` | `timeoutSeconds?` | Long-poll for the next peer event (message, file, disconnect); default 50 s, max 300 s | confirmed channel |\n| `bond_accept` | `transferId` | Write a pending file to `~/.covalent/incoming/` and return its content wrapped as untrusted data | human consent |\n| `bond_decline` | `transferId` | Discard a pending transfer (the sender is not notified) | human consent |\n| `bond_end` | — | Disconnect and clear session state, including pending transfers | — |\n\n`?` marks an optional parameter. **confirmed channel** means the tool refuses to run until key confirmation has succeeded on both sides; **human consent** means the agent may only call it after the human explicitly decides on the pending transfer.\n\nIncoming events raise a desktop notification (disable with\n`COVALENT_NOTIFICATIONS=off`). File size defaults to 256 KB, overridable via\n`COVALENT_MAX_FILE_KB` (up to 384 KB, bounded by the relay's wire limit).\n\n## Security\n\nEach session is secured by **two** secrets: ephemeral **X25519** keys exchanged through the relay, and a short **session code** the two humans share out-of-band. The code is mixed into the encryption key but **never sent to the relay**, so a relay that tampers with the key exchange (a MITM) can't derive the key, key confirmation fails, and the session aborts before any data flows. The relay only ever sees a routing ID, public keys, and AES-256-GCM ciphertext. Every incoming file waits for explicit human consent, and every operation is logged.\n\n**Full details, threat model, and handshake diagram:** [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).\n\n> **Share the session code over a channel the relay operator doesn't control.** That out-of-band step is what makes the channel authenticated, not just encrypted.\n\n## Testing\n\n```bash\nnpm test          # all suites, via test/run-all.js, against an in-process mock relay\n```\n\nNo network or `wrangler` needed. The suite covers the key schedule, the full handshake and file transfer, two MCP servers end-to-end, a simulated malicious relay (`mitm`), and the relay's hardening. See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md#testing) for the breakdown, and [docs/TWO-MACHINE-TEST.md](docs/TWO-MACHINE-TEST.md) for a real two-machine run.\n\n## Deploying the relay\n\nThe relay is a Cloudflare Worker in [`cloudflare-worker/`](cloudflare-worker/README.md) with one Durable Object per session. It stores only routing IDs, public keys, and ciphertext, expiring 30 minutes after the last activity. It can't decrypt anything.\n\n## Status\n\nAuthenticated E2EE, MCP integration wired end-to-end, full test suite green. Pre-1.0: the protocol and API may still change.\n\n## Contributing & security reports\n\nContributions are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md), which includes the security invariants and the branch/PR workflow. To report a vulnerability, please use the private process in [SECURITY.md](SECURITY.md), not a public issue.\n\n## License\n\nMIT; see [LICENSE](LICENSE).\n\n---\n\n<p align=\"center\">\n  <sub>Two machines. One way of working. <a href=\"#covalent-bond\">Back to top ↑</a></sub>\n</p>\n",
  "bytes": 14858,
  "sha": "1288a58acf8f41e5fdac8a36ae920dd2e3e0d0d4759a108c650ffafa86cb9997",
  "repo_slug": "gopalrajsuresh/covalent-bond",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_gopalrajsuresh_covalent_bond_64c6eba7/readme"
}