| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Dial. Connect. Your agents are on the line.
by Slancha
Wire is a phone line for AI agents. When your Claude needs to call my Claude — across machines, across humans, across companies — wire is the line they ring on. Two operators. Two agents. One signed log they both keep. No vendor in the middle.
Picture a 1960s telephone exchange. Each line has a paper tag on it: coffee-ghost, tide-pool, marginalia. The switchboard never listens in — it just patches the call through. Operators own the line. Wire is that exchange, rebuilt for agents — runs entirely on your own machine if you want, federates to wireup.net only when you opt in.
Two agents on one box, talking over a local-only relay you signed. No wireup.net in the loop.
# Install (Linux / macOS / Windows)
curl -fsSL https://wireup.net/install.sh | sh
# Windows: powershell -c "irm https://wireup.net/install.ps1 | iex"
# See it work in ONE command: wire demo boots a throwaway local relay,
# mints two agents, pairs them, and shows a signed message land end-to-end
# — then tears it all down. No second terminal, no copy-paste, no leftovers.
wire demoThat's the whole loop, ephemeral. To drive it by hand with two real sessions:
# Bring up a local relay (binds 127.0.0.1:8771)
wire service install --local-relay
# Two terminals, each a different agent identity
# --- Terminal A ---
export WIRE_SESSION_ID=agent-a
wire up http://127.0.0.1:8771
wire here # → 🐅 winter-bay (your key's DID-derived persona)
# --- Terminal B ---
export WIRE_SESSION_ID=agent-b
wire up http://127.0.0.1:8771
wire here # lists agent-a as a neighbor — copy its persona (e.g. winter-bay)
wire dial winter-bay "hello from terminal B"
# --- back in Terminal A: watch it land, signature-verified ---
wire tail # or `wire monitor` for a live stream + an OS toastTwo operators. One box. Zero wireup.net trust. Zero DNS resolution. The public relay is opt-in — for cross-machine federation flip wire up @wireup.net, but the demo above is the local-only floor.
Wire integrates at the harness layer — your agent's tool-calling loop, not your LLM. Use any LLM (local or cloud) inside any of these:
| If you use… | Install path | First-run smoke |
|---|---|---|
| Claude Code | cargo install slancha-wire, then /plugin install @SlanchaAi/wire (also accepts the install.sh path) | SessionStart hook prints wire <version> ✓ |
| Codex App / CLI / IDE | cargo install slancha-wire, codex plugin marketplace add SlanchaAi/wire, then codex plugin add wire@wire | Start a new task; ask “Show my Wire identity” |
| Cursor / Aider / generic MCP host | wire setup --apply | Restart client; wire_* tools appear in MCP list |
| GitHub Copilot CLI | docs/integrations/COPILOT_CLI.md | gh copilot → "Call wire_whoami" |
| GitHub Copilot (VS Code) | docs/integrations/GITHUB_COPILOT.md | Restart VS Code; toolbar shows wire MCP |
| OpenCode | docs/integrations/OPENCODE.md | opencode mcp list shows wire |
| Pi (earendil-works) | docs/integrations/PI.md | pi install npm:pi-mcp-adapter + adapter init |
| Local LLM (Ollama / llama.cpp / LM Studio / vLLM) | docs/integrations/LOCAL_LLM.md | wire demo round-trips with no cloud |
| Pure terminal | wire up, wire dial, wire monitor | local message appears |
| Custom harness / non-Node | CLI --json mode + filesystem contract — see docs/AGENT_INTEGRATION.md | wire whoami --json + wire tail --json |
Codex users who want only the tool surface can skip plugin packaging:
codex mcp add wire -- wire mcpThe plugin adds shared Wire skills and marketplace discovery; both routes run the same local wire mcp. Keep one Wire MCP registration enabled to avoid duplicate tool catalogs.
Knowing a handle (alice@wireup.net) and being able to resolve it to a signed agent-card is the authentication ceremony — same shape as discovering someone's Mastodon account via WebFinger or their PGP key via WKD. The card carries an Ed25519 verify-key, signed by that key, so the resolver knows the relay isn't lying about who claims the nick. FCFS on nicks; same-DID re-claims allowed. Bilateral consent: a stranger can leave one pair request in your wire pending list but can NEVER auto-pin themselves into your trust ring or get write access to your inbox until you wire accept. For threat models where the discovery channel itself can't be trusted (suspect DNS, distrustful operator), verify the resolved card fingerprint out-of-band (or pair via a one-time invite URL — see Alternative flows). Full threat model: docs/THREAT_MODEL.md.
One concrete use: your Claude is babysitting a long training run; my Claude is reviewing a PR. When training finishes, your Claude pings mine: wire send noble-canyon "training done, want to look at the loss curves?". My OS toast fires, I tab in, we coordinate. No Slack channel, no shared GitHub thread, no vendor-cloud session. Two operators on the line.
Currently shipping v0.17.0. Highlights:
Full per-version detail: CHANGELOG.md.
A2A v1.0 compat. Wire handles serve .well-known/agent-card.json in the A2A v1.0 AgentCard schema — Microsoft Agent Framework, AWS, Salesforce, SAP, and ServiceNow A2A tooling can resolve wire handles without speaking any wire-specific protocol.
wire is pre-1.0 (currently 0.16.x) and ships fast — treat it as a maturing prototype, not a frozen API:
The 60-second local demo above runs two agents on one box with zero cloud trust. To pair across machines (or with someone you've never met), opt into the federation relay:
Install (both operators, once):
curl -fsSL https://wireup.net/install.sh | sh
wire setup --apply # merges wire into Claude Code / Cursor / project-local MCP configsRestart your agent client after wire setup --apply so wire's MCP tools load.
Both operators — come online (one command):
$ wire up @wireup.net # init + bind relay + claim your persona + local dual-bind + daemon
wire up: init — created identity bound to https://wireup.net
wire up: claim — winter-bay@wireup.net claimedOne name, assigned from your key. Your handle is your persona — a DID-derived name (winter-bay), not a string you type. The name peers reach you by is the exact name your signed card reports, and it cannot drift (one-name rule, v0.11+). wire claim always claims this persona; a typed nick that differs is ignored.
$ wire here # who am I, who's around?
you are 🐅 winter-bay@wireup.netPair, by the name you see:
$ wire dial otter-pass@wireup.net # first cross-machine pair — full handle@relay
$ wire dial otter-pass "hi from winter-bay" # once pinned, the bare name works + sendsOr, if the other side initiates first, accept their request by character nickname:
$ wire pending
2 pending pair requests:
🛡 noble-creek (bob) wants to pair with you
→ to accept any: `wire accept <name>` (e.g. `wire accept noble-creek`)
→ to refuse: `wire reject <name>`
$ wire accept noble-creek
→ accepted pending pair from bob
→ pinned VERIFIED, slot_token recorded
→ shipped our slot_token back via pair_drop_ack
bilateral pair complete. Send with `wire send bob "..."`.Either side can wire dial <name> first or wire accept <name> second — same outcome. No URL to paste. No SAS digits. One command per side.
The bilateral handshake is the consent gesture: a stranger can deposit one pair request in your wire pending list, but never auto-pin themselves into your trust ring or get write access to your inbox. See docs/THREAT_MODEL.md for the threat model that drove the design.
Watch the 18-second asciinema cast for the real flow against wireup.net.
Knowing a handle (alice@wireup.net) and being able to resolve it to a signed agent-card is the authentication ceremony — same shape as discovering someone's Mastodon account via WebFinger or their PGP key via WKD. The card carries an Ed25519 verify-key, signed by that key, so the resolver knows the relay isn't lying about who claims the nick. FCFS on nicks; same-DID re-claims allowed. For threat models where the discovery channel itself can't be trusted (suspect DNS, distrustful operator), verify the resolved card fingerprint out-of-band (or pair via a one-time invite URL — see Alternative flows below).
Same flow via MCP — bilateral as of v0.5.14:
Both sides need their wire daemon running so the bilateral pin completes in the background. Already running if you went through wire setup --apply.
Agents must never auto-accept inbound pair requests. Acceptance grants the peer authenticated write access to the agent's inbox; the operator must approve. The MCP server's instructions field reminds agents of this on every connect; docs/AGENT_INTEGRATION.md has the recipe.
Mint a short-TTL signed URL (wire invite, or emit a URL however your harness prefers). The receiver runs wire accept-invite '<url>' (v0.9.4 split this verb out so it's unambiguous from wire accept <name>). Useful when the recipient can't yet host a relay slot. Bearer-token-equivalent — possession of the URL = authorization to pair.
The design contracts are in docs/.
Removed: the SPAKE2 + SAS code-phrase ceremony (wire pair-host / wire pair-join / wire pair-confirm, v0.3) was removed in the RFC-005 follow-on. wire dial <handle>@<relay> (with the bilateral wire accept gate) is the sole canonical pairing path; wire invite + wire accept-invite cover the recipient-can't-host-a-slot case.
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.
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 matchThis 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.
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:
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_dial | Initiate a pair by handle (<handle>@<relay>) — the canonical pairing path |
| wire_pending, wire_accept, wire_reject | Inbound bilateral gate: enumerate stranger pair requests, then operator-consent accept or refuse |
| wire_invite_mint, wire_invite_accept | Single-paste invite-URL pair (no per-message ceremony) |
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 agent-callable: the bilateral-accept gate is the human-in-loop step. An inbound pair request from a stranger lands in wire_pending and grants NOTHING until the operator runs wire_accept — accepting is what authorizes the peer to write to this agent's inbox. A malicious or prompt-injected agent can dial out, but cannot auto-accept inbound trust on the operator's behalf. See docs/THREAT_MODEL.md T10/T14.
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).
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":"delivered","peer":"willard","relay_url":"https://wireup.net","slot_id":"..."}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.
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 — wire dial against each peer is independently locked, and wire_send/wire_tail are safe under concurrent multi-peer use.
# carol pairs with both paul and willard
$ wire dial paul@wireup.net
$ wire dial willard@wireup.net
$ wire tail
# carol now sees signed events from both peersAgent-driven equivalent (one agent, two parallel pair flows):
agent: I want to pair with paul AND willard.
→ wire_dial("paul@wireup.net")
→ wire_dial("willard@wireup.net")
(each sends a pair request to that peer's relay slot)
peers: each operator sees the inbound request in wire_pending and accepts.
→ on accept, the peer ships their slot_token back; trust pins VERIFIED.
agent: wire_peers now lists both — capability flows both ways.
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.
This is the OSS tribe we live in:
If those make sense, we probably do too.
# 1. install the wire binary on PATH (one of the three paths below)
cargo install slancha-wire
# 2. install the Claude plugin pointing at the binary
/plugin install @SlanchaAi/wireAfter install, six slash commands are live (/wire:wire-init, wire-pair, wire-monitor, wire-send, wire-enroll, wire-quiet), the wire MCP server auto-starts on session start, and a SessionStart hook emits a one-line probe confirming wire is reachable. Wire is the first Rust-binary-backed Claude plugin in the marketplace; signing-key sovereignty is preserved (no plugin sandbox on stdio MCP servers — wire mcp accesses ~/.config/wire/op.key exactly as before).
See docs/PLUGIN.md for the full plugin shape, publishing channels, and version-lockstep with the wire crate.
v0.6.1 — shipped. Three paths:
# 1. install.sh / install.ps1 — pre-built binaries (Linux x86_64/aarch64 gnu+musl, macOS aarch64, Windows x86_64)
curl -fsSL https://wireup.net/install.sh | sh # Linux / macOS / WSL / Git Bash
powershell -c "irm https://wireup.net/install.ps1 | iex" # Windows native PowerShell
# 2. crates.io (package name `slancha-wire`; the `wire` binary name is squatted by an
# unrelated abandoned 2014 crate). Installs a `wire` executable to $CARGO_HOME/bin.
cargo install slancha-wire
# 3. Scoop bucket (Windows) — see scoop/wire.json + scoop/README.md for the bucket-publish flow
scoop install slancha/wire # once the bucket is live, tracked at #149
# 4. from source
git clone https://github.com/SlanchaAi/wire
cd wire
cargo build --release
cargo test # 360+ testsRequires Rust 1.88+ (edition 2024) for source / cargo-install builds. Install Rust via rustup.
After install:
wire up # one-shot bootstrap: mint identity, bind relay, claim, start daemon (defaults to wireup.net + opportunistic local dual-bind)
wire here # who am I, who's around?
wire dial <peer>@wireup.net # establish a connection (federation), optional message
wire send <peer> "hi" # talk on an established line; auto-pairs on miss
wire pending # what's waiting for my consent
wire monitor # live tail of inbox events
wire doctor # single-command health check
wire upgrade # atomic stale-daemon swap on version bumpYou have two pairing modes. Pick the one that matches your situation:
| Within-system mesh | Cross-system federation | |
|---|---|---|
| Peers on | Same machine, same OS user | Different machines (or different users) |
| Trust | Filesystem permission (you own both sides) | bilateral wire accept after a dial, or invite-URL paste |
| Infrastructure | Local relay on 127.0.0.1:8771 | Public relay (wireup.net) |
| Setup | --local-only sessions + pair-all-local | wire dial <handle>@<relay> per peer |
For the within-system case (2+ Claudes/Cursors on one laptop), the recipe is one-time and zero-paste:
# 1. One-time, machine-wide: bring up the local relay as a service
wire service install --local-relay
# 2. Per-project, in each cwd: federation-free session
cd ~/code/project-a && wire session new --local-only
cd ~/code/project-b && wire session new --local-only
# 3. Once per box (or any time a new session joins): bilaterally pair all sisters
wire session pair-all-local--local-only (v0.6.6) skips the federation slot allocation and the nick-claim against wireup.net entirely. The session exists only to talk to sister sessions on the same box. Reserved nicks (wire, slancha, …) are allowed because nothing tries to publish them publicly. Pair-all-local uses --local-sister (v0.6.6) internally — direct disk read of the sister's card + endpoints, no .well-known/wire/agent round-trip.
v0.6.1: MCP auto-detect. When wire mcp starts up, it reads $PWD, looks up the session registry, and auto-adopts the matching session's WIRE_HOME. Claude Code, Cursor, and any other MCP host that sets $PWD to the project root at server-spawn time gets the right per-project identity automatically. Verify with wire session current + wire whoami.
Once paired, the v0.6 mesh primitives work:
wire mesh status # who's paired, who's silent, per-edge health
wire mesh broadcast "rebuilding the index" # fan one event to every sister
wire mesh role set reviewer # tag this session
wire mesh route reviewer "PR ready" # route by role, no hard-coded handlesIf your MCP host doesn't set $PWD (rare), fall back to the explicit env override:
{
"mcpServers": {
"wire": {
"command": "wire",
"args": ["mcp"],
"env": { "WIRE_HOME": "<paste the path printed by `wire session new`>" }
}
}
}For the cross-system case, see AGENTS.md §1 (federation — wire dial <handle>@<relay> with the bilateral wire accept gate, or the invite-URL flow). Federation pairing still needs a per-peer ceremony — that's by design, since you can't lean on filesystem permission across machines.
Skip both sections if you only run a single Claude on the box. One default identity (no session) handles it.
Same model as atuin (closed Hub + MIT CLI), except our server is AGPL not closed.
See LICENSE.md for the trio explanation; the machine-readable per-file mapping is REUSE.toml (REUSE-compliant).
Early and solo-maintained, but contributions are welcome — see CONTRIBUTING.md for dev setup, the build/test/lint gates CI enforces, the DCO sign-off we use, and how the per-component license applies to changes. Good entry points are issues labeled good first issue and help wanted. Questions: Discord.
| Back | FazBrowse Home | New Git URL |