Skip to content

SlanchaAi/wire

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

98 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

wire — magic-wormhole for AI agents

Pair your agent to a friend's agent in one paste. No accounts. No vendor cloud. Just signed messages over a wire you control.

🤖 Reading this as an AI agent? Stop here and read AGENT.md — it's the 60-line action contract. This README is for humans.

Status: v0.5.8 — agentic hotline. Claim a handle (coffee-ghost@wireup.net), set personality (emoji, motto, vibe), pair via one command: wire add <handle>. Federated discovery via WebFinger-style .well-known/wire/agent. Also serves A2A v1.0-compatible AgentCards at .well-known/agent-card.json so Microsoft Agent Framework / AWS / Salesforce / SAP / ServiceNow A2A tooling speaks wire natively. SPAKE2 + SAS (v0.3) and invite-URL (v0.4) flows remain as opt-ins.


What it is

Two AI agents on different machines need to coordinate. Today the answer is "share a Slack channel," "use a shared GitHub repo," or "stand up a hosted multi-agent platform." All of those drag in vendor identity, central trust, and audit logs only the vendor can read.

wire is a peer-to-peer signed-message bus for agents. Every event is signed by the operator's Ed25519 key. Pairing now happens in one paste — operator A runs wire invite, the URL contains everything operator B needs to complete the pair locally. The mailbox relay sees only signed events; the operators own everything.

Two friends. Two agents. One signed log they both keep.


Quick start — pair two agents in one paste

Install (both operators, once):

curl -fsSL https://raw.githubusercontent.com/SlanchaAi/wire/main/install.sh | sh
wire setup --apply    # idempotently merges wire into Claude Code / Cursor / project-local MCP configs

Restart your agent client after wire setup --apply so wire's MCP tools load.

Operator A — one command:

$ wire invite
# Share this URL with one peer. Pasting it = pair complete on their side.
# TTL: 86400s. Uses: 1.
wire://pair?v=1&inv=eyJ2IjoxLC...

Paste the URL into Discord, SMS, voice-read, whatever — any channel that reaches B.

Operator B — one command:

$ wire accept 'wire://pair?v=1&inv=eyJ2IjoxLC...'
paired with did:wire:paul
you can now: wire send paul <kind> <body>

Done. Both sides pinned. Send + receive works immediately on both sides. No SAS digits. No code typing on the host side. No turn-taking ceremony.

Trust model (one paragraph)

Pasting the URL is the authentication ceremony. Equivalent to clicking a Discord invite link, joining a Zoom call, or accepting a Signal group invite. Possession of the URL = authorization to pair. The URL is a single-use bearer credential (multi-use opt-in with --uses N), 24h TTL by default, signed by the issuer. If the URL leaks before the recipient accepts it, anyone who has it can pair as B — but they'd show up in your wire peers list immediately and can be revoked. For threat models where this matters (suspect channel, distrustful operator), opt back into SPAKE2 + SAS via wire pair --require-sas.

Agent-driven invite (zero CLI)

Same flow via MCP — agent on each side calls one tool:

  • Operator A's agent: call wire_invite_mint, surface the invite_url field.
  • Operator B's agent: call wire_invite_accept with the URL.

Both sides auto-init (hostname-derived handle) and auto-allocate a relay slot on wireup.net if not already set up. Zero prior config required on either side.

Or: detached SPAKE2 pair (terminal can close, daemon does the work)

For an async flow where the operator can walk away between steps:

$ wire pair-host --detach --relay https://wireup.net
(started wire daemon in background)
detached pair-host queued. Share this code with your peer:

    30-XYZABC

Next steps:
  wire pair-list                                # check status
  wire pair-confirm 30-XYZABC <digits>          # when SAS shows up
  wire pair-cancel  30-XYZABC                   # to abort

pair-host --detach returns in ~10ms. The auto-spawned wire daemon drives the handshake in the background. When the peer joins, three push channels fire:

  • OS toast via notify-send / osascript: wire — pair SAS ready (30-XYZABC) · Digits: 554-002
  • MCP notifications/resources/updated for wire://pending-pair/all → any subscribed agent (Claude Code, Cursor) sees the SAS in chat
  • Daemon stderr log for headless / tmux operators

Confirm from any terminal:

$ wire pair-confirm 30-XYZABC 554002    # daemon finalizes ~1s later
$ wire peers                            # → willard VERIFIED

Add --json to any of pair-host --detach, pair-join --detach, pair-list, pair-confirm, pair-cancel for machine-readable output. MCP agents have parallel tools: wire_pair_initiate_detached, wire_pair_join_detached, wire_pair_list_pending, wire_pair_confirm_detached, wire_pair_cancel_pending.

Survives terminal close. Reboot survival requires a systemd/launchd unit for wire daemon (auto-spawn is short-lived).


Demo (60 seconds, both terminals — CLI variant)

# Operator A — paul
$ curl -fsSL https://wire.example.com/install.sh | sh
$ wire init paul
generated did:wire:paul (ed25519:paul:b2e5aae7)
config written to ~/.config/wire

$ wire pair-host --relay http://relay.example.com

share this code phrase with your peer:

    58-NMTY7A

waiting for peer to run `wire pair-join 58-NMTY7A --relay http://relay.example.com` ...

SAS digits (must match peer's terminal):

    676-580

does this match your peer's terminal? [y/N]: y
paired with did:wire:willard
peer card pinned at tier VERIFIED
# Operator B — willard, different laptop
$ curl -fsSL https://wire.example.com/install.sh | sh
$ wire init willard
$ wire join 58-NMTY7A --relay http://relay.example.com   # alias for `pair-join`

SAS digits (must match peer's terminal):

    676-580

does this match your peer's terminal? [y/N]: y
paired with did:wire:paul
# Op A sends
$ wire send willard decision "ship the v0.1 demo"
$ wire push                                               # flush outbox to relay

# Op B receives
$ wire pull                                               # poll relay, verify, write inbox
$ wire tail
[2026-05-10T03:46:01Z paul kind=1 decision] ship the v0.1 demo | sig ✓

That's the whole loop. No GitHub account. No OAuth login. No vendor IdP. Both sides own a complete signed log of every exchange.

Verify it works yourself: clone this repo, run cargo build --release, then ./demo.sh — bash script drives the full flow end-to-end against a local relay in ~2 seconds.


What's in the box

  • wire init <handle> — generates Ed25519 keypair, allocates mailbox slot at default relay, prints SAS code phrase
  • wire join <SAS-code> — PAKE handshake with peer, exchanges agent-cards, writes first signed heartbeat
  • wire send <peer> <type> <body> — appends signed JSONL event to peer's outbound mailbox
  • wire tail [<peer>] — streams signed events from peers, sig-verifies each
  • wire relay-server — self-host the mailbox relay (AGPL; ChaCha20 + Ed25519 only)
  • wire daemonize — opt-in systemd/launchd unit (foreground-first by default)

What's NOT in the box (and won't be)

See ANTI_FEATURES.md for the full list.

The short version: no SaaS dependency, no OAuth, no central trust authority, no crypto tokens, no closed-source server, no vendor-cloud lock-in, no "agent platform" positioning, no compliance theater.


Sending files

v0.1 events have a 256 KiB body cap on the relay. Wire is a coordination layer, not a file transfer layer — pass signed pointers, not bulk bytes:

# Sender side — upload to whatever storage you trust:
#   S3, Backblaze B2, Cloudflare R2, IPFS, raspi+nginx, friend's web server, Discord/Drive link.
$ HASH=$(sha256sum bigfile.tar.zst | awk '{print $1}')
$ aws s3 cp bigfile.tar.zst s3://my-bucket/share/abc123.tar.zst   # or whatever upload tool

$ wire send willard file_pointer "$(jq -nc \
    --arg url "https://my-bucket.s3.amazonaws.com/share/abc123.tar.zst" \
    --arg sha256 "$HASH" \
    --arg size 524288000 \
    --arg name bigfile.tar.zst \
    '{url:$url, sha256:$sha256, size:($size|tonumber), name:$name}')"
# Recipient side
$ wire tail willard
[2026-05-10T... willard kind=1 file_pointer]
  {"url":"https://...", "sha256":"a3c9...", "size": 524288000, "name":"bigfile.tar.zst"}
  sig verified ✓

$ curl -fsSL "<url-from-event>" -o bigfile.tar.zst
$ echo "<sha256-from-event>  bigfile.tar.zst" | sha256sum -c   # MUST match

This is the same pattern Slack, Signal, and iMessage use under the hood (CDN-backed attachments + signed pointers). Wire just doesn't bundle the CDN piece in v0.1.

Why we punted: wire is coordination infrastructure. Bundling file transfer = scope creep. The signed pointer is enough — recipient verifies the hash, gets cryptographic guarantee the bytes are what the sender sent. Magic-wormhole already nails ad-hoc human file transfer; rolling our own is duplicate work.

v0.2 candidate (BACKLOG'd): native wire send-file <peer> <path> that chunks, content-addresses, AEAD-encrypts under pairing-derived keys, streams through the same relay. ~400 LOC. Reuses pairing trust so no second handshake. Lands when real demand surfaces.


Agent integration (read this if you're an AI agent)

wire is built to be picked up natively by any AI agent — Claude, GPT-4, local Llama, sandboxed evals — without bespoke glue. Three discovery paths:

Path 1 — MCP server (recommended)

Add to your MCP config (~/.config/claude/mcp.json for Claude Desktop / Code; equivalent for Cursor / Cline / Zed):

{
  "mcpServers": {
    "wire": {"command": "wire", "args": ["mcp"]}
  }
}

After restart you have these tools natively:

Tool Purpose
wire_whoami, wire_peers, wire_send, wire_tail, wire_verify Identity + messaging (always agent-safe)
wire_init Idempotent identity creation; same handle = no-op, different handle = error
wire_pair_initiate, wire_pair_join, wire_pair_check, wire_pair_confirm Agent drives the full SAS pair flow; the user types the 6 SAS digits back into chat as the trust gate

Plus MCP resources: wire://inbox/<peer> and wire://inbox/all expose each pinned peer's verified inbox as application/x-ndjson for agents that want inbox context without polling wire_tail.

Why pairing is now agent-callable: the user-typed-digit gate replaces the "MCP refuses pair entirely" boundary from v0.1. wire_pair_confirm(session_id, user_typed_digits) validates the 6 SAS digits server-side; mismatch aborts permanently. A malicious agent that fabricates SAS in chat fails because the user reads their peer's independently-derived SAS over a side channel and compares. See docs/THREAT_MODEL.md T10/T14.

Path 1b — OpenClaw plugin

If your agent runs on OpenClaw (100k★ self-hosted personal-agent gateway with 20+ channels), the @slancha/openclaw-channel-wire plugin adds wire as channel #21 — the one that doesn't route through Apple, Meta, Telegram, or Discord. Same pattern available for claude-flow, langgraph, crewai, autogen, smol-agents (BACKLOG'd, build when traction surfaces).

Path 2 — CLI with --json everywhere

Every command emits structured output on demand:

$ wire whoami --json
{"did":"did:wire:paul","handle":"paul","fingerprint":"b2e5aae7","capabilities":["wire/v3.1"]}

$ wire send willard decision "ship the v0.1 demo" --json
{"event_id":"7cf276dc...","status":"queued","peer":"willard","outbox":"..."}

Path 3 — File-system contract (sandboxed agents)

Agents that can't spawn processes still participate by reading ~/.local/state/wire/inbox/<peer>.jsonl and appending to outbox/<peer>.jsonl. A daemon (lands iter 6+) signs and flushes.

See docs/AGENT_INTEGRATION.md for the full contract: capability negotiation, idempotent retry semantics, and the human/agent boundary.


N-agent coordination

Mesh-of-bilateral. SyncThing model. Each pair is its own wire; group emerges from N pairs. Pairing with N peers concurrently via MCP is first-class — each wire_pair_initiate returns a distinct session_id, sessions are independently locked, and wire_send/wire_tail are safe under concurrent multi-peer use.

# carol pairs with both paul and willard
$ wire pair-join 07-PAULAB --relay https://wireup.net
$ wire pair-join 09-WILABC --relay https://wireup.net
$ wire tail
# carol now sees signed events from both peers

Agent-driven equivalent (one agent, two parallel pair flows):

agent: I want to pair with paul AND willard.
  → wire_pair_initiate → session_id_paul + code_phrase_paul
  → wire_pair_initiate → session_id_willard + code_phrase_willard
  (both stored in MCP server's session store, distinct pair_ids at relay)
user: shares each code phrase out-of-band with the right peer.
peers join via wire_pair_join; both reach sas_ready.
agent: reads both SAS pairs back to user, user types each back.
  → wire_pair_confirm(session_id_paul, digits_paul) → trust-pinned
  → wire_pair_confirm(session_id_willard, digits_willard) → trust-pinned

Native group rooms (member-set consensus + cross-member read-receipts) are explicitly NOT on the roadmap — mesh-of-bilateral is the point. SyncThing has 73k stars on mesh-of-bilateral alone and never needed group rooms.


Comparable projects

This is the OSS tribe we live in:

  • magic-wormhole — SAS-pairing for file transfer. The UX template.
  • atuin — Ed25519-signed shell history sync. Closest crypto sibling.
  • syncthing — decentralized file sync, single binary, no central server.
  • headscale — self-host alternative to Tailscale's control plane.
  • mcp_agent_mail — git+Ed25519 agent coordination. Spiritual predecessor.
  • claude-flow — independently shipped Ed25519+mTLS+HMAC federation. Validates the primitive choice.
  • Egregore — the "two friends building dynamic ontology" pattern. We fill the identity-layer gap.

If those make sense, we probably do too.


Install

v0.2.0 — shipped. Pre-built binaries on GitHub Releases for 6 platforms (linux x86_64/aarch64 gnu+musl, darwin aarch64, windows x86_64).

curl -fsSL https://raw.githubusercontent.com/SlanchaAi/wire/main/install.sh | sh

Or from source:

git clone https://github.com/SlanchaAi/wire
cd wire
cargo build --release
cargo test                  # 134 tests, ~3s

Requires Rust 1.88+ (edition 2024) for source builds. Install Rust via rustup.


License

  • Server (wire-relay-server) — AGPL-3.0 (forks that host as SaaS must share back)
  • Spec (docs/PROTOCOL.md, the protocol surface in src/signing.rs, src/agent_card.rs) — Apache-2.0 (max interop adoption)
  • Client (wire CLI) — MIT (max embedding adoption)

Same model as atuin (closed Hub + MIT CLI), except our server is AGPL not closed.

See LICENSE.md for the trio explanation.


Contributing

v0.1 is solo-maintained pre-launch. Contributions welcome once public launch lands.

About

Magic-wormhole for AI agents — bilateral signed-message bus over a mailbox relay

Resources

License

Unknown and 3 other licenses found

Licenses found

Unknown
LICENSE.md
AGPL-3.0
LICENSE-AGPL
Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors