API Reference
Get a handle with sandbox(name) from @alienplatform/sdk (TypeScript) or alien_bindings::Bindings::from_env()?.sandbox(name).await? (Rust). The Rust request and response types live in alien_bindings::traits.
Every sandbox uses the image, limits, and network rules declared in alien.ts. No call can override them.
An operation the platform does not support raises OPERATION_NOT_SUPPORTED. Check Platform Capabilities or call capabilities() before relying on anything beyond create, run, and terminate.
capabilities
Lists what this platform's backend supports.
const names: string[] = await box.capabilities()
if (names.includes("jobs")) { /* start a job */ }Returns: TypeScript: the names of the supported capabilities. Rust: a SandboxCapabilities struct with one bool per capability. The TypeScript list never contains snapshot, because the TypeScript binding has no method for it.
create
Creates a sandbox and resolves once it can run a command.
create(options?: CreateSandboxOptions): Promise<SandboxInstance>
const created = await box.create()| Parameter | Type | Required | Description |
|---|---|---|---|
sandboxId | string | No | Requested id. Honored on Local and Kubernetes. AWS, Azure, and GCP allocate their own id and ignore this. |
env | Record<string, string> | No | Environment for every command. Azure only; AWS and GCP refuse it, Kubernetes and Local ignore it. Use env on runCommand for portable code. |
tenantKey | string | No | Not supported. AWS, Azure, and GCP refuse it; Kubernetes and Local ignore it. |
timeoutMs | number | No | Lifetime of this sandbox in milliseconds. AWS and GCP only. It can shorten the declared maxLifetimeSeconds, never extend it. |
Returns: a SandboxInstance. Keep its sandboxId; every later call addresses the sandbox by it.
Errors: OPERATION_NOT_SUPPORTED for an option the platform refuses. SANDBOX_UNREACHABLE (AWS, GCP) or SANDBOX_COMMAND_FAILED (Azure) when the sandbox isn't ready in time. SANDBOX_NOT_AS_DECLARED (Azure) when it started without its egress policy; create a new one.
get
Fetches a sandbox by id. Requires reconnect.
get(sandboxId: string): Promise<SandboxInstance | null>
const found = await box.get(sandboxId)| Parameter | Type | Required | Description |
|---|---|---|---|
sandboxId | string | Yes | The id create or getOrCreate returned. |
Returns: the sandbox, or null / None if it doesn't exist. On Kubernetes, only the process that created a sandbox can get it.
getOrCreate
Fetches the sandbox named by sandboxId, or creates one if it does not exist, and reports which happened.
getOrCreate(options?: CreateSandboxOptions): Promise<ResolvedSandbox>
const { sandbox, created } = await box.getOrCreate({ sandboxId: savedId })Takes the same options as create. timeoutMs bounds only a sandbox this call creates; a found sandbox keeps the lifetime it was created with.
Returns: { sandbox, created }. The call isn't atomic: two callers with the same id can both get created: true.
list
Lists the sandboxes of this Sandbox resource.
list(): Promise<SandboxInstance[]>Returns: the sandboxes on GCP and Local. On Kubernetes, only the sandboxes the calling process created.
Errors: OPERATION_NOT_SUPPORTED on AWS and Azure. Reach a sandbox whose id you hold with get.
runCommand
Runs a command and streams its output.
runCommand(sandboxId: string, command: string, options: RunCommandOptions): AsyncIterable<CommandFrame>
for await (const frame of box.runCommand(sandboxId, "python3", {
args: ["main.py"],
timeoutMs: 60_000,
})) {
if (frame.kind === "stdout") process.stdout.write(frame.data)
if (frame.kind === "exit") console.log(frame.exitCode, frame.truncated)
}| Parameter | Type | Required | Description |
|---|---|---|---|
sandboxId | string | Yes | The sandbox to run in. |
command | string | Yes | The program to run, without a shell. For a shell line, pass sh with args: ["-c", line]. |
options.timeoutMs | number | Yes | How long the command may run. At most 24 hours on Azure and Local. |
options.args | string[] | No | Arguments, each passed as one argument. |
options.cwd | string | No | Working directory inside the sandbox. |
options.env | Record<string, string> | No | Environment for this command, on top of the sandbox's own. |
Returns: stdout and stderr frames with raw bytes, then one exit frame with the exit code. truncated is true when output hit the size cap. A non-zero exit code is not an error.
Errors: SANDBOX_COMMAND_FAILED when the command didn't finish, including a timeout. SANDBOX_OUTCOME_UNKNOWN when it was sent and may have run; don't repeat it. SANDBOX_UNREACHABLE when it was never sent; safe to retry.
startJob
Starts a command as a job that outlives this call. Requires jobs (AWS, GCP, Kubernetes).
startJob(sandboxId: string, command: string, options: RunCommandOptions): Promise<string>
const jobId = await box.startJob(sandboxId, "make", { args: ["test"], timeoutMs: 20 * 60_000 })Takes the same parameters as runCommand.
Returns: the job id (JobStart { job_id } in Rust).
Errors: SANDBOX_OUTCOME_UNKNOWN when the job may have started; don't repeat it. A start is refused while 16 jobs are running.
pollJob
Reads a job's output after a sequence number, and how it ended once it has. Requires jobs.
pollJob(sandboxId: string, jobId: string, sinceSeq?: number): Promise<JobPoll>
const poll = await box.pollJob(sandboxId, jobId, lastSeq)| Parameter | Type | Required | Description |
|---|---|---|---|
sandboxId | string | Yes | The sandbox the job runs in. |
jobId | string | Yes | The id startJob returned. |
sinceSeq | number | No | Return only frames after this seq. Omit to read from the first frame; afterwards pass the highest seq you have seen. |
Returns: { running, frames, exit?, error? }. exit is set when the command exited, error when it ended another way, such as a timeout.
Errors: SANDBOX_UNREACHABLE is safe to retry.
cancelJob
Stops a job's command. Requires jobs.
cancelJob(sandboxId: string, jobId: string): Promise<void>Errors: SANDBOX_UNREACHABLE is safe to retry.
readFile
Reads a file out of the sandbox. Requires files.
readFile(sandboxId: string, path: string): Promise<Buffer>
const report = await box.readFile(sandboxId, "work/report.json")| Parameter | Type | Required | Description |
|---|---|---|---|
sandboxId | string | Yes | The sandbox to read from. |
path | string | Yes | Path inside the sandbox. .. is refused. See Files. |
Returns: the file's bytes. At most 32 MiB on AWS, GCP, and Kubernetes.
Errors: A refused path or a file over the size cap is not retryable. SANDBOX_UNREACHABLE is safe to retry.
writeFiles
Writes files into the sandbox, creating parent directories. Requires files.
writeFiles(sandboxId: string, files: Record<string, Buffer | string>): Promise<void>
await box.writeFiles(sandboxId, { "work/main.py": "print('hello')" })| Parameter | Type | Required | Description |
|---|---|---|---|
sandboxId | string | Yes | The sandbox to write to. |
files | Record<string, Buffer | string> | Yes | Path to contents. A string is written as UTF-8. At most 32 MiB per file on AWS, GCP, and Kubernetes. |
The TypeScript binding writes files one at a time, so a failure can leave some files written.
Errors: A refused path or a file over the size cap is not retryable. SANDBOX_UNREACHABLE is safe to retry.
pause / resume
Pauses a sandbox with its state preserved, and resumes it. Requires pauseResume (AWS, Azure).
pause(sandboxId: string): Promise<void>
resume(sandboxId: string): Promise<void>A running command is suspended with the sandbox, and its timeout stops counting until resume. On Azure, the sandbox is deleted once a paused command's timeout passes.
terminate
Destroys a sandbox. Idempotent: terminating a sandbox that does not exist succeeds.
terminate(sandboxId: string): Promise<void>On Azure and GCP, terminate returns after the platform confirms the sandbox is gone.
preview
Returns an endpoint and headers for reaching a port inside the sandbox, such as a web server the code started. Requires preview: AWS when the declaration lists previewPorts, and Local.
preview(sandboxId: string, port: number): Promise<SandboxPreview>
const preview = await box.preview(sandboxId, 8080)| Parameter | Type | Required | Description |
|---|---|---|---|
sandboxId | string | Yes | The sandbox to reach. |
port | number | Yes | Must be listed in the declaration's previewPorts. Any other port raises OPERATION_NOT_SUPPORTED. |
Returns: a SandboxPreview (Rust: PreviewCapability): send requests to endpoint with the headers. On AWS it expires after 30 minutes. On Local it's bound to 127.0.0.1 and doesn't expire.
snapshot
Rust only. No platform reports it. GCP captures a snapshot that nothing can restore yet; elsewhere the call raises OPERATION_NOT_SUPPORTED.
async fn snapshot(&self, sandbox_id: &str) -> Result<String>Types
interface SandboxInstance {
sandboxId: string // the id every later call addresses
state: "starting" | "running" | "paused" | "terminated"
generation: number // changes when the sandbox is replaced; compare for equality
}
interface ResolvedSandbox {
sandbox: SandboxInstance
created: boolean // true when this call created it
}
interface CreateSandboxOptions {
sandboxId?: string
tenantKey?: string
env?: Record<string, string>
timeoutMs?: number
}
interface RunCommandOptions {
timeoutMs: number
args?: string[]
cwd?: string
env?: Record<string, string>
}
type CommandFrame =
| { kind: "stdout" | "stderr"; seq: number; data: Buffer }
| { kind: "exit"; exitCode: number; truncated: boolean }
interface JobPoll {
running: boolean
frames: CommandFrame[]
exit?: { code: number; truncated: boolean }
error?: { code: string; message: string } // code, e.g. "timeoutExceeded"
}Errors
Raised when the stack is planned:
| Code | Meaning | Retryable |
|---|---|---|
SANDBOX_CAPABILITY_UNSUPPORTED | The declaration needs a capability the target platform lacks. The message names the capability and the platform. | No |
SANDBOX_LIMIT_INVALID | A field of the declaration is invalid for the target platform, such as a quantity no AWS size or Azure sizing rule allows, or an image in the wrong form. | No |
SANDBOX_PLATFORM_UNSUPPORTED | The target platform has no sandbox backend. | No |
Raised by the binding:
| Code | Meaning | Retryable |
|---|---|---|
OPERATION_NOT_SUPPORTED | The platform does not support this operation or option. | No |
SANDBOX_UNREACHABLE | The operation did not reach the sandbox, or the connection dropped before it took effect. | Yes |
SANDBOX_OUTCOME_UNKNOWN | The operation was sent and never reported its outcome. It may have taken effect; don't repeat a command or job start. | No |
SANDBOX_COMMAND_FAILED | A command or sandbox operation did not complete, including a command that reached its timeout. | No |
SANDBOX_NOT_AS_DECLARED | Azure only. The sandbox came up without a restriction its declaration asked for, such as its egress policy. Create a new one. | No |
INVALID_INPUT | A request value is invalid, such as a create-time timeoutMs of 0 on AWS or GCP. | No |
In TypeScript, errors are AlienError values; match on error.code. isSandboxOutcomeUnknown(error) from @alienplatform/bindings also finds the code when it is wrapped in another error.
Platform Capabilities
The capabilities a declaration is checked against when the stack is planned. Create, run, and terminate work everywhere and are not listed.
| Capability | AWS | GCP | Azure | Kubernetes | Local |
|---|---|---|---|---|---|
files: read and write files | yes | yes | yes | yes | yes |
reconnect: reach a sandbox from a later call | yes | yes | yes | yes | yes |
jobs: start, poll, and cancel jobs | yes | yes | no | yes | no |
preview: reach a port inside the sandbox | yes | no | no | no | yes |
pauseResume | yes | no | yes | no | no |
snapshot | no | no | no | no | no |
domainEgressRules: allowDomains egress | no | no | yes | no | no |
egressDeny: deny egress is enforced | yes, except DNS | yes | yes | yes | yes |
enforcedLimits: cpu, memory, and disk ceilings | yes | yes, except disk | yes | yes | yes |
processLimit: maxProcesses | no | no | no | no | yes |
sandboxLifetime: maxLifetimeSeconds | yes | yes | no | yes | no |
supervisorPidNamespace | no | no | no | no | no |
supervisorIsolation: the command runs as a different user than the process supervising it | yes | no | no | no | yes |
At runtime, capabilities() returns the same table, except that AWS reports preview only when the declaration lists previewPorts, and Kubernetes doesn't report sandboxLifetime.