clawmatrix 0.2.9 → 0.3.1

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/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Ruiming Zhuang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Note: The contents of `contrib/ios-node/` and `contrib/mac-app/` are licensed
26
+ separately under the Business Source License 1.1 (BSL-1.1). See the LICENSE
27
+ files in those directories for details.
package/README.md CHANGED
@@ -2,19 +2,31 @@
2
2
 
3
3
  # ClawMatrix
4
4
 
5
- A decentralized mesh cluster plugin that connects multiple [OpenClaw](https://github.com/nicepkg/openclaw) Gateways into a peer-to-peer network, sharing Agents, models, tools, and optionally workspace knowledge files across nodes.
5
+ A decentralized mesh cluster plugin that connects multiple [OpenClaw](https://github.com/nicepkg/openclaw) Gateways into a peer-to-peer network, sharing Agents, models, tools, files, and workspace knowledge across nodes.
6
6
 
7
7
  > **Warning**: This project is under active development and testing. APIs and protocols may change without notice. Not recommended for production use.
8
8
 
9
9
  ## Features
10
10
 
11
+ **Model Proxy** — No API key on your home node? Use LLMs from intranet nodes through the cluster, as if they were local models. Supports both Chat Completions and Responses API with auto-detection.
12
+
13
+ **Task Handoff** — Need intranet resources? Delegate tasks to remote Agents with repository access and stream results back. Supports input continuation for mid-task prompts and automatic failover.
14
+
15
+ **Tool Proxy** — Want to run a command or read a file on a remote node? Call it directly without delegating the entire task. Supports batch invocations in a single round-trip.
16
+
17
+ **ACP Agent Proxy** — Spawn remote coding agents (Claude Code, Codex, Gemini) on other nodes via ACP protocol with persistent sessions.
18
+
19
+ **Interactive Terminal** — Open a PTY session on any remote node for interactive shell access.
20
+
21
+ **File Transfer** — Transfer files up to 100MB between nodes with chunked transfer and SHA-256 integrity check.
22
+
11
23
  **Knowledge Sync (optional)** — Synchronize workspace files such as `MEMORY.md`, `memory/*.md`, `skills/`, and other selected knowledge files across nodes using CRDT + mesh sync, with git-friendly local files as the source of truth.
12
24
 
13
- **Model Proxy** — No API key on your home node? Use LLMs from intranet nodes through the cluster, as if they were local models.
25
+ **Sentinel** — A detached subprocess that survives OpenClaw crashes, maintains peer connections, and handles diagnostic commands when the gateway is down.
14
26
 
15
- **Task Handoff** — Need intranet resources? Delegate tasks to remote Agents with repository access and stream results back.
27
+ **Peer Approval** — Control which nodes can join your mesh with notify or required approval modes. Enabled by default.
16
28
 
17
- **Tool Proxy** — Want to run a command or read a file on a remote node? Call it directly without delegating the entire task.
29
+ **E2EE** — X25519 ECDH end-to-end encryption for all post-handshake frames, enabled by default.
18
30
 
19
31
  **Auto-Discovery & Failover** — Gossip protocol automatically discovers nodes; requests are rerouted to backups when a node goes down.
20
32
 
@@ -79,13 +91,15 @@ Edit `openclaw.json` to add the plugin configuration. All nodes share the same `
79
91
  "secret": "your-shared-secret-min-16-chars",
80
92
  "peers": [{ "nodeId": "cloud-01", "url": "wss://cloud-01.example.com:19000" }],
81
93
  "agents": [{ "id": "assistant", "description": "Personal assistant", "tags": ["general"] }],
82
- "proxyModels": [{ "id": "claude-sonnet", "nodeId": "office-01" }]
94
+ "proxyModels": [
95
+ { "nodeId": "office-01", "models": [{ "id": "claude-sonnet" }] }
96
+ ]
83
97
  }
84
98
  ```
85
99
 
86
100
  **Important**: Nodes sharing models only need to declare `{ id, provider }` in `models`. ClawMatrix automatically reads the corresponding `baseUrl` and `apiKey` from OpenClaw's `models.providers` and calls the model API directly (bypassing the OpenClaw Gateway's agent system).
87
101
 
88
- Nodes consuming remote models need to register them in `models.providers` (using the nodeId as the key, with baseUrl pointing to `http://127.0.0.1:19001`). See [BOOTSTRAP.md](BOOTSTRAP.md) for details.
102
+ Nodes consuming remote models need to register them in `models.providers` (using the nodeId as the key, with baseUrl pointing to the proxy port). See [BOOTSTRAP.md](BOOTSTRAP.md) for details.
89
103
 
90
104
  To use a cluster model: `/model <nodeId>/<modelId>`.
91
105
 
@@ -103,34 +117,128 @@ After installation, the Agent automatically gains access to the following tools:
103
117
  | Tool | Description |
104
118
  |------|-------------|
105
119
  | `cluster_handoff` | Delegate a task to a remote Agent and wait for the result |
120
+ | `cluster_handoff_reply` | Continue a handoff by sending additional input to the remote Agent |
106
121
  | `cluster_send` | Send a one-way message to a remote Agent |
107
122
  | `cluster_peers` | View cluster topology and connection status |
108
123
  | `cluster_exec` | Execute a command on a remote node |
109
124
  | `cluster_read` | Read a file on a remote node |
110
125
  | `cluster_write` | Write a file on a remote node |
126
+ | `cluster_edit` | Edit (find-and-replace) a file on a remote node |
127
+ | `cluster_batch` | Execute multiple tools on a remote node in one round-trip |
111
128
  | `cluster_tool` | Invoke any OpenClaw tool on a remote node |
129
+ | `cluster_terminal` | Open an interactive PTY session on a remote node |
130
+ | `cluster_transfer` | Transfer files between local and remote nodes (up to 100MB) |
131
+ | `cluster_events` | Query and consume cluster events |
132
+ | `cluster_diagnostic` | Diagnose or exec on a remote node's sentinel (works even when gateway is down) |
133
+ | `cluster_acp` | Spawn a remote coding agent (Claude Code, Codex, Gemini, etc.) via ACP |
112
134
 
113
135
  The target parameter supports nodeId (`"office-01"`) or tag queries (`"tags:coding"`).
114
136
 
115
137
  ## Configuration Reference
116
138
 
139
+ ### Core
140
+
117
141
  | Field | Type | Default | Description |
118
142
  |-------|------|---------|-------------|
119
143
  | `nodeId` | string | required | Unique node identifier |
120
144
  | `secret` | string | required | Cluster shared secret (>= 16 characters) |
121
145
  | `listen` | boolean | `false` | Accept inbound WS connections |
122
146
  | `listenHost` | string | `"0.0.0.0"` | Listen address |
123
- | `listenPort` | number | `19000` | Inbound WS port |
147
+ | `listenPort` | number | `0` (random) | Inbound WS port |
124
148
  | `peers` | array | `[]` | Peers to connect to: `{ nodeId, url }` |
125
149
  | `agents` | array | `[]` | Local Agents: `{ id, description, tags }` |
126
150
  | `models` | array | `[]` | Models shared with the cluster: `{ id, provider }` (auto-reads OpenClaw provider config; optional `baseUrl`/`apiKey` override) |
127
- | `proxyModels` | array | `[]` | Remote models to consume: `{ id, nodeId? }` |
128
- | `tags` | array | `[]` | Free-form tags |
129
- | `proxyPort` | number | `19001` | Local model proxy port |
151
+ | `proxyModels` | array | `[]` | Remote model groups to consume: `{ nodeId, models: [{ id }] }` |
152
+ | `tags` | array | `[]` | Free-form node tags |
153
+ | `proxyPort` | number | `0` (random) | Local model proxy port |
154
+ | `e2ee` | boolean | `true` | End-to-end encryption (X25519 ECDH) |
155
+ | `compression` | boolean | `false` | Message compression |
156
+
157
+ ### Timeouts
158
+
159
+ | Field | Type | Default | Description |
160
+ |-------|------|---------|-------------|
130
161
  | `handoffTimeout` | number | `600000` | Handoff timeout (ms) |
162
+ | `modelTimeout` | number | `120000` | Model proxy request timeout (ms) |
163
+ | `toolTimeout` | number | `30000` | Tool execution timeout (ms) |
164
+ | `disconnectGrace` | number | `30000` | Grace period before broadcasting peer_leave (ms) |
165
+
166
+ ### Tool Proxy
167
+
168
+ | Field | Type | Default | Description |
169
+ |-------|------|---------|-------------|
131
170
  | `toolProxy.enabled` | boolean | `false` | Allow remote tool execution |
132
- | `toolProxy.allow` | array | `[]` | Allowed tool names; `["*"]` or `[]` means all. `exec`/`read`/`write`/`edit` run locally, others go through Gateway |
171
+ | `toolProxy.allow` | array | `[]` | Allowed tool names; `["*"]` or `[]` means all |
133
172
  | `toolProxy.deny` | array | `[]` | Denied tools (takes precedence over allow) |
173
+ | `toolProxy.maxOutputBytes` | number | `1048576` | Max tool output size (bytes) |
174
+
175
+ ### Peer Approval
176
+
177
+ Peer approval accepts either a boolean shorthand or an object. The default is `true` (required mode enabled).
178
+
179
+ | Field | Type | Default | Description |
180
+ |-------|------|---------|-------------|
181
+ | `peerApproval` | boolean \| object | `true` | `true` = required mode, `false` = disabled, or object for fine-grained config |
182
+ | `peerApproval.enabled` | boolean | `false` | Enable peer approval (object form) |
183
+ | `peerApproval.mode` | string | `"notify"` | `"notify"` (log only) or `"required"` (block until approved) |
184
+ | `peerApproval.timeout` | number | `1200000` | Approval request timeout (ms) |
185
+ | `peerApproval.allowList` | array | `[]` | NodeIds that skip approval |
186
+ | `peerApproval.persistPath` | string | `"approved-peers.json"` | Path to store approved peers |
187
+ | `peerApproval.notifyTargets` | array | `[]` | Notification targets: `{ channel, to, accountId?, threadId? }` |
188
+
189
+ ### Terminal
190
+
191
+ | Field | Type | Default | Description |
192
+ |-------|------|---------|-------------|
193
+ | `terminal.enabled` | boolean | `true` | Allow remote PTY sessions |
194
+ | `terminal.shell` | string | system default | Shell to use |
195
+ | `terminal.sessionTTL` | number | `1800000` | Idle session timeout (ms) |
196
+ | `terminal.maxSessions` | number | `3` | Max concurrent PTY sessions |
197
+ | `terminal.allowFrom` | array | `[]` | Allowed nodeIds (empty = all) |
198
+
199
+ ### File Transfer
200
+
201
+ | Field | Type | Default | Description |
202
+ |-------|------|---------|-------------|
203
+ | `fileTransfer.enabled` | boolean | `false` | Allow file transfers |
204
+ | `fileTransfer.chunkSize` | number | `262144` | Chunk size in bytes (256KB) |
205
+ | `fileTransfer.maxFileSize` | number | `104857600` | Max file size (100MB) |
206
+ | `fileTransfer.timeout` | number | `300000` | Per-chunk timeout (ms) |
207
+ | `fileTransfer.allowedPaths` | array | `[]` | Allowed paths (empty = no restriction) |
208
+
209
+ ### Knowledge Sync
210
+
211
+ | Field | Type | Default | Description |
212
+ |-------|------|---------|-------------|
213
+ | `knowledge.enabled` | boolean | `false` | Enable CRDT knowledge sync |
214
+ | `knowledge.paths` | array | `[]` | File/glob patterns to sync |
215
+ | `knowledge.debounce` | number | `5000` | File watch debounce (ms) |
216
+ | `knowledge.maxFileSize` | number | `524288` | Max file size to sync (bytes) |
217
+
218
+ ### ACP Agents
219
+
220
+ | Field | Type | Default | Description |
221
+ |-------|------|---------|-------------|
222
+ | `acp.enabled` | boolean | `false` | Enable ACP agent proxy |
223
+ | `acp.agents` | array | `[]` | Available agents: `{ id, description }` |
224
+ | `acp.commands` | object | `{}` | Override spawn commands per agent name |
225
+ | `acp.timeout` | number | `600000` | Per-turn timeout (ms) |
226
+ | `acp.sessionTTL` | number | `1800000` | Idle session TTL (ms) |
227
+ | `acp.maxSessions` | number | `5` | Max concurrent ACP sessions |
228
+
229
+ ### Sentinel
230
+
231
+ | Field | Type | Default | Description |
232
+ |-------|------|---------|-------------|
233
+ | `sentinel.enabled` | boolean | `true` | Enable sentinel subprocess |
234
+ | `sentinel.listenPort` | number | same as `listenPort` | Port sentinel listens on (takes over when gateway dies) |
235
+
236
+ ### Web UI
237
+
238
+ | Field | Type | Default | Description |
239
+ |-------|------|---------|-------------|
240
+ | `web.enabled` | boolean | `false` | Enable HTTP web interface |
241
+ | `web.token` | string | required if enabled | Auth token (>= 8 characters) |
134
242
 
135
243
  ## Architecture
136
244
 
@@ -149,9 +257,12 @@ The target parameter supports nodeId (`"office-01"`) or tag queries (`"tags:codi
149
257
  ```
150
258
 
151
259
  - Decentralized mesh — no leader, no consensus protocol
152
- - HMAC-SHA256 challenge-response authentication
260
+ - X25519 TOFU identity + HMAC-SHA256 challenge-response authentication
261
+ - End-to-end encryption via X25519 ECDH (enabled by default)
153
262
  - Message relay + TTL loop prevention + ID deduplication
263
+ - Per-IP rate limiting on inbound connections
154
264
  - Heartbeat detection + exponential backoff reconnection + automatic failover
265
+ - Sentinel survives gateway crashes and takes over the listen port
155
266
  - `wss://` (TLS) recommended for production
156
267
 
157
268
  ## Development
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmatrix",
3
- "version": "0.2.9",
3
+ "version": "0.3.1",
4
4
  "description": "Decentralized mesh cluster plugin for OpenClaw — inter-gateway communication, model proxy, task handoff, and tool proxy.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "scripts": {
30
30
  "test": "bun test",
31
+ "coverage": "bun test --coverage",
31
32
  "release": "bunx bumpp"
32
33
  },
33
34
  "dependencies": {