Rust CLI tool for deploying OpenClaw to DigitalOcean, AWS Lightsail, Tencent Cloud, Microsoft Azure, or BytePlus Cloud — with Claude Code, Codex, and Gemini CLI pre-installed.
- Multi-cloud: Deploy to DigitalOcean, AWS Lightsail, Tencent Cloud, Microsoft Azure, or BytePlus Cloud with
--providerflag - 1-click deploy: generate SSH keys, provision a cloud instance, install Node 24 + OpenClaw + Claude Code + Codex + Gemini CLI + OpenCode, restore config, configure
.env(API + messaging), start the gateway, and auto-configure model failover - Cloud-to-cloud migration: SSH into a source instance, back up remotely, deploy to a new instance, restore
- Snapshot & restore: create and restore named snapshots for DigitalOcean, BytePlus, and AWS Lightsail
- Destroy: delete an instance by name with confirmation, clean up SSH keys (cloud + local)
- Status: list all openclaw-tagged instances with IPs
- Backup: back up local
~/.openclaw/config into a timestamped.tar.gz - Web UI: browser-based deploy interface with a lobster-red OpenClaw-inspired theme and real-time SSE progress streaming (optional)
- Security groups: auto-create firewall rules on Tencent Cloud and BytePlus (SSH + HTTP/HTTPS + Gateway)
| Provider | Flag | Credentials | Prerequisite |
|---|---|---|---|
| DigitalOcean | --provider=digitalocean (default) |
--do-token |
— |
| AWS Lightsail | --provider=lightsail (or aws) |
--aws-access-key-id + --aws-secret-access-key |
AWS CLI installed |
| Tencent Cloud | --provider=tencent |
--tencent-secret-id + --tencent-secret-key |
— |
| Microsoft Azure | --provider=azure (or az) |
--azure-tenant-id + --azure-subscription-id + --azure-client-id + --azure-client-secret |
Azure CLI installed |
| BytePlus Cloud | --provider=byteplus (or bp) |
--byteplus-access-key + --byteplus-secret-key |
— |
Pre-built binaries for every release are available on the Releases page:
| Platform | Architecture | Full Build | Minimal Build |
|---|---|---|---|
| Linux | x86_64 | clawmacdo-linux-amd64-full.tar.gz |
clawmacdo-linux-amd64-minimal.tar.gz |
| macOS | Apple Silicon (arm64) | clawmacdo-darwin-arm64-full.tar.gz |
clawmacdo-darwin-arm64-minimal.tar.gz |
| Windows | x86_64 | clawmacdo-windows-amd64-full.zip |
clawmacdo-windows-amd64-minimal.zip |
npm install -g clawmacdoDownload the archive for your platform from Releases, extract, and add to your PATH.
cargo build --release
# Binary: target/release/clawmacdo (4.6MB)cargo build --release --no-default-features --features minimal
# Binary: target/release/clawmacdo (3.1MB - 32% smaller!)cargo build --release --no-default-features --features digitalocean-only
# Binary: target/release/clawmacdo (3.1MB, no Tencent Cloud)cargo build --release --no-default-features --features aws-only
# Binary: target/release/clawmacdo (Lightsail only, requires AWS CLI)| Feature | Description | Default |
|---|---|---|
web-ui |
Browser-based deployment interface | ✅ |
lightsail |
AWS Lightsail provider support (via AWS CLI) | ✅ |
tencent-cloud |
Tencent Cloud provider support | ✅ |
azure |
Microsoft Azure provider support (via Azure CLI) | ✅ |
byteplus |
BytePlus Cloud provider support | ✅ |
digitalocean |
DigitalOcean provider support | ✅ |
aws-only |
Lightsail-only build (no DO or Tencent) | ❌ |
minimal |
CLI-only, no web UI or optional features | ❌ |
# Install
npm install -g clawmacdo
# Deploy to DigitalOcean
clawmacdo deploy --provider digitalocean \
--customer-name "my-openclaw" --customer-email "you@example.com" \
--do-token "$DO_TOKEN" --anthropic-key "$ANTHROPIC_API_KEY"
# Deploy to AWS Lightsail
clawmacdo deploy --provider lightsail \
--customer-name "my-openclaw" --customer-email "you@example.com" \
--aws-access-key-id "$AWS_ACCESS_KEY_ID" \
--aws-secret-access-key "$AWS_SECRET_ACCESS_KEY"
# Track deploy progress
clawmacdo track <deploy-id> --follow
# Set up Telegram bot
clawmacdo telegram-setup --instance <deploy-id> --bot-token "$TELEGRAM_TOKEN"
clawmacdo telegram-setup --instance <deploy-id> --bot-token "$TELEGRAM_TOKEN" --reset # reset + setup in one SSH session
clawmacdo telegram-pair --instance <deploy-id> --code <PAIRING_CODE>
clawmacdo telegram-chat-id --instance <deploy-id>
clawmacdo telegram-reset --instance <deploy-id> # clear pairing, force new code
# Set up WhatsApp (displays QR code to scan)
clawmacdo whatsapp-setup --instance <deploy-id> --phone-number "+6512345678"
clawmacdo whatsapp-setup --instance <deploy-id> --phone-number "+6512345678" --reset # reset + setup in one SSH session
clawmacdo whatsapp-qr --instance <deploy-id> # re-fetch QR if expired
clawmacdo whatsapp-reset --instance <deploy-id> # clear session, force new QR
clawmacdo whatsapp-status --instance <deploy-id> # check channel status via Gateway API
clawmacdo whatsapp-wait --instance <deploy-id> # poll until connected (default 120s)
clawmacdo whatsapp-wait --instance <deploy-id> --timeout 60 # custom timeout
# Lightsail/Azure instances automatically use their default SSH users for WhatsApp repair/QR.
# The web UI QR fetch now ignores a missing prior login process instead of failing with an empty SSH error.
# OpenClaw version management
clawmacdo openclaw-versions # list available versions
clawmacdo openclaw-versions --json # JSON output
clawmacdo openclaw-install --instance <deploy-id> --version 2026.3.22 # pin version
clawmacdo deploy --provider digitalocean --openclaw-version 2026.3.22 ... # deploy with pinned version
# Change AI model on a running instance
clawmacdo update-model --instance <deploy-id> \
--primary-model openai --openai-key "$OPENAI_API_KEY"
# Install a plugin
clawmacdo plugin-install --instance <deploy-id> --plugin "@openguardrails/moltguard"
# Refresh IP after instance restart
clawmacdo update-ip --instance <deploy-id>
# Enable Tailscale Funnel (public HTTPS access)
# Performs clean Tailscale registration (wipes stale state if hostname mismatch)
clawmacdo tailscale-funnel --instance <deploy-id> --auth-key "$TAILSCALE_AUTH_KEY"
clawmacdo funnel-on --instance <deploy-id>
# Create and restore snapshots
clawmacdo do-snapshot --do-token "$DO_TOKEN" --droplet-id 12345 --snapshot-name "backup"
clawmacdo do-restore --do-token "$DO_TOKEN" --snapshot-name "backup"
# Destroy an instance
clawmacdo destroy --provider digitalocean --do-token "$DO_TOKEN" --name "openclaw-abc123"
# Start the web UI
clawmacdo serve --port 3456Full CLI reference with all examples, curl commands, and sample responses: docs/clawmacdo_usage.md
# Set your DO token
export DO_TOKEN="your_digitalocean_api_token"
# Deploy with backup & restore
clawmacdo deploy \
--customer-name "my-openclaw" \
--restore-from ~/backups/openclaw-backup-2024-03-09.tar.gzPrerequisite: AWS CLI must be installed and accessible in your
PATH.
# Set AWS credentials
export AWS_ACCESS_KEY_ID="your_access_key_id"
export AWS_SECRET_ACCESS_KEY="your_secret_access_key"
export AWS_REGION="us-east-1" # default region
# Deploy to Lightsail
clawmacdo deploy \
--provider lightsail \
--customer-name "my-openclaw" \
--customer-email "you@example.com" \
--aws-region us-east-1clawmacdo --size |
Lightsail Bundle | vCPU | RAM | Price |
|---|---|---|---|---|
s-1vcpu-2gb |
small_3_0 |
1 | 2 GB | ~$10/mo |
s-2vcpu-4gb (default) |
medium_3_0 |
2 | 4 GB | ~$20/mo |
s-4vcpu-8gb |
large_3_0 |
4 | 8 GB | ~$40/mo |
# Set Tencent credentials
export TENCENT_SECRET_ID="your_secret_id"
export TENCENT_SECRET_KEY="your_secret_key"
# Deploy to Hong Kong region
clawmacdo deploy \
--provider tencent \
--customer-name "my-openclaw-hk" \
--region ap-hongkong# Set BytePlus credentials
export BYTEPLUS_ACCESS_KEY="your_access_key"
export BYTEPLUS_SECRET_KEY="your_secret_key"
# Deploy with BytePlus ARK as primary AI model
clawmacdo deploy \
--provider byteplus \
--customer-name "my-openclaw-bp" \
--region ap-southeast-1 \
--primary-model byteplus \
--byteplus-ark-api-key "$BYTEPLUS_ARK_API_KEY" \
--anthropic-key "$ANTHROPIC_API_KEY"clawmacdo --size |
vCPU | RAM | Notes |
|---|---|---|---|
ecs.c3i.large |
2 | 4 GB | Compute-optimized |
ecs.g3i.large (default) |
2 | 8 GB | General purpose |
ecs.c3i.xlarge |
4 | 8 GB | Compute-optimized |
ecs.g3i.xlarge |
4 | 16 GB | General purpose |
Set a primary AI model and optional failovers for the deployed instance. Supported models: anthropic, openai, gemini, byteplus, opencode.
# Anthropic as primary (default)
clawmacdo deploy --provider do --customer-email "user@example.com" \
--primary-model anthropic --anthropic-key "$ANTHROPIC_API_KEY"
# BytePlus ARK as primary with Anthropic failover
clawmacdo deploy --provider bp --customer-email "user@example.com" \
--primary-model byteplus --failover-1 anthropic \
--byteplus-ark-api-key "$BYTEPLUS_ARK_API_KEY" \
--anthropic-key "$ANTHROPIC_API_KEY"
# Multi-model failover chain
clawmacdo deploy --provider do --customer-email "user@example.com" \
--primary-model anthropic --failover-1 openai --failover-2 gemini \
--anthropic-key "$ANTHROPIC_API_KEY" \
--openai-key "$OPENAI_API_KEY" --gemini-key "$GEMINI_API_KEY"
# OpenCode with MiniMax M2.5 Free as primary (no API key required)
clawmacdo deploy --provider do --customer-email "user@example.com" \
--primary-model opencode| Model | --primary-model value |
Model identifier | Required flag |
|---|---|---|---|
| Anthropic Claude | anthropic |
anthropic/claude-opus-4-6 |
--anthropic-key |
| OpenAI | openai |
openai/gpt-5-mini |
--openai-key |
| Google Gemini | gemini |
google/gemini-2.5-flash |
--gemini-key |
| BytePlus ARK | byteplus |
byteplus/ark-code-latest |
--byteplus-ark-api-key |
| OpenCode (MiniMax M2.5 Free) | opencode |
opencode/minimax-m2.5-free |
none (free) |
Change the primary AI model or failover chain on a deployed OpenClaw instance without redeploying.
# Switch to OpenAI as primary
clawmacdo update-model --instance <deploy-id> \
--primary-model openai --openai-key "$OPENAI_API_KEY"
# Switch to BytePlus ARK with Anthropic failover
clawmacdo update-model --instance <deploy-id> \
--primary-model byteplus --failover-1 anthropic \
--byteplus-ark-api-key "$BYTEPLUS_ARK_API_KEY" \
--anthropic-key "$ANTHROPIC_API_KEY"
# Multi-model failover chain
clawmacdo update-model --instance <deploy-id> \
--primary-model anthropic --failover-1 openai --failover-2 gemini \
--anthropic-key "$ANTHROPIC_API_KEY" \
--openai-key "$OPENAI_API_KEY" --gemini-key "$GEMINI_API_KEY"
# Switch to OpenCode (MiniMax M2.5 Free, no API key required)
clawmacdo update-model --instance <deploy-id> \
--primary-model opencodeThe command updates API keys in .env, configures provider settings (BytePlus openclaw.json), sets the model via openclaw models set, adds failovers, and restarts the gateway service. When opencode is selected, OpenCode is installed via curl -fsSL https://opencode.ai/install | bash and configured with MiniMax M2.5 Free (opencode/minimax-m2.5-free) — no API key required. API keys for other providers are optional — if omitted, the existing key on the instance is preserved.
Generate temporary BytePlus ARK API keys or list available endpoints.
# List available ARK endpoints
clawmacdo ark-api-key --list
# Generate a 7-day API key for an endpoint
clawmacdo ark-api-key \
--resource-ids ep-20260315233753-58rpv
# Generate a 30-day key for multiple endpoints
clawmacdo ark-api-key \
--resource-ids ep-abc123,ep-def456 \
--duration 2592000Send chat prompts directly to BytePlus ARK model endpoints from the CLI.
# Direct usage
clawmacdo ark-chat \
--api-key "$ARK_API_KEY" \
--endpoint-id ep-20260315233753-58rpv \
"Hello, what model are you?"
# Using environment variables
export ARK_API_KEY="your_ark_api_key"
export ARK_ENDPOINT_ID="ep-20260315233753-58rpv"
clawmacdo ark-chat "Explain quantum computing in 3 sentences."Create a named snapshot from an existing DigitalOcean droplet. Optionally shuts down the droplet first for a clean snapshot.
# Create a snapshot (droplet stays running)
clawmacdo do-snapshot \
--do-token "$DO_TOKEN" \
--droplet-id 558765268 \
--snapshot-name "my-openclaw-2026-03-19"
# Recommended: shut down first for a clean snapshot, then power back on
clawmacdo do-snapshot \
--do-token "$DO_TOKEN" \
--droplet-id 558765268 \
--snapshot-name "my-openclaw-2026-03-19" \
--power-offCreate a new droplet from an existing DigitalOcean snapshot. The droplet name follows the standard openclaw-{id} naming convention.
# Restore from a snapshot by name
clawmacdo do-restore \
--do-token "$DO_TOKEN" \
--snapshot-name "my-openclaw-snapshot"
# With region and size overrides
clawmacdo do-restore \
--do-token "$DO_TOKEN" \
--snapshot-name "my-openclaw-snapshot" \
--region nyc1 \
--size s-4vcpu-8gbCreate a named snapshot of a BytePlus ECS instance's system disk.
clawmacdo bp-snapshot \
--instance-id i-abc123 \
--snapshot-name "my-openclaw-backup"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.
# Restore from a snapshot by name
clawmacdo bp-restore \
--snapshot-name "my-openclaw-backup"
# With spot instance for cost savings
clawmacdo bp-restore \
--snapshot-name "my-openclaw-backup" \
--size ecs.g3i.large \
--spotCreate a snapshot of an AWS Lightsail instance.
clawmacdo ls-snapshot \
--instance-name "openclaw-abc123" \
--snapshot-name "my-openclaw-backup" \
--region ap-southeast-1Create a new instance directly from an existing Lightsail snapshot.
# Restore from a snapshot by name
clawmacdo ls-restore \
--snapshot-name "my-openclaw-backup" \
--region ap-southeast-1
# With size override
clawmacdo ls-restore \
--snapshot-name "my-openclaw-backup" \
--size s-4vcpu-8gbDelete an instance by name across any supported provider. Removes cloud SSH key, local key, and (for BytePlus) EIP and VPC resources.
# DigitalOcean
clawmacdo destroy \
--provider digitalocean \
--do-token "$DO_TOKEN" \
--name "openclaw-abc123"
# Tencent Cloud (skip confirmation prompt)
clawmacdo destroy \
--provider tencent \
--tencent-secret-id "$TENCENT_SECRET_ID" \
--tencent-secret-key "$TENCENT_SECRET_KEY" \
--name "openclaw-abc123" \
--yes
# BytePlus (also releases EIP and VPC resources)
clawmacdo destroy \
--provider byteplus \
--byteplus-access-key "$BYTEPLUS_ACCESS_KEY" \
--byteplus-secret-key "$BYTEPLUS_SECRET_KEY" \
--name "openclaw-abc123"Snapshot and restore operations return an operation_id immediately and run asynchronously. Track progress via SSE:
# Start a snapshot (returns operation_id immediately)
curl -X POST http://localhost:3456/api/deployments/{id}/snapshot \
-H 'Content-Type: application/json' \
-d '{"snapshot_name": "my-backup", "do_token": "$DO_TOKEN"}'
# Response: {"ok": true, "message": "Snapshot operation started.", "operation_id": "abc-123"}
# Start a restore (returns operation_id immediately)
curl -X POST http://localhost:3456/api/snapshots/restore \
-H 'Content-Type: application/json' \
-d '{"provider": "digitalocean", "snapshot_name": "my-backup", "do_token": "$DO_TOKEN"}'
# Response: {"ok": true, "message": "Restore operation started.", "operation_id": "def-456"}
# Stream progress via SSE
curl -N http://localhost:3456/api/deploy/{operation_id}/events
# SSE messages include [Step N/T] for progress bars
# Terminal: SNAPSHOT_COMPLETE_JSON:{...} or RESTORE_COMPLETE_JSON:{...}
# Error: SNAPSHOT_ERROR:... or RESTORE_ERROR:...# Track by deploy ID, hostname, or IP
clawmacdo track <deploy-id>
# Follow mode — live refresh until complete
clawmacdo track <deploy-id> --follow
# JSON output (NDJSON)
clawmacdo track <deploy-id> --json# Start browser interface
clawmacdo serve --port 3456
# Open http://localhost:3456The login screen uses a 6-digit PIN gate and shows invalid PIN attempts as an inline alert on the page.
# Migrate from one cloud to another
clawmacdo migrate \
--source-ip 1.2.3.4 \
--source-ssh-key ~/.ssh/old_instance \
--target-provider tencent \
--customer-name "migrated-openclaw"# Create local backup
clawmacdo backup
# List backups
clawmacdo list-backups
# Deploy with specific backup
clawmacdo deploy --restore-from ~/.openclaw/backups/openclaw-2024-03-09_14-30-15.tar.gz# Download all memory archives from an instance to the current directory
clawmacdo memory-download --instance my-server
# Download to a specific output directory
clawmacdo memory-download --instance my-server --output ~/backups/
# Download to a specific file path
clawmacdo memory-download --instance 1.2.3.4 --output ~/backups/memory.tar.gzThe command SSHes into the instance, creates a tar.gz of all files under /home/openclaw/.openclaw/memory/, downloads it locally, and cleans up the temporary archive on the remote host.
# Add a scheduled message (sent via telegram on a cron schedule)
clawmacdo cron-message \
--instance my-server \
--name "daily-digest" \
--schedule "0 9 * * *" \
--message "Summarise today's headlines" \
--channel telegram
# Add a scheduled message using an interval instead of a cron expression
clawmacdo cron-message \
--instance my-server \
--name "hourly-check" \
--every 1h \
--message "What is the current BTC price?" \
--channel telegram \
--to 7547736315
# Add a scheduled tool execution
clawmacdo cron-tool \
--instance my-server \
--name "weekly-report" \
--schedule "0 8 * * 1" \
--tool web-search \
--args "latest AI news" \
--channel telegram
# List all cron jobs on an instance
clawmacdo cron-list --instance my-server
# Remove a cron job by name
clawmacdo cron-remove --instance my-server --name daily-digestPerformance note: All cron commands batch the device-pairing approval step with the first gateway command into a single SSH session, minimising handshake overhead.
# Enable webhook hooks on an instance (generates token, creates default notify mapping)
clawmacdo hooks-enable --instance my-server
# Send a task to the agent via webhook (delivers response to Telegram)
clawmacdo hooks-send --instance my-server --task "Check today's weather for Singapore"
# Send to a specific mapping
clawmacdo hooks-send --instance my-server --task "Generate a report" --mapping notify
# Show hooks status and all mappings
clawmacdo hooks-status --instance my-server
# Disable webhook hooks
clawmacdo hooks-disable --instance my-serverExternal services can also POST directly:
curl -X POST https://<funnel-url>/hooks/notify \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"task":"your instruction to the agent"}'Template note: The
messageTemplateuses{{task}}to extract thetaskfield from the JSON payload. Other available template variables:{{payload.field}},{{headers.X-Header}},{{query.param}},{{path}},{{now}}.
clawmacdo deploy \
--provider digitalocean \
--customer-name "production-openclaw" \
--customer-email "admin@company.com" \
--size s-2vcpu-4gb \
--region nyc1 \
--primary-model anthropic \
--failover-1 openai \
--failover-2 gemini \
--anthropic-key "$ANTHROPIC_API_KEY" \
--openai-key "$OPENAI_API_KEY" \
--gemini-key "$GEMINI_API_KEY" \
--telegram-bot-token "$TELEGRAM_TOKEN" \
--whatsapp-phone-number "+1234567890" \
--tailscale \
--tailscale-auth-key "$TAILSCALE_AUTH" \
--backup ~/openclaw-backup.tar.gz# List all instances
clawmacdo status
# Check specific provider
clawmacdo status --provider tencentThe npm package exports getBinaryPath() so you can call clawmacdo from Node.js scripts or automation tools.
npm install clawmacdoconst { execSync, spawn } = require("child_process");
const { getBinaryPath } = require("clawmacdo");
const bin = getBinaryPath(); // absolute path to the clawmacdo binary
// --- Deploy a new instance ---
const deploy = execSync(`${bin} deploy \
--provider lightsail \
--customer-name "my-openclaw" \
--customer-email "you@example.com" \
--aws-access-key-id "${process.env.AWS_ACCESS_KEY_ID}" \
--aws-secret-access-key "${process.env.AWS_SECRET_ACCESS_KEY}" \
--anthropic-key "${process.env.ANTHROPIC_API_KEY}" \
--primary-model anthropic \
--json`, { encoding: "utf8" });
console.log(JSON.parse(deploy));
// --- Track deploy progress (streaming) ---
const track = spawn(bin, ["track", "<deploy-id>", "--follow", "--json"]);
track.stdout.on("data", (chunk) => {
console.log("progress:", chunk.toString());
});
// --- Set up Telegram bot ---
execSync(`${bin} telegram-setup \
--instance <deploy-id> \
--bot-token "${process.env.TELEGRAM_TOKEN}"`, { stdio: "inherit" });
// --- Set up WhatsApp (displays QR code) ---
execSync(`${bin} whatsapp-setup \
--instance <deploy-id> \
--phone-number "+6512345678"`, { stdio: "inherit" });
// --- Fetch WhatsApp QR code ---
const qr = execSync(`${bin} whatsapp-qr --instance <deploy-id>`, { encoding: "utf8" });
console.log(qr); // ASCII QR code
// --- Check WhatsApp status ---
const status = execSync(`${bin} whatsapp-status --instance <deploy-id>`, { encoding: "utf8" });
console.log(status); // "connected", "pending_qr", etc.
// --- Wait for WhatsApp scan (blocks until connected or timeout) ---
execSync(`${bin} whatsapp-wait --instance <deploy-id> --timeout 120`, { stdio: "inherit" });
// --- Change AI model ---
execSync(`${bin} update-model \
--instance <deploy-id> \
--primary-model openai \
--openai-key "${process.env.OPENAI_API_KEY}"`, { stdio: "inherit" });
// --- Install a plugin ---
execSync(`${bin} plugin-install \
--instance <deploy-id> \
--plugin "@openguardrails/moltguard"`, { stdio: "inherit" });
// --- Refresh IP after restart ---
execSync(`${bin} update-ip --instance <deploy-id>`, { stdio: "inherit" });
// --- Create snapshot ---
execSync(`${bin} do-snapshot \
--do-token "${process.env.DO_TOKEN}" \
--droplet-id 12345 \
--snapshot-name "my-backup"`, { stdio: "inherit" });
// --- Restore from snapshot ---
execSync(`${bin} do-restore \
--do-token "${process.env.DO_TOKEN}" \
--snapshot-name "my-backup"`, { stdio: "inherit" });
// --- Destroy an instance ---
execSync(`${bin} destroy \
--provider digitalocean \
--do-token "${process.env.DO_TOKEN}" \
--name "openclaw-abc123" --yes`, { stdio: "inherit" });
// --- Start the web UI programmatically ---
const server = spawn(bin, ["serve", "--port", "3456"], { stdio: "inherit" });import { getBinaryPath } from "clawmacdo";
import { execSync } from "child_process";
const bin: string = getBinaryPath();
execSync(`${bin} deploy --provider lightsail ...`, { stdio: "inherit" });| Variable | Description | Required |
|---|---|---|
DO_TOKEN |
DigitalOcean API token | For DO deploys |
AWS_ACCESS_KEY_ID |
AWS IAM access key ID | For Lightsail deploys |
AWS_SECRET_ACCESS_KEY |
AWS IAM secret access key | For Lightsail deploys |
AWS_REGION |
AWS region (default: us-east-1) |
For Lightsail deploys |
TENCENT_SECRET_ID |
Tencent Cloud Secret ID | For Tencent deploys |
TENCENT_SECRET_KEY |
Tencent Cloud Secret Key | For Tencent deploys |
AZURE_TENANT_ID |
Azure AD tenant ID | For Azure deploys |
AZURE_SUBSCRIPTION_ID |
Azure subscription ID | For Azure deploys |
AZURE_CLIENT_ID |
Azure service principal client ID | For Azure deploys |
AZURE_CLIENT_SECRET |
Azure service principal client secret | For Azure deploys |
BYTEPLUS_ACCESS_KEY |
BytePlus Access Key | For BytePlus deploys |
BYTEPLUS_SECRET_KEY |
BytePlus Secret Key | For BytePlus deploys |
BYTEPLUS_ARK_API_KEY |
BytePlus ARK API key (for AI model inference) | For BytePlus ARK model |
ARK_API_KEY |
ARK bearer token for ark-chat |
For ark-chat |
ARK_ENDPOINT_ID |
ARK endpoint ID for ark-chat |
For ark-chat |
CLAUDE_API_KEY |
Anthropic Claude API key | Optional |
OPENAI_API_KEY |
OpenAI API key | Optional |
TELEGRAM_TOKEN |
Telegram bot token | Optional |
TAILSCALE_AUTH_KEY |
Tailscale auth key | Optional |
CLAWMACDO_API_KEY |
API key protecting /api/* endpoints |
Optional (Web UI) |
CLAWMACDO_PIN |
6-digit PIN for web UI login page | Optional (Web UI) |
CLAWMACDO_BIND |
Server bind address (default: 127.0.0.1) |
Optional (Web UI) |
SKILLS_API_URL |
Railway skills API base URL | For skill commands |
USER_SKILLS_API_KEY |
API key for user-skills endpoints | For skill commands |
The skills-data-api/ directory contains a standalone Node.js/Express service for browsing and serving Claude Code skill marketplace data, backed by MongoDB.
# Install dependencies
cd skills-data-api
npm install
# Load skills data into MongoDB
pwsh -File ./load-mongo.ps1
# Start the API server
node index.jsOperational repo scripts now ship with PowerShell entrypoints under scripts/*.ps1 and can be run cross-platform with pwsh -File.
cd skills-data-api
docker build -t skills-data-api .
docker run -p 3000:3000 \
-e MONGODB_URI="mongodb://host.docker.internal:27017/skills" \
skills-data-api| Method | Path | Description |
|---|---|---|
GET |
/api/skills |
List all skills (paginated) |
GET |
/api/skills/:name |
Get a skill by name |
GET |
/api/skills/search?q=... |
Search skills by keyword |
See skills-data-api/README.md for full API documentation.
clawmacdo/
├── Cargo.toml # Workspace configuration
├── crates/ # All crates in workspace
│ ├── clawmacdo-cli/ # 🖥️ Main CLI binary & command orchestration
│ ├── clawmacdo-core/ # 🔧 Config, errors, shared types
│ ├── clawmacdo-cloud/ # ☁️ Cloud provider implementations
│ ├── clawmacdo-provision/# 🔨 Server provisioning & setup logic
│ ├── clawmacdo-db/ # 💾 Database operations & storage
│ ├── clawmacdo-ssh/ # 🔑 SSH/SCP operations & key management
│ └── clawmacdo-ui/ # 🎨 Web UI, progress bars, user prompts
├── skills-data-api/ # 🧠 Node.js skills marketplace API (MongoDB)
├── e2e/ # 🧪 Playwright end-to-end test suite
├── assets/ # Static assets (mascot, etc.)
└── docs/ # Design docs and usage reference
| Crate | Purpose | Dependencies |
|---|---|---|
| clawmacdo-cli | Main binary, command parsing, orchestration | All other crates |
| clawmacdo-core | Configuration, errors, shared types | Minimal (serde, anyhow) |
| clawmacdo-cloud | DigitalOcean, AWS Lightsail, Tencent Cloud & BytePlus APIs | reqwest, async-trait |
| clawmacdo-provision | Server setup, package installation | SSH, Core, UI |
| clawmacdo-db | SQLite operations, job tracking | rusqlite |
| clawmacdo-ssh | SSH connections, file transfers | ssh2 |
| clawmacdo-ui | Progress bars, web interface | indicatif, axum |
# Build all crates
cargo build
# Test all crates
cargo test
# Build specific crate
cargo build -p clawmacdo-core
# Run clippy on workspace
cargo clippy --all
# Update dependencies
cargo updateAdd to workspace Cargo.toml:
[workspace.dependencies]
new-crate = "1.0"Then reference in individual crate:
[dependencies]
new-crate = { workspace = true }The refactored workspace follows a dependency hierarchy:
- clawmacdo-core - Foundation (no internal deps)
- clawmacdo-ssh - Depends on core
- clawmacdo-db - Depends on core
- clawmacdo-ui - Depends on core
- clawmacdo-cloud - Depends on core
- clawmacdo-provision - Depends on core, ssh, ui, cloud
- clawmacdo-cli - Orchestration layer (depends on all)
This prevents circular dependencies and enables clean testing.
- LTO enabled for release builds
- Panic = abort for smaller binaries
- Symbol stripping in release mode
- Feature gates for optional components
- Minimal Tokio features (not "full")
- Privileged remote provisioning commands now run through stdin-fed shells instead of nested quoted
sudo/su -cwrappers. - User-supplied hostnames are normalized and validated before any deploy flow uses them.
- The web UI now only accepts backup archives from
~/.clawmacdo/backupsand SSH keys from~/.clawmacdo/keys. - Backup restore validates the local
.tar.gzbefore upload and extracts remotely with--no-same-ownerand--no-same-permissionsinto a dedicated restore directory. - The gateway service now reads
~/.openclaw/gateway.envinstead of the broader.env, so setup-only secrets such asANTHROPIC_SETUP_TOKENare not inherited by the long-running service. - Deploy Step 15 gateway health check uses exponential backoff (max ~70s) instead of 150 fixed 1s polls; model setup and profile setup are batched into a single SSH session per provider.
- Direct Docker-group access for
openclawhas been removed. If sandbox mode is requested during deploy, the deploy now forces sandbox mode off until a safer non-root mediation path exists. - Lightsail credentials are passed only to the child AWS CLI processes instead of mutating process-global environment variables or writing
~/.aws/credentials. - Tencent's optional security-group helper now takes SSH ingress from
CLAWMACDO_TENCENT_SSH_CIDRand defaults to127.0.0.1/32instead of opening SSH to the world.
See docs/HIGH_SECURITY_FIXES.md for the finding-by-finding code map, rationale, and functionality impact.
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Run
cargo clippyandcargo test - Submit a pull request
Copyright (c) 2026 Kenneth Phang
This software is licensed under a dual license model:
-
GNU General Public License v3.0 — for open source use See LICENSE-GPL.md for details.
-
Commercial License — for proprietary/commercial use See LICENSE-COMMERCIAL.md for details.
For licensing inquiries, contact: bunnyppl@gmail.com
| Document | Description |
|---|---|
| CLI Usage Guide | Complete reference for all subcommands with examples and sample responses |
| Deployment Architecture | Cloud provider architecture research and design decisions |
| Codebase Logic & Data Flow | End-to-end logic flow, module boundaries, and data structures |
| Tracking Architecture | Deploy/snapshot/restore progress tracking system design |
| TanStack Progress Tracking | Frontend integration guide for TanStack (React Query) progress bars |
| Security Scan | Security scanning CLI and vulnerability assessment |
| Security Flaw Evaluation | Security flaw evaluation report and findings |
| High Security Fixes | Code-level remediation map for all HIGH findings |
| Tencent Cloud Plan | Tencent Cloud provider support plan |
| Repository Guidelines | Contribution guidelines and repository conventions |
See CHANGELOG.md for version history and release notes.
Current version: 0.69.0
