clawmacdo 0.49.0 → 0.51.0

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.
Files changed (2) hide show
  1. package/README.md +193 -322
  2. package/package.json +4 -4
package/README.md CHANGED
@@ -5,164 +5,17 @@
5
5
 
6
6
  Rust CLI tool for deploying [OpenClaw](https://openclaw.ai) to **DigitalOcean**, **AWS Lightsail**, **Tencent Cloud**, **Microsoft Azure**, or **BytePlus Cloud** — with Claude Code, Codex, and Gemini CLI pre-installed.
7
7
 
8
- ## ✨ What's New in v0.49.0
9
-
10
- - **`skill-remove` subcommand** — delete a deployed skill by name from an instance's workspace and restart the gateway (`--instance` + `--skill`)
11
- - **`skill-list` subcommand** — list all skill directories on an instance with their gateway-registered name and readiness status
12
- - **`skill-check-perms` subcommand** — audit file ownership and permissions for a deployed skill; add `--fix` to auto-correct to `openclaw:openclaw` / `644`/`755`
13
-
14
- ## What's New in v0.49.0
15
-
16
- - **`skill-diff` subcommand** — compare a local skill directory against the deployed skill on an instance; reports files that are in-sync (✓), modified (≠), new locally (+), or only on instance (−); also shows gateway skill status
17
-
18
- ## What's New in v0.46.4
19
-
20
- - **`cron-message` subcommand** — schedule a recurring message to the OpenClaw gateway agent; the agent processes it and delivers the response to Telegram, WhatsApp, or any other connected channel (uses `openclaw cron add` under the hood)
21
- - **`cron-tool` subcommand** — schedule recurring tool execution on a deployed instance; the agent runs the named tool and announces the result to the chosen channel
22
- - **`cron-list` subcommand** — list all cron jobs on a deployed instance
23
- - **`cron-remove` subcommand** — remove a cron job by name from a deployed instance
24
- - **`skill-deploy` subcommand** — upload a `.zip` of OpenClaw skills to a deployed instance; extracts into `~/.openclaw/workspace/skills/` and restarts the gateway automatically
25
-
26
- ## What's New in v0.38.0
27
-
28
- - **No spurious CLI warnings on non-deploy commands** — `telegram-setup`, `telegram-pair`, and other SSH-only commands no longer print "Azure/AWS CLI not found" at startup; provider CLI checks now run only when deploying to that provider
29
- - **`telegram-setup` `gateway.env` fix** — bot token is now written to both `.env` and `gateway.env`; the systemd gateway service loads `gateway.env` via `EnvironmentFile`, so previously a re-run with a new token left the running service polling with the old bot
30
- - **`telegram-setup` resets pairing state** — clears previous bot's pairing credentials and update offsets before reconfiguring, giving users a clean pairing flow with the new bot
31
-
32
- ## What's New in v0.46.4
33
-
34
- - **SSH performance** — `telegram-setup` and `whatsapp-setup` reuse a single SSH session for all 4 steps (one TCP connect + handshake instead of four); cipher negotiation now prefers faster AEAD ciphers (`chacha20-poly1305`, `aes128-gcm`); ephemeral deploy keys use RSA-2048 instead of RSA-4096 (~4× faster key generation); `wait_for_ssh` no longer probes wrong users on Lightsail (`ubuntu`) and Azure (`azureuser`)
35
- - **Telegram/WhatsApp Lightsail fix** — `telegram-setup`, `telegram-pair`, `whatsapp-setup`, and `whatsapp-qr` now SSH as `ubuntu` (not `root`) on Lightsail instances
36
- - **`update-model` subcommand** — change the AI model on a running OpenClaw instance without redeploying (updates API keys, provider config, model settings, and restarts the gateway)
37
- - **`update-ip` subcommand** — refresh the IP address of a deployed instance from the cloud provider API (Lightsail, DigitalOcean, BytePlus) and update both JSON deploy record and SQLite
38
- - **Refresh IP button** — new "Refresh IP" button in Deployments tab queries the cloud provider and updates the IP in-place
39
- - **Deployments action dropdown** — deployment row actions now open in a stacked menu so controls stay readable instead of overlapping in narrow tables
40
- - **Deployments table fit** — deployments table now uses a tighter fixed layout with wrapped cell content to avoid left-right scrolling in the tab
41
- - **Funnel actions in dropdown** — the Deployments tab now handles the two-step funnel flow from the Actions menu: first toggle funnel on/off, then open the funnel URL once it becomes available
42
- - **Snapshot/restore progress tracking** — snapshot and restore operations are now async with step-by-step progress via SSE; the frontend can display real-time progress bars using `GET /api/deploy/{operation_id}/events`
43
- - **Deploy progress in Deployments tab** — running deployments show an animated progress bar with current step label, polling every 3 seconds
44
- - **Funnel verification** — toggling funnel ON now polls the funnel status with a progress bar before showing the Open button
45
- - **Docker fix: systemd user manager restart** — "Fix Agent Docker Access" now restarts the systemd user service manager so the gateway picks up the docker group
46
- - **`KillMode=control-group`** — gateway service now kills the entire cgroup on restart, preventing orphaned child processes from holding the port
47
- - **AWS credential passthrough** — web UI credentials are written to `~/.aws/credentials` so the AWS CLI uses them instead of stale local config
48
- - **Lightsail destroy with credentials** — destroy modal now prompts for AWS Access Key ID and Secret Access Key
49
- - **Lightsail snapshot listing** — credentials from the web UI are now passed through to the AWS CLI for snapshot listing
50
- - **`whatsapp-setup` subcommand** — set up WhatsApp on a deployed instance (set phone number, enable plugin, restart gateway, fetch pairing QR code)
51
- - **`whatsapp-qr` subcommand** — fetch the WhatsApp pairing QR code from a deployed instance (re-fetch if expired)
52
- - **`plugin-install` subcommand** — install OpenClaw plugins on deployed instances via `clawmacdo plugin-install --instance <id> --plugin @openguardrails/moltguard` (installs via pnpm, enables plugin, restarts gateway)
53
- - **Windows PowerShell scripts** — all shell scripts now have `.ps1` equivalents for Windows support (`release.ps1`, `npm-package.ps1`, `npm-publish.ps1`, scan scripts, etc.)
54
- - **Agent Docker Access warning** — deploy form shows the common Docker socket permission error with a clear fix instruction
55
- - **Dual license** — switched from MIT to GPLv3 (open source) + Commercial (proprietary) dual license model
56
-
57
- ### Previous highlights (v0.25.x – v0.26.x)
58
- - **`do-snapshot` subcommand** — create a named DigitalOcean snapshot from an existing droplet by ID, with optional `--power-off` flag for clean shutdown/snapshot/power-on cycle
59
- - **BytePlus EIP cost reduction** — switched from pay-by-bandwidth to pay-by-traffic billing, reduced default bandwidth from 10 Mbps to 5 Mbps
60
- - **BytePlus spot instances** — new `--spot` flag on deploy enables `SpotAsPriceGo` strategy for up to ~80% compute cost savings
61
- - **`bp-snapshot` / `bp-restore`** — snapshot and restore for BytePlus ECS instances
62
- - **`ls-snapshot` / `ls-restore`** — snapshot and restore for AWS Lightsail instances
63
- - **BytePlus EIP orphan cleanup** — destroy command now finds and releases unbound EIPs left behind after instance termination
64
-
65
- ### Previous highlights (v0.21.x – v0.23.x)
66
- - **`destroy` subcommand** — delete any openclaw instance across all 5 cloud providers with interactive confirmation
67
- - **`skills-data-api` service** — Node.js/Express API backed by MongoDB for browsing, scraping, and serving Claude Code skill marketplace data
68
- - **Playwright e2e test suite** — CSV-driven deploy form testing under `e2e/`, covering all 5 cloud providers with 30+ scenarios
69
-
70
- ### Previous highlights (v0.20.x)
71
- - **`do-restore` subcommand** — restore a DigitalOcean droplet from a snapshot by name, with standard `openclaw-{id}` naming and deploy record saved to both JSON and SQLite (visible in web UI Deployments tab)
72
-
73
- ### Previous highlights (v0.19.x)
74
- - **One-click Funnel access** — "Open" button in Deployments tab opens the Funnel webchat with gateway token pre-injected (no manual token paste or device pairing needed)
75
- - **Auto-disable device pairing for Funnel** — Funnel setup sets `dangerouslyDisableDeviceAuth: true` so browser connections via Tailscale Funnel skip the pairing screen
76
-
77
- ### Previous highlights (v0.18.x)
78
- - **Tailscale Funnel** — `tailscale-funnel` subcommand: install Tailscale, enable Funnel, configure `openclaw.json`, auto-approve devices, and print public webchat URL
79
- - **Funnel toggle** — `funnel-on` / `funnel-off` CLI commands and web UI Deployments tab toggle button
80
- - **Customer skill management** — `skill-upload`, `skill-download`, `skill-push` subcommands for per-deployment SKILL.md
81
-
82
- ### Previous highlights (v0.17.x)
83
- - **Web UI security hardening (CRIT-01)** — API key auth, 6-digit PIN login, CORS, rate limiting, localhost-only binding
84
- - **All 4 CRITICAL security findings resolved**
85
-
86
- ### Previous highlights (v0.14.x – v0.15.x)
87
- - **Windows builds fixed** — Dependencies correctly scoped, native MSVC builds
88
- - **`digitalocean` feature flag** — DigitalOcean provider now properly gated as a default feature
89
-
90
- ### Previous highlights (v0.13.x)
91
- - **`ark-api-key`** — Generate temporary BytePlus ARK API keys from access/secret credentials, or list endpoints with `--list`
92
- - **`ark-chat`** — Send prompts to BytePlus ARK models directly from the CLI
93
- - **`telegram-setup` / `telegram-pair` / `telegram-chat-id`** — Configure, pair, and inspect Telegram bots on deployed instances via SSH
94
- - **Web UI destroy** — Destroy cloud instances directly from the Deployments tab with provider-specific credential prompts
95
- - **Detach mode improvements** — Proper `setsid()` session detachment, stdout/stderr logging to file
96
- - **Workspace path fix** — Automatic `/root/` → `/home/openclaw/` path correction during provisioning
97
-
98
- ### Earlier highlights (v0.9.x – v0.12.x)
99
- - **BytePlus Cloud** — 5th cloud provider added (`--provider=byteplus` or `bp`)
100
- - **BytePlus ECS client** — HMAC-SHA256 signed REST API with auto-provisioning of VPC, subnet, and security group
101
- - **Preflight CLI checks** — Azure CLI and AWS CLI verified at startup, auto-installed if missing
102
- - **Full-width professional web UI** — layout widened to 1536px max, compact hero with inline mascot
103
- - **Deploy progress tracking** — All 16 deploy steps persisted to SQLite in real-time
104
- - **`clawmacdo track` command** — Query deploy progress by ID, hostname, or IP address
105
- - **Follow mode** (`--follow`) — Live-polling display that refreshes until deployment finishes
106
- - **5 cloud providers** — DigitalOcean, AWS Lightsail, Tencent Cloud, Microsoft Azure, BytePlus Cloud
107
- - **npm distribution** — `npm install -g clawmacdo`
108
-
109
- ## Security Hardening
110
-
111
- - Privileged remote provisioning commands now run through stdin-fed shells instead of nested quoted `sudo` / `su -c` wrappers.
112
- - User-supplied hostnames are normalized and validated before any deploy flow uses them.
113
- - The web UI now only accepts backup archives from `~/.clawmacdo/backups` and SSH keys from `~/.clawmacdo/keys`.
114
- - Backup restore validates the local `.tar.gz` before upload and extracts remotely with `--no-same-owner` and `--no-same-permissions` into a dedicated restore directory.
115
- - The gateway service now reads `~/.openclaw/gateway.env` instead of the broader `.env`, so setup-only secrets such as `ANTHROPIC_SETUP_TOKEN` are not inherited by the long-running service.
116
- - Direct Docker-group access for `openclaw` has been removed. If sandbox mode is requested during deploy, the deploy now forces sandbox mode off until a safer non-root mediation path exists.
117
- - Lightsail credentials are passed only to the child AWS CLI processes instead of mutating process-global environment variables or writing `~/.aws/credentials`.
118
- - Tencent's optional security-group helper now takes SSH ingress from `CLAWMACDO_TENCENT_SSH_CIDR` and defaults to `127.0.0.1/32` instead of opening SSH to the world.
119
-
120
- See [docs/HIGH_SECURITY_FIXES.md](docs/HIGH_SECURITY_FIXES.md) for the finding-by-finding code map, rationale, and functionality impact.
121
-
122
- ## 🏗️ Project Structure
123
-
124
- ```
125
- clawmacdo/
126
- ├── Cargo.toml # Workspace configuration
127
- ├── crates/ # All crates in workspace
128
- │ ├── clawmacdo-cli/ # 🖥️ Main CLI binary & command orchestration
129
- │ ├── clawmacdo-core/ # 🔧 Config, errors, shared types
130
- │ ├── clawmacdo-cloud/ # ☁️ Cloud provider implementations
131
- │ ├── clawmacdo-provision/# 🔨 Server provisioning & setup logic
132
- │ ├── clawmacdo-db/ # 💾 Database operations & storage
133
- │ ├── clawmacdo-ssh/ # 🔑 SSH/SCP operations & key management
134
- │ └── clawmacdo-ui/ # 🎨 Web UI, progress bars, user prompts
135
- ├── skills-data-api/ # 🧠 Node.js skills marketplace API (MongoDB)
136
- ├── e2e/ # 🧪 Playwright end-to-end test suite
137
- ├── assets/ # Static assets (mascot, etc.)
138
- └── docs/ # Design docs and usage reference
139
- ```
140
-
141
- ### 📦 Crate Overview
142
-
143
- | Crate | Purpose | Dependencies |
144
- |-------|---------|--------------|
145
- | **clawmacdo-cli** | Main binary, command parsing, orchestration | All other crates |
146
- | **clawmacdo-core** | Configuration, errors, shared types | Minimal (serde, anyhow) |
147
- | **clawmacdo-cloud** | DigitalOcean, AWS Lightsail, Tencent Cloud & BytePlus APIs | reqwest, async-trait |
148
- | **clawmacdo-provision** | Server setup, package installation | SSH, Core, UI |
149
- | **clawmacdo-db** | SQLite operations, job tracking | rusqlite |
150
- | **clawmacdo-ssh** | SSH connections, file transfers | ssh2 |
151
- | **clawmacdo-ui** | Progress bars, web interface | indicatif, axum |
152
-
153
8
  ## Features
154
9
 
155
10
  - **Multi-cloud**: Deploy to DigitalOcean, AWS Lightsail, Tencent Cloud, Microsoft Azure, or BytePlus Cloud with `--provider` flag
156
- - **Backup** local `~/.openclaw/` config into a timestamped `.tar.gz`
157
11
  - **1-click deploy**: generate SSH keys, provision a cloud instance, install Node 24 + OpenClaw + Claude Code + Codex + Gemini CLI, restore config, configure `.env` (API + messaging), start the gateway, and auto-configure model failover
158
12
  - **Cloud-to-cloud migration**: SSH into a source instance, back up remotely, deploy to a new instance, restore
159
- - **Snapshot restore**: create a DigitalOcean droplet from a snapshot by name, with deploy record saved to SQLite for web UI visibility
160
- - **Snapshot create**: create a named snapshot from an existing DigitalOcean droplet, with optional power-off for data consistency
13
+ - **Snapshot & restore**: create and restore named snapshots for DigitalOcean, BytePlus, and AWS Lightsail
161
14
  - **Destroy**: delete an instance by name with confirmation, clean up SSH keys (cloud + local)
162
15
  - **Status**: list all openclaw-tagged instances with IPs
163
- - **List backups**: show local backup archives with sizes and dates
164
- - **Web UI**: Browser-based deploy interface with real-time SSE progress streaming (optional)
165
- - **Security groups**: Auto-create firewall rules on Tencent Cloud and BytePlus (SSH + HTTP/HTTPS + Gateway)
16
+ - **Backup**: back up local `~/.openclaw/` config into a timestamped `.tar.gz`
17
+ - **Web UI**: browser-based deploy interface with real-time SSE progress streaming (optional)
18
+ - **Security groups**: auto-create firewall rules on Tencent Cloud and BytePlus (SSH + HTTP/HTTPS + Gateway)
166
19
 
167
20
  ## Supported Cloud Providers
168
21
 
@@ -235,97 +88,6 @@ cargo build --release --no-default-features --features aws-only
235
88
  | `aws-only` | Lightsail-only build (no DO or Tencent) | ❌ |
236
89
  | `minimal` | CLI-only, no web UI or optional features | ❌ |
237
90
 
238
- ## Programmatic Usage (Node.js)
239
-
240
- The npm package exports `getBinaryPath()` so you can call clawmacdo from Node.js scripts or automation tools.
241
-
242
- ```bash
243
- npm install clawmacdo
244
- ```
245
-
246
- ```javascript
247
- const { execSync, spawn } = require("child_process");
248
- const { getBinaryPath } = require("clawmacdo");
249
-
250
- const bin = getBinaryPath(); // absolute path to the clawmacdo binary
251
-
252
- // --- Deploy a new instance ---
253
- const deploy = execSync(`${bin} deploy \
254
- --provider lightsail \
255
- --customer-name "my-openclaw" \
256
- --customer-email "you@example.com" \
257
- --aws-access-key-id "${process.env.AWS_ACCESS_KEY_ID}" \
258
- --aws-secret-access-key "${process.env.AWS_SECRET_ACCESS_KEY}" \
259
- --anthropic-key "${process.env.ANTHROPIC_API_KEY}" \
260
- --primary-model anthropic \
261
- --json`, { encoding: "utf8" });
262
- console.log(JSON.parse(deploy));
263
-
264
- // --- Track deploy progress (streaming) ---
265
- const track = spawn(bin, ["track", "<deploy-id>", "--follow", "--json"]);
266
- track.stdout.on("data", (chunk) => {
267
- console.log("progress:", chunk.toString());
268
- });
269
-
270
- // --- Set up Telegram bot ---
271
- execSync(`${bin} telegram-setup \
272
- --instance <deploy-id> \
273
- --bot-token "${process.env.TELEGRAM_TOKEN}"`, { stdio: "inherit" });
274
-
275
- // --- Set up WhatsApp (displays QR code) ---
276
- execSync(`${bin} whatsapp-setup \
277
- --instance <deploy-id> \
278
- --phone-number "+6512345678"`, { stdio: "inherit" });
279
-
280
- // --- Fetch WhatsApp QR code ---
281
- const qr = execSync(`${bin} whatsapp-qr --instance <deploy-id>`, { encoding: "utf8" });
282
- console.log(qr); // ASCII QR code
283
-
284
- // --- Change AI model ---
285
- execSync(`${bin} update-model \
286
- --instance <deploy-id> \
287
- --primary-model openai \
288
- --openai-key "${process.env.OPENAI_API_KEY}"`, { stdio: "inherit" });
289
-
290
- // --- Install a plugin ---
291
- execSync(`${bin} plugin-install \
292
- --instance <deploy-id> \
293
- --plugin "@openguardrails/moltguard"`, { stdio: "inherit" });
294
-
295
- // --- Refresh IP after restart ---
296
- execSync(`${bin} update-ip --instance <deploy-id>`, { stdio: "inherit" });
297
-
298
- // --- Create snapshot ---
299
- execSync(`${bin} do-snapshot \
300
- --do-token "${process.env.DO_TOKEN}" \
301
- --droplet-id 12345 \
302
- --snapshot-name "my-backup"`, { stdio: "inherit" });
303
-
304
- // --- Restore from snapshot ---
305
- execSync(`${bin} do-restore \
306
- --do-token "${process.env.DO_TOKEN}" \
307
- --snapshot-name "my-backup"`, { stdio: "inherit" });
308
-
309
- // --- Destroy an instance ---
310
- execSync(`${bin} destroy \
311
- --provider digitalocean \
312
- --do-token "${process.env.DO_TOKEN}" \
313
- --name "openclaw-abc123" --yes`, { stdio: "inherit" });
314
-
315
- // --- Start the web UI programmatically ---
316
- const server = spawn(bin, ["serve", "--port", "3456"], { stdio: "inherit" });
317
- ```
318
-
319
- ### TypeScript
320
-
321
- ```typescript
322
- import { getBinaryPath } from "clawmacdo";
323
- import { execSync } from "child_process";
324
-
325
- const bin: string = getBinaryPath();
326
- execSync(`${bin} deploy --provider lightsail ...`, { stdio: "inherit" });
327
- ```
328
-
329
91
  ## Quick Start (CLI)
330
92
 
331
93
  ```bash
@@ -550,27 +312,7 @@ export ARK_ENDPOINT_ID="ep-20260315233753-58rpv"
550
312
  clawmacdo ark-chat "Explain quantum computing in 3 sentences."
551
313
  ```
552
314
 
553
- ### Restore DigitalOcean Droplet from Snapshot
554
-
555
- Create a new droplet from an existing DigitalOcean snapshot. The droplet name follows the standard `openclaw-{id}` naming convention.
556
-
557
- ```bash
558
- # Restore from a snapshot by name
559
- clawmacdo do-restore \
560
- --do-token "$DO_TOKEN" \
561
- --snapshot-name "my-openclaw-snapshot"
562
-
563
- # With region and size overrides
564
- clawmacdo do-restore \
565
- --do-token "$DO_TOKEN" \
566
- --snapshot-name "my-openclaw-snapshot" \
567
- --region nyc1 \
568
- --size s-4vcpu-8gb
569
- ```
570
-
571
- The command generates a new SSH key pair, looks up the snapshot by name, creates the droplet, waits for it to become active, and saves a deploy record for use with other `clawmacdo` commands.
572
-
573
- ### Create a DigitalOcean Snapshot from a Droplet
315
+ ### Create a DigitalOcean Snapshot
574
316
 
575
317
  Create a named snapshot from an existing DigitalOcean droplet. Optionally shuts down the droplet first for a clean snapshot.
576
318
 
@@ -589,9 +331,25 @@ clawmacdo do-snapshot \
589
331
  --power-off
590
332
  ```
591
333
 
592
- The command verifies the droplet exists, optionally shuts it down, creates the snapshot, polls until complete, confirms the snapshot, and optionally powers the droplet back on.
334
+ ### Restore a DigitalOcean Droplet from Snapshot
335
+
336
+ Create a new droplet from an existing DigitalOcean snapshot. The droplet name follows the standard `openclaw-{id}` naming convention.
593
337
 
594
- ### Create a BytePlus Snapshot from an ECS Instance
338
+ ```bash
339
+ # Restore from a snapshot by name
340
+ clawmacdo do-restore \
341
+ --do-token "$DO_TOKEN" \
342
+ --snapshot-name "my-openclaw-snapshot"
343
+
344
+ # With region and size overrides
345
+ clawmacdo do-restore \
346
+ --do-token "$DO_TOKEN" \
347
+ --snapshot-name "my-openclaw-snapshot" \
348
+ --region nyc1 \
349
+ --size s-4vcpu-8gb
350
+ ```
351
+
352
+ ### Create a BytePlus Snapshot
595
353
 
596
354
  Create a named snapshot of a BytePlus ECS instance's system disk.
597
355
 
@@ -601,7 +359,7 @@ clawmacdo bp-snapshot \
601
359
  --snapshot-name "my-openclaw-backup"
602
360
  ```
603
361
 
604
- ### Restore a BytePlus ECS Instance from a Snapshot
362
+ ### Restore a BytePlus ECS Instance from Snapshot
605
363
 
606
364
  Create a new instance from an existing BytePlus snapshot. This creates a custom image from the snapshot, then launches a new instance from that image.
607
365
 
@@ -628,7 +386,7 @@ clawmacdo ls-snapshot \
628
386
  --region ap-southeast-1
629
387
  ```
630
388
 
631
- ### Restore a Lightsail Instance from a Snapshot
389
+ ### Restore a Lightsail Instance from Snapshot
632
390
 
633
391
  Create a new instance directly from an existing Lightsail snapshot.
634
392
 
@@ -776,6 +534,126 @@ clawmacdo status
776
534
  clawmacdo status --provider tencent
777
535
  ```
778
536
 
537
+ ## Programmatic Usage (Node.js)
538
+
539
+ The npm package exports `getBinaryPath()` so you can call clawmacdo from Node.js scripts or automation tools.
540
+
541
+ ```bash
542
+ npm install clawmacdo
543
+ ```
544
+
545
+ ```javascript
546
+ const { execSync, spawn } = require("child_process");
547
+ const { getBinaryPath } = require("clawmacdo");
548
+
549
+ const bin = getBinaryPath(); // absolute path to the clawmacdo binary
550
+
551
+ // --- Deploy a new instance ---
552
+ const deploy = execSync(`${bin} deploy \
553
+ --provider lightsail \
554
+ --customer-name "my-openclaw" \
555
+ --customer-email "you@example.com" \
556
+ --aws-access-key-id "${process.env.AWS_ACCESS_KEY_ID}" \
557
+ --aws-secret-access-key "${process.env.AWS_SECRET_ACCESS_KEY}" \
558
+ --anthropic-key "${process.env.ANTHROPIC_API_KEY}" \
559
+ --primary-model anthropic \
560
+ --json`, { encoding: "utf8" });
561
+ console.log(JSON.parse(deploy));
562
+
563
+ // --- Track deploy progress (streaming) ---
564
+ const track = spawn(bin, ["track", "<deploy-id>", "--follow", "--json"]);
565
+ track.stdout.on("data", (chunk) => {
566
+ console.log("progress:", chunk.toString());
567
+ });
568
+
569
+ // --- Set up Telegram bot ---
570
+ execSync(`${bin} telegram-setup \
571
+ --instance <deploy-id> \
572
+ --bot-token "${process.env.TELEGRAM_TOKEN}"`, { stdio: "inherit" });
573
+
574
+ // --- Set up WhatsApp (displays QR code) ---
575
+ execSync(`${bin} whatsapp-setup \
576
+ --instance <deploy-id> \
577
+ --phone-number "+6512345678"`, { stdio: "inherit" });
578
+
579
+ // --- Fetch WhatsApp QR code ---
580
+ const qr = execSync(`${bin} whatsapp-qr --instance <deploy-id>`, { encoding: "utf8" });
581
+ console.log(qr); // ASCII QR code
582
+
583
+ // --- Change AI model ---
584
+ execSync(`${bin} update-model \
585
+ --instance <deploy-id> \
586
+ --primary-model openai \
587
+ --openai-key "${process.env.OPENAI_API_KEY}"`, { stdio: "inherit" });
588
+
589
+ // --- Install a plugin ---
590
+ execSync(`${bin} plugin-install \
591
+ --instance <deploy-id> \
592
+ --plugin "@openguardrails/moltguard"`, { stdio: "inherit" });
593
+
594
+ // --- Refresh IP after restart ---
595
+ execSync(`${bin} update-ip --instance <deploy-id>`, { stdio: "inherit" });
596
+
597
+ // --- Create snapshot ---
598
+ execSync(`${bin} do-snapshot \
599
+ --do-token "${process.env.DO_TOKEN}" \
600
+ --droplet-id 12345 \
601
+ --snapshot-name "my-backup"`, { stdio: "inherit" });
602
+
603
+ // --- Restore from snapshot ---
604
+ execSync(`${bin} do-restore \
605
+ --do-token "${process.env.DO_TOKEN}" \
606
+ --snapshot-name "my-backup"`, { stdio: "inherit" });
607
+
608
+ // --- Destroy an instance ---
609
+ execSync(`${bin} destroy \
610
+ --provider digitalocean \
611
+ --do-token "${process.env.DO_TOKEN}" \
612
+ --name "openclaw-abc123" --yes`, { stdio: "inherit" });
613
+
614
+ // --- Start the web UI programmatically ---
615
+ const server = spawn(bin, ["serve", "--port", "3456"], { stdio: "inherit" });
616
+ ```
617
+
618
+ ### TypeScript
619
+
620
+ ```typescript
621
+ import { getBinaryPath } from "clawmacdo";
622
+ import { execSync } from "child_process";
623
+
624
+ const bin: string = getBinaryPath();
625
+ execSync(`${bin} deploy --provider lightsail ...`, { stdio: "inherit" });
626
+ ```
627
+
628
+ ## Environment Variables
629
+
630
+ | Variable | Description | Required |
631
+ |----------|-------------|----------|
632
+ | `DO_TOKEN` | DigitalOcean API token | For DO deploys |
633
+ | `AWS_ACCESS_KEY_ID` | AWS IAM access key ID | For Lightsail deploys |
634
+ | `AWS_SECRET_ACCESS_KEY` | AWS IAM secret access key | For Lightsail deploys |
635
+ | `AWS_REGION` | AWS region (default: `us-east-1`) | For Lightsail deploys |
636
+ | `TENCENT_SECRET_ID` | Tencent Cloud Secret ID | For Tencent deploys |
637
+ | `TENCENT_SECRET_KEY` | Tencent Cloud Secret Key | For Tencent deploys |
638
+ | `AZURE_TENANT_ID` | Azure AD tenant ID | For Azure deploys |
639
+ | `AZURE_SUBSCRIPTION_ID` | Azure subscription ID | For Azure deploys |
640
+ | `AZURE_CLIENT_ID` | Azure service principal client ID | For Azure deploys |
641
+ | `AZURE_CLIENT_SECRET` | Azure service principal client secret | For Azure deploys |
642
+ | `BYTEPLUS_ACCESS_KEY` | BytePlus Access Key | For BytePlus deploys |
643
+ | `BYTEPLUS_SECRET_KEY` | BytePlus Secret Key | For BytePlus deploys |
644
+ | `BYTEPLUS_ARK_API_KEY` | BytePlus ARK API key (for AI model inference) | For BytePlus ARK model |
645
+ | `ARK_API_KEY` | ARK bearer token for `ark-chat` | For `ark-chat` |
646
+ | `ARK_ENDPOINT_ID` | ARK endpoint ID for `ark-chat` | For `ark-chat` |
647
+ | `CLAUDE_API_KEY` | Anthropic Claude API key | Optional |
648
+ | `OPENAI_API_KEY` | OpenAI API key | Optional |
649
+ | `TELEGRAM_TOKEN` | Telegram bot token | Optional |
650
+ | `TAILSCALE_AUTH_KEY` | Tailscale auth key | Optional |
651
+ | `CLAWMACDO_API_KEY` | API key protecting `/api/*` endpoints | Optional (Web UI) |
652
+ | `CLAWMACDO_PIN` | 6-digit PIN for web UI login page | Optional (Web UI) |
653
+ | `CLAWMACDO_BIND` | Server bind address (default: `127.0.0.1`) | Optional (Web UI) |
654
+ | `SKILLS_API_URL` | Railway skills API base URL | For skill commands |
655
+ | `USER_SKILLS_API_KEY` | API key for user-skills endpoints | For skill commands |
656
+
779
657
  ## Skills Data API
780
658
 
781
659
  The `skills-data-api/` directory contains a standalone Node.js/Express service for browsing and serving Claude Code skill marketplace data, backed by MongoDB.
@@ -814,6 +692,37 @@ docker run -p 3000:3000 \
814
692
 
815
693
  See [`skills-data-api/README.md`](skills-data-api/README.md) for full API documentation.
816
694
 
695
+ ## Project Structure
696
+
697
+ ```
698
+ clawmacdo/
699
+ ├── Cargo.toml # Workspace configuration
700
+ ├── crates/ # All crates in workspace
701
+ │ ├── clawmacdo-cli/ # 🖥️ Main CLI binary & command orchestration
702
+ │ ├── clawmacdo-core/ # 🔧 Config, errors, shared types
703
+ │ ├── clawmacdo-cloud/ # ☁️ Cloud provider implementations
704
+ │ ├── clawmacdo-provision/# 🔨 Server provisioning & setup logic
705
+ │ ├── clawmacdo-db/ # 💾 Database operations & storage
706
+ │ ├── clawmacdo-ssh/ # 🔑 SSH/SCP operations & key management
707
+ │ └── clawmacdo-ui/ # 🎨 Web UI, progress bars, user prompts
708
+ ├── skills-data-api/ # 🧠 Node.js skills marketplace API (MongoDB)
709
+ ├── e2e/ # 🧪 Playwright end-to-end test suite
710
+ ├── assets/ # Static assets (mascot, etc.)
711
+ └── docs/ # Design docs and usage reference
712
+ ```
713
+
714
+ ### Crate Overview
715
+
716
+ | Crate | Purpose | Dependencies |
717
+ |-------|---------|--------------|
718
+ | **clawmacdo-cli** | Main binary, command parsing, orchestration | All other crates |
719
+ | **clawmacdo-core** | Configuration, errors, shared types | Minimal (serde, anyhow) |
720
+ | **clawmacdo-cloud** | DigitalOcean, AWS Lightsail, Tencent Cloud & BytePlus APIs | reqwest, async-trait |
721
+ | **clawmacdo-provision** | Server setup, package installation | SSH, Core, UI |
722
+ | **clawmacdo-db** | SQLite operations, job tracking | rusqlite |
723
+ | **clawmacdo-ssh** | SSH connections, file transfers | ssh2 |
724
+ | **clawmacdo-ui** | Progress bars, web interface | indicatif, axum |
725
+
817
726
  ## Development
818
727
 
819
728
  ### Workspace Commands
@@ -849,42 +758,13 @@ Then reference in individual crate:
849
758
  new-crate = { workspace = true }
850
759
  ```
851
760
 
852
- ## Environment Variables
853
-
854
- | Variable | Description | Required |
855
- |----------|-------------|----------|
856
- | `DO_TOKEN` | DigitalOcean API token | For DO deploys |
857
- | `AWS_ACCESS_KEY_ID` | AWS IAM access key ID | For Lightsail deploys |
858
- | `AWS_SECRET_ACCESS_KEY` | AWS IAM secret access key | For Lightsail deploys |
859
- | `AWS_REGION` | AWS region (default: `us-east-1`) | For Lightsail deploys |
860
- | `TENCENT_SECRET_ID` | Tencent Cloud Secret ID | For Tencent deploys |
861
- | `TENCENT_SECRET_KEY` | Tencent Cloud Secret Key | For Tencent deploys |
862
- | `AZURE_TENANT_ID` | Azure AD tenant ID | For Azure deploys |
863
- | `AZURE_SUBSCRIPTION_ID` | Azure subscription ID | For Azure deploys |
864
- | `AZURE_CLIENT_ID` | Azure service principal client ID | For Azure deploys |
865
- | `AZURE_CLIENT_SECRET` | Azure service principal client secret | For Azure deploys |
866
- | `BYTEPLUS_ACCESS_KEY` | BytePlus Access Key | For BytePlus deploys |
867
- | `BYTEPLUS_SECRET_KEY` | BytePlus Secret Key | For BytePlus deploys |
868
- | `BYTEPLUS_ARK_API_KEY` | BytePlus ARK API key (for AI model inference) | For BytePlus ARK model |
869
- | `ARK_API_KEY` | ARK bearer token for `ark-chat` | For `ark-chat` |
870
- | `ARK_ENDPOINT_ID` | ARK endpoint ID for `ark-chat` | For `ark-chat` |
871
- | `CLAUDE_API_KEY` | Anthropic Claude API key | Optional |
872
- | `OPENAI_API_KEY` | OpenAI API key | Optional |
873
- | `TELEGRAM_TOKEN` | Telegram bot token | Optional |
874
- | `TAILSCALE_AUTH_KEY` | Tailscale auth key | Optional |
875
- | `CLAWMACDO_API_KEY` | API key protecting `/api/*` endpoints | Optional (Web UI) |
876
- | `CLAWMACDO_PIN` | 6-digit PIN for web UI login page | Optional (Web UI) |
877
- | `CLAWMACDO_BIND` | Server bind address (default: `127.0.0.1`) | Optional (Web UI) |
878
- | `SKILLS_API_URL` | Railway skills API base URL | For skill commands |
879
- | `USER_SKILLS_API_KEY` | API key for user-skills endpoints | For skill commands |
880
-
881
761
  ## Architecture Notes
882
762
 
883
763
  The refactored workspace follows a **dependency hierarchy**:
884
764
 
885
765
  1. **clawmacdo-core** - Foundation (no internal deps)
886
766
  2. **clawmacdo-ssh** - Depends on core
887
- 3. **clawmacdo-db** - Depends on core
767
+ 3. **clawmacdo-db** - Depends on core
888
768
  4. **clawmacdo-ui** - Depends on core
889
769
  5. **clawmacdo-cloud** - Depends on core
890
770
  6. **clawmacdo-provision** - Depends on core, ssh, ui, cloud
@@ -900,11 +780,24 @@ This prevents circular dependencies and enables clean testing.
900
780
  - **Feature gates** for optional components
901
781
  - **Minimal Tokio features** (not "full")
902
782
 
783
+ ## Security Hardening
784
+
785
+ - Privileged remote provisioning commands now run through stdin-fed shells instead of nested quoted `sudo` / `su -c` wrappers.
786
+ - User-supplied hostnames are normalized and validated before any deploy flow uses them.
787
+ - The web UI now only accepts backup archives from `~/.clawmacdo/backups` and SSH keys from `~/.clawmacdo/keys`.
788
+ - Backup restore validates the local `.tar.gz` before upload and extracts remotely with `--no-same-owner` and `--no-same-permissions` into a dedicated restore directory.
789
+ - The gateway service now reads `~/.openclaw/gateway.env` instead of the broader `.env`, so setup-only secrets such as `ANTHROPIC_SETUP_TOKEN` are not inherited by the long-running service.
790
+ - Direct Docker-group access for `openclaw` has been removed. If sandbox mode is requested during deploy, the deploy now forces sandbox mode off until a safer non-root mediation path exists.
791
+ - Lightsail credentials are passed only to the child AWS CLI processes instead of mutating process-global environment variables or writing `~/.aws/credentials`.
792
+ - Tencent's optional security-group helper now takes SSH ingress from `CLAWMACDO_TENCENT_SSH_CIDR` and defaults to `127.0.0.1/32` instead of opening SSH to the world.
793
+
794
+ See [docs/HIGH_SECURITY_FIXES.md](docs/HIGH_SECURITY_FIXES.md) for the finding-by-finding code map, rationale, and functionality impact.
795
+
903
796
  ## Contributing
904
797
 
905
798
  1. Fork the repository
906
799
  2. Create a feature branch
907
- 3. Add tests for new functionality
800
+ 3. Add tests for new functionality
908
801
  4. Run `cargo clippy` and `cargo test`
909
802
  5. Submit a pull request
910
803
 
@@ -933,37 +826,15 @@ For licensing inquiries, contact: bunnyppl@gmail.com
933
826
  | [TanStack Progress Tracking](docs/tanstack-progress-tracking.md) | Frontend integration guide for TanStack (React Query) progress bars |
934
827
  | [Security Scan](docs/SECURITY_SCAN.md) | Security scanning CLI and vulnerability assessment |
935
828
  | [Security Flaw Evaluation](docs/EVAL_SECURITY_FLAW.md) | Security flaw evaluation report and findings |
936
-
937
- Security scan scripts always write their main outputs to the system temp directory and only mirror them into `/root/.openclaw/workspace` when that directory is accessible.
938
829
  | [High Security Fixes](docs/HIGH_SECURITY_FIXES.md) | Code-level remediation map for all HIGH findings |
939
830
  | [Tencent Cloud Plan](docs/TENCENT_PLAN.md) | Tencent Cloud provider support plan |
940
831
  | [Repository Guidelines](docs/AGENTS.md) | Contribution guidelines and repository conventions |
941
832
 
942
833
  ## Changelog
943
834
 
944
- See [CHANGELOG.md](CHANGELOG.md) for version history and breaking changes.
835
+ See [CHANGELOG.md](CHANGELOG.md) for version history and release notes.
945
836
 
946
837
  ---
947
838
 
948
- **Last updated:** March 19, 2026
949
- **Current version:** 0.49.0
950
- **Architecture version:** 2.0 (modular workspace)
951
-
952
-
953
-
954
-
955
-
956
-
957
-
958
-
959
-
960
-
961
-
962
-
963
-
964
-
965
-
966
-
967
-
968
-
839
+ **Current version:** 0.51.0
969
840
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmacdo",
3
- "version": "0.49.0",
3
+ "version": "0.51.0",
4
4
  "description": "CLI tool for deploying OpenClaw to multiple cloud providers with pre-installed AI dev tools",
5
5
  "keywords": [
6
6
  "openclaw",
@@ -30,8 +30,8 @@
30
30
  "node": ">=16"
31
31
  },
32
32
  "optionalDependencies": {
33
- "@clawmacdo/darwin-arm64": "0.49.0",
34
- "@clawmacdo/linux-x64": "0.49.0",
35
- "@clawmacdo/win32-x64": "0.49.0"
33
+ "@clawmacdo/darwin-arm64": "0.51.0",
34
+ "@clawmacdo/linux-x64": "0.51.0",
35
+ "@clawmacdo/win32-x64": "0.51.0"
36
36
  }
37
37
  }