CLI
#Name
crabbox
One-liner: lease shared remote test boxes, sync local work, run commands, and clean up.
#Usage
crabbox [global flags] <command> [args]
Global flags:
-h, --help
--version
Primary output goes to stdout. Progress, diagnostics, and errors go to stderr. JSON output is stable enough for scripts.
#Commands
crabbox doctor
crabbox login [--url <url>] [--provider hetzner|aws] [--no-browser]
crabbox login --url <url> --token-stdin [--provider hetzner|aws]
crabbox logout
crabbox whoami [--json]
crabbox init [--force]
crabbox config show [--json]
crabbox config path
crabbox config set-broker --url <url> --token-stdin [--provider hetzner|aws]
crabbox warmup [--provider hetzner|aws|blacksmith-testbox] [--profile <name>] [--idle-timeout <duration>]
crabbox run [--id <lease-id-or-slug>] [--shell] [--checksum] [--debug] [--force-sync-large] [--blacksmith-workflow <workflow>] -- <command...>
crabbox sync-plan [--limit <n>]
crabbox history [--lease <lease-id>] [--owner <email>] [--org <name>] [--limit <n>] [--json]
crabbox logs <run-id> [--json]
crabbox results <run-id> [--json]
crabbox cache stats --id <lease-id-or-slug> [--json]
crabbox cache purge --id <lease-id-or-slug> --kind pnpm|npm|docker|git|all --force
crabbox cache warm --id <lease-id-or-slug> -- <command...>
crabbox actions hydrate --id <lease-id-or-slug> [--workflow <file|name|id>] [--wait-timeout <duration>]
crabbox actions register --id <lease-id-or-slug> [--repo owner/name]
crabbox actions dispatch [--workflow <file|name|id>] [-f key=value]
crabbox status --id <lease-id-or-slug> [--wait]
crabbox list [--json]
crabbox usage [--scope user|org|all] [--user <email>] [--org <name>] [--month YYYY-MM] [--json]
crabbox admin leases [--state active|released|expired|failed] [--owner <email>] [--org <name>] [--json]
crabbox admin release <lease-id-or-slug> [--delete]
crabbox admin delete <lease-id-or-slug> --force
crabbox ssh --id <lease-id-or-slug>
crabbox inspect --id <lease-id-or-slug> [--json]
crabbox stop <lease-id-or-slug>
crabbox cleanup [--dry-run]
#Common Flows
One-shot run:
crabbox run --profile project-check -- pnpm check:changed
AWS EC2 Spot run:
crabbox run --class beast -- pnpm check:changed
Warm a box, then reuse it:
crabbox warmup --profile project-check
crabbox run --id blue-lobster -- pnpm test:changed
crabbox run --id blue-lobster --shell 'pnpm install --frozen-lockfile && pnpm test'
crabbox stop blue-lobster
Hydrate through GitHub Actions, then run local dirty work in the hydrated workspace:
crabbox warmup
crabbox actions hydrate --id blue-lobster
crabbox run --id blue-lobster -- pnpm test:changed
crabbox stop blue-lobster
Use Blacksmith Testboxes through the same Crabbox surface:
blacksmith auth login
crabbox warmup --provider blacksmith-testbox --blacksmith-workflow .github/workflows/ci-check-testbox.yml --blacksmith-job test
crabbox run --provider blacksmith-testbox --id blue-lobster -- pnpm test:changed
crabbox run --provider blacksmith-testbox --blacksmith-workflow .github/workflows/ci-check-testbox.yml --blacksmith-job test -- pnpm test
crabbox stop --provider blacksmith-testbox blue-lobster
Inspect pool:
crabbox list
crabbox list --json
Inspect local sync size:
crabbox sync-plan
crabbox sync-plan --limit 10
Inspect usage and estimated cost:
crabbox usage
crabbox usage --scope org --org openclaw
crabbox usage --scope all --json
Cleanup direct-provider leftovers:
crabbox cleanup --dry-run
crabbox cleanup
Cleanup is intentionally conservative: it skips kept machines, deletes expired ready/leased/active direct machines, and gives running/provisioning direct machines an extra stale safety window. When a coordinator is configured, brokered cleanup is owned by the Durable Object alarm instead of provider-side sweeping.
Debug config:
crabbox doctor
crabbox whoami
crabbox config show
crabbox config show --json
Inspect recorded runs:
crabbox run --id blue-lobster --junit junit.xml -- go test ./...
crabbox history --lease cbx_abcdef123456
crabbox logs run_123
crabbox results run_123
Inspect or warm caches on a kept box:
crabbox cache stats --id blue-lobster
crabbox cache warm --id blue-lobster -- pnpm install --frozen-lockfile
crabbox cache purge --id blue-lobster --kind pnpm --force
Trusted operator lease controls:
crabbox admin leases --state active
crabbox admin release blue-lobster
crabbox admin delete cbx_abcdef123456 --force
#run
crabbox run is the main command.
Behavior:
- Load config.
- Acquire a lease unless
--idis provided. - Verify SSH readiness.
- Use the GitHub Actions workspace when the lease has a hydration marker.
- Sync current repo, unless a matching sync fingerprint lets Crabbox skip rsync.
- Seed remote Git from the configured origin/base ref before first sync when possible.
- Run command over SSH.
- Stream remote output and retain the latest log tail in coordinator history.
- Heartbeat coordinator leases in the background.
- Release lease unless
--keepis set. - Exit with the remote command exit code.
Fresh non-kept leases retry once with a new machine when bootstrap never reaches SSH readiness. Existing leases and --keep runs are not retried automatically, so commands are not duplicated on a machine the user asked to keep. Runner bootstrap retries apt and installs only Crabbox plumbing before crabbox-ready is allowed to pass.
Flags:
--id <lease-id-or-slug> reuse an existing lease
--provider <name> hetzner, aws, or blacksmith-testbox
--profile <name> profile to run on
--class <name> machine class override
--type <name> provider server or instance type override
--ttl <duration> maximum lease lifetime, default 90m
--idle-timeout <duration> idle expiry, default 30m
--no-sync run without syncing
--sync-only sync and exit
--force-sync-large allow a sync candidate above configured fail thresholds
--keep keep lease after command exits
--shell run the command string through bash -lc
--checksum use checksum rsync instead of size/time
--debug print sync timing and itemized rsync output
--junit <paths> comma-separated remote JUnit XML paths to attach to run history
--reclaim claim an existing lease for the current repo
--blacksmith-org <org> Blacksmith organization
--blacksmith-workflow <file|name|id> Blacksmith Testbox workflow
--blacksmith-job <job> Blacksmith Testbox workflow job
--blacksmith-ref <ref> Blacksmith Testbox git ref
Secrets must not be accepted as flag values. Env forwarding is name-based only.
Crabbox stores local lease claims under its state directory. warmup and first reuse claim the lease for the current repo; later run, ssh, cache, and actions hydrate/register refuse a conflicting repo claim unless --reclaim is set.
With provider: blacksmith-testbox, Crabbox delegates machine setup, sync, and command transport to the Blacksmith CLI. --sync-only is unsupported, sync timing is reported as sync=delegated, and Blacksmith auth is handled by blacksmith auth login, not crabbox login.
#Exit Codes
0 success
1 generic Crabbox failure
2 invalid usage or config
3 auth failure
4 no capacity
5 provisioning failure
6 sync failure
7 SSH failure
8 lease expired
10+ remote command exit code when available
If the remote command exits with a code, crabbox run returns that code unless Crabbox itself failed first.
#Config Files
The implemented config format is YAML. The default path is:
macOS: ~/.config/crabbox/config.yaml through XDG, or ~/Library/Application Support/crabbox/config.yaml
Linux: ~/.config/crabbox/config.yaml
repo: crabbox.yaml or .crabbox.yaml
User config:
broker:
url: https://crabbox.openclaw.ai
provider: aws
token: ...
profile: project-check
class: beast
lease:
idleTimeout: 30m
ttl: 90m
capacity:
market: spot
strategy: most-available
fallback: on-demand-after-120s
aws:
region: eu-west-1
rootGB: 400
ssh:
key: ~/.ssh/id_ed25519
user: crabbox
port: "2222"
# Ordered fallback ports tried after ssh.port; use [] to disable fallback.
fallbackPorts:
- "22"
Open GitHub browser login:
crabbox login
Trusted operators can still set shared-token broker auth without putting the token in shell history:
printf '%s' "$TOKEN" | crabbox login \
--url https://crabbox.openclaw.ai \
--provider aws \
--token-stdin
crabbox config set-broker remains available for scripts that only want to edit config without verifying identity.
Repo-local config is YAML and should hold project-specific choices:
profile: project-check
class: beast
actions:
workflow: .github/workflows/crabbox.yml
ref: main
runnerLabels:
- crabbox
sync:
delete: true
checksum: false
gitSeed: true
fingerprint: true
baseRef: main
timeout: 15m
warnFiles: 50000
warnBytes: 5368709120
failFiles: 150000
failBytes: 21474836480
allowLarge: false
exclude:
- node_modules
- .turbo
- dist
env:
allow:
- CI
- NODE_OPTIONS
- PROJECT_*
results:
junit:
- junit.xml
cache:
pnpm: true
npm: true
docker: true
git: true
maxGB: 80
purgeOnRelease: false
Blacksmith Testbox config:
provider: blacksmith-testbox
blacksmith:
org: openclaw
workflow: .github/workflows/ci-check-testbox.yml
job: test
ref: main
idleTimeout: 90m
debug: false
#Environment Variables
CRABBOX_COORDINATOR
CRABBOX_COORDINATOR_TOKEN
CRABBOX_PROVIDER
CRABBOX_PROFILE
CRABBOX_CONFIG
CRABBOX_DEFAULT_CLASS
CRABBOX_SERVER_TYPE
CRABBOX_IDLE_TIMEOUT
CRABBOX_TTL
CRABBOX_SSH_KEY
CRABBOX_SSH_USER
CRABBOX_SSH_PORT
CRABBOX_SSH_FALLBACK_PORTS comma-separated fallback ports, or none
CRABBOX_WORK_ROOT
CRABBOX_ACTIONS_WORKFLOW
CRABBOX_ACTIONS_JOB
CRABBOX_ACTIONS_REF
CRABBOX_ACTIONS_REPO
CRABBOX_ACTIONS_RUNNER_VERSION
CRABBOX_ACTIONS_RUNNER_LABELS
CRABBOX_ACTIONS_EPHEMERAL
CRABBOX_BLACKSMITH_ORG
CRABBOX_BLACKSMITH_WORKFLOW
CRABBOX_BLACKSMITH_JOB
CRABBOX_BLACKSMITH_REF
CRABBOX_BLACKSMITH_IDLE_TIMEOUT
CRABBOX_BLACKSMITH_DEBUG
CRABBOX_RESULTS_JUNIT
CRABBOX_SYNC_CHECKSUM
CRABBOX_SYNC_DELETE
CRABBOX_SYNC_GIT_SEED
CRABBOX_SYNC_FINGERPRINT
CRABBOX_SYNC_BASE_REF
CRABBOX_SYNC_TIMEOUT
CRABBOX_SYNC_WARN_FILES
CRABBOX_SYNC_WARN_BYTES
CRABBOX_SYNC_FAIL_FILES
CRABBOX_SYNC_FAIL_BYTES
CRABBOX_SYNC_ALLOW_LARGE
CRABBOX_ENV_ALLOW
CRABBOX_CACHE_PNPM/NPM/DOCKER/GIT
CRABBOX_CACHE_MAX_GB
CRABBOX_CACHE_PURGE_ON_RELEASE
Provider/deploy variables live outside normal CLI operation:
CRABBOX_CLOUDFLARE_API_TOKEN
CRABBOX_CLOUDFLARE_ACCOUNT_ID
CRABBOX_CLOUDFLARE_ZONE_ID
HCLOUD_TOKEN
AWS_PROFILE/AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY
GITHUB_TOKEN
#Output Rules
Human output:
acquiring lease profile=project-check ttl=90m
leased cbx_abcdef123456 slug=blue-lobster provider=aws server=i-0123 type=c7a.48xlarge ip=203.0.113.10 idle_timeout=30m0s expires=2026-05-01T17:30:00Z
syncing 184 files -> /work/crabbox/cbx_abcdef123456/openclaw
running pnpm check:changed
...
released cbx_abcdef123456
JSON output:
{
"leaseId": "cbx_abcdef123456",
"machineId": "hz-ccx33-01",
"state": "released",
"exitCode": 0
}
No progress bars when stdout is not a TTY.