remote-agents 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +250 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,24 +1,187 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Remote Agents
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
[](https://github.com/47-ronn/tunshell_mcp_agents/actions/workflows/ci.yml)
|
|
4
|
+
[](LICENSE)
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
A unified, [MCP](https://modelcontextprotocol.io)-compatible system for
|
|
7
|
+
controlling fleets of remote machines through AI agents (Claude, opencode).
|
|
8
|
+
Agents connect outbound to a relay; an MCP server lets the AI run commands,
|
|
9
|
+
manage files, drive git, schedule tasks, and orchestrate the whole fleet — all
|
|
10
|
+
over end-to-end-encrypted channels.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Single Rust binary** (`remote-agent`) — runs as an agent daemon (`run`), an
|
|
15
|
+
MCP stdio server (`mcp`), or installs itself as a service (`install`).
|
|
16
|
+
- **End-to-end encryption** (AES-GCM-256) on by default; the relay forwards only
|
|
17
|
+
ciphertext.
|
|
18
|
+
- **Safety modes** per host — `plan` (read-only), `edit` (writes with backups),
|
|
19
|
+
`bypass`, `disabled` — with path/command allow- & deny-lists.
|
|
20
|
+
- **Fleet as one computer** — run any operation (`exec`/`read`/`write`/`git`)
|
|
21
|
+
across all agents, by tags, or by OS family; results aggregated per host.
|
|
22
|
+
- **Distributed MapReduce** — partition data across the fleet, map with a shell
|
|
23
|
+
command, reduce the outputs, with per-partition retry.
|
|
24
|
+
- **Autonomous mode** — delegate AI tasks to a host that runs them with its own
|
|
25
|
+
credentials (token-saving orchestration).
|
|
26
|
+
- **Two interchangeable relays** — Cloudflare Workers (Durable Objects) or a
|
|
27
|
+
self-hosted Rust WebSocket relay; switch by changing `relay_url`.
|
|
28
|
+
- **Direct UDP data channel** with hole-punching and WebSocket fallback.
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
34
|
+
│ opencode / Claude Desktop │
|
|
35
|
+
│ remote-agent mcp (Rust binary, MCP stdio server) │
|
|
36
|
+
└───────────────────────────────┬──────────────────────────────┘
|
|
37
|
+
│ wss:// (CF Worker or self-hosted relay)
|
|
38
|
+
▼
|
|
39
|
+
┌───────────────────────────────────┐
|
|
40
|
+
│ Relay (rooms route by token) │
|
|
41
|
+
└───────────────────────────────────┘
|
|
42
|
+
▲ ▲ ▲
|
|
43
|
+
│ wss │ wss │ wss
|
|
44
|
+
┌──────┴─────┐ ┌──────┴─────┐ ┌──────┴─────┐
|
|
45
|
+
│ Agent │ │ Agent │ │ Agent │
|
|
46
|
+
│ (daemon) │ │ (daemon) │ │ (daemon) │
|
|
47
|
+
└────────────┘ └────────────┘ └────────────┘
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Workspace layout
|
|
51
|
+
|
|
52
|
+
| Crate / dir | Purpose |
|
|
53
|
+
|------------------------|-----------------------------------------------------------|
|
|
54
|
+
| `crates/shared` | Wire protocol, AES-GCM crypto, UDP channel types |
|
|
55
|
+
| `crates/mcp-server` | The `remote-agent` binary: agent, MCP server, executors |
|
|
56
|
+
| `crates/relay` | Self-hosted Rust WebSocket relay (`remote-agents-relay`) |
|
|
57
|
+
| `worker/` | Cloudflare Worker relay (Durable Objects) |
|
|
8
58
|
|
|
9
59
|
## Install
|
|
10
60
|
|
|
11
61
|
```bash
|
|
62
|
+
# Via npm (downloads the prebuilt binary for your platform)
|
|
63
|
+
npm install -g remote-agents # then: remote-agents --help
|
|
64
|
+
# or run on demand:
|
|
65
|
+
npx remote-agents mcp --help
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# From source
|
|
70
|
+
cargo build --release --workspace
|
|
71
|
+
cargo install --path crates/mcp-server # → ~/.cargo/bin/remote-agent
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Prebuilt binaries for macOS / Linux / Windows are also attached to each GitHub
|
|
75
|
+
release.
|
|
76
|
+
|
|
77
|
+
## Running: one binary, two ways
|
|
78
|
+
|
|
79
|
+
`remote-agents` is **one binary** that behaves the same whether you launch it
|
|
80
|
+
directly with flags or an AI host (opencode / Claude) starts it as an MCP
|
|
81
|
+
server. Connection settings resolve identically in both cases:
|
|
82
|
+
**CLI flag > `REMOTE_AGENTS_*` env var > `config.toml` > default**.
|
|
83
|
+
|
|
84
|
+
It is a flat **peer network** — there are no controller/agent roles. Every node
|
|
85
|
+
joins a relay room as an equal peer: visible to all, able to dispatch work, and
|
|
86
|
+
(unless `--no-agent`) able to execute commands from others.
|
|
87
|
+
|
|
88
|
+
| Mode | Command | The node… |
|
|
89
|
+
|------|---------|-----------|
|
|
90
|
+
| `run` | `remote-agents run …` | is a headless full peer (executes + dispatches), no local AI |
|
|
91
|
+
| `mcp` | `remote-agents mcp …` | is a full peer **plus** an MCP server for a local AI (opencode / Claude) |
|
|
92
|
+
| `hybrid` | `remote-agents hybrid …` | alias for `mcp` (kept for compatibility) |
|
|
93
|
+
|
|
94
|
+
Every mode is a **full peer that accepts commands by default**. Add `--no-agent`
|
|
95
|
+
to make a node **send-only** (stays visible and dispatches work, but never runs
|
|
96
|
+
others' commands — for prod controllers or browser dashboards). `--no-agent`
|
|
97
|
+
also works in an MCP `env` block as `REMOTE_AGENTS_*` config.
|
|
98
|
+
|
|
99
|
+
Common flags: `--relay <wss://host>` `--room <name>` `--token <secret>`
|
|
100
|
+
`--name <id>` `--tags a,b` `--no-agent`.
|
|
101
|
+
|
|
102
|
+
### Keeping a host always online
|
|
103
|
+
|
|
104
|
+
A `mcp` node lives only as long as the AI host (opencode / Claude) keeps it
|
|
105
|
+
running — close the session and the node leaves the room. For a host that should
|
|
106
|
+
stay in the fleet **24/7, independent of any AI session**, install it as a
|
|
107
|
+
background service running `run`:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
remote-agents install --room dev --token <secret> --relay wss://<your-relay-host>
|
|
111
|
+
# systemd user service (Linux) / launchd LaunchAgent (macOS); auto-starts,
|
|
112
|
+
# survives logout/reboot, auto-restarts. Remove with: remote-agents uninstall
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
A machine has **one persistent identity** (`agent-id`), and the relay keys peers
|
|
116
|
+
by id, so don't run both a `run` service and an `mcp` session on the same machine
|
|
117
|
+
with the same id — they'd evict each other. Typical topology: target hosts run
|
|
118
|
+
the `run` service (always online); the workstation that drives the fleet runs
|
|
119
|
+
`mcp` per session.
|
|
120
|
+
|
|
121
|
+
## Quick start
|
|
122
|
+
|
|
123
|
+
### 1. Run an agent on a remote host (with flags)
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Install once (downloads the prebuilt binary for your platform):
|
|
12
127
|
npm install -g remote-agents
|
|
13
|
-
|
|
14
|
-
|
|
128
|
+
|
|
129
|
+
# Run as a peer agent:
|
|
130
|
+
remote-agents run --relay wss://<your-relay-host> --room dev --token <secret> \
|
|
131
|
+
--name web-1 --tags backend
|
|
132
|
+
|
|
133
|
+
# ...or install it as an auto-starting user service (systemd / launchd):
|
|
134
|
+
remote-agents install --room dev --token <secret> --relay wss://<your-relay-host>
|
|
15
135
|
```
|
|
16
136
|
|
|
17
|
-
|
|
137
|
+
### 2. Choose a relay
|
|
18
138
|
|
|
19
|
-
|
|
139
|
+
**Self-hosted (Rust):**
|
|
20
140
|
|
|
21
|
-
```
|
|
141
|
+
```bash
|
|
142
|
+
remote-agents-relay --bind 0.0.0.0:8080
|
|
143
|
+
# agents/MCP then use relay_url = ws://<host>:8080
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Cloudflare Worker:**
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
cd worker
|
|
150
|
+
npm install
|
|
151
|
+
CLOUDFLARE_API_TOKEN=<token> npx wrangler deploy
|
|
152
|
+
# → wss://<your-worker-subdomain>.workers.dev
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 3. Install as an MCP server for Claude Desktop / opencode
|
|
156
|
+
|
|
157
|
+
After `npm install -g remote-agents`, point your AI host at the same binary in
|
|
158
|
+
`mcp` mode (stdio). The machine joins the room as a full peer (executes commands
|
|
159
|
+
from others) — add `"--no-agent"` to the args if it should be a send-only
|
|
160
|
+
controller instead:
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"mcpServers": {
|
|
165
|
+
"remote-agents": {
|
|
166
|
+
"command": "remote-agents",
|
|
167
|
+
"args": [
|
|
168
|
+
"mcp",
|
|
169
|
+
"--relay", "wss://<your-relay-host>",
|
|
170
|
+
"--room", "myroom",
|
|
171
|
+
"--token", "<secret>"
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
(opencode uses the same shape under its own `mcp` config key — see
|
|
179
|
+
`~/.config/opencode/opencode.json`.)
|
|
180
|
+
|
|
181
|
+
Connection settings are resolved as **CLI flag > env var > `config.toml` >
|
|
182
|
+
default**, so you can instead supply them via `env` in the MCP config:
|
|
183
|
+
|
|
184
|
+
```json
|
|
22
185
|
{
|
|
23
186
|
"mcpServers": {
|
|
24
187
|
"remote-agents": {
|
|
@@ -34,38 +197,100 @@ Supported platforms: linux x64/arm64, macOS x64/arm64, windows x64.
|
|
|
34
197
|
}
|
|
35
198
|
```
|
|
36
199
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
for the full documentation.
|
|
200
|
+
Without any relay/room/token the server runs locally only (no remote agent
|
|
201
|
+
control); nothing points at a hosted endpoint by default.
|
|
40
202
|
|
|
41
|
-
|
|
203
|
+
### One-command client registration
|
|
42
204
|
|
|
43
|
-
|
|
44
|
-
|
|
205
|
+
Instead of hand-editing each agent's config, let the binary write it. The
|
|
206
|
+
connection flags are baked into the registered server's args:
|
|
45
207
|
|
|
46
208
|
```bash
|
|
47
209
|
remote-agents install-mcp --client cursor \
|
|
48
210
|
--relay wss://<your-relay-host> --room myroom --token <secret>
|
|
211
|
+
# ✓ Registered MCP server 'remote-agents' for Cursor (created ~/.cursor/mcp.json)
|
|
49
212
|
|
|
50
213
|
remote-agents install-mcp # no --client: list supported clients
|
|
51
214
|
```
|
|
52
215
|
|
|
53
216
|
Supported: `claude-desktop`, `claude-code`, `cursor`, `cline`, `roo`, `kilo`,
|
|
54
|
-
`windsurf`, `zed`, `opencode` (config merged in place, preserving
|
|
55
|
-
|
|
217
|
+
`windsurf`, `zed`, `opencode` (config merged in place, preserving any servers
|
|
218
|
+
you already have) and `continue`, `goose` (YAML — a ready-to-paste snippet is
|
|
219
|
+
printed). Add `--server-name`, `--name`, `--tags`, or `--no-agent` to customize
|
|
220
|
+
the registered entry.
|
|
221
|
+
|
|
222
|
+
## MCP tools
|
|
223
|
+
|
|
224
|
+
| Tool | Description |
|
|
225
|
+
|------|-------------|
|
|
226
|
+
| `exec` | Run a shell command (locally or on a remote agent via `agent_id`) |
|
|
227
|
+
| `read_file` / `write_file` / `list_dir` | File operations (write requires Edit/Bypass) |
|
|
228
|
+
| `get_info` / `set_mode` | Inspect / change an agent's mode at runtime |
|
|
229
|
+
| `git_status` / `git_pull` / `git_commit` / `git_push` | Git operations |
|
|
230
|
+
| `schedule_add` / `schedule_remove` / `schedule_list` | Cron-style tasks on a host |
|
|
231
|
+
| `task_dispatch` / `task_get` / `task_list` / `task_wait` | Autonomous AI tasks run with the host's own credentials |
|
|
232
|
+
| `list_agents` | List agents connected to the relay room |
|
|
233
|
+
| `fleet_exec` / `fleet_read` / `fleet_write` / `fleet_git` / `fleet_search` | Run an operation across the fleet — `target = all \| tag1,tag2 \| os:<family>` |
|
|
234
|
+
| `file_search` / `file_stat` / `send_file` / `transfer_get` | Find files on a host, and move a file host→host (UDP, SHA-256 verified) |
|
|
235
|
+
| `mapreduce` | Distributed map/reduce over the fleet (shell map/reduce functions) |
|
|
236
|
+
|
|
237
|
+
Each agent advertises platform metadata (OS family, distro, kernel, shell) and
|
|
238
|
+
is aware of its peers, so the orchestrator can target hosts by OS and tailor
|
|
239
|
+
commands per platform.
|
|
240
|
+
|
|
241
|
+
## File search, download & transfer
|
|
56
242
|
|
|
57
|
-
|
|
243
|
+
Find and move files across the fleet — over the same end-to-end-encrypted
|
|
244
|
+
channel:
|
|
58
245
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
246
|
+
- **Search** a host's files by name, content, or images-only (`file_search`,
|
|
247
|
+
with sensible default roots: home + Pictures/Documents/Downloads/Desktop). When
|
|
248
|
+
a deterministic search comes up empty, the host's AI can locate the file.
|
|
249
|
+
- **Preview & download** to the browser: images get a host-generated thumbnail;
|
|
250
|
+
any file downloads via a **binary-safe, chunked pull** through the relay (each
|
|
251
|
+
chunk is its own request, staying under the relay's frame limit — no UDP needed
|
|
252
|
+
in the browser).
|
|
253
|
+
- **Host↔host transfer**: `send_file` streams a file from one host to another
|
|
254
|
+
over the **direct UDP data channel** (a channel is opened on demand, with
|
|
255
|
+
automatic relay fallback), verified end-to-end with SHA-256. Receiving writes
|
|
256
|
+
to disk and requires Edit/Bypass mode on the destination.
|
|
257
|
+
|
|
258
|
+
The browser panel (`fleet-chat`) exposes all of this: a 📁 Files view to search,
|
|
259
|
+
preview photos in chat, download, and move files between hosts with live
|
|
260
|
+
progress.
|
|
261
|
+
|
|
262
|
+
It also surfaces each host's **local AI-chat history**, labelled by host and
|
|
263
|
+
provider. Resumable providers (`claude`, `opencode`) can be continued from the
|
|
264
|
+
panel; the VS Code agents (`cline`, `roo`, `kilo`) and `zed` are imported
|
|
265
|
+
read-only — their transcripts are shown for browsing but have no headless resume.
|
|
266
|
+
|
|
267
|
+
## Security modes
|
|
268
|
+
|
|
269
|
+
| Mode | Behavior |
|
|
270
|
+
|------|----------|
|
|
271
|
+
| `plan` | Read-only (read, ls, git status, safe exec) |
|
|
272
|
+
| `edit` | Writes allowed, with automatic backups |
|
|
273
|
+
| `bypass` | Unrestricted |
|
|
274
|
+
| `disabled` | Agent rejects all operations |
|
|
275
|
+
|
|
276
|
+
Command payloads are encrypted end-to-end (AES-GCM-256) with a key derived from
|
|
277
|
+
the room token (or an explicit `encryption_key`); the relay only ever sees
|
|
278
|
+
ciphertext. A hard deny-list applies even in `bypass` mode.
|
|
279
|
+
|
|
280
|
+
## Development
|
|
63
281
|
|
|
64
282
|
```bash
|
|
65
|
-
|
|
283
|
+
cargo test --workspace # unit + integration tests
|
|
284
|
+
cargo clippy --workspace --all-targets -- -D warnings
|
|
285
|
+
cargo run --release -p remote-agents-relay -- --bind 127.0.0.1:8080
|
|
286
|
+
(cd worker && npx tsc --noEmit -p .) # worker typecheck
|
|
287
|
+
|
|
288
|
+
# Fuzzing (nightly + cargo-fuzz)
|
|
289
|
+
cargo +nightly fuzz run <target> --fuzz-dir crates/mcp-server/fuzz
|
|
66
290
|
```
|
|
67
291
|
|
|
68
|
-
|
|
292
|
+
CI (`.github/workflows/ci.yml`) runs the test suite, Clippy (deny-warnings), and
|
|
293
|
+
the worker typecheck on every push and pull request.
|
|
69
294
|
|
|
70
295
|
## License
|
|
71
296
|
|
package/package.json
CHANGED