clawmacdo 0.50.0 → 0.52.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 +195 -323
  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
@@ -356,6 +116,8 @@ clawmacdo telegram-chat-id --instance <deploy-id>
356
116
  # Set up WhatsApp (displays QR code to scan)
357
117
  clawmacdo whatsapp-setup --instance <deploy-id> --phone-number "+6512345678"
358
118
  clawmacdo whatsapp-qr --instance <deploy-id> # re-fetch QR if expired
119
+ # Lightsail/Azure instances automatically use their default SSH users for WhatsApp repair/QR.
120
+ # The web UI QR fetch now ignores a missing prior login process instead of failing with an empty SSH error.
359
121
 
360
122
  # Change AI model on a running instance
361
123
  clawmacdo update-model --instance <deploy-id> \
@@ -552,27 +314,7 @@ export ARK_ENDPOINT_ID="ep-20260315233753-58rpv"
552
314
  clawmacdo ark-chat "Explain quantum computing in 3 sentences."
553
315
  ```
554
316
 
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
317
+ ### Create a DigitalOcean Snapshot
576
318
 
577
319
  Create a named snapshot from an existing DigitalOcean droplet. Optionally shuts down the droplet first for a clean snapshot.
578
320
 
@@ -591,9 +333,25 @@ clawmacdo do-snapshot \
591
333
  --power-off
592
334
  ```
593
335
 
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.
336
+ ### Restore a DigitalOcean Droplet from Snapshot
337
+
338
+ Create a new droplet from an existing DigitalOcean snapshot. The droplet name follows the standard `openclaw-{id}` naming convention.
595
339
 
596
- ### Create a BytePlus Snapshot from an ECS Instance
340
+ ```bash
341
+ # Restore from a snapshot by name
342
+ clawmacdo do-restore \
343
+ --do-token "$DO_TOKEN" \
344
+ --snapshot-name "my-openclaw-snapshot"
345
+
346
+ # With region and size overrides
347
+ clawmacdo do-restore \
348
+ --do-token "$DO_TOKEN" \
349
+ --snapshot-name "my-openclaw-snapshot" \
350
+ --region nyc1 \
351
+ --size s-4vcpu-8gb
352
+ ```
353
+
354
+ ### Create a BytePlus Snapshot
597
355
 
598
356
  Create a named snapshot of a BytePlus ECS instance's system disk.
599
357
 
@@ -603,7 +361,7 @@ clawmacdo bp-snapshot \
603
361
  --snapshot-name "my-openclaw-backup"
604
362
  ```
605
363
 
606
- ### Restore a BytePlus ECS Instance from a Snapshot
364
+ ### Restore a BytePlus ECS Instance from Snapshot
607
365
 
608
366
  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
367
 
@@ -630,7 +388,7 @@ clawmacdo ls-snapshot \
630
388
  --region ap-southeast-1
631
389
  ```
632
390
 
633
- ### Restore a Lightsail Instance from a Snapshot
391
+ ### Restore a Lightsail Instance from Snapshot
634
392
 
635
393
  Create a new instance directly from an existing Lightsail snapshot.
636
394
 
@@ -778,6 +536,126 @@ clawmacdo status
778
536
  clawmacdo status --provider tencent
779
537
  ```
780
538
 
539
+ ## Programmatic Usage (Node.js)
540
+
541
+ The npm package exports `getBinaryPath()` so you can call clawmacdo from Node.js scripts or automation tools.
542
+
543
+ ```bash
544
+ npm install clawmacdo
545
+ ```
546
+
547
+ ```javascript
548
+ const { execSync, spawn } = require("child_process");
549
+ const { getBinaryPath } = require("clawmacdo");
550
+
551
+ const bin = getBinaryPath(); // absolute path to the clawmacdo binary
552
+
553
+ // --- Deploy a new instance ---
554
+ const deploy = execSync(`${bin} deploy \
555
+ --provider lightsail \
556
+ --customer-name "my-openclaw" \
557
+ --customer-email "you@example.com" \
558
+ --aws-access-key-id "${process.env.AWS_ACCESS_KEY_ID}" \
559
+ --aws-secret-access-key "${process.env.AWS_SECRET_ACCESS_KEY}" \
560
+ --anthropic-key "${process.env.ANTHROPIC_API_KEY}" \
561
+ --primary-model anthropic \
562
+ --json`, { encoding: "utf8" });
563
+ console.log(JSON.parse(deploy));
564
+
565
+ // --- Track deploy progress (streaming) ---
566
+ const track = spawn(bin, ["track", "<deploy-id>", "--follow", "--json"]);
567
+ track.stdout.on("data", (chunk) => {
568
+ console.log("progress:", chunk.toString());
569
+ });
570
+
571
+ // --- Set up Telegram bot ---
572
+ execSync(`${bin} telegram-setup \
573
+ --instance <deploy-id> \
574
+ --bot-token "${process.env.TELEGRAM_TOKEN}"`, { stdio: "inherit" });
575
+
576
+ // --- Set up WhatsApp (displays QR code) ---
577
+ execSync(`${bin} whatsapp-setup \
578
+ --instance <deploy-id> \
579
+ --phone-number "+6512345678"`, { stdio: "inherit" });
580
+
581
+ // --- Fetch WhatsApp QR code ---
582
+ const qr = execSync(`${bin} whatsapp-qr --instance <deploy-id>`, { encoding: "utf8" });
583
+ console.log(qr); // ASCII QR code
584
+
585
+ // --- Change AI model ---
586
+ execSync(`${bin} update-model \
587
+ --instance <deploy-id> \
588
+ --primary-model openai \
589
+ --openai-key "${process.env.OPENAI_API_KEY}"`, { stdio: "inherit" });
590
+
591
+ // --- Install a plugin ---
592
+ execSync(`${bin} plugin-install \
593
+ --instance <deploy-id> \
594
+ --plugin "@openguardrails/moltguard"`, { stdio: "inherit" });
595
+
596
+ // --- Refresh IP after restart ---
597
+ execSync(`${bin} update-ip --instance <deploy-id>`, { stdio: "inherit" });
598
+
599
+ // --- Create snapshot ---
600
+ execSync(`${bin} do-snapshot \
601
+ --do-token "${process.env.DO_TOKEN}" \
602
+ --droplet-id 12345 \
603
+ --snapshot-name "my-backup"`, { stdio: "inherit" });
604
+
605
+ // --- Restore from snapshot ---
606
+ execSync(`${bin} do-restore \
607
+ --do-token "${process.env.DO_TOKEN}" \
608
+ --snapshot-name "my-backup"`, { stdio: "inherit" });
609
+
610
+ // --- Destroy an instance ---
611
+ execSync(`${bin} destroy \
612
+ --provider digitalocean \
613
+ --do-token "${process.env.DO_TOKEN}" \
614
+ --name "openclaw-abc123" --yes`, { stdio: "inherit" });
615
+
616
+ // --- Start the web UI programmatically ---
617
+ const server = spawn(bin, ["serve", "--port", "3456"], { stdio: "inherit" });
618
+ ```
619
+
620
+ ### TypeScript
621
+
622
+ ```typescript
623
+ import { getBinaryPath } from "clawmacdo";
624
+ import { execSync } from "child_process";
625
+
626
+ const bin: string = getBinaryPath();
627
+ execSync(`${bin} deploy --provider lightsail ...`, { stdio: "inherit" });
628
+ ```
629
+
630
+ ## Environment Variables
631
+
632
+ | Variable | Description | Required |
633
+ |----------|-------------|----------|
634
+ | `DO_TOKEN` | DigitalOcean API token | For DO deploys |
635
+ | `AWS_ACCESS_KEY_ID` | AWS IAM access key ID | For Lightsail deploys |
636
+ | `AWS_SECRET_ACCESS_KEY` | AWS IAM secret access key | For Lightsail deploys |
637
+ | `AWS_REGION` | AWS region (default: `us-east-1`) | For Lightsail deploys |
638
+ | `TENCENT_SECRET_ID` | Tencent Cloud Secret ID | For Tencent deploys |
639
+ | `TENCENT_SECRET_KEY` | Tencent Cloud Secret Key | For Tencent deploys |
640
+ | `AZURE_TENANT_ID` | Azure AD tenant ID | For Azure deploys |
641
+ | `AZURE_SUBSCRIPTION_ID` | Azure subscription ID | For Azure deploys |
642
+ | `AZURE_CLIENT_ID` | Azure service principal client ID | For Azure deploys |
643
+ | `AZURE_CLIENT_SECRET` | Azure service principal client secret | For Azure deploys |
644
+ | `BYTEPLUS_ACCESS_KEY` | BytePlus Access Key | For BytePlus deploys |
645
+ | `BYTEPLUS_SECRET_KEY` | BytePlus Secret Key | For BytePlus deploys |
646
+ | `BYTEPLUS_ARK_API_KEY` | BytePlus ARK API key (for AI model inference) | For BytePlus ARK model |
647
+ | `ARK_API_KEY` | ARK bearer token for `ark-chat` | For `ark-chat` |
648
+ | `ARK_ENDPOINT_ID` | ARK endpoint ID for `ark-chat` | For `ark-chat` |
649
+ | `CLAUDE_API_KEY` | Anthropic Claude API key | Optional |
650
+ | `OPENAI_API_KEY` | OpenAI API key | Optional |
651
+ | `TELEGRAM_TOKEN` | Telegram bot token | Optional |
652
+ | `TAILSCALE_AUTH_KEY` | Tailscale auth key | Optional |
653
+ | `CLAWMACDO_API_KEY` | API key protecting `/api/*` endpoints | Optional (Web UI) |
654
+ | `CLAWMACDO_PIN` | 6-digit PIN for web UI login page | Optional (Web UI) |
655
+ | `CLAWMACDO_BIND` | Server bind address (default: `127.0.0.1`) | Optional (Web UI) |
656
+ | `SKILLS_API_URL` | Railway skills API base URL | For skill commands |
657
+ | `USER_SKILLS_API_KEY` | API key for user-skills endpoints | For skill commands |
658
+
781
659
  ## Skills Data API
782
660
 
783
661
  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 +694,37 @@ docker run -p 3000:3000 \
816
694
 
817
695
  See [`skills-data-api/README.md`](skills-data-api/README.md) for full API documentation.
818
696
 
697
+ ## Project Structure
698
+
699
+ ```
700
+ clawmacdo/
701
+ ├── Cargo.toml # Workspace configuration
702
+ ├── crates/ # All crates in workspace
703
+ │ ├── clawmacdo-cli/ # 🖥️ Main CLI binary & command orchestration
704
+ │ ├── clawmacdo-core/ # 🔧 Config, errors, shared types
705
+ │ ├── clawmacdo-cloud/ # ☁️ Cloud provider implementations
706
+ │ ├── clawmacdo-provision/# 🔨 Server provisioning & setup logic
707
+ │ ├── clawmacdo-db/ # 💾 Database operations & storage
708
+ │ ├── clawmacdo-ssh/ # 🔑 SSH/SCP operations & key management
709
+ │ └── clawmacdo-ui/ # 🎨 Web UI, progress bars, user prompts
710
+ ├── skills-data-api/ # 🧠 Node.js skills marketplace API (MongoDB)
711
+ ├── e2e/ # 🧪 Playwright end-to-end test suite
712
+ ├── assets/ # Static assets (mascot, etc.)
713
+ └── docs/ # Design docs and usage reference
714
+ ```
715
+
716
+ ### Crate Overview
717
+
718
+ | Crate | Purpose | Dependencies |
719
+ |-------|---------|--------------|
720
+ | **clawmacdo-cli** | Main binary, command parsing, orchestration | All other crates |
721
+ | **clawmacdo-core** | Configuration, errors, shared types | Minimal (serde, anyhow) |
722
+ | **clawmacdo-cloud** | DigitalOcean, AWS Lightsail, Tencent Cloud & BytePlus APIs | reqwest, async-trait |
723
+ | **clawmacdo-provision** | Server setup, package installation | SSH, Core, UI |
724
+ | **clawmacdo-db** | SQLite operations, job tracking | rusqlite |
725
+ | **clawmacdo-ssh** | SSH connections, file transfers | ssh2 |
726
+ | **clawmacdo-ui** | Progress bars, web interface | indicatif, axum |
727
+
819
728
  ## Development
820
729
 
821
730
  ### Workspace Commands
@@ -851,42 +760,13 @@ Then reference in individual crate:
851
760
  new-crate = { workspace = true }
852
761
  ```
853
762
 
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
763
  ## Architecture Notes
884
764
 
885
765
  The refactored workspace follows a **dependency hierarchy**:
886
766
 
887
767
  1. **clawmacdo-core** - Foundation (no internal deps)
888
768
  2. **clawmacdo-ssh** - Depends on core
889
- 3. **clawmacdo-db** - Depends on core
769
+ 3. **clawmacdo-db** - Depends on core
890
770
  4. **clawmacdo-ui** - Depends on core
891
771
  5. **clawmacdo-cloud** - Depends on core
892
772
  6. **clawmacdo-provision** - Depends on core, ssh, ui, cloud
@@ -902,11 +782,24 @@ This prevents circular dependencies and enables clean testing.
902
782
  - **Feature gates** for optional components
903
783
  - **Minimal Tokio features** (not "full")
904
784
 
785
+ ## Security Hardening
786
+
787
+ - Privileged remote provisioning commands now run through stdin-fed shells instead of nested quoted `sudo` / `su -c` wrappers.
788
+ - User-supplied hostnames are normalized and validated before any deploy flow uses them.
789
+ - The web UI now only accepts backup archives from `~/.clawmacdo/backups` and SSH keys from `~/.clawmacdo/keys`.
790
+ - 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.
791
+ - 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.
792
+ - 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.
793
+ - Lightsail credentials are passed only to the child AWS CLI processes instead of mutating process-global environment variables or writing `~/.aws/credentials`.
794
+ - 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.
795
+
796
+ See [docs/HIGH_SECURITY_FIXES.md](docs/HIGH_SECURITY_FIXES.md) for the finding-by-finding code map, rationale, and functionality impact.
797
+
905
798
  ## Contributing
906
799
 
907
800
  1. Fork the repository
908
801
  2. Create a feature branch
909
- 3. Add tests for new functionality
802
+ 3. Add tests for new functionality
910
803
  4. Run `cargo clippy` and `cargo test`
911
804
  5. Submit a pull request
912
805
 
@@ -935,37 +828,16 @@ For licensing inquiries, contact: bunnyppl@gmail.com
935
828
  | [TanStack Progress Tracking](docs/tanstack-progress-tracking.md) | Frontend integration guide for TanStack (React Query) progress bars |
936
829
  | [Security Scan](docs/SECURITY_SCAN.md) | Security scanning CLI and vulnerability assessment |
937
830
  | [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
831
  | [High Security Fixes](docs/HIGH_SECURITY_FIXES.md) | Code-level remediation map for all HIGH findings |
941
832
  | [Tencent Cloud Plan](docs/TENCENT_PLAN.md) | Tencent Cloud provider support plan |
942
833
  | [Repository Guidelines](docs/AGENTS.md) | Contribution guidelines and repository conventions |
943
834
 
944
835
  ## Changelog
945
836
 
946
- See [CHANGELOG.md](CHANGELOG.md) for version history and breaking changes.
837
+ See [CHANGELOG.md](CHANGELOG.md) for version history and release notes.
947
838
 
948
839
  ---
949
840
 
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
-
841
+ **Current version:** 0.52.0
970
842
 
971
843
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmacdo",
3
- "version": "0.50.0",
3
+ "version": "0.52.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.52.0",
34
+ "@clawmacdo/linux-x64": "0.52.0",
35
+ "@clawmacdo/win32-x64": "0.52.0"
36
36
  }
37
37
  }