worldinmotion

mcp
Guvenlik Denetimi
Basarisiz
Health Uyari
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Basarisiz
  • exec() — Shell command execution in .github/scripts/plugin-pin.mjs
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

End-to-end encrypted, real-time messaging between AI agent sessions across machines and accounts

README.md
Distronode

worldinmotion

OpenSSF Best Practices
OpenSSF Scorecard
Latest release

worldinmotion lets AI agent sessions (Claude Code, Gemini CLI, Antigravity, bots) send each
other messages in real time, across machines and across accounts. Messages are end-to-end
encrypted between devices and pass through a relay that cannot read them. Each session gets an
address like reviewer@laptop, and can see who is online, send, wait for a reply, and join rooms.

Two sessions on one machine: writer sends reviewer a message, reviewer answers, each watching in its own terminal

Two sessions talking through wim, drawn from a transcript recorded with wim 0.1.7.

No account required, no telemetry, sealed offline delivery.

Status: pre-release, v0.1. It works end to end, but the wire format and the commands may
still change before v1.0. Use it for work you can afford to redo. Crossing accounts is how it is
built (a mesh never uses a vendor account), but the formal two-account test has not run yet.

Why

Built-in messaging stays inside one vendor and one account, through that vendor's servers. Since
August 2026 (Claude Code v2.1.224), Claude Code sessions on one account can message each other
across machines, through Anthropic's servers. Beyond one machine that needs a claude.ai sign-in,
so it does not work with an API key or on Amazon Bedrock, Google Cloud or Microsoft Foundry.

worldinmotion is for what that does not cover: sessions under different accounts or
organisations, agents from different vendors, and a path in the middle that cannot read the
messages (each agent's own model provider still sees what that agent reads). Without it, when
two such agents work on the same problem (one writing code under your account, one reviewing it
under a client's), a person ends up copying text between them.

What the line at the top means:

  • No account required. A mesh is a set of device keys that you create. The hosted relay needs
    no sign-up, and no vendor account is involved.
  • No telemetry. The client, the Claude Code plugin and the VS Code extension send no usage
    data. The client connects only to the relay you choose (and, for wim bot and wim ci, to the
    provider you configure).
  • Sealed offline delivery. A message to a session that is offline waits on the relay for up to
    24 hours, sealed to the recipient's device, while the sender may go offline too.

First run: three machines, one person

This guide sets up one person's three machines (here laptop, desk and build) on one mesh,
using the hosted relay at wss://worldinmotion.distronode.com, which is free during the
preview. Read its terms first. To run your own relay instead, see
Self-hosting a relay.

Every step says where it happens:

  • [Terminal] a terminal you opened yourself (in VS Code: Terminal > New Terminal). Never the
    Claude chat box, and never ! in Claude Code: both run the command inside Claude's session,
    where wim refuses the steps that ask for a passphrase, show a secret, decide trust or approve
    a held message (it says so: CLAUDECODE is set: this shell belongs to Claude Code).
  • [Claude chat] the Claude Code prompt.
  • [VS Code] the VS Code window itself (Extensions view, command palette).

1. Install, on each machine

You need Node.js 22.18 or newer.

[Terminal] Install the wim command:

npm install --global worldinmotion
wim --version

If the shell then says wim: command not found, npm's global bin directory is not on your
PATH. Fix it for this shell, and add the same line to ~/.bashrc or ~/.zshrc:

export PATH="$(npm prefix -g)/bin:$PATH"

Without npm: download wim.mjs and SHA256SUMS from the latest
GitHub Release, check it with
sha256sum -c SHA256SUMS (macOS: shasum -a 256 -c SHA256SUMS), and install it with
install -m 755 wim.mjs ~/.local/bin/wim, or run node wim.mjs wherever this guide says wim.

[Claude chat] Install the Claude Code plugin:

/plugin marketplace add distronode-corporation/worldinmotion
/plugin install worldinmotion@worldinmotion

A Claude Code session that was already open does not get the plugin: start new ones.

[VS Code] Optional: install the extension, distronode.worldinmotion on the Visual Studio
Marketplace and Open VSX. Search for worldinmotion in the Extensions view, or run
code --install-extension distronode.worldinmotion --pre-release. The extension is published as a
pre-release only until 1.0, so the command needs --pre-release (or a version,
distronode.worldinmotion@<version>): without either it looks for a stable version, finds none, and
prints only "Failed Installing Extensions".

2. Create the mesh, on the first machine

[Terminal on laptop]

wim init --name laptop --relay wss://worldinmotion.distronode.com

This makes the device's keys, creates a new mesh on the relay with this device as its admin, and
shows a recovery code once. Keep it offline (a password manager, or paper): it is as powerful
as an admin device. Never paste it into a Claude chat or send it over the mesh. (Run anywhere it
cannot be shown, such as through an agent or a pipe, wim init says why and offers it to
wim recovery show, run in your own terminal within 10 minutes.)

3. Add the other two machines

Do this once for desk and once for build, with a new invite each time.

[Terminal on laptop]

wim invite

It prints a single-use short invite code, wim2-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX, and waits. Move
the code to the other machine yourself: a password manager, AirDrop, a file on a USB stick, or
read it out. Never through Claude or another agent, and not over the mesh. (A machine on wim
0.1.4 or older needs the full code: wim invite --full.)

[Terminal on desk]

wim join <code> --name desk

desk shows a comparison code like 7KQ2M-X4D9P. Type it on laptop, where wim invite asks
for it: laptop never shows its own copy, so typing it is the check that the request came from
desk and not from someone else who saw the invite. A code that does not match is refused: make
a new invite. Both commands ask for a person at the terminal, so run them in a terminal you
opened yourself, not through an agent.

wim join makes the device's keys too, so a new machine needs no wim init. If wim invite was
no longer running when desk asked to join, wim devices pending on laptop lists it, and
wim devices admit desk <comparison code> admits it.

For an unattended machine you control (a bot or a build box), wim invite --auto admits the first
device that uses the code, with no comparison code to type. Because that code alone admits a
device, it is printed only in a terminal you opened yourself. Run through an agent or with its
output piped, wim invite --auto keeps the code in memory and asks you to run wim invite show
in your own terminal, within 10 minutes and before the invite expires, to see it once.

4. Trust your own devices

Until you trust a device, its messages are held for your approval. After an admit and after a
join, each terminal asks "Is desk your own device? Trust its messages here?": answer y for your
own devices. For three machines that is six trusts, two on each machine. Any you skipped, on each
machine:

[Terminal on laptop, desk and build]

wim devices trust --all

wim devices trust <name> trusts one device, and wim devices lists the devices and what this
one does with each one's messages. Both trust commands list each device with its id and wait for
your y; the id should match the line marked this device in wim devices list on that machine.

5. Optional: keep the keys out of Claude's reach

By default the device keys are in a file your OS user can read, and so can any agent with a
shell. The signer keeps them in a separate process instead.

[Terminal] Once per machine:

wim agent encrypt   # once: encrypts the key file under a passphrase you choose
wim agent start     # asks for the passphrase and starts the signer in the background

The signer keeps running after you close the terminal or VS Code, and stops when you log out,
restart or run wim agent stop. To have it start at each log in, run
wim agent autostart enable once: a login item starts it and asks for the passphrase in a dialog
of its own (--keyring keeps the passphrase in the macOS keychain or libsecret instead; read
SECURITY-MODEL.md section 5.8 first). Without autostart, run wim agent start again after each
restart.

Start it before you open Claude when you can. A Claude tab opened earlier says on its status line
that no signer is running, and links by itself a few seconds after the signer starts.
wim agent status only reads, so Claude may run it for you; wim agent lock wipes the keys from
the signer's memory until wim agent unlock.

6. Check each machine

[Terminal] wim doctor checks the keys, the state directory (and why it is the one: WIM_HOME,
CLAUDE_CONFIG_DIR or the default), the relay, the clock and the roster, and lists any other
device directory on the machine.

[Claude chat] In a new Claude Code tab, /wim status shows the same for that tab: its address,
the relay connection, the signer and the state directory.

7. Addresses

address what it is
cli@<device> the device's terminal inbox: wim inbox reads it once (--peek to look without marking anything read; a pipe or file marks nothing unless --mark-read), wim watch follows it. Registered when the device creates or joins the mesh; the relay forgets it after 24 hours offline with nothing queued, and the next wim inbox or wim watch there registers it again
<folder>@<device> a Claude Code tab: its working directory's base name, for example billing@laptop. The tab's status line shows it; /wim name <name> renames it
vscode@<device> the VS Code extension

A message to cli@desk waits in desk's terminal inbox; it does not reach a Claude tab on desk.
When a Claude tab is live there, wim send says so: live on desk now: billing@desk (claude-code).

8. Terminal test: all six routes

[Terminal on each machine] Leave wim watch running in one terminal, so each machine has a live
session. Then, in another terminal on each machine:

wim ping --all

It pings every live session, and each device's client answers with a pong by itself (no agent,
no inbox). A pong proves both directions between the two devices, encryption included, so three
machines that each print both directions ok for the other two have tested all six routes.

To test real messages as well, send to the other two from each machine and wait for the
receipts:

# on laptop
wim send cli@desk "hello from laptop" --wait 2m
wim send cli@build "hello from laptop" --wait 2m
# on desk, then on build: the same to the other two

Each send answers routed (handed to a live session; not yet read) while a wim watch reads
there, else queued. The wim watch on the other machine prints the message, and the waiting
wim send prints delivered once that session has taken it. Answer each one to test the way
back, for example on desk: wim send cli@laptop "reply from desk" --wait 2m. Without a
wim watch, wim inbox reads the terminal inbox once and, at a terminal, marks each item read
once it is printed. When its output is not a terminal (a pipe or a file) it marks nothing, since a
pipe such as | head can cut an item off part-way without the writer knowing, and it says so on
stderr; --mark-read marks what it printed anyway. wim inbox --peek prints it all and marks
nothing. A message from a device you did not trust prints held with how to approve
it there (wim held approve <id>, in a terminal on that machine: it shows the sender and the text
and waits for your y). A wim send --wait keeps waiting through held and prints delivered
once the person there approves it, or refused if they refuse it.

9. Claude-to-Claude test

[Claude chat on desk] Open a Claude Code tab in a folder, say ~/src/demo. Its status line shows
demo@desk. Leave it idle.

[Claude chat on laptop] In a Claude Code tab (say notes@laptop), ask:

Send demo@desk this message: "Please reply to notes@laptop with the word pong."

Without anything typed on desk, the demo@desk tab starts a turn for the message and replies
with SendMessage, and the reply arrives in the notes@laptop tab as a new turn. To a device you
trusted, SendMessage asks nothing; to any other device Claude asks you first.

10. When a message does not arrive

  • wim peers lists the live sessions; a Claude tab shows as kind claude-code. A tab missing
    there was opened before the plugin was installed (start a new one), or its status line says
    why it is not linked.
  • A tab that names a different state directory than your terminal (/wim status against
    wim doctor) is a different device: usually CLAUDE_CONFIG_DIR is set for one and not the
    other. Use the same WIM_HOME in both, or set up that directory as its own device.
  • Held messages: wim held list, or /wim in Claude Code.

11. Optional: a ping when a message is held

A held message waits until you approve it, which is easy to miss when you are away from the
machine. The client can run a program of your choice each time a message is held. It passes one
short line with no message content, such as worldinmotion: 2 messages held for approval, and
never the text or the sender. (The same ping also fires when a device asks to join, naming that
device, and when the roster forks.) You still approve at the machine: the ping cannot approve
anything.

[Terminal] Write notify.json in the state directory that wim doctor names (by default
~/.config/worldinmotion/notify.json). This one posts to an ntfy topic with
curl:

{ "provider": "command", "command": ["curl", "-fsS", "-H", "Title: worldinmotion", "https://ntfy.sh/<your-topic>", "-d"] }

The client runs the program without a shell and adds the line as its last argument, so this runs
curl ... -d "<line>". It pings at most once a minute ("minIntervalMs" changes that). Anyone
who knows a public ntfy topic name can read it, so pick a long random one, or use your own ntfy
server. Sessions read notify.json when they start: restart them after a change. wim notify-test
sends a test line.

Other agents

How a message reaches an agent depends on the agent. These docs use three labels for it:

delivery what it means agents today
push a message lands in the running turn, or starts a new turn in an idle session Claude Code, through the plugin
turn a message is handed over at the agent's next tool call or turn end none yet
pull the agent sees messages only when it calls the inbox or wait tool every other MCP agent below

Only Claude Code wakes today. Gemini CLI and Antigravity CLI were tested on 2026-10-24: each
listed peers and sent a message that arrived. Claude Desktop, Codex CLI and Cursor are not yet
tested.

  • Gemini CLI, Antigravity, Claude Desktop, Codex, Cursor and any other MCP client:
    docs/peers.md has the configuration and test status for each.
  • A plain model API as a peer: wim bot.
  • Claude Code: plugins/claude-code covers the plugin, its
    /wim pane and its status line.
  • VS Code: the extension shows the mesh, held messages and live
    activity.

wim help lists every command.

How it works

  laptop                                            build box
 +------------------------+                       +------------------------+
 | agent (Claude Code)    |                       | agent (Gemini CLI)     |
 |   |                    |                       |   |                    |
 | plugin or MCP server   |                       | plugin or MCP server   |
 |   |                    |                       |   |                    |
 | wim client             |                       | wim client             |
 |  (device keys, crypto) |                       |  (device keys, crypto) |
 +-----------|------------+                       +-----------|------------+
             |  WSS                                     WSS   |
             v                                                v
        +-------------------------------------------------------+
        | relay (Cloudflare Worker, or self-hosted Node relay)  |
        |   +-----------------------------------------------+   |
        |   | one Durable Object per mesh:                  |   |
        |   |   signed roster, sessions, offline queues     |   |
        |   +-----------------------------------------------+   |
        +-------------------------------------------------------+
  • A device (one machine, one OS user, one agent profile) holds its own signing and
    encryption keys. A mesh is a set of devices that trust each other, listed in a
    roster that admin devices sign.
  • Each running agent is a session with one WebSocket to the relay. A new device joins
    with a one-time invite code from an admin.
  • The relay routes encrypted messages, queues them for offline sessions for up to 24
    hours, and reports delivery. On Cloudflare each mesh lives in its own Durable Object;
    the self-hosted relay keeps the same model in one Node process.

The wire protocol is in SPEC.md. How the pieces on one machine fit together is in
docs/design.md.

Security, in plain words

  • End-to-end encrypted. Message text is encrypted on the sending device for each
    recipient device, and signed. The relay never has the keys.
  • Signed roster. Only an admin device can add or remove a device, by signing a new
    roster version that every client checks against the chain it already trusts. A relay
    cannot slip in a device of its own.
  • The relay sees metadata only. It sees which devices and sessions exist, who sends to
    whom, when, and how much. It cannot read, forge or alter a message without the receiver
    dropping it. It can drop or delay messages, which senders notice as a missing receipt.
  • Peer text is framed as another AI session's text. Everything a peer sends reaches an agent
    inside a frame that says so. This reduces the risk that an agent obeys a peer, and it is not a
    guarantee (SECURITY-MODEL.md section 7.1). A device you trust (wim devices trust) can ask
    your agents for work, within their normal permissions. Messages from a device you do not trust
    are held for your approval.
  • Secret filter, best effort. Outgoing text that matches common credential formats (cloud and
    API keys, tokens, private keys, invite and recovery codes) is refused. An encoded or unusual
    secret gets through, so it catches accidents, not a determined agent (SECURITY-MODEL.md section
    7.4).
  • Loop and cost breaker. Two agents that wake each other could loop and spend tokens without
    end, so each device counts how often peers wake its agents. In a new mesh the defaults are 120
    messages per sender device and 300 in total per hour, plus a pause on a fast exchange of short
    messages (more than 32 back and forth in 10 minutes). Past a limit, that device's messages are
    held for you and the notice names the rule that tripped. A mesh.json written before 0.1.8
    keeps the limits written in it (20, 60 and 8); docs/design.md (loop and cost breaker) shows how
    to raise them.
  • Forward secrecy, bounded. Each device rotates a signed prekey daily and deletes each
    prekey's secret 72 hours after it expires, and every message is sealed to the recipient's
    current prekey with a fresh ephemeral key. A key file stolen later opens nothing sealed to its
    device more than 120 hours earlier, and nothing the device sent. Until 1.0, a device that
    publishes no prekey (a v0.1 client) still gets a v0.1 box without forward secrecy, and
    wim send says so. Details: SECURITY-MODEL.md section 6.14.
  • Optional: keep the keys out of your agent's reach. By default the device keys are in a file
    only your OS user can read, which also means any agent with a shell can read them. wim agent encrypt encrypts that file under a passphrase; wim agent start, run in your own terminal, asks
    for it once and keeps the keys in a separate signer process that sessions ask to sign and
    decrypt. A copy of the files is then useless without the passphrase, and wim agent lock stops
    all use of the keys until you unlock it. A process running as you can still ask the unlocked
    signer to act for the device. Details: SECURITY-MODEL.md section 5.8.
  • Approving and trusting happen at your own terminal. wim held approve, refuse and
    resume, and wim devices trust and untrust, run only when their input and output are an
    interactive terminal and no agent's variables are set (CLAUDECODE and the others listed in
    SECURITY-MODEL.md section 7.2). They show what is being decided and wait for a typed y. No
    MCP tool does any of them. This stops an agent that runs wim the usual way, by mistake or
    because a peer asked it to. It does not stop a program running as your OS user, which can unset
    the variables, open a terminal of its own, or edit wim's files directly (section 5.8).

The full threat model, including what is out of scope, is in
SECURITY-MODEL.md. For a security team deciding whether wim may run inside a
company, docs/security-teams.md maps it to the OWASP agent risks and
names the gaps. To report a vulnerability, see SECURITY.md.

Self-hosting a relay

The relay is untrusted for message content, so running your own is about availability, limits
and metadata, not about who can read your messages. Two options:

  • Node relay, one process for many meshes, from source or as the container image
    ghcr.io/distronode-corporation/worldinmotion-relay, behind your own TLS:
    packages/relay-node.
  • Cloudflare Worker, one Durable Object per mesh, in your own Cloudflare account:
    packages/relay-cloudflare.

A relay refuses to create meshes until you choose who may: set WIM_CREATE_KEY (then
wim mesh create --relay <url> --key-env NAME must carry that key) or WIM_OPEN_CREATE=1 (anyone
who can reach it). A mesh lives on the relay that created it; v0.1 cannot move a mesh to another
relay.

The hosted relay

wss://worldinmotion.distronode.com is a Cloudflare Worker run by Distronode. During the preview
(until v1.0) anyone may create a mesh on it, with no key and no sign-up, within limits: at most
2,000 meshes in total, 25 MiB of files per mesh per day, rate limits per network, and a mesh with
no connection for 30 days is deleted. There is no SLA, and the offer may end with 60 days' notice.
wim doctor shows what the relay says about its offer. The full terms, what it can see and how
to report abuse are in docs/hosted-relay.md.

Contributing

See CONTRIBUTING.md. This project follows the
Contributor Covenant. Changes are listed in CHANGELOG.md.

Licence

Apache License 2.0. See LICENSE and NOTICE.

Yorumlar (0)

Sonuc bulunamadi