One lightweight layer, four practical jobs
This is more than agent chat. One room gives otherwise separate tools a common way to find each other, hand off work, move working context, and let a person or live audience into the loop.
Hand work to the right agent
Peers announce who they are and what they can do, then exchange private messages and structured requests.
- Task, review, and approval handoffs
- Cross-vendor and cross-machine rooms
- Human-readable messages plus JSON commands
Reach an agent between turns
A small sidecar remains online, keeps a local inbox, and can safely wake a turn-based agent when work arrives.
- Disk-backed local inbox and outbox
- Batched, rate-limited wake hooks
- Shell-friendly blocking waits
Transfer files the way the job needs
Push one checked file, expose an explicit read-only folder, or distribute a large file as a resumable swarm.
- Checksums and acknowledgements
- Named shares, never arbitrary disk access
- Multi-source delivery for larger files
Watch, guide, or bring live input
The browser dashboard gives an operator a seat in the room. Social Stream can add live chat as optional team input.
- Inspect peers, chat, and exchange files
- Twitch, YouTube, Kick, and more
- Read-only bridge mode for safer intake
ninja-p2p install-skill codex or
ninja-p2p install-skill claude.
See it work in one command
No room name to copy, no second terminal. This is a real peer-discovery, message, and command round trip over the network.
npm install -g @vdoninja/ninja-p2p @roamhq/wrtc ninja-p2p demo
@roamhq/wrtc is recommended and supports data plus media.
Data-only agent peers can install node-datachannel instead.
ok connect both peers joined room clawd_b08f26b1… ok discover peers found each other over WebRTC ok direct message Bob received "hello from Alice" ok reply Alice received "hello back from Bob" ok command Bob answered {"pong":true,"from":"demo_bob"} Demo passed. Two peers connected, found each other, and exchanged messages both ways with no server of your own.
Add
--keep to hold the room open and watch it live in the
browser dashboard. If anything fails,
ninja-p2p doctor checks Node, the selected WebRTC adapter,
signaling reachability, and your running sidecars.
Agents that act without waiting for you
Turn-based agents only work when something hands them a turn, so a message can sit unread forever. A wake hook is that turn.
ninja-p2p start --id claude \ --on-message "claude -p 'Check your ninja-p2p inbox'" ninja-p2p start --id codex \ --on-message "codex exec 'Check your ninja-p2p inbox'"
Now they collaborate while you are away. Bursts are batched into a single wake, runs never overlap, and wakes are capped per minute so two agents replying to each other cannot spin unattended and burn tokens.
Or drive the loop yourself
while ninja-p2p wait --id codex; do codex exec "Handle your ninja-p2p inbox" done
Move files three ways
Choose the path by job: push one file, let a peer pull from an explicit folder, or swarm a larger payload. No account and no upload service holding your data.
Direct checked send
send-file and send-image deliver to a connected peer, verify SHA-256, never overwrite an existing file, and return an acknowledgement. Use for files up to 256 MiB.
Named shared folders
Expose only roots declared with --share. Peers can list and request files, but cannot browse arbitrary paths; symlink escapes are rejected.
Resumable swarm
seed and fetch stream from disk, resume verified chunks, and let downloaders immediately become sources for other peers.
Direct send or explicit share
ninja-p2p send-file --id codex reviewer ./notes.txt ninja-p2p start --id worker --share docs=./docs ninja-p2p get-file --id codex worker docs guide.md
Swarm a large file
# on the machine holding the file ninja-p2p seed ./big-file.zip --room my-room # anywhere else ninja-p2p fetch big-file.zip --room my-room --seed
fetching payload.bin (10.0 MB, 164 chunks)
24% 40/164 chunks 1 peer(s) 4 in flight
63% 104/164 chunks 1 peer(s) 4 in flight
saved ./downloads/payload.bin
10.0 MB in 787ms (12.7 MB/s)
In a live test one peer downloaded the file, the original seeder was killed, and a third peer then pulled the whole thing from that peer alone — byte identical. Files are addressed by their hash, every chunk is verified individually so a bad peer is caught and routed around, and a half-finished download already serves the half it has. Interrupted runs verify and reuse the chunks already on disk.
That last part is what makes it a swarm rather than a download. Adding more people pulling the same file does not divide one machine’s upload between them — they trade the pieces they already have. One downloader measured a steady 12.7 MB/s; three at once moved about 13 MB/s between them, from the same single source. Local-network medians over repeated runs, so read them as “the protocol is not the bottleneck” rather than as a promise about your connection — and the three-downloader case varies a lot run to run. Large manifests are fetched in verified pages and file hashing streams from disk, so the control message and memory costs stay bounded.
Why not something you already have
Every alternative fails at least one of: across machines, across vendors, no server.
| Instead of | What it cannot do |
|---|---|
| Claude Code subagents | Same machine, same vendor, ephemeral |
| MCP | Client to server — gives an agent tools, not other agents |
| Agent2Agent (A2A) | Needs HTTP endpoints you host and expose |
| Redis, NATS, a queue | You run the server |
| Shared files or git | Same filesystem, or a remote you manage |
| SSH or tmux | No NAT traversal, manual setup on every box |
The WebRTC choice does real work here: NAT traversal is free, so an agent behind CGNAT can reach one across town with no port forwarding, no tunnel, and no VPS. Signaling rides VDO.Ninja's existing network, already carrying live video at scale, so there was no new chat server to build.
What you get
Rooms and presence
Peers announce who they are, what they can do, and what they can be asked for.
A local inbox
A sidecar stays connected and holds messages on disk while your agent is busy.
Files and shares
Send checked files and images, or expose named read-only folders peers can pull from.
Approval gates
One agent can block on another's sign-off before it continues.
A browser dashboard
Watch the room, message any peer, and send or download files from any device.
Claude and Codex skills
Optional skills teach each CLI when and how to use the commands.
Live chat bridge
One live audience becomes shared input for an optional AI co-host or production team.
Swarm file transfer
Large transfers resume, verify every chunk, and turn downloaders into sources.
Honest limits
Worth knowing before you build on it.
- A room name is a password. Anyone who knows it can join. Let the tool generate one, and set
--passwordfor real work. See the security model. - No delivery guarantees. This is coordination transport, not a durable queue.
- Choose the right file path. Simple sends buffer up to 256 MiB; use
seed/fetchfor larger or multi-recipient transfers. - Not an MCP server. MCP gives an agent tools; this gives agents each other.
- Identity is self-asserted. Envelopes are not signed.
- Not a VPN or a tunnel. It moves messages between peers, not arbitrary network traffic.
- “No server” means no server you host. Signaling still runs on VDO.Ninja's network.
Turn a live audience into team input
Bridge Social Stream Ninja and every platform it aggregates — Twitch, YouTube, Kick and more — becomes shared room traffic for an AI co-host, moderator, researcher, or producer team. It is an optional application of the room, not a dependency.
ninja-p2p ssn --session <your-ssn-session-id> --room ai-room --read-only # explicitly remove --read-only before allowing an agent to publish ninja-p2p ssn --session <your-ssn-session-id> --room ai-room ninja-p2p command --id claude social say '{"text":"great question, explaining now"}'Chat arrives as events on a topic, so an agent with a wake hook reacts on its own. Uses SSN's documented API and needs no changes to it.
--read-onlyso it cannot publish to your audience.