Read when:
- choosing
provider: boat(preferred) or the legacyprovider: ascii-box; - configuring the Boat / ASCII Box API endpoint or workdir;
- changing
internal/providers/asciibox.
Rename note (September 2026): ASCII renamed Box to Boat. Crabbox accepts
boatas the current user-facing provider selector. The historicalascii-box,ascii, andasciiboxnames remain compatible so existing configuration and durable lease state continue to resolve safely.The canonical provider id stays
ascii-boxso durable lease and claim state keeps resolving. Crabbox reads both the renamedsandbox/sandboxesCLI JSON envelopes and the legacybox/boxesones, and prefers theboatbinary when the legacyboxcommand is not installed, so one build works across the migration.
Boat (by ASCII) provides persistent Ubuntu sandbox VMs.
Crabbox uses the documented legacy box --json automation surface and the public
Box API for keyed fixed-ID creation, lets box ssh prepare the CLI-managed SSH key, and then runs
normal Crabbox sync and commands over SSH. The provider does not depend on
private exec, upload, or command-stream REST endpoints.
Use Boat when commands should run in ASCII-managed Ubuntu sandboxes through the provider's SSH endpoint. Use a delegated provider such as Upstash Box, Modal, E2B, Islo, or Cloudflare when the provider owns command execution instead of exposing SSH.
- Create a Boat/ASCII account. Current product home: https://boat.dev.
- Export the existing API key as
ASCII_BOX_API_KEYorCRABBOX_ASCII_BOX_API_KEYwhile the Crabbox adapter remains on the legacy compatibility contract. - Install the compatible
boxCLI. Crabbox discovers the platform-specific config path throughbox status --json, writes a private config from the API key under its state directory, and does not require a pre-existingbox login.
The current Boat website advertises a new boat CLI. Migrating Crabbox's native
CLI invocation, environment names, API base URL, config keys, and persisted claim
identity should be done as a separately verified compatibility change rather than
silently changing all of those boundaries at once.
crabbox warmup --provider boat
crabbox run --provider boat -- pnpm test
crabbox run --provider boat --id blue-lobster --shell 'pnpm install && pnpm test'
crabbox status --provider boat --id blue-lobster
crabbox stop --provider boat blue-lobsterLegacy selectors remain accepted:
ascii-box
ascii
asciibox
export ASCII_BOX_API_KEY=...CRABBOX_ASCII_BOX_BASE_URL or asciiBox.baseUrl can override the current
legacy adapter default https://ascii.dev. Custom endpoints require HTTPS,
except literal loopback hosts may use HTTP. Userinfo, queries, and fragments are
rejected before the API key is written to CLI configuration or passed to the
CLI. On 2026-10-03, authenticated list requests to both https://ascii.dev
and https://boat.dev returned HTTP 200 directly, without redirects. The default
therefore remains https://ascii.dev; keep a lease on its recorded endpoint.
BOX_ORG selects an organization by ID or name. Without it, Crabbox explicitly
uses personal; the native CLI's sticky organization selection is not inherited.
Keep the same endpoint and organization selector when reusing or stopping a lease.
For fixed-ID API creation, use an organization ID, rather than its display
name, in BOX_ORG; omit it or use personal for personal billing.
crabbox warmup --provider boat --lease-id cbx_123456789abc
crabbox warmup --provider boat --lease-id cbx_123456789abc
crabbox stop --provider boat cbx_123456789abcThe shared fixed-lease engine durably records the normalized intent, endpoint and
organization-or-personal scope, and an Idempotency-Key derived from the lease ID
and intent fingerprint before sending POST /api/box/v1/boxes. The API chooses
the immutable Box ID; there is no caller-chosen native ID or create-time name.
Crabbox stores the returned ID before readiness or SSH preparation. Identical
replays look up that exact ID and verify its creation timestamp within the
tolerance described below, plus its recorded scope. Changed intent, scope, or native identity produces lease_id_conflict.
Identity requires an exact Box id match and a valid API createdAt within
±5 seconds, inclusive, of the create-response timestamp. Fixed claims retain
that original timestamp in CloudImmutableID and ascii_box_created_at through
replay, readiness, and release; later reads never move the comparison window.
Existing claims already use this format and require no migration.
The timestamp witnesses possible ID reuse, rather than exact clock agreement.
Boat generates random bx_ IDs; a different box reusing the same ID within five
seconds is not a realistic reuse scenario. Its create response and stored row do
use different clocks: live create/read observations differed by 11 ms and 15 ms.
A different ID, invalid timestamp, or timestamp outside the window remains a
conflict. subdomain and createdById are not identity witnesses: fresh create
responses can omit both, and the API permits renaming subdomains.
An identity mismatch immediately after this claim submitted creation fails
acquisition with ascii_box_identity_contract, naming the Box and its stop
command. If the exact Box ID still matches and the durable submission journal
proves the failed create (observed/submitting phase), inspect remains available
and stop can delete that Box using the ID alone. Interrupted deletion preserves
this authority for retry. This exception never authorizes acquisition, an
already acquired claim whose timestamp is outside the tolerance, or a different
Box ID. Existing scope, deletion-operation, and complete-inventory checks apply.
The public API retains idempotency keys
for 24 hours (asciiBoxIdempotencyWindow). If the response is lost before
Crabbox records a Box ID, the engine permits one recovery submission with the
same key and body, strictly before 24 hours have elapsed from its recorded first
submission. The existing intent TTL may expire earlier. The engine records the
recovery submission before sending it and bounds its context to the remaining
window; the HTTP client also limits each call to 30 seconds. Redirects and hidden
HTTP transport replays are disabled. A crash after admission consumes that
submission even if the request never reached the service.
After that one recovery attempt, at or beyond the window boundary, or if the clock moves behind the original submission time, Crabbox retains the unresolved attempt and never submits another create. A returned Box ID also permanently ends create submission, including when that Box is temporarily absent or fails readiness. Complete inventory has no idempotency-key attribution, so Crabbox does not adopt a Box from its name or a coincidental inventory match. Preserve local Crabbox state and inspect unresolved resources with the provider tools.
Release validates the exact-ID deletion operation and proves the Box absent
with a native 404 and complete inventory confirmation. Background data purge
may still be pending or blocked; the fixed terminal receipt preserves its
operation ID as informational metadata. The engine retains a single-use terminal
tombstone. Repeating stop is safe, and the lease ID can never allocate another Box. Use a
new lease ID for later work. Native 404 plus complete inventory absence can
finalize a known Box; an uncertain attempt without a returned ID stays retained.
Account identity remains a limitation: scope evidence is only the endpoint and organization selector. Two personal account keys on the same endpoint are indistinguishable, while native idempotency keys are account-scoped. Keep the original account selected for recovery, replay, and release; switching accounts invalidates the provider's same-key guarantee. Credentials are not persisted in the engine's attempt or fingerprint.
Preferred provider selector with the current compatibility configuration block:
provider: boat
target: linux
asciiBox:
baseUrl: https://ascii.dev
cliPath: box
workdir: /home/user/crabboxProvider flags (legacy compatibility names):
--ascii-box-base-url
--ascii-box-cli
--ascii-box-workdir
Environment overrides (legacy compatibility names):
CRABBOX_ASCII_BOX_API_KEY / ASCII_BOX_API_KEY
CRABBOX_ASCII_BOX_BASE_URL / ASCII_BOX_BASE_URL
CRABBOX_ASCII_BOX_CLI / BOX_CLI
CRABBOX_ASCII_BOX_HOME
CRABBOX_ASCII_BOX_WORKDIR
BOX_ORG
The following describes ordinary, generated lease IDs. Fixed IDs use the shared engine described above and retain terminal records instead of removing claims.
crabbox warmup --provider boatcreates a sandbox throughbox new --json, verifies the original Box ID and creation timestamp (within ±5 seconds) throughbox info, stores an exact local ownership claim before preparing the SSH key withbox ssh <id> -- true, waits for SSH, and keeps the sandbox untilcrabbox stop. The default SSH key lives in the private CLI home (CRABBOX_ASCII_BOX_HOME, otherwise Crabbox state).crabbox run --provider boatprovisions a sandbox for one run, or reuses an existing claimed lease/slug/Box ID, then uses the standard SSH sync and run path. Reuse requires a matching endpoint, organization, Box ID, and creation timestamp within ±5 seconds.--reclaimmay transfer repository ownership of an already owned lease; it does not adopt an unclaimed sandbox.crabbox statusresolves the local lease claim or raw Box id and reads native state throughbox info --json.crabbox stoprequires the exact, unchanged local claim and freshly matching native identity before remote teardown or each native mutation. It releases the sandbox withbox stop --json, requests deletion withbox delete --json --yes, and validates the returned deletion operation's ID, kind, and exact Box target. It releases the claim once an exact native 404 and completebox list --allinventory prove the Box absent, even if the background data purge remains pending, processing, or blocked. While the Box is still observable, Crabbox continues checking its deletion operation and retains the claim. A successful native process exit alone does not prove resource absence or data purge completion. The claim stays locked through teardown, deletion, retries, confirmation, and local removal. If the service temporarily refuses deletion until a recent snapshot exists, Crabbox shortens the sandbox TTL, waits for its managed stop transition, and retries deletion for up to two minutes, within a three-minute overall release budget that also honors caller cancellation, including deletion-operation polling. Missing, malformed, or changed operation evidence, failed absence checks, and cancellation retain the claim without recording completion. The shared native CLI SSH key is retained.
The Boat API deletion-operation schema
distinguishes resource removal from background data purge. Once an operation
exists, its target is unavailable to list, restore, and fork. Purge stages can
wait for upload URLs to expire, retained dependent snapshots, active restores,
or automatic retries. These waits do not extend Crabbox's release budget:
Crabbox proves resource absence independently and does not claim that stored
data has finished purging. Fixed terminal receipts retain
ascii_box_deletion_operation for subsequent provider-side inspection.
When the legacy box executable also prints a rename notice on stderr, the
structured JSON response on stdout remains authoritative for exact not-found
evidence.
Cleanup reports its current native-call phase and elapsed time at roughly ten-second intervals, including while a native command is blocked. A remaining budget is shown only when that command's context has a deadline; progress does not extend it or impose a new whole-command timeout. Claim-lock waits and best-effort remote teardown are outside this native-call progress reporter. Deletion-wait failures retain the exact operation and its last validated status in the error. Native command capture is capped at 8 MiB per stream; oversized or incomplete output is an error, never evidence of completed deletion.
SSH host trust is separate from the shared native authentication key. Readiness,
reuse, and guarded teardown use a protected known_hosts file for the exact
Crabbox lease, so a new Box may reuse an IP or gateway endpoint without inheriting
another lease's host key. A changed host key within the same lease is still
rejected. Existing leases from before lease-scoped trust enroll on their first
connection with the new client; Crabbox does not copy or remove pins from the
old provider-wide file.
If this release observes a valid native deletion acceptance but cannot finish
proving absence because of a timeout, cancellation, or lookup failure, it
durably records the exact operation ID and its claim binding before returning
the error. The binding covers the original provider scope, Box ID, creation
timestamp, and repository owner. This records acceptance, not completion. A later
crabbox stop first checks the exact Box identity. If the Box remains observable,
Crabbox validates any recorded operation before proceeding. Pending, processing,
or blocked operations retain the claim without SSH teardown or another deletion
request. A matching operation that reports completed also retains the claim
while the Box remains observable because those native results are inconsistent.
If box info instead returns a recognized native 404 and complete
box list --all inventory also omits the exact Box ID, Crabbox reconciles the
unchanged local claim without reading a stale operation or repeating native
deletion. Crabbox repeats these checks inside the actual release fence before
removing the claim; an earlier lookup during lease resolution does not authorize
finalization.
If the data purge reports completion but final absence confirmation
fails or is canceled, it durably records that completed deletion in the
still-locked claim before returning the error. The record is bound to the
original claim, including its provider scope, Box ID, creation timestamp, and
repository owner. A later crabbox stop can finish cleanup without repeating
native deletion only when that record still matches, box info reports
not-found, and complete native inventory confirms absence. Failed lookups,
changed claims, or an observable sandbox retain the claim.
Completion records from earlier unreleased builds that proved only native request acceptance are rejected, not upgraded into operation-completion evidence.
Exact native 404 plus complete inventory absence independently proves absence;
it authorizes only removal of the unchanged local claim and never another native
mutation. Failed or partial inventory, an observable matching ID, a replacement
identity, cancellation, and missing or malformed native responses retain the
claim. Command startup, output-capture, and transport failures do not count as
native 404 evidence, even when their text mentions 404 or not found.
Ordinary stop and stop --force --provider boat --id <canonical-cbx-id> use
the same core absence-evidence transaction. It verifies the original endpoint
and organization selector, exact native not-found, and complete unfiltered
inventory before removing only the unchanged local claim under its lock. The
result is forgotten locally (resource absent), distinct from a native release.
Fixed-ID records, checkpoint holds, and coordinator/runtime-adapter registrations
remain with their existing lifecycle owners.
ASCII Box exposes no authenticated account-attestation operation. Its claim
scope is the endpoint plus BOX_ORG, defaulting to personal. Two personal
account keys on the same endpoint are indistinguishable by this evidence; keep
the original account selected when recovering an absent resource. Crabbox does
not infer an account identity from an empty inventory.
Missing, malformed, changed, or incomplete operation-record bindings are
rejected before native lookups. There is no automatic adoption
of an external deletion receipt, replacement of a recorded operation, or
conversion of an old claim into completed-deletion authority.
Raw IDs, provider aliases, and legacy claims without the full ownership binding
remain inspectable but cannot authorize reuse or deletion. Missing or changed
identity outside the timestamp tolerance, failed lookups, incomplete inventory,
and uncertain deletion preserve the local claim. Apart from failed-own-create
cleanup described above, there is no implicit adoption or legacy upgrade; inspect such
resources with the native provider tools and manage them explicitly there after
verifying ownership. Setup rollback likewise targets only the original confirmed
creation attempt. If that attempt already published an exact claim, rollback
preserves accepted-operation references and completed-deletion records in that
same claim for a later safe crabbox stop retry. Unpublished attempts keep their
separate expected-absence guard; rollback never adopts a replacement claim.
Resources are retained when ownership or completion cannot be proven.
The adapter intentionally does not rewrite historical claim provider names or
ownership labels as part of the branding change. Those values participate in
fail-closed lifecycle checks. boat is routed to the same registered provider,
so users can adopt the current name without invalidating pre-rename local state.
A future native-CLI/config migration should preserve or explicitly migrate those
bindings with regression and live lifecycle proof.
status, list, and read-only resolution report the Box's native creation,
update, and expiry fields. Missing native facts stay unknown; reading a Box does
not reset its age, substitute the reader's lease defaults, or invent an expiry.
A matching local claim can supply recorded TTL, idle timeout, retention, and
Crabbox activity. Native update time is not Crabbox activity, and native Box
expiry is separate from the local lease's inactivity deadline.
Acquisition records the effective requested TTL and retention once. Ordinary
reuse preserves those recorded values and the existing idle timeout rather than
replacing them with new defaults, including for fixed lease IDs. Explicit run --id ... --idle-timeout ... or
heartbeat --id ... --idle-timeout ... updates local idle policy. Heartbeat
persists local activity and any explicit idle replacement, but does not extend
the Box's native expiry. Claims with deletion recovery pending cannot be touched;
finish their existing stop recovery first.
Older versions could overwrite recorded policy during reuse. The original values cannot be reconstructed; observations preserve the history that is actually recorded, and reads never manufacture missing history. Native identity and the existing deletion-operation evidence remain separate from display metadata.
--class,--type, image, size, and keep-alive options are not exposed because the currently integrated CLI lifecycle surface does not document them.- Desktop/VNC/code features are not advertised through Crabbox for this provider. Use the official Boat/ASCII tools directly for interactive sessions.