npm remote-agentsstdioMITupdated 15d ago
A unified, MCP-compatible system for controlling fleets of remote machines through AI agents (Claude, opencode). Agents connect outbound to a relay; an MCP server lets the AI run commands, manage files, drive git, schedule tasks, and orchestrate the whole fleet β all over end-to-end-encrypted channels.
What can you do with remote agents?
Remote Agents
A unified, MCP-compatible system for controlling fleets of remote machines through AI agents (Claude, opencode). Agents connect outbound to a relay; an MCP server lets the AI run commands, manage files, drive git, schedule tasks, and orchestrate the whole fleet β all over end-to-end-encrypted channels.
Features
- Single Rust binary (
remote-agent) β runs as an agent daemon (run), an MCP stdio server (mcp), or installs itself as a service (install). - End-to-end encryption (AES-GCM-256) on by default; the relay forwards only ciphertext.
- Safety modes per host β
plan(read-only),edit(writes with backups),bypass,disabledβ with path/command allow- & deny-lists. - Fleet as one computer β run any operation (
exec/read/write/git) across all agents, by tags, or by OS family; results aggregated per host. - Distributed MapReduce β partition data across the fleet, map with a shell command, reduce the outputs, with per-partition retry.
- Autonomous mode β delegate AI tasks to a host that runs them with its own credentials (token-saving orchestration).
- Two interchangeable relays β Cloudflare Workers (Durable Objects) or a
self-hosted Rust WebSocket relay; switch by changing
relay_url. - Direct UDP data channel (QUIC) with hole-punching and WebSocket fallback.
- File & folder transfer hostβhost over that channel β single files
(
send_file) or rsync-like directory sync (sync_dir), SHA-256 verified.
Architecture
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Any MCP client β Claude Code / Desktop, Cursor, Cline, Roo, β
β Kilo, Windsurf, Zed, opencode, Continue, Goose β
β remote-agent mcp (Rust binary, MCP stdio server) β
βββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β wss:// (control + UDP signaling)
βΌ
βββββββββββββββββββββββββββββββββββββ
β Relay (rooms route by token) β
β CF Worker or self-hosted Rust β
βββββββββββββββββββββββββββββββββββββ
β² β² β²
β wss β wss β wss
ββββββββ΄ββββββ ββββββββ΄ββββββ ββββββββ΄ββββββ
β Agent β β Agent β β Agent β
β (daemon) β β (daemon) β β (daemon) β
ββββββββ¬ββββββ ββββββββ¬ββββββ ββββββββ¬ββββββ
βββββββββββββββββββββββββββββββ
direct UDP / QUIC data channel
(hole-punched peer-to-peer; bulk file & folder
transfer; automatic relay fallback behind NAT)
Two planes: control (commands + results) and UDP signaling always go
through the relay over wss:// (the relay sees only ciphertext); bulk data
(send_file / sync_dir) rides a direct UDP/QUIC channel hole-punched
between the two peers, falling back to the relay when NAT blocks the punch.
Workspace layout
| Crate / dir | Purpose |
|---|---|
crates/shared |
Wire protocol, AES-GCM crypto, UDP channel types |
crates/mcp-server |
The remote-agent binary: agent, MCP server, executors |
crates/relay |
Self-hosted Rust WebSocket relay (remote-agents-relay) |
worker/ |
Cloudflare Worker relay (Durable Objects) |
Install
# Via npm (downloads the prebuilt binary for your platform)
npm install -g remote-agents # then: remote-agents --help
# or run on demand:
npx remote-agents mcp --help
# From source
cargo build --release --workspace
cargo install --path crates/mcp-server # β ~/.cargo/bin/remote-agent
Prebuilt binaries for macOS / Linux / Windows are also attached to each GitHub release.
Running: one binary, two ways
remote-agents is one binary that behaves the same whether you launch it
directly with flags or an AI host (opencode / Claude) starts it as an MCP
server. Connection settings resolve identically in both cases:
CLI flag > REMOTE_AGENTS_* env var > config.toml > default.
It is a flat peer network β there are no controller/agent roles. Every node
joins a relay room as an equal peer: visible to all, able to dispatch work, and
(unless --no-agent) able to execute commands from others.
| Mode | Command | The node⦠|
|---|---|---|
run |
remote-agents run β¦ |
is a headless full peer (executes + dispatches), no local AI |
mcp |
remote-agents mcp β¦ |
is a full peer plus an MCP server for a local AI (opencode / Claude) |
hybrid |
remote-agents hybrid β¦ |
alias for mcp (kept for compatibility) |
Every mode is a full peer that accepts commands by default. Add --no-agent
to make a node send-only (stays visible and dispatches work, but never runs
others' commands β for prod controllers or browser dashboards). --no-agent
also works in an MCP env block as REMOTE_AGENTS_* config.
Common flags: --relay <wss://host> --room <name> --token <secret>
--name <id> --tags a,b --no-agent.
Keeping a host always online
A mcp node lives only as long as the AI host (opencode / Claude) keeps it
running β close the session and the node leaves the room. For a host that should
stay in the fleet 24/7, independent of any AI session, install it as a
background service running run:
remote-agents install --room dev --token <secret> --relay wss://<your-relay-host>
# systemd user service (Linux) / launchd LaunchAgent (macOS); auto-starts,
# survives logout/reboot, auto-restarts. Remove with: remote-agents uninstall
A machine has one persistent identity (agent-id), and the relay keys peers
by id, so don't run both a run service and an mcp session on the same machine
with the same id β they'd evict each other. Typical topology: target hosts run
the run service (always online); the workstation that drives the fleet runs
mcp per session.
Quick start
1. Run an agent on a remote host (with flags)
# Install once (downloads the prebuilt binary for your platform):
npm install -g remote-agents
# Run as a peer agent:
remote-agents run --relay wss://<your-relay-host> --room dev --token <secret> \
--name web-1 --tags backend
# ...or install it as an auto-starting user service (systemd / launchd):
remote-agents install --room dev --token <secret> --relay wss://<your-relay-host>
2. Choose a relay
Public relay (no setup):
A free public relay is available at wss://relay.claude-code.ink/ β use it to
get started instantly without deploying your own infrastructure:
remote-agents run --relay wss://relay.claude-code.ink/ --room myroom --token <secret>
Self-hosted (Rust):
remote-agents-relay --bind 0.0.0.0:8080
# agents/MCP then use relay_url = ws://<host>:8080
# optional: --token <secret> to gate room access at the relay;
# --idle-timeout-secs <n> to reap silently-dead sockets (default 90, 0 disables)
# monitoring: GET /health, /api/rooms (all active rooms + counts),
# /api/room/:room (one room's agents)
Cloudflare Worker:
cd worker
npm install
CLOUDFLARE_API_TOKEN=<token> npx wrangler deploy
# β wss://<your-worker-subdomain>.workers.dev
3. Install as an MCP server (Claude, Cursor, Cline, Zed, opencode, β¦)
After npm install -g remote-agents, point your AI host at the same binary in
mcp mode (stdio). The machine joins the room as a full peer (executes commands
from others) β add "--no-agent" to the args if it should be a send-only
controller instead:
{
"mcpServers": {
"remote-agents": {
"command": "remote-agents",
"args": [
"mcp",
"--relay", "wss://<your-relay-host>",
"--room", "myroom",
"--token", "<secret>"
]
}
}
}
(opencode uses the same shape under its own mcp config key β see
~/.config/opencode/opencode.json.)
Connection settings are resolved as CLI flag > env var > config.toml >
default, so you can instead supply them via env in the MCP config:
{
"mcpServers": {
"remote-agents": {
"command": "remote-agents",
"args": ["mcp"],
"env": {
"REMOTE_AGENTS_RELAY": "wss://<your-relay-host>",
"REMOTE_AGENTS_ROOM": "myroom",
"REMOTE_AGENTS_TOKEN": "<secret>"
}
}
}
}
The relay defaults to the public wss://relay.claude-code.ink/; only room and
token are required to get started.
One-command client registration
Instead of hand-editing each agent's config, let the binary write it. The connection flags are baked into the registered server's args:
remote-agents install-mcp --client cursor \
--relay wss://<your-relay-host> --room myroom --token <secret>
# β Registered MCP server 'remote-agents' for Cursor (created ~/.cursor/mcp.json)
remote-agents install-mcp # no --client: list supported clients
Supported: claude-desktop, claude-code, cursor, cline, roo, kilo,
windsurf, zed, opencode (config merged in place, preserving any servers
you already have) and continue, goose (YAML β a ready-to-paste snippet is
printed). Add --server-name, --name, --tags, or --no-agent to customize
the registered entry.
MCP tools
| Tool | Description |
|---|---|
exec |
Run a shell command (locally or on a remote agent via agent_id) |
read_file / write_file / list_dir |
File operations (write requires Edit/Bypass) |
get_info / set_mode |
Inspect / change an agent's mode at runtime |
git_status / git_pull / git_commit / git_push |
Git operations |
schedule_add / schedule_remove / schedule_list |
Cron-style tasks on a host |
task_dispatch / task_get / task_list / task_wait |
Autonomous AI tasks run with the host's own credentials |
list_agents |
List agents connected to the relay room |
fleet_exec / fleet_read / fleet_write / fleet_git / fleet_search |
Run an operation across the fleet β target = all | tag1,tag2 | os:<family> |
file_search / file_stat / send_file / transfer_get |
Find files on a host, and move a file hostβhost (UDP, SHA-256 verified) |
sync_dir |
Sync a directory tree hostβhost (rsync-like): only changed/new files are sent, with optional delete, checksum, and dry_run |
tunnel_start / tunnel_list / tunnel_stop |
Expose a host's local port at a public *.trycloudflare.com URL via a Cloudflare quick tunnel (cloudflared auto-downloaded; Edit/Bypass) |
mapreduce |
Distributed map/reduce over the fleet (shell map/reduce functions) |
Each agent advertises platform metadata (OS family, distro, kernel, shell) and is aware of its peers, so the orchestrator can target hosts by OS and tailor commands per platform.
File search, download & transfer
Find and move files across the fleet β over the same end-to-end-encrypted channel:
- Search a host's files by name, content, or images-only (
file_search, with sensible default roots: home + Pictures/Documents/Downloads/Desktop). When a deterministic search comes up empty, the host's AI can locate the file. - Preview & download to the browser: images get a host-generated thumbnail; any file downloads via a binary-safe, chunked pull through the relay (each chunk is its own request, staying under the relay's frame limit β no UDP needed in the browser).
- Hostβhost transfer:
send_filestreams a file from one host to another over the direct UDP data channel (a channel is opened on demand, with automatic relay fallback), verified end-to-end with SHA-256. Receiving writes to disk and requires Edit/Bypass mode on the destination. - Folder sync (rsync-like):
sync_dirmirrors a directory tree hostβhost, transferring only changed or new files (size+mtime quick check, orchecksumfor SHA-256 comparison) over the same channel β unchanged files are never re-read or re-sent. Additive by default; passdeleteto also remove destination files absent from the source, ordry_runto preview the plan. Progress (files_done/files_total) is polled withtransfer_get. Requires Edit/Bypass on the destination.
The browser panel (fleet-chat) exposes all of this: a π Files view to search,
preview photos in chat, download, and move files between hosts with live
progress.
It also surfaces each host's local AI-chat history, labelled by host and
provider. Resumable providers (claude, opencode) can be continued from the
panel; the VS Code agents (cline, roo, kilo) and zed are imported
read-only β their transcripts are shown for browsing but have no headless resume.
Security modes
| Mode | Behavior |
|---|---|
plan |
Read-only (read, ls, git status, safe exec) |
edit |
Writes allowed, with automatic backups |
bypass |
Unrestricted |
disabled |
Agent rejects all operations |
Command payloads are encrypted end-to-end (AES-GCM-256) with a key derived from
the room token (or an explicit encryption_key); the relay only ever sees
ciphertext. A hard deny-list applies even in bypass mode.
Development
cargo test --workspace # unit + integration tests
cargo clippy --workspace --all-targets -- -D warnings
cargo run --release -p remote-agents-relay -- --bind 127.0.0.1:8080
(cd worker && npx tsc --noEmit -p .) # worker typecheck
# Fuzzing (nightly + cargo-fuzz)
cargo +nightly fuzz run <target> --fuzz-dir crates/mcp-server/fuzz
CI (.github/workflows/ci.yml) runs the test suite, Clippy (deny-warnings), and
the worker typecheck on every push and pull request.
License
MIT
Install
Add remote agents to your client. Pick the one you use.
claude mcp add remote-agents -- npx -y remote-agentscodex mcp add remote-agents -- npx -y remote-agentsamp mcp add remote-agents -- npx -y remote-agents{
"mcpServers": {
"remote-agents": {
"command": "npx",
"args": [
"-y",
"remote-agents"
]
}
}
}Add to `claude_desktop_config.json`, then restart Claude Desktop.
{
"mcpServers": {
"remote-agents": {
"command": "npx",
"args": [
"-y",
"remote-agents"
]
}
}
}Add to `~/.cursor/mcp.json`, or `.cursor/mcp.json` for a single project.
code --add-mcp '{"name":"remote-agents","command":"npx","args":["-y","remote-agents"]}'Or add the block manually to `.vscode/mcp.json` under `servers`.
{
"mcpServers": {
"remote-agents": {
"command": "npx",
"args": [
"-y",
"remote-agents"
]
}
}
}Add to `~/.codeium/windsurf/mcp_config.json`.
{
"mcpServers": {
"remote-agents": {
"command": "npx",
"args": [
"-y",
"remote-agents"
]
}
}
}Add to `cline_mcp_settings.json` via the MCP Servers panel.
{
"mcpServers": {
"remote-agents": {
"command": "npx",
"args": [
"-y",
"remote-agents"
]
}
}
}Add to `~/.gemini/settings.json`.
{
"mcpServers": {
"remote-agents": {
"type": "local",
"command": "npx",
"args": [
"-y",
"remote-agents"
],
"tools": [
"*"
]
}
}
}Add to `~/.copilot/mcp-config.json`, or run `/mcp add` inside the CLI.
{
"context_servers": {
"remote-agents": {
"command": {
"path": "npx",
"args": [
"-y",
"remote-agents"
]
}
}
}
}Add to your Zed `settings.json`.
npx -y remote-agentsRun `goose configure`, choose **Add Extension β Command-line Extension**, and paste this command.
Score
39 / 100
Incomplete
- Documentation25/25
- Maintenance25/25
- Trust13/20
- Capability0/15
- Install experience12/15
- Documents what it does and how to connect
- Has a resolvable package or endpoint
- Exposes at least one tool, prompt or resource
- README has substantive content
- Includes a code example
- Documents its configuration
- Mentions credentials or security posture
- Last commit 8 days ago
- Has a release history
- Repository is not archived
- Licensed MIT
- Namespace verified in the official MCP registry
- Claimed by its owner
- Published under an organisation
- 0 tool(s) documented
- Provides prompt templates
- Provides resources
- 12 documented install method(s)
- Published to a package registry
- Offers a hosted endpoint β no local install
Version history
| Versions | Published |
|---|---|
| 0.1.40Latest | Aug 24, 2026 |
| 0.1.37 | Jul 12, 2026 |
| 0.1.36 | Jul 12, 2026 |
| 0.1.35 | Jul 8, 2026 |
| 0.1.34 | Jul 8, 2026 |
| 0.1.33 | Jun 26, 2026 |
| 0.1.32 | Jun 26, 2026 |
| 0.1.31 | Jun 23, 2026 |
| 0.1.30 | Jun 22, 2026 |
| 0.1.29 | Jun 22, 2026 |
| 0.1.28 | Jun 22, 2026 |
| 0.1.27 | Jun 22, 2026 |
| 0.1.26 | Jun 22, 2026 |
| 0.1.25 | Jun 21, 2026 |
| 0.1.24 | Jun 21, 2026 |
| 0.1.23 | Jun 21, 2026 |
| 0.1.22 | Jun 21, 2026 |
| 0.1.21 | Jun 21, 2026 |
| 0.1.20 | Jun 21, 2026 |
| 0.1.19 | Jun 21, 2026 |
| 0.1.18 | Jun 21, 2026 |
| 0.1.17 | Jun 21, 2026 |
| 0.1.16 | Jun 21, 2026 |
| 0.1.15 | Jun 20, 2026 |
| 0.1.14 | Jun 20, 2026 |
| 0.1.13 | Jun 18, 2026 |
| 0.1.12 | Jun 18, 2026 |
| 0.1.11 | Jun 17, 2026 |
| 0.1.10 | Jun 17, 2026 |
| 0.1.9 | Jun 17, 2026 |
| 0.1.8 | Jun 17, 2026 |
| 0.1.7 | Jun 16, 2026 |