clawmacdo 0.50.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 -324
  2. package/package.json +4 -4
package/README.md CHANGED
@@ -5,166 +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.50.0
9
-
10
- - **`telegram-chat-id` subcommand** — retrieve the Telegram chat ID from a deployed instance by searching openclaw credentials and data directories via SSH
11
- - **`skill-remove` subcommand** — delete a deployed skill by name from an instance's workspace and restart the gateway (`--instance` + `--skill`)
12
- - **`skill-list` subcommand** — list all skill directories on an instance with their gateway-registered name and readiness status
13
- - **`skill-check-perms` subcommand** — audit file ownership and permissions for a deployed skill; add `--fix` to auto-correct to `openclaw:openclaw` / `644`/`755`
14
- - **`skill-deploy` performance** — single SSH session for upload + extract + restart; `unzip` instead of Python; one-pass permission fix
15
-
16
- ## What's New in v0.50.0
17
-
18
- - **`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
19
-
20
- ## What's New in v0.46.4
21
-
22
- - **`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)
23
- - **`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
24
- - **`cron-list` subcommand** — list all cron jobs on a deployed instance
25
- - **`cron-remove` subcommand** — remove a cron job by name from a deployed instance
26
- - **`skill-deploy` subcommand** — upload a `.zip` of OpenClaw skills to a deployed instance; extracts into `~/.openclaw/workspace/skills/` and restarts the gateway automatically
27
-
28
- ## What's New in v0.38.0
29
-
30
- - **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
31
- - **`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
32
- - **`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
33
-
34
- ## What's New in v0.46.4
35
-
36
- - **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`)
37
- - **Telegram/WhatsApp Lightsail fix** — `telegram-setup`, `telegram-pair`, `whatsapp-setup`, and `whatsapp-qr` now SSH as `ubuntu` (not `root`) on Lightsail instances
38
- - **`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)
39
- - **`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
40
- - **Refresh IP button** — new "Refresh IP" button in Deployments tab queries the cloud provider and updates the IP in-place
41
- - **Deployments action dropdown** — deployment row actions now open in a stacked menu so controls stay readable instead of overlapping in narrow tables
42
- - **Deployments table fit** — deployments table now uses a tighter fixed layout with wrapped cell content to avoid left-right scrolling in the tab
43
- - **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
44
- - **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`
45
- - **Deploy progress in Deployments tab** — running deployments show an animated progress bar with current step label, polling every 3 seconds
46
- - **Funnel verification** — toggling funnel ON now polls the funnel status with a progress bar before showing the Open button
47
- - **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
48
- - **`KillMode=control-group`** — gateway service now kills the entire cgroup on restart, preventing orphaned child processes from holding the port
49
- - **AWS credential passthrough** — web UI credentials are written to `~/.aws/credentials` so the AWS CLI uses them instead of stale local config
50
- - **Lightsail destroy with credentials** — destroy modal now prompts for AWS Access Key ID and Secret Access Key
51
- - **Lightsail snapshot listing** — credentials from the web UI are now passed through to the AWS CLI for snapshot listing
52
- - **`whatsapp-setup` subcommand** — set up WhatsApp on a deployed instance (set phone number, enable plugin, restart gateway, fetch pairing QR code)
53
- - **`whatsapp-qr` subcommand** — fetch the WhatsApp pairing QR code from a deployed instance (re-fetch if expired)
54
- - **`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)
55
- - **Windows PowerShell scripts** — all shell scripts now have `.ps1` equivalents for Windows support (`release.ps1`, `npm-package.ps1`, `npm-publish.ps1`, scan scripts, etc.)
56
- - **Agent Docker Access warning** — deploy form shows the common Docker socket permission error with a clear fix instruction
57
- - **Dual license** — switched from MIT to GPLv3 (open source) + Commercial (proprietary) dual license model
58
-
59
- ### Previous highlights (v0.25.x – v0.26.x)
60
- - **`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
61
- - **BytePlus EIP cost reduction** — switched from pay-by-bandwidth to pay-by-traffic billing, reduced default bandwidth from 10 Mbps to 5 Mbps
62
- - **BytePlus spot instances** — new `--spot` flag on deploy enables `SpotAsPriceGo` strategy for up to ~80% compute cost savings
63
- - **`bp-snapshot` / `bp-restore`** — snapshot and restore for BytePlus ECS instances
64
- - **`ls-snapshot` / `ls-restore`** — snapshot and restore for AWS Lightsail instances
65
- - **BytePlus EIP orphan cleanup** — destroy command now finds and releases unbound EIPs left behind after instance termination
66
-
67
- ### Previous highlights (v0.21.x – v0.23.x)
68
- - **`destroy` subcommand** — delete any openclaw instance across all 5 cloud providers with interactive confirmation
69
- - **`skills-data-api` service** — Node.js/Express API backed by MongoDB for browsing, scraping, and serving Claude Code skill marketplace data
70
- - **Playwright e2e test suite** — CSV-driven deploy form testing under `e2e/`, covering all 5 cloud providers with 30+ scenarios
71
-
72
- ### Previous highlights (v0.20.x)
73
- - **`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)
74
-
75
- ### Previous highlights (v0.19.x)
76
- - **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)
77
- - **Auto-disable device pairing for Funnel** — Funnel setup sets `dangerouslyDisableDeviceAuth: true` so browser connections via Tailscale Funnel skip the pairing screen
78
-
79
- ### Previous highlights (v0.18.x)
80
- - **Tailscale Funnel** — `tailscale-funnel` subcommand: install Tailscale, enable Funnel, configure `openclaw.json`, auto-approve devices, and print public webchat URL
81
- - **Funnel toggle** — `funnel-on` / `funnel-off` CLI commands and web UI Deployments tab toggle button
82
- - **Customer skill management** — `skill-upload`, `skill-download`, `skill-push` subcommands for per-deployment SKILL.md
83
-
84
- ### Previous highlights (v0.17.x)
85
- - **Web UI security hardening (CRIT-01)** — API key auth, 6-digit PIN login, CORS, rate limiting, localhost-only binding
86
- - **All 4 CRITICAL security findings resolved**
87
-
88
- ### Previous highlights (v0.14.x – v0.15.x)
89
- - **Windows builds fixed** — Dependencies correctly scoped, native MSVC builds
90
- - **`digitalocean` feature flag** — DigitalOcean provider now properly gated as a default feature
91
-
92
- ### Previous highlights (v0.13.x)
93
- - **`ark-api-key`** — Generate temporary BytePlus ARK API keys from access/secret credentials, or list endpoints with `--list`
94
- - **`ark-chat`** — Send prompts to BytePlus ARK models directly from the CLI
95
- - **`telegram-setup` / `telegram-pair` / `telegram-chat-id`** — Configure, pair, and inspect Telegram bots on deployed instances via SSH
96
- - **Web UI destroy** — Destroy cloud instances directly from the Deployments tab with provider-specific credential prompts
97
- - **Detach mode improvements** — Proper `setsid()` session detachment, stdout/stderr logging to file
98
- - **Workspace path fix** — Automatic `/root/` → `/home/openclaw/` path correction during provisioning
99
-
100
- ### Earlier highlights (v0.9.x – v0.12.x)
101
- - **BytePlus Cloud** — 5th cloud provider added (`--provider=byteplus` or `bp`)
102
- - **BytePlus ECS client** — HMAC-SHA256 signed REST API with auto-provisioning of VPC, subnet, and security group
103
- - **Preflight CLI checks** — Azure CLI and AWS CLI verified at startup, auto-installed if missing
104
- - **Full-width professional web UI** — layout widened to 1536px max, compact hero with inline mascot
105
- - **Deploy progress tracking** — All 16 deploy steps persisted to SQLite in real-time
106
- - **`clawmacdo track` command** — Query deploy progress by ID, hostname, or IP address
107
- - **Follow mode** (`--follow`) — Live-polling display that refreshes until deployment finishes
108
- - **5 cloud providers** — DigitalOcean, AWS Lightsail, Tencent Cloud, Microsoft Azure, BytePlus Cloud
109
- - **npm distribution** — `npm install -g clawmacdo`
110
-
111
- ## Security Hardening
112
-
113
- - Privileged remote provisioning commands now run through stdin-fed shells instead of nested quoted `sudo` / `su -c` wrappers.
114
- - User-supplied hostnames are normalized and validated before any deploy flow uses them.
115
- - The web UI now only accepts backup archives from `~/.clawmacdo/backups` and SSH keys from `~/.clawmacdo/keys`.
116
- - 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.
117
- - 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.
118
- - 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.
119
- - Lightsail credentials are passed only to the child AWS CLI processes instead of mutating process-global environment variables or writing `~/.aws/credentials`.
120
- - 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.
121
-
122
- See [docs/HIGH_SECURITY_FIXES.md](docs/HIGH_SECURITY_FIXES.md) for the finding-by-finding code map, rationale, and functionality impact.
123
-
124
- ## 🏗️ Project Structure
125
-
126
- ```
127
- clawmacdo/
128
- ├── Cargo.toml # Workspace configuration
129
- ├── crates/ # All crates in workspace
130
- │ ├── clawmacdo-cli/ # 🖥️ Main CLI binary & command orchestration
131
- │ ├── clawmacdo-core/ # 🔧 Config, errors, shared types
132
- │ ├── clawmacdo-cloud/ # ☁️ Cloud provider implementations
133
- │ ├── clawmacdo-provision/# 🔨 Server provisioning & setup logic
134
- │ ├── clawmacdo-db/ # 💾 Database operations & storage
135
- │ ├── clawmacdo-ssh/ # 🔑 SSH/SCP operations & key management
136
- │ └── clawmacdo-ui/ # 🎨 Web UI, progress bars, user prompts
137
- ├── skills-data-api/ # 🧠 Node.js skills marketplace API (MongoDB)
138
- ├── e2e/ # 🧪 Playwright end-to-end test suite
139
- ├── assets/ # Static assets (mascot, etc.)
140
- └── docs/ # Design docs and usage reference
141
- ```
142
-
143
- ### 📦 Crate Overview
144
-
145
- | Crate | Purpose | Dependencies |
146
- |-------|---------|--------------|
147
- | **clawmacdo-cli** | Main binary, command parsing, orchestration | All other crates |
148
- | **clawmacdo-core** | Configuration, errors, shared types | Minimal (serde, anyhow) |
149
- | **clawmacdo-cloud** | DigitalOcean, AWS Lightsail, Tencent Cloud & BytePlus APIs | reqwest, async-trait |
150
- | **clawmacdo-provision** | Server setup, package installation | SSH, Core, UI |
151
- | **clawmacdo-db** | SQLite operations, job tracking | rusqlite |
152
- | **clawmacdo-ssh** | SSH connections, file transfers | ssh2 |
153
- | **clawmacdo-ui** | Progress bars, web interface | indicatif, axum |
154
-
155
8
  ## Features
156
9
 
157
10
  - **Multi-cloud**: Deploy to DigitalOcean, AWS Lightsail, Tencent Cloud, Microsoft Azure, or BytePlus Cloud with `--provider` flag
158
- - **Backup** local `~/.openclaw/` config into a timestamped `.tar.gz`
159
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
160
12
  - **Cloud-to-cloud migration**: SSH into a source instance, back up remotely, deploy to a new instance, restore
161
- - **Snapshot restore**: create a DigitalOcean droplet from a snapshot by name, with deploy record saved to SQLite for web UI visibility
162
- - **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
163
14
  - **Destroy**: delete an instance by name with confirmation, clean up SSH keys (cloud + local)
164
15
  - **Status**: list all openclaw-tagged instances with IPs
165
- - **List backups**: show local backup archives with sizes and dates
166
- - **Web UI**: Browser-based deploy interface with real-time SSE progress streaming (optional)
167
- - **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)
168
19
 
169
20
  ## Supported Cloud Providers
170
21
 
@@ -237,97 +88,6 @@ cargo build --release --no-default-features --features aws-only
237
88
  | `aws-only` | Lightsail-only build (no DO or Tencent) | ❌ |
238
89
  | `minimal` | CLI-only, no web UI or optional features | ❌ |
239
90
 
240
- ## Programmatic Usage (Node.js)
241
-
242
- The npm package exports `getBinaryPath()` so you can call clawmacdo from Node.js scripts or automation tools.
243
-
244
- ```bash
245
- npm install clawmacdo
246
- ```
247
-
248
- ```javascript
249
- const { execSync, spawn } = require("child_process");
250
- const { getBinaryPath } = require("clawmacdo");
251
-
252
- const bin = getBinaryPath(); // absolute path to the clawmacdo binary
253
-
254
- // --- Deploy a new instance ---
255
- const deploy = execSync(`${bin} deploy \
256
- --provider lightsail \
257
- --customer-name "my-openclaw" \
258
- --customer-email "you@example.com" \
259
- --aws-access-key-id "${process.env.AWS_ACCESS_KEY_ID}" \
260
- --aws-secret-access-key "${process.env.AWS_SECRET_ACCESS_KEY}" \
261
- --anthropic-key "${process.env.ANTHROPIC_API_KEY}" \
262
- --primary-model anthropic \
263
- --json`, { encoding: "utf8" });
264
- console.log(JSON.parse(deploy));
265
-
266
- // --- Track deploy progress (streaming) ---
267
- const track = spawn(bin, ["track", "<deploy-id>", "--follow", "--json"]);
268
- track.stdout.on("data", (chunk) => {
269
- console.log("progress:", chunk.toString());
270
- });
271
-
272
- // --- Set up Telegram bot ---
273
- execSync(`${bin} telegram-setup \
274
- --instance <deploy-id> \
275
- --bot-token "${process.env.TELEGRAM_TOKEN}"`, { stdio: "inherit" });
276
-
277
- // --- Set up WhatsApp (displays QR code) ---
278
- execSync(`${bin} whatsapp-setup \
279
- --instance <deploy-id> \
280
- --phone-number "+6512345678"`, { stdio: "inherit" });
281
-
282
- // --- Fetch WhatsApp QR code ---
283
- const qr = execSync(`${bin} whatsapp-qr --instance <deploy-id>`, { encoding: "utf8" });
284
- console.log(qr); // ASCII QR code
285
-
286
- // --- Change AI model ---
287
- execSync(`${bin} update-model \
288
- --instance <deploy-id> \
289
- --primary-model openai \
290
- --openai-key "${process.env.OPENAI_API_KEY}"`, { stdio: "inherit" });
291
-
292
- // --- Install a plugin ---
293
- execSync(`${bin} plugin-install \
294
- --instance <deploy-id> \
295
- --plugin "@openguardrails/moltguard"`, { stdio: "inherit" });
296
-
297
- // --- Refresh IP after restart ---
298
- execSync(`${bin} update-ip --instance <deploy-id>`, { stdio: "inherit" });
299
-
300
- // --- Create snapshot ---
301
- execSync(`${bin} do-snapshot \
302
- --do-token "${process.env.DO_TOKEN}" \
303
- --droplet-id 12345 \
304
- --snapshot-name "my-backup"`, { stdio: "inherit" });
305
-
306
- // --- Restore from snapshot ---
307
- execSync(`${bin} do-restore \
308
- --do-token "${process.env.DO_TOKEN}" \
309
- --snapshot-name "my-backup"`, { stdio: "inherit" });
310
-
311
- // --- Destroy an instance ---
312
- execSync(`${bin} destroy \
313
- --provider digitalocean \
314
- --do-token "${process.env.DO_TOKEN}" \
315
- --name "openclaw-abc123" --yes`, { stdio: "inherit" });
316
-
317
- // --- Start the web UI programmatically ---
318
- const server = spawn(bin, ["serve", "--port", "3456"], { stdio: "inherit" });
319
- ```
320
-
321
- ### TypeScript
322
-
323
- ```typescript
324
- import { getBinaryPath } from "clawmacdo";
325
- import { execSync } from "child_process";
326
-
327
- const bin: string = getBinaryPath();
328
- execSync(`${bin} deploy --provider lightsail ...`, { stdio: "inherit" });
329
- ```
330
-
331
91
  ## Quick Start (CLI)
332
92
 
333
93
  ```bash
@@ -552,27 +312,7 @@ export ARK_ENDPOINT_ID="ep-20260315233753-58rpv"
552
312
  clawmacdo ark-chat "Explain quantum computing in 3 sentences."
553
313
  ```
554
314
 
555
- ### Restore DigitalOcean Droplet from Snapshot
556
-
557
- Create a new droplet from an existing DigitalOcean snapshot. The droplet name follows the standard `openclaw-{id}` naming convention.
558
-
559
- ```bash
560
- # Restore from a snapshot by name
561
- clawmacdo do-restore \
562
- --do-token "$DO_TOKEN" \
563
- --snapshot-name "my-openclaw-snapshot"
564
-
565
- # With region and size overrides
566
- clawmacdo do-restore \
567
- --do-token "$DO_TOKEN" \
568
- --snapshot-name "my-openclaw-snapshot" \
569
- --region nyc1 \
570
- --size s-4vcpu-8gb
571
- ```
572
-
573
- 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.
574
-
575
- ### Create a DigitalOcean Snapshot from a Droplet
315
+ ### Create a DigitalOcean Snapshot
576
316
 
577
317
  Create a named snapshot from an existing DigitalOcean droplet. Optionally shuts down the droplet first for a clean snapshot.
578
318
 
@@ -591,9 +331,25 @@ clawmacdo do-snapshot \
591
331
  --power-off
592
332
  ```
593
333
 
594
- 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.
595
337
 
596
- ### 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
597
353
 
598
354
  Create a named snapshot of a BytePlus ECS instance's system disk.
599
355
 
@@ -603,7 +359,7 @@ clawmacdo bp-snapshot \
603
359
  --snapshot-name "my-openclaw-backup"
604
360
  ```
605
361
 
606
- ### Restore a BytePlus ECS Instance from a Snapshot
362
+ ### Restore a BytePlus ECS Instance from Snapshot
607
363
 
608
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.
609
365
 
@@ -630,7 +386,7 @@ clawmacdo ls-snapshot \
630
386
  --region ap-southeast-1
631
387
  ```
632
388
 
633
- ### Restore a Lightsail Instance from a Snapshot
389
+ ### Restore a Lightsail Instance from Snapshot
634
390
 
635
391
  Create a new instance directly from an existing Lightsail snapshot.
636
392
 
@@ -778,6 +534,126 @@ clawmacdo status
778
534
  clawmacdo status --provider tencent
779
535
  ```
780
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
+
781
657
  ## Skills Data API
782
658
 
783
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.
@@ -816,6 +692,37 @@ docker run -p 3000:3000 \
816
692
 
817
693
  See [`skills-data-api/README.md`](skills-data-api/README.md) for full API documentation.
818
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
+
819
726
  ## Development
820
727
 
821
728
  ### Workspace Commands
@@ -851,42 +758,13 @@ Then reference in individual crate:
851
758
  new-crate = { workspace = true }
852
759
  ```
853
760
 
854
- ## Environment Variables
855
-
856
- | Variable | Description | Required |
857
- |----------|-------------|----------|
858
- | `DO_TOKEN` | DigitalOcean API token | For DO deploys |
859
- | `AWS_ACCESS_KEY_ID` | AWS IAM access key ID | For Lightsail deploys |
860
- | `AWS_SECRET_ACCESS_KEY` | AWS IAM secret access key | For Lightsail deploys |
861
- | `AWS_REGION` | AWS region (default: `us-east-1`) | For Lightsail deploys |
862
- | `TENCENT_SECRET_ID` | Tencent Cloud Secret ID | For Tencent deploys |
863
- | `TENCENT_SECRET_KEY` | Tencent Cloud Secret Key | For Tencent deploys |
864
- | `AZURE_TENANT_ID` | Azure AD tenant ID | For Azure deploys |
865
- | `AZURE_SUBSCRIPTION_ID` | Azure subscription ID | For Azure deploys |
866
- | `AZURE_CLIENT_ID` | Azure service principal client ID | For Azure deploys |
867
- | `AZURE_CLIENT_SECRET` | Azure service principal client secret | For Azure deploys |
868
- | `BYTEPLUS_ACCESS_KEY` | BytePlus Access Key | For BytePlus deploys |
869
- | `BYTEPLUS_SECRET_KEY` | BytePlus Secret Key | For BytePlus deploys |
870
- | `BYTEPLUS_ARK_API_KEY` | BytePlus ARK API key (for AI model inference) | For BytePlus ARK model |
871
- | `ARK_API_KEY` | ARK bearer token for `ark-chat` | For `ark-chat` |
872
- | `ARK_ENDPOINT_ID` | ARK endpoint ID for `ark-chat` | For `ark-chat` |
873
- | `CLAUDE_API_KEY` | Anthropic Claude API key | Optional |
874
- | `OPENAI_API_KEY` | OpenAI API key | Optional |
875
- | `TELEGRAM_TOKEN` | Telegram bot token | Optional |
876
- | `TAILSCALE_AUTH_KEY` | Tailscale auth key | Optional |
877
- | `CLAWMACDO_API_KEY` | API key protecting `/api/*` endpoints | Optional (Web UI) |
878
- | `CLAWMACDO_PIN` | 6-digit PIN for web UI login page | Optional (Web UI) |
879
- | `CLAWMACDO_BIND` | Server bind address (default: `127.0.0.1`) | Optional (Web UI) |
880
- | `SKILLS_API_URL` | Railway skills API base URL | For skill commands |
881
- | `USER_SKILLS_API_KEY` | API key for user-skills endpoints | For skill commands |
882
-
883
761
  ## Architecture Notes
884
762
 
885
763
  The refactored workspace follows a **dependency hierarchy**:
886
764
 
887
765
  1. **clawmacdo-core** - Foundation (no internal deps)
888
766
  2. **clawmacdo-ssh** - Depends on core
889
- 3. **clawmacdo-db** - Depends on core
767
+ 3. **clawmacdo-db** - Depends on core
890
768
  4. **clawmacdo-ui** - Depends on core
891
769
  5. **clawmacdo-cloud** - Depends on core
892
770
  6. **clawmacdo-provision** - Depends on core, ssh, ui, cloud
@@ -902,11 +780,24 @@ This prevents circular dependencies and enables clean testing.
902
780
  - **Feature gates** for optional components
903
781
  - **Minimal Tokio features** (not "full")
904
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
+
905
796
  ## Contributing
906
797
 
907
798
  1. Fork the repository
908
799
  2. Create a feature branch
909
- 3. Add tests for new functionality
800
+ 3. Add tests for new functionality
910
801
  4. Run `cargo clippy` and `cargo test`
911
802
  5. Submit a pull request
912
803
 
@@ -935,37 +826,15 @@ For licensing inquiries, contact: bunnyppl@gmail.com
935
826
  | [TanStack Progress Tracking](docs/tanstack-progress-tracking.md) | Frontend integration guide for TanStack (React Query) progress bars |
936
827
  | [Security Scan](docs/SECURITY_SCAN.md) | Security scanning CLI and vulnerability assessment |
937
828
  | [Security Flaw Evaluation](docs/EVAL_SECURITY_FLAW.md) | Security flaw evaluation report and findings |
938
-
939
- 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.
940
829
  | [High Security Fixes](docs/HIGH_SECURITY_FIXES.md) | Code-level remediation map for all HIGH findings |
941
830
  | [Tencent Cloud Plan](docs/TENCENT_PLAN.md) | Tencent Cloud provider support plan |
942
831
  | [Repository Guidelines](docs/AGENTS.md) | Contribution guidelines and repository conventions |
943
832
 
944
833
  ## Changelog
945
834
 
946
- See [CHANGELOG.md](CHANGELOG.md) for version history and breaking changes.
835
+ See [CHANGELOG.md](CHANGELOG.md) for version history and release notes.
947
836
 
948
837
  ---
949
838
 
950
- **Last updated:** March 19, 2026
951
- **Current version:** 0.50.0
952
- **Architecture version:** 2.0 (modular workspace)
953
-
954
-
955
-
956
-
957
-
958
-
959
-
960
-
961
-
962
-
963
-
964
-
965
-
966
-
967
-
968
-
969
-
970
-
839
+ **Current version:** 0.51.0
971
840
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmacdo",
3
- "version": "0.50.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.50.0",
34
- "@clawmacdo/linux-x64": "0.50.0",
35
- "@clawmacdo/win32-x64": "0.50.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
  }