Tensorlake Provider
Read when:
- choosing
provider: tensorlake(aliases:tl,tensorlake-sbx); - configuring the Tensorlake sandbox image, snapshot, sizing, organization, or project;
- changing
internal/providers/tensorlake.
Tensorlake is a delegated run provider (provider family firecracker). Crabbox shells out to the tensorlake CLI (tensorlake sbx ...) for sandbox lifecycle and command execution. Tensorlake owns the Firecracker MicroVM and the command transport; Crabbox owns local config, repo claims, sync manifests and guardrails, slugs, timing summaries, and normalized list/status rendering.
#When To Use
Use Tensorlake when the remote sandbox should be a Tensorlake Firecracker MicroVM and commands should run through tensorlake sbx exec. Use AWS, Hetzner, Static SSH, or Daytona when you need Crabbox-native SSH access, since Tensorlake does not expose SSH through Crabbox.
#Prerequisites
- The
tensorlakeCLI must be onPATH, or pointed at with--tensorlake-cli/tensorlake.cliPath. Crabbox invokestensorlake sbx create,exec,cp,describe,ls,terminate, andwhoami --output json. Use a current native CLI with API-key scope introspection and exact sandbox details (verified with Tensorlake CLI 0.5.118). - A Tensorlake API key from cloud.tensorlake.ai. Crabbox passes it to the CLI through the
TENSORLAKE_API_KEYenvironment variable; it is never placed on the command line.
#Commands
crabbox warmup --provider tensorlake --tensorlake-image <image>
crabbox run --provider tensorlake -- pnpm test
crabbox run --provider tensorlake --id blue-lobster --shell 'pnpm install && pnpm test'
crabbox status --provider tensorlake --id blue-lobster
crabbox stop --provider tensorlake blue-lobster
Tensorlake publishes a Crabbox-ready public image, tl-crabbox (--tensorlake-image tl-crabbox): the standard Ubuntu base plus a writable /workspace parent for Crabbox's default /workspace/crabbox workdir and pnpm preinstalled. On the stock Tensorlake images, commands run as tl-user, which cannot create /workspace; either pin tl-crabbox or set tensorlake.workdir to a user-writable path such as /home/tl-user/crabbox.
Ordinary nonzero native CLI exits remain command exits. Transport, cancellation, deadline, and output errors instead fail the run with exit code 1 and the matching timing status, even when the local process also reports a nonzero exit code. An already observed command exit is not replaced by later cancellation. Native CLI diagnostic exits cannot be distinguished from remote workload exits without stronger evidence from the native protocol.
#Auth
export TENSORLAKE_API_KEY=tl_apiKey_...
The API key is read from CRABBOX_TENSORLAKE_API_KEY or TENSORLAKE_API_KEY. It remains environment-only in Crabbox configuration, with no YAML field or key flag. The first raw nonempty primary or fallback environment value wins. TENSORLAKE_API_URL (or tensorlake.apiUrl) overrides the default https://api.tensorlake.ai. TENSORLAKE_ORGANIZATION_ID and TENSORLAKE_PROJECT_ID select the org and project when your account spans more than one; the namespace also falls back to INDEXIFY_NAMESPACE.
Crabbox pins the effective API URL and namespace on every native invocation (defaults: https://api.tensorlake.ai and default). The API key's introspected organization and project must agree with any explicit selectors. Rotating a key within the same scope is supported; changing accounts, endpoints, or namespaces does not retarget existing leases. Native login/config defaults and inherited PAT, debug, or Git-token overrides cannot replace that binding. Scope probes capture and discard native credential prefixes; neither keys nor their prefixes are stored in ownership claims or printed by these probes.
#Config
provider: tensorlake
target: linux
tensorlake:
apiUrl: https://api.tensorlake.ai
cliPath: tensorlake
image: tl-crabbox # Crabbox-ready public image; "" uses the CLI default
snapshot: "" # snapshot ID to restore from (alternative to image)
organizationId: ""
projectId: ""
namespace: ""
workdir: /workspace/crabbox # absolute path; sync target and -w for exec
cpus: 1.0
memoryMB: 1024
diskMB: 10240
timeoutSecs: 0 # sandbox lifetime timeout; 0 leaves it to Tensorlake
noInternet: false # block outbound internet from the sandbox
Provider flags:
--tensorlake-api-url
--tensorlake-cli
--tensorlake-image
--tensorlake-snapshot
--tensorlake-organization-id
--tensorlake-project-id
--tensorlake-namespace
--tensorlake-workdir
--tensorlake-cpus
--tensorlake-memory-mb
--tensorlake-disk-mb
--tensorlake-timeout-secs
--tensorlake-no-internet
Each flag has a matching CRABBOX_TENSORLAKE_* environment override (for example CRABBOX_TENSORLAKE_IMAGE, CRABBOX_TENSORLAKE_CPUS, CRABBOX_TENSORLAKE_NO_INTERNET). The API URL, organization, project, and namespace are passed to the CLI as --api-url, --organization, --project, and --namespace.
All fourteen configuration bindings share one typed declaration. Nonempty YAML strings override earlier values without trimming; omitted, null, and empty strings preserve them. YAML CPU, memory, disk, and timeout values apply only when positive. Environment numeric parsers retain the earlier value on malformed input but accept parsed zero/negative values, as do explicit flags. Existing native creation omits nonpositive sizing/timeouts; configuration loading does not add a new rejection. Explicit noInternet: false remains meaningful.
The API URL, native CLI binary, and workdir helpers share their compiled defaults while retaining their different trimming rules. Empty image/snapshot values still leave the choice to Tensorlake. The native namespace fallback to default is scope-pinning policy, not a nonempty config default. Credential-source tracking, the later explicit-API-URL flag phase, native environment binding, and ownership checks remain unchanged.
#Runtime environment forwarding
Forwarding uses the normal Crabbox allowlist:
crabbox run --provider tensorlake --allow-env API_TOKEN -- printenv API_TOKEN
crabbox run --provider tensorlake --env-from-profile ~/.my-live.profile --allow-env API_TOKEN -- npm test
Crabbox prints only redacted presence/length metadata for the forwarded names. The allowed values are written to a temporary local shell profile, uploaded into the sandbox under /tmp, sourced for the duration of the command, and removed (local and remote) best-effort afterward. Values are never placed on the local tensorlake process argv.
#Lifecycle
warmuporrunwithout--idgenerates a Crabbox-owned sandbox name (crabbox-<repo-slug>-<random6>) and runstensorlake sbx createwith the configured CPU, memory, disk, timeout, image, and snapshot. The Tensorlake-assigned sandbox ID is parsed from stdout and used as the canonical identifier.- The local lease is stored as
tlsbx_<sandbox-id>with a friendly slug and a durable repo claim bound to the exact sandbox ID, API endpoints, API-key organization/project, requested namespace, and reported sandbox namespace. - By default
runarchive-syncs the working tree: agit ls-files-driven manifest is packed into a gzipped tar locally, uploaded withtensorlake sbx cpto/tmp/crabbox-tensorlake-sync-*.tgz, and extracted into the configured workdir. The complete archive is checked and built before fresh allocation. Delete-sync stages extraction before replacing the existing workspace; non-delete sync merges into it. A bounded cleanup attempt removes partial uploads and staging directories even when transfer fails or is canceled, warning on cleanup failure without replacing the original outcome. Pass--no-syncto skip the archive step (the workdir is still created). - The command runs via
tensorlake sbx exec -w <workdir> <id> -- <cmd>, streaming stdout and stderr back through Crabbox. - On release the original claim and provider scope are rechecked while claim changes are fenced, then the sandbox is terminated with
tensorlake sbx terminate <id>unless--keepwas set. The claim is removed only after exact sandbox metadata confirmsterminated. Failed or ambiguous confirmation retains the claim; retrying stop can confirm archived terminated metadata without issuing another termination.--keep-on-failureretains a newly created sandbox after a failed run and prints a rerun/stop hint.
Reuse, one-shot teardown, and failed-acquisition rollback use the same exact identity checks. A changed claim blocks stale cleanup. Native control calls are bounded; authentication, malformed output, and missing metadata fail closed. An empty list or a not found response alone is not deletion proof.
Run retention, cleanup outcomes, and final timing use the shared delegated lifecycle. Fresh setup, sync, and command-preparation failures honor --keep-on-failure; failed automatic termination returns a failed run with a kept recovery session. Later cleanup or timing errors do not replace an earlier command failure. Environment-profile cleanup remains warning-only. Profile and sandbox cleanup receive separate bounded contexts; a timing writer failure after successful deletion cannot make the deleted sandbox recoverable again.
Local options and required configuration are validated first. Fresh archives are still prepared before allocation; reused leases are authorized before archive preparation. This normalizes failure ordering without changing exact ownership checks or adding another provider-specific preparation policy.
Cleanup of an existing bound claim has a single 30-second budget covering the claim-lock wait, identity recheck, termination, and confirmation. A shorter caller deadline still applies. Expiry before admission performs no native operation and retains the claim for retry. Run-admission and create/reclaim publication waits also honor the caller's context. Failed-create rollback gets its own detached 30-second budget before waiting for the absent-claim fence; caller cancellation does not prevent cleanup of the original verified resource, while an appearing claim still blocks termination. A rollback timeout retains the unclaimed sandbox for manual inspection.
Successful provider actions still finish durable publication or removal if cancellation arrives afterward. Read-only List/Status fence waits retain their existing policy, and local filesystem syscalls are not forcibly interruptible.
#Legacy and uncertain ownership
Older provider-only claims cannot prove account or resource ownership. Crabbox will not reuse, stop, or silently adopt them, including with --reclaim. Preserve the claim and inspect the exact sandbox with the native CLI using the intended API endpoint, namespace, and API key. After independently verifying ownership, an operator can terminate it with tensorlake sbx terminate <sandbox-id> and confirm its terminated state with tensorlake sbx describe <sandbox-id>. Create a fresh Crabbox lease for future managed runs; do not edit an old claim to add guessed binding fields. Uncertain creation reports the generated sandbox name or ID for this same manual inspection path.
The local claim fence coordinates Crabbox processes, not external Tensorlake administrators. Native termination has no atomic expected-account condition; Crabbox verifies scope immediately before it and never falls back from a canonical sandbox ID to a mutable name.
run --lease-output records the Tensorlake lease, reuse/retention state, and matching crabbox stop --provider tensorlake --id ... cleanup command for orchestrators that need to inspect or clean up retained sandboxes later.
#Capabilities
- SSH: not driven by Crabbox. The
tensorlakeCLI offers its owntensorlake sbx ssh, but Crabbox does not proxy it. - Crabbox sync: yes — gzipped tar uploaded via
tensorlake sbx cpand extracted in-sandbox. - Provider sync: no separate Tensorlake sync command.
- URL bridge: no — Tensorlake does not expose a per-sandbox ingress URL through Crabbox today.
- Desktop / browser / code: no Crabbox VNC or code-server surface.
- Actions hydration: no.
- Coordinator: no — Tensorlake always runs direct from the CLI and never goes through the broker.
#Gotchas
--sync-onlyand--checksumare rejected because Tensorlake does not expose Crabbox's rsync semantics. Other transport-owning flags (such as local stdout/stderr captures,--download,--artifact-glob, and--require-artifact) are rejected by the core delegated-sync gate. Use--no-syncwith an explicit--idif the sandbox is already primed.- Large-sync guardrails still apply; pass
--force-sync-largewhen a large archive sync is intentional. --shellwraps the command asbash -lc '<joined args>'. Inferred shell source and unquoted operators or leading assignments use the same shell. Literal profile arguments stay data, including assignment-shaped executable names. Adding an environment profile does not reinterpret those arguments as shell syntax; a single inferred source string remains executable source.- Forwarded environment values live in a temporary in-sandbox profile for the duration of the command, with an unpredictable per-operation name. The private local source is removed after upload returns, including partial-upload failure. Cleanup is attempted after upload failure or cancellation with a fresh 30-second budget, but refuses remote mutation if the original claim or provider scope no longer matches. Cleanup failures warn without replacing the original outcome. The command does not run if sourcing its profile fails. Remote file permissions remain governed by native
sbx cp, not a new Crabbox permission guarantee. Avoid forwarding broad wildcard allowlists unless you trust the sandbox and command. tensorlake.workdirmust be an absolute path (default/workspace/crabbox) and cannot be a broad system directory such as/,/tmp, or/workspace. It serves as both the sync target and the-wworking directory for exec. The default requires a writable/workspace; thetl-crabboximage provides one, otherwise pointworkdirat a user-writable path.- IDs accepted by
--idandstopare Crabbox slugs,tlsbx_<sandbox-id>lease IDs, and canonical 21-character lowercase-alphanumeric sandbox IDs that have an exact bound local Crabbox claim. Sandboxes without such a claim are rejected; an exact ID never falls back to a matching slug.
Related docs:
- Run your test suite with Crabbox — Tensorlake's walkthrough for running Crabbox on Tensorlake sandboxes.
- Provider backends