npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

clawmacdo

v0.72.0

Published

CLI tool for deploying OpenClaw to multiple cloud providers with pre-installed AI dev tools

Readme

clawmacdo

Release Changelog

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.

Features

  • Multi-cloud: Deploy to DigitalOcean, AWS Lightsail, Tencent Cloud, Microsoft Azure, or BytePlus Cloud with --provider flag
  • 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)

Supported Cloud Providers

| 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 | — |

Download

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 |

Installation

From npm (recommended)

npm install -g clawmacdo

From release binary

Download the archive for your platform from Releases, extract, and add to your PATH.

From source

Full build (all features)

cargo build --release
# Binary: target/release/clawmacdo (4.6MB)

Minimal build (CLI only, no web UI)

cargo build --release --no-default-features --features minimal
# Binary: target/release/clawmacdo (3.1MB - 32% smaller!)

DigitalOcean-only build

cargo build --release --no-default-features --features digitalocean-only
# Binary: target/release/clawmacdo (3.1MB, no Tencent Cloud)

AWS Lightsail-only build

cargo build --release --no-default-features --features aws-only
# Binary: target/release/clawmacdo (Lightsail only, requires AWS CLI)

Build Features

| 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 | ❌ |

Quick Start (CLI)

# Install
npm install -g clawmacdo

# Deploy to DigitalOcean
clawmacdo deploy --provider digitalocean \
  --customer-name "my-openclaw" --customer-email "[email protected]" \
  --do-token "$DO_TOKEN" --anthropic-key "$ANTHROPIC_API_KEY"

# Deploy to AWS Lightsail
clawmacdo deploy --provider lightsail \
  --customer-name "my-openclaw" --customer-email "[email protected]" \
  --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"

# Set OpenClaw display name and owner context
clawmacdo openclaw-identity --instance <deploy-id> \
  --openclaw-name "Clawdia" --owner-name "Kenneth"

# Download OpenClaw Markdown context files and memory logs as a ZIP
clawmacdo openclaw-md-download --instance <deploy-id> --output ~/backups/

# Regenerate the OpenClaw gateway token
clawmacdo openclaw-gateway-token --instance <deploy-id>

# Configure Remotion avatar app and return a Cloudflare Quick Tunnel URL
clawmacdo remotion-avatar-setup --instance <deploy-id> --name "Kenny" \
  --openai-api-key "$OPENAI_API_KEY" --voice-gender female \
  --avatar-glb ./kenny_avatar.glb

# 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 3456

Usage

Full CLI reference with all examples, curl commands, and sample responses: docs/clawmacdo_usage.md

Deploy OpenClaw to DigitalOcean

# 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.gz

Deploy to AWS Lightsail

Prerequisite: 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 "[email protected]" \
  --aws-region us-east-1

Lightsail Instance Sizes

| clawmacdo --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 |

Deploy to Tencent Cloud

# 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

Deploy to BytePlus Cloud

# 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"

BytePlus Instance Sizes

| 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 |

AI Model Configuration

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 "[email protected]" \
  --primary-model anthropic --anthropic-key "$ANTHROPIC_API_KEY"

# BytePlus ARK as primary with Anthropic failover
clawmacdo deploy --provider bp --customer-email "[email protected]" \
  --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 "[email protected]" \
  --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 "[email protected]" \
  --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) |

Update AI Model on a Running Instance

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 opencode

The 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.

ARK API Key Management

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 2592000

ARK Chat

Send 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 DigitalOcean Snapshot

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-off

Restore a DigitalOcean Droplet from Snapshot

Create 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-8gb

Create a BytePlus Snapshot

Create a named snapshot of a BytePlus ECS instance's system disk.

clawmacdo bp-snapshot \
  --instance-id i-abc123 \
  --snapshot-name "my-openclaw-backup"

Restore a BytePlus ECS Instance from Snapshot

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 \
  --spot

Create a Lightsail Snapshot

Create a snapshot of an AWS Lightsail instance.

clawmacdo ls-snapshot \
  --instance-name "openclaw-abc123" \
  --snapshot-name "my-openclaw-backup" \
  --region ap-southeast-1

Restore a Lightsail Instance from Snapshot

Create 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-8gb

Destroy an Instance

Delete 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/Restore Progress Tracking

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 Deploy Progress

# 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

Web UI Mode

# Start browser interface
clawmacdo serve --port 3456
# Open http://localhost:3456

The login screen uses a 6-digit PIN gate and shows invalid PIN attempts as an inline alert on the page.

Cloud Migration

# 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"

Backup & Restore

# 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

Memory Archive Download

# 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.gz

The 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.

OpenClaw Identity

clawmacdo openclaw-identity --instance my-server \
  --openclaw-name "Clawdia" \
  --owner-name "Kenneth"

This command sets the target agent's OpenClaw identity and writes managed owner context into the remote workspace USER.md, then restarts the gateway.

OpenClaw Markdown Download

clawmacdo openclaw-md-download --instance my-server --output ~/backups/

Downloads the active OpenClaw workspace Markdown context files as a ZIP: AGENTS.md, SOUL.md, IDENTITY.md, USER.md, TOOLS.md, HEARTBEAT.md, BOOTSTRAP.md when present, plus daily memory logs under memory/*.md.

Gateway Token Rotation

clawmacdo openclaw-gateway-token --instance my-server

Regenerates gateway.auth.token in /home/openclaw/.openclaw/openclaw.json, keeps password auth in sync when configured, backs up the old config to openclaw.json.bak, and restarts the gateway.

Remotion Avatar Setup

clawmacdo remotion-avatar-setup --instance my-server --name "Kenny" \
  --openai-api-key "$OPENAI_API_KEY" \
  --voice-gender female \
  --avatar-glb ./kenny_avatar.glb

Configures /home/openclaw/.openclaw/workspace/remotion-3d-AI-avatar/.env with CHAT_BASE_URL=http://127.0.0.1:18789/v1, CHAT_API_KEY from the OpenClaw gateway token, CHAT_MODEL=openclaw, VITE_AVATAR_NAME from --name, OPENAI_API_KEY from --openai-api-key/OPENAI_API_KEY, and voice settings (VOICE_GENDER, TTS_VOICE; male maps to onyx, female maps to nova); optionally uploads avatar.glb or <userid>_avatar.glb to the app as public/avatar.glb; replaces kenken64 with the provided name; starts the app; starts a free Cloudflare Quick Tunnel to the frontend port; and prints the public trycloudflare.com URL.

Scheduled Cron Jobs

# 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-digest

Performance note: All cron commands batch the device-pairing approval step with the first gateway command into a single SSH session, minimising handshake overhead.

Webhook Hooks

# 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-server

External 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 messageTemplate uses {{task}} to extract the task field from the JSON payload. Other available template variables: {{payload.field}}, {{headers.X-Header}}, {{query.param}}, {{path}}, {{now}}.

Examples

Full Deploy with All Options

clawmacdo deploy \
  --provider digitalocean \
  --customer-name "production-openclaw" \
  --customer-email "[email protected]" \
  --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

Quick Status Check

# List all instances
clawmacdo status

# Check specific provider
clawmacdo status --provider tencent

Programmatic Usage (Node.js)

The npm package exports getBinaryPath() so you can call clawmacdo from Node.js scripts or automation tools.

npm install clawmacdo
const { 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 "[email protected]" \
  --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" });

TypeScript

import { getBinaryPath } from "clawmacdo";
import { execSync } from "child_process";

const bin: string = getBinaryPath();
execSync(`${bin} deploy --provider lightsail ...`, { stdio: "inherit" });

Environment Variables

| 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 |

Skills Data API

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.js

Operational repo scripts now ship with PowerShell entrypoints under scripts/*.ps1 and can be run cross-platform with pwsh -File.

Docker

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

Key Endpoints

| 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.

Project Structure

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 Overview

| 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 |

Development

Workspace Commands

# Build all crates
cargo build

# Run the full Rust quality pipeline
cargo fmt --all
cargo clippy --all-targets --all-features -- -D warnings
cargo test

# Build specific crate
cargo build -p clawmacdo-core

# Update dependencies
cargo update

The workspace now includes focused Rust tests around config/path validation, deployment database lookups, cron/hook command construction helpers, QR parsing, and web middleware behavior. Add new tests close to the module they protect.

Adding Dependencies

Add to workspace Cargo.toml:

[workspace.dependencies]
new-crate = "1.0"

Then reference in individual crate:

[dependencies]
new-crate = { workspace = true }

Architecture Notes

The refactored workspace follows a dependency hierarchy:

  1. clawmacdo-core - Foundation (no internal deps)
  2. clawmacdo-ssh - Depends on core
  3. clawmacdo-db - Depends on core
  4. clawmacdo-ui - Depends on core
  5. clawmacdo-cloud - Depends on core
  6. clawmacdo-provision - Depends on core, ssh, ui, cloud
  7. clawmacdo-cli - Orchestration layer (depends on all)

This prevents circular dependencies and enables clean testing.

Performance Optimizations

  • 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")

Security Hardening

  • Privileged remote provisioning commands now run through stdin-fed shells instead of nested quoted sudo / su -c wrappers.
  • User-supplied hostnames are normalized and validated before any deploy flow uses them.
  • The web UI now only accepts backup archives from ~/.clawmacdo/backups and SSH keys from ~/.clawmacdo/keys.
  • 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.
  • 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.
  • 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 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.
  • 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_CIDR and defaults to 127.0.0.1/32 instead of opening SSH to the world.

See docs/HIGH_SECURITY_FIXES.md for the finding-by-finding code map, rationale, and functionality impact.

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Run cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test
  5. Submit a pull request

License

Copyright (c) 2026 Kenneth Phang

This software is licensed under a dual license model:

  1. GNU General Public License v3.0 — for open source use See LICENSE-GPL.md for details.

  2. Commercial License — for proprietary/commercial use See LICENSE-COMMERCIAL.md for details.

For licensing inquiries, contact: [email protected]

Documentation

| 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 |

Changelog

See CHANGELOG.md for version history and release notes.


Current version: 0.72.0