Machine0 Provider
Machine0 is a built-in direct Linux SSH-lease provider. Crabbox uses the machine0 CLI for VM lifecycle and its stable JSON surfaces, then uses the normal Crabbox OpenSSH transport for sync, commands, desktop tunnels, WebVNC, and code-server.
Targets: Linux.
Capabilities: SSH, Crabbox sync, cleanup, desktop/browser/code, explicit pause/resume, provider-native versioned image checkpoints, and live CPU/GPU size and cost discovery.
#Install and authenticate
Install the Machine0 CLI yourself; Crabbox never installs or upgrades it:
npm install -g @machine0/cli
machine0 --version
machine0 login
For non-interactive environments, Machine0 also supports MACHINE0_API_TOKEN. Authentication remains owned by Machine0: Crabbox passes the current process environment to the CLI but never reads, logs, or persists the token. crabbox doctor --provider machine0 checks the CLI, authentication, inventory, live size catalog, and the same SSH-key prerequisites used before new VM creation. It does not create VMs, upload/download keys, or change the account default. ssh_key_prerequisites=checked is not proof of successful guest SSH authentication; runtime remains unchecked without a running lease.
#Quick start
machine0 sizes --json
crabbox providers sizes machine0
crabbox warmup --provider machine0 --slug linux-ci
crabbox warmup --provider machine0 --class fast --slug larger-ci
crabbox run --provider machine0 --id linux-ci -- go test ./...
crabbox ssh --provider machine0 --id linux-ci
crabbox stop --provider machine0 linux-ci
stop destroys the Machine0 VM by default. This is deliberate: Machine0 VMs are persistent, and retaining either compute or snapshots can continue to cost money.
#Configuration
provider: machine0
machine0:
cliPath: machine0
image: ubuntu-24-04-loaded
imageVersion: 0 # 0 selects the active image version
desktopImage: "" # optional prepared image used only with --desktop
size: large
region: eu
key: ci-key # optional; empty uses Machine0's default SSH key
workRoot: "" # dynamic: /home/<resolved-ssh-user>/crabbox
releasePolicy: destroy
createTimeout: 15m
pollInterval: 60s
The equivalent flags are:
--machine0-cli
--machine0-image
--machine0-image-version
--machine0-desktop-image
--machine0-size
--machine0-region
--machine0-key
--machine0-work-root
--machine0-release-policy destroy|suspend
--machine0-create-timeout
--machine0-poll-interval
Environment overrides use the same names with the CRABBOX_MACHINE0_ prefix, for example CRABBOX_MACHINE0_SIZE, CRABBOX_MACHINE0_REGION, CRABBOX_MACHINE0_IMAGE, CRABBOX_MACHINE0_KEY, and CRABBOX_MACHINE0_RELEASE_POLICY.
An omitted or empty machine0.workRoot is a dynamic sentinel. After resolving the VM, Crabbox uses the same effective SSH username for access and storage: /home/ubuntu/crabbox for Ubuntu and /home/nix/crabbox for NixOS. The resolved root is recorded on the server and claim, then reused for repository sync, later runs, resolves, and checkpoint workdirs. crabbox config show renders the unresolved default as <dynamic:/home/<resolved-ssh-user>/crabbox>.
An explicit machine0.workRoot, --machine0-work-root, or CRABBOX_MACHINE0_WORK_ROOT is preserved exactly and replaces the dynamic home-root behavior.
Machine0's key is the registered public or managed key name supplied to machine0 new --key. When the VM details return key.fileName, that filename is authoritative because it identifies the key actually injected into the VM. When inventory omits the filename but retains a managed key name, Crabbox derives Machine0's canonical machine0__<key-name> filename instead. It resolves the provider-owned filename under SSH_KEY_PATH or the default ~/.ssh directory before readiness checks. Crabbox runs machine0 ssh <vm> true only when the resolved private-key file is absent, then verifies that the CLI actually materialized the file. Existing key files skip the Machine0 CLI entirely, so ordinary resume and checkpoint restart do not depend on the CLI's global known_hosts; Crabbox continues to perform its own direct SSH host-key handling. The provider-owned path overrides a generic --ssh-key, which remains available only when Machine0 provides no usable provider-owned key identity. Set SSH_KEY_PATH when Machine0 uses a custom key directory.
Before creating a VM with a PUBLIC key, Crabbox checks the selected key's local filename and rejects a proven mismatch with the registered public key. It uses noninteractive ssh-keygen -y on the private file, not its .pub sidecar. Encrypted or unsupported keys, nonregular files, and missing public metadata remain unverified; this check does not prove that SSH authentication will succeed. Crabbox never changes the selected key or downloads PUBLIC private keys to repair a mismatch.
Before creation, Crabbox reads machine0 keys get <name> --json for the configured key or the default name discovered by machine0 keys ls --json. List rows can omit fileName; the detail response supplies the authoritative filename for the existing PUBLIC-key preflight. A selected default without a name, or a failed or mismatched detail read, stops preflight. These reads do not request or download private-key fields.
When no default key is registered and no explicit key is selected, the native Machine0 CLI falls back to id_rsa and id_rsa.pub under SSH_KEY_PATH (or ~/.ssh). Doctor and new creation require both to be regular files before allowing that path. Their presence does not prove their contents form a usable key pair. Doctor never invokes the native fallback, which can upload a public key during creation. To avoid that fallback, select an existing managed or PUBLIC key with --machine0-key. Replaying an already-owned fixed lease keeps its recorded key identity and does not recheck today's default-key selection.
Machine0 SSH targets use a provider-isolated host-trust file under <key-directory>/crabbox/machine0/known_hosts.d/, keyed by a hash of the immutable Machine0 machine ID. The directory is private (0700), OpenSSH host checking remains enabled with accept-new, and Crabbox never edits the user's shared ~/.ssh/known_hosts. Ordinary acquire and resolve operations preserve the per-machine file for continuity. After a provider-authorized checkpoint restart or suspended-machine resume, Crabbox removes only that machine's isolated file before its SSH readiness check so a rotated host key can be accepted even when Machine0 reuses the same IP.
#Live sizes, GPUs, and cost
Crabbox publishes the following convenience mappings for its standard machine classes, using shapes from the Machine0 size catalog:
| Class | Machine0 size | vCPUs | RAM |
|---|---|---|---|
tiny | large | 2 | 4 GB |
small | xl | 4 | 8 GB |
standard | xxl | 8 | 16 GB |
fast | xxxl | 16 | 64 GB |
large | 4xl | 32 | 128 GB |
beast | 5xl | 48 | 192 GB |
The static classCatalog in crabbox providers --json and crabbox providers describe machine0 --json reports these mappings. Machine0 does not appear in the legacy top-level classes compatibility projection. These aliases are conditional creation choices, not a guarantee of current availability or a way to resize an existing machine. The live native size catalog is authoritative for sizes, resources, prices, and available regions.
An explicitly configured machine0.size, CRABBOX_MACHINE0_SIZE, or --machine0-size always wins over a portable class, even when the selected size is the normal large default. Native sizes follow the usual configuration precedence: YAML, then environment, then CLI. They may name any live Machine0 size, including GPU, NVMe, premium, and larger CPU shapes outside this convenience catalog. An explicitly selected class supplies its mapped size only when no native size was configured; omitting both preserves the existing large default. Crabbox never hardcodes a reduced allowed-size enum or price table: before creation it reads machine0 sizes --all --json and verifies that the selected size exists and is currently offered in the requested region.
crabbox providers sizes machine0 --json
crabbox providers sizes machine0 --all --refresh
crabbox providers sizes machine0 --with-context --class fast --all --json
crabbox warmup --provider machine0 --class fast --type xl-nvme --slug native-ci
The static matrix and providers describe machine0 --json advertise sizeSelection: "type". Each live catalog name is the exact value for the existing --type flag; native names are not portable class names. Keep the configured --class and omit --type to preserve configured defaults. Add --type <name> only to select a native size explicitly. Generic --type wins over both native configuration and --machine0-size, regardless of flag order; --machine0-size wins over inherited native or generic type configuration.
With --with-context --json, discovery returns sizes plus selection: { "selector": "type", "effectiveType": "xxxl", "region": "eu" } for class fast with no explicit native configuration. YAML or environment native large instead reports effectiveType: "large". The region is the effective Machine0 region. Unavailable or missing configured types remain visible in selection; no fallback size or resource estimate is invented. The ordinary JSON array and human table do not change. --all includes sizes unavailable everywhere; check a row's regions for availability in the effective region. The installed Machine0 CLI must also support the chosen size.
The JSON output preserves exact hourly microcurrency integers (1_000_000 = 1 currency unit), vCPU, RAM, boot disk, transfer allowance, estimated snapshot size, default image, available regions, and GPU label, VRAM, and scratch-disk capacity. Human output converts the exact integer to a currency-unit hourly value only for display.
The current Machine0 region names are us-east, us-west, uk, eu, and asia, but the live size catalog is authoritative. Capacity can still fail regionally after validation; Crabbox preserves the CLI diagnostic and removes a partially created VM unless --keep was explicit.
Before accepting a created VM, Crabbox verifies that its reported size equals the requested size. A mismatch fails with the existing rollback policy for ordinary leases; fixed leases retain their durable attempt and refuse mismatched replay. GPU catalog membership does not prove image compatibility: Crabbox supplies its configured image explicitly, so Machine0's automatic GPU image selection does not apply.
A fixed create with a retained attempt but no attested resource ID remains unresolved. Crabbox cannot authorize deletion from its name alone; inspect the exact VM through Machine0 before any manual provider cleanup.
#Lifecycle and reuse
Native size, region, image, image version, desktop image, and registered key select a new machine. Their flags report creationOnly: true in crabbox providers describe machine0 --json. Machine0 has no supported in-place resize: changing these selectors or a generic class does not resize or replace an existing lease. Reuse reports the observed machine size and retains its immutable Machine0 ID. Config values and class labels are selection intent, not evidence of an existing machine's capacity. Creating or forking a separate machine remains a distinct lifecycle operation.
Prewarm uses these selectors for creation but does not forward their flags to hydration or probes, which reuse the created lease. It validates the provider configuration those follow-ups will reload before allocating a machine. A creation override does not repair an invalid saved value for a follow-up; correct the saved configuration first.
CLI path, work root, release policy, polling interval, and creation timeout remain usable with existing machines. Despite its name, creation timeout also bounds resume, suspend, and checkpoint waits.
machine0 new returns before a VM is usable. Crabbox polls get --json through CREATING and STARTING, requires a RUNNING VM with an IP, and treats ERRORED and UNAVAILABLE as terminal failures with the Machine0 diagnostic. Provisioning can take 20 minutes or longer, so set machine0.createTimeout to cover the expected creation window when necessary.
The Machine0 resource ID—not its IP—is the stable lease identity. Every resolve refreshes the VM JSON and SSH endpoint. This matters after suspend: stop/start preserves an IP, while suspend removes compute and a later start can assign a different IP. Crabbox always prefers defaultSSHUsername returned by Machine0, falling back to ubuntu for Ubuntu and nix for NixOS.
For canonical dashed UUID lookups (8-4-4-4-12 hexadecimal digits), Crabbox reads machine0 ls --json, validates the inventory and every row's UUID, and requires exactly one matching UUID, ignoring hexadecimal letter case. It then fetches full details with machine0 get <current-name> --json and requires both the original UUID and the selected name to match. Inventory summaries are never returned as full details: they can omit the SSH key, default SSH username, and other metadata. Ordinary name lookups, including named readiness polls, remain direct detail reads without an extra inventory request.
Only a successful, complete, valid inventory with no exact UUID match reports the UUID as absent from the current authorized inventory. Missing or malformed IDs, duplicate matches, authentication/read/JSON errors, and failed detail reads fail closed; they do not establish absence. A reused name or a UUID/name change between inventory and detail reads is rejected. The name is only a transport address: CloudID, ImmutableID, and claim scope remain bound to the UUID, and lookup does not delete or rebind claims. This verifies identity across the lookup reads; it does not make later name-addressed mutations atomic with those reads or remove the existing remote name-reuse race before mutation.
Use --keep to keep a normal Crabbox run lease for later reuse. Adopt an existing unclaimed Machine0 VM only through an explicit --reclaim reuse; destructive release requires an exact local claim bound to the Machine0 ID.
If a local claim is missing, a canonical Crabbox lease ID can suggest a Crabbox-named VM from Machine0 inventory, but the short name hash cannot prove the full lease identity. Even a unique match fails closed with a candidate-name hint. Inspect that machine and use its explicit name with --reclaim to adopt it; Crabbox fetches its full details, including its SSH key and endpoint. Discovery alone never authorizes reuse or deletion.
Machine0 VM names are limited to 31 lowercase letters, digits, and hyphens. Crabbox truncates only the human slug portion and retains an eight-character lease hash, so long requested slugs remain deterministic. The short hash can collide; durable claims, not name hashes, establish lease ownership.
#Fixed-ID replay
warmup --lease-id cbx_<12 lowercase hex> makes direct Machine0 acquisition idempotent across process restarts. Before machine0 new, Crabbox writes the normalized create intent and exact create request to the ordinary durable lease claim under its existing cross-process lock. The intent is bound to the deterministic VM name derived from the lease ID and allocated slug. The durable create attempt authorizes the first visible matching VM and records its exact Machine0 resource ID; every later adoption must match that ID. A matching name or slug alone never authorizes reuse.
Canonical cbx_ lease IDs are never passed to Machine0 as native VM names. Without a local claim, inventory provides only the recovery hint described above; no matching candidate returns not found. Native-name and UUID inspection remain available.
Prepared fixed claims remain held until a durable attempt and full native machine details establish ownership. An empty persisted record is not proof that creation never started: older clients could erase an ambiguous attempt. This also means a current preflight failure, although known not to have submitted in that invocation, cannot authorize creation or cancellation from its empty record in a later process. inspect, status, and stop report unresolved ownership instead of inventing an absent or never-started resource.
For an attested resource, inspect and stop resolve the original fixed lease ID without replaying creation, starting the VM, or requiring SSH readiness. They work with creating, stopped, suspended, and errored VMs. The immutable UUID is persisted after the first attested detail, before later readiness or SSH failure can lose the binding. A prepared attempt absent from inventory stays held, even when it was previously observed; an acquired resource whose absence is confirmed can be finalized by stop. Automatic cleanup skips incomplete fixed acquisition.
An acquired fixed lease missing from the current inventory is not enough to prove deletion in its original account: stop retains the claim for inspection. Account-bound checkpoint retirement can reconcile its own source absence.
Validated released tombstones report state: "released"; repeat stop succeeds without changing or removing the tombstone, and status --wait reports the existing terminal-state error. Malformed tombstones fail closed. Released fixed IDs can never be replayed. Resuming a released or confirmed-missing fixed lease returns an error rather than reporting success without a live machine.
Current catalog capacity is checked only when creating a new VM. An exact, attested owned VM can replay even if its size disappears from the catalog or loses regional availability. A changed selector still conflicts with the durable intent before any provider mutation; replay never substitutes a size or creates a replacement VM.
An ambiguous create remains pinned to its original name, size, region, image, image version, and key. Replay fails closed without another machine0 new call while that attempt has no visible machine, deliberately accepting a false negative if the process stopped after persisting the attempt but before sending the request. When machine0 new returns an error, the same resolver checks inventory for an attested VM. An empty result never clears the attempt or proves the request cannot finish later. Further inspection, stop, or exact replay may reconcile a visible resource, but never submit another create.
The machine0 ls --json summary can omit imageVersion and a VM's SSH-key object. Fixed replay uses inventory only to discover the exact resource, then reads machine0 get <vm> --json before validating the durable attempt or starting the VM. Detail must match both the inventory ID and name, the pinned size, region, image and version, and any selected SSH key. Missing pinned versions, mismatched fields, and failed detail reads stop replay without creating a replacement. When detail omits only the key type, Crabbox preserves the inventory type after rejecting conflicting key names or types. Public-key semantics and generic SSH-key fallback without a selected provider key remain supported. Readiness refreshes must pass the same attestation before binding or starting. Destroy rechecks full details under the claim lock immediately before the name-based removal. These checks reject observed replacements; they do not provide atomic fencing against a privileged replacement inside the native CLI request.
Once creation may have succeeded, later readiness or SSH failures never roll the VM back: the caller's fixed lease identity remains bound to it, and a matching replay can finish adoption. Repository binding is also durable; --reclaim is the explicit override for replay from a different repository. With machine0.releasePolicy: suspend, release keeps the live fixed claim and replay starts the exact suspended machine before refreshing its endpoint.
Destroy release replaces the live claim with a compact terminal tombstone, so a fixed ID is single-use and automatic cleanup never makes it replayable. Fixed claims and tombstones use the downgrade-safe local discriminator machine0-fixed-v1: current clients map it to runtime provider machine0, while older clients see an unknown provider and skip or refuse destructive cleanup instead of erasing fixed identity state.
Machine0 stop and suspend are intentionally distinct:
machine0 stoppreserves the instance and IP and continues billing compute. Do not treat it as a cost-saving operation.crabbox pause --provider machine0 <lease>callsmachine0 suspend --yes, polls until Machine0 reports exactSUSPENDED, then clears the recorded SSH endpoint. This preserves the boot disk as billed snapshot storage while releasing compute.crabbox resume --provider machine0 <lease>callsmachine0 start, waits forRUNNING, and records the refreshed IP.crabbox stopdestroys withmachine0 rm --yesunlessmachine0.releasePolicy: suspendor the matching flag is explicitly active.
#Images and checkpoints
Machine0 named images are reusable, versioned snapshots. Crabbox exposes them through the provider-neutral checkpoint commands:
crabbox checkpoint create --id linux-ci --mode native --strategy image --name ci-baseline
crabbox checkpoint inspect <checkpoint-id> --verify
crabbox checkpoint fork <checkpoint-id> --slug experiment
crabbox checkpoint fork <checkpoint-id> --class fast --type xl-nvme --slug native-fork
crabbox checkpoint delete <checkpoint-id>
Verified inspection and listing (--verify), deletion, and pruning use the current Crabbox configuration, including machine0.cliPath (or CRABBOX_MACHINE0_CLI) and machine0.pollInterval. A custom executable does not need to be on PATH. Provider-backed deletion keeps the local checkpoint record if configuration or resource verification fails.
An explicit --type also selects the exact native size for a checkpoint fork. The fork uses the checkpoint's recorded region and image version. The provider still enforces image and disk compatibility; a catalog row alone does not prove that a smaller target can boot a larger snapshot.
Creation flushes a running source over SSH, calls machine0 stop, waits for exact STOPPED, and then uses machine0 images save <vm> <image>. The VM stays stopped while Crabbox polls the exact metadata-matching version until its underlying snapshot reports READY. Only then does Crabbox start a source it stopped, wait for RUNNING and SSH, and atomically refresh the endpoint in the lease claim. A source that was already STOPPED also waits for snapshot readiness but remains stopped afterward; Crabbox never pretends it owned that state transition.
Machine0's stopped-snapshot barrier is mandatory even with checkpoint --wait=false: that flag may allow the returned version to remain DRAFT, but its underlying snapshot must be READY before a running source can restart. The barrier uses --wait-timeout when it is positive, otherwise machine0.createTimeout. Stop continues billing compute, so this is a consistency requirement rather than a cost-saving lifecycle action.
For source retirement, use the explicit replayable checkpoint create --retire-source contract with a caller-persisted --checkpoint-id. It records submission and observed image/version identity durably, returns pending without starting the source, and removes the source only after its exact snapshot is READY. STARTING and STOPPING are pending observations, not destruction proof. Lost save or remove responses retain the same operation for reconciliation. Ordinary stop, resume, reuse, and cleanup cannot take over its source. Readiness probes hold the source claim fence through start, SSH preparation, and endpoint publication; status touches authorize inside their mutation fence as well. Capture admission uses that same fence, including the interval after journal reservation but before claim binding. Read-only status does not start the source or publish a new claim generation.
The native CLI accepts names for save and lifecycle mutations. Crabbox checks the immutable source identity again at each observable boundary and rejects a replacement; remote checkpoint metadata is correlation, not independent source attestation. These checks are not atomic remote fencing: a separately privileged administrator replacing a managed name inside an opaque native CLI request is outside the cooperating Crabbox owner contract. The adapter does not assume an undocumented immutable-ID getter or conditional mutation API.
Reusing an image name creates a new version, which Crabbox records and passes back through --image-version when forking. A draft becomes usable only after its underlying snapshot reports READY; DRAFT status by itself is not readiness. Deletion is always an explicit checkpoint operation: Crabbox removes a whole image only when that checkpoint created the name, the exact owned version metadata still matches, and it remains the image's only version. If later versions exist, Crabbox refuses whole-image deletion so it cannot erase unrelated work. For an existing image name, deletion targets only the recorded draft version. Machine0 suspend snapshots such as suspended-<machine>-<timestamp> remain lifecycle artifacts, not reusable named checkpoint records.
If an ordinary or legacy image has no captured account binding, missing inventory cannot prove deletion: verification and deletion retain its checkpoint metadata. A visible, exact legacy image can still be deleted; that invocation verifies absence under the same freshly observed account without rewriting old metadata.
If the image still exists but its recorded version is already missing before deletion, verification reports unknown/check_runtime and deletion refuses with exit 4, retaining local metadata for manual reconciliation. A version deletion admitted after exact ownership checks can confirm that version's removal in the same invocation, including after a lost remove response, while preserving sibling versions. Whole-image deletion requires confirmed absence of the whole image; an existing image with no versions is not sufficient. Failed lookups, credentials, or identity checks never prove absence. No ordinary deletion-attempt state is persisted to authorize a later retry.
Image and suspended-snapshot storage is billed separately. Removing or destroying a VM does not imply that unrelated named images should be deleted. Image-version storage prices may be fractional values; Crabbox preserves their JSON decimal representation in checkpoint metadata instead of coercing them to integer microcurrency.
#Rate limits and troubleshooting
Machine0 accounts have finite hourly API read quotas, and one CLI status or inventory invocation can perform multiple API requests. The default machine0.pollInterval of 60s reduces polling volume about twelvefold compared with 5s; a 20-minute boot needs roughly 20 polls instead of roughly 240, leaving headroom for final inspection and cleanup. At most 55 seconds of additional readiness-observation latency is negligible beside the documented 15-minute timeout and observed 10–21-minute creation windows.
When the CLI returns either exact Rate limited. Please wait a moment and try again. or The cloud provider is temporarily unavailable. Please try again shortly. response, Crabbox quietly retries read-only inventory and status calls (get, ls, sizes, and image reads) until the current command's context expires or is canceled. The retry cadence follows machine0.pollInterval (default 60s, with a one-second minimum) and prints only one concise warning. A cached-credentials warning preceding either response does not prevent recognition.
Crabbox never automatically retries Machine0 mutations such as create, start, stop, suspend, remove, image save/delete, or SSH key priming. A failed mutation may already have reached Machine0, so inspect the exact VM or image identity before deciding whether a manual retry is safe.
#Optional live smoke
The dedicated live runner builds the current Crabbox binary unless CRABBOX_BIN is explicit, performs read-only Machine0 auth/catalog/key preflight, creates one short-lived VM, proves no-sync execution and ID-stable pause/resume with an IP change, exercises a native checkpoint by default, then destroys the VM and verifies the machine, image, and local claim are gone.
CRABBOX_LIVE=1 \
CRABBOX_LIVE_COORDINATOR=0 \
CRABBOX_LIVE_PROVIDERS=machine0 \
CRABBOX_LIVE_MACHINE0_SIZE=medium \
CRABBOX_LIVE_MACHINE0_IMAGE=ubuntu-24-04 \
CRABBOX_LIVE_MACHINE0_REGION=eu \
CRABBOX_LIVE_MACHINE0_KEY=ci-key \
scripts/live-smoke.sh
Use CRABBOX_LIVE_MACHINE0_SIZE, CRABBOX_LIVE_MACHINE0_IMAGE, CRABBOX_LIVE_MACHINE0_REGION, and CRABBOX_LIVE_MACHINE0_CLI to select the safe test capacity. Defaults are medium, ubuntu-24-04, and eu. CRABBOX_LIVE_MACHINE0_CHECKPOINT=0 skips the checkpoint lane; checkpoint coverage defaults on. The runner never enables desktop/VNC or opens ports.
#Desktop and network security
Machine0 does not provide a built-in desktop. --desktop, --browser, and --code use Crabbox's existing Linux SSH preparation and tunnel flow. An optional machine0.desktopImage can select a prepared reusable desktop image; when empty, Crabbox's automatic package preparation currently assumes the Ubuntu/default apt-compatible image. NixOS and custom images should provide a prepared machine0.desktopImage with the required desktop, VNC, and WebVNC packages instead of relying on automatic setup.
crabbox warmup --provider machine0 --desktop --browser
crabbox webvnc --provider machine0 --id <lease> --open
Crabbox does not open VNC 5901 or WebVNC 6080 publicly. Access remains inside the SSH tunnel, and the provider never attaches a Machine0 profile or forwards profile credentials during creation. Machine0's authenticated HTTPS URL proxies the VM's port 80 and is retained in provider metadata for inspection; it is not a substitute for the SSH-tunneled desktop path.
Machine0 images can contain credentials written into the guest, and those credentials survive snapshots. Keep image contents generic, review them before sharing, and use Crabbox's normal allowlisted run-time environment forwarding instead of baking secrets into a reusable image.
#CLI contract
On POSIX hosts, Crabbox captures native JSON responses through private regular files because the CLI can exit before asynchronous pipe writes finish. Capture files are unlinked before the CLI starts; they leave no named output files, including when the operation is killed. Windows and non-JSON commands retain pipe capture.
Each output stream retains the existing 16 MiB limit. Crabbox monitors file growth and cancels the command on overflow; temporary disk use can exceed that limit between observations and process termination, while returned output is strictly capped. An inherited writer that outlives the command produces an explicit incomplete-capture error, with no partial output accepted as success.
The adapter uses the documented CLI. Prior lifecycle testing used @machine0/cli 1.0.155:
machine0 new,get --json,ls --json,start,suspend --yes, andrm --yesfor VM lifecycle;machine0 sshonly to verify/materialize Machine0-managed key access;machine0 sizes --all --jsonfor live availability and prices;machine0 images ls/get/save/rmand image-version removal for native checkpoints.
On 2026-08-28, read-only checks with @machine0/cli 1.0.164 observed native get <UUID> returning No such procedure for an existing VM, while inventory and full details by name succeeded under the same authentication. The repaired Crabbox UUID lookup returned that same VM's verified identity and SSH username; an absent UUID returned a clean absence error. A missing-procedure error alone neither diagnoses authentication failure nor establishes resource existence. These checks did not verify the full 1.0.164 lifecycle. The public 1.0.164 package routes canonical UUIDs to machines.getMachineById, names to machines.getByName, and inventory to machines.list through the same CLI authentication client. The native machine command documentation describes get <vm>; the separately documented MCP UUID lookup uses a different transport and is not Crabbox's CLI contract.
Crabbox therefore resolves canonical UUIDs through inventory and verified name-addressed full details without issuing native UUID get first or matching an error message to trigger a fallback. Both reads retain the existing outage retry behavior. Mutations remain single-attempt, with existing ownership guards unchanged; no direct API or MCP authentication path is added.
Crabbox does not use Machine0's published OpenAPI document because it is not the VM control-plane contract. All command execution is behind an injectable runner so unit tests require neither a Machine0 account nor network access.