Sandboxes
@solarisdk/sandbox: classes SandboxClient and Sandbox. A sandbox is a headless microVM for commands, code, files, and git. See the TypeScript SDK hub for install and configuration.
npm install @solarisdk/sandboxSandbox method below is inherited from SessionHandle and is also available on Desktop. A Desktop is a Sandbox plus the GUI surface.Contents
SandboxClient: new SandboxClient(), create(), createDesktop(), connect(), get(), list(), listAll(), kill(), listSnapshots(), getSnapshot(), deleteSnapshot(), promoteSnapshot(), volumes.create(), volumes.list(), volumes.get(), volumes.delete()Sandbox: connect(), reconnect(), close(), commands.run(), commands.start(), commands.connect(), pty.create(), runCode(), createCodeContext(), files.*, git.*, env(), downloadUrl(), uploadUrl(), volumes.mount(), metrics(), snapshot(), revert(), pause(), resume(), setTimeout(), previewUrl(), kill()- Types:
CreateSandboxOptions,SandboxView,CommandOptions,CommandResult,CommandHandle,PtyOptions,PtyHandle,RunCodeOptions,RunCodeResult,Chart,FsEntry,FsStat,GitStatus,MetricsResult,SnapshotView,VolumeView, errors
SandboxClient
The sandbox entry point. Talks the gateway HTTP API.
Properties
volumesVolumeClient: persistent volume CRUD. Attach one at create time viacreate({ volumes }).
Constructors
new SandboxClient()
new SandboxClient(options: SandboxClientOptions, kind?: "sandbox" | "desktop"): SandboxClientCreates a client. Does not open any connection.
Parameters:
options.apiKeystring: required.options.baseUrlstring: required, e.g.https://api.getsolari.com.options.fetch?typeof fetch: defaults to the global.options.callTimeoutMs?number: per-RPC timeout for handles this client creates.kind?"sandbox" | "desktop": the flavourcreate()makes. Default"sandbox".
Returns: SandboxClient
Throws: SolariError if apiKey or baseUrl is missing.
Example:
import { SandboxClient } from "@solarisdk/sandbox";
const client = new SandboxClient({
apiKey: process.env.SOLARI_API_KEY!,
baseUrl: "https://api.getsolari.com",
});Methods
create()
create(opts?: CreateSandboxOptions): Promise<Sandbox>Creates a sandbox and returns a live handle. The call sends an idempotency key, so retrying is safe.
Parameters:
opts?CreateSandboxOptions: see CreateSandboxOptions.
Returns: Promise<Sandbox>
Throws: AuthError, PlanError, ConcurrencyLimitError, NoCapacityError, or GatewayError.
Example:
const sbx = await client.create({
template: "base",
cpu: 2,
memMb: 4096,
envs: { NODE_ENV: "test" },
});createDesktop()
createDesktop(opts?: CreateDesktopV2Options): Promise<Desktop>Creates a GUI session over the same /sandboxes route and returns a Desktop handle. Adds resolution and record to the sandbox options.
Parameters:
opts?CreateDesktopV2Options:CreateSandboxOptionsplusresolution?string andrecord?boolean.
Returns: Promise<Desktop>
Example:
const vm = await client.createDesktop({
template: "office",
resolution: "1280x720",
});connect()
connect(sandboxId: string): Promise<Sandbox>Re-attaches to a running sandbox by id.
Parameters:
sandboxIdstring: the sandbox id.
Returns: Promise<Sandbox>
Throws: GatewayError if the id is unknown.
Example:
const sbx = await client.connect("sbx_abc123");
await sbx.commands.run("uptime");DesktopClient.connect(), this only rebuilds a handle from get(). Call resume() on it if the sandbox is paused.get()
get(sandboxId: string): Promise<SandboxView>Fetches a sandbox’s current record: state, kind, metadata, resources. Does not return a handle.
Parameters:
sandboxIdstring: the sandbox id.
Returns: Promise<SandboxView>
Example:
const view = await client.get("sbx_abc123");
console.log(view.state); // "running" | "paused" | ...list()
list(opts?: ListSandboxesOptions): Promise<ListSandboxesResponse>Lists sandboxes with optional filters. One page. Follow nextCursor, or use listAll().
Parameters:
opts.metadata?Record<string, string>: match on caller-set metadata.opts.state?SandboxState:starting,running,paused,archived,releasing,gone.opts.kind?SandboxKind:sandboxordesktop.opts.limit?number: page size.opts.cursor?string: page cursor.
Returns: Promise<ListSandboxesResponse>: sandboxes + optional nextCursor.
Example:
const page = await client.list({ state: "running", limit: 50 });
console.log(page.sandboxes.length, page.nextCursor);listAll()
listAll(opts?: Omit<ListSandboxesOptions, "cursor">): AsyncGenerator<SandboxView>Auto-paginates list(), following nextCursor until exhausted.
Parameters:
opts?ListSandboxesOptions: same filters aslist(), minuscursor.
Returns: AsyncGenerator<SandboxView>
Example:
for await (const s of client.listAll({ state: "running" })) {
console.log(s.sandboxId, s.cpu, s.memMb);
}kill()
kill(sandboxId: string): Promise<void>Destroys a sandbox. Idempotent.
Parameters:
sandboxIdstring: the sandbox id.
Returns: Promise<void>
Example:
await client.kill("sbx_abc123");listSnapshots()
listSnapshots(opts?: ListSnapshotsOptions): Promise<{ snapshots: SnapshotView[] }>Lists snapshots, optionally filtered by template or kind.
Parameters:
opts.template?string,opts.kind?SandboxKind,opts.limit?number.
Returns: Promise<{ snapshots: SnapshotView[] }>
Example:
const { snapshots } = await client.listSnapshots({ template: "base" });getSnapshot()
getSnapshot(snapshotId: string): Promise<SnapshotView>Fetches one snapshot record.
Parameters:
snapshotIdstring: e.g.snap_abc123.
Returns: Promise<SnapshotView>
Example:
const snap = await client.getSnapshot("snap_abc123");
console.log(snap.sizeBytes, snap.parent);deleteSnapshot()
deleteSnapshot(snapshotId: string): Promise<void>Deletes a snapshot.
Parameters:
snapshotIdstring: the snapshot id.
Returns: Promise<void>
Throws: GatewayError if the snapshot has live children.
Example:
await client.deleteSnapshot("snap_abc123");promoteSnapshot()
promoteSnapshot(snapshotId: string, name: string): Promise<{ templateId: string; name: string }>Promotes a snapshot to a reusable template you can pass as template on future creates.
Parameters:
snapshotIdstring: the snapshot id.namestring: template name.
Returns: Promise<{ templateId: string; name: string }>
Example:
const id = await sbx.snapshot("deps-installed");
const tpl = await client.promoteSnapshot(id, "my-stack");
const fresh = await client.create({ template: tpl.templateId });volumes.create()
volumes.create(opts?: CreateVolumeOptions): Promise<VolumeView>Creates a persistent, S3-backed volume your org owns. It outlives any session.
Parameters:
opts.name?string: defaults to"volume".opts.sizeMb?number: advisory hint; storage is elastic, not a hard cap.opts.metadata?Record<string, string>: opaque labels.
Returns: Promise<VolumeView>
Example:
const vol = await client.volumes.create({ name: "datasets" });
const sbx = await client.create({
volumes: [{ volumeId: vol.volumeId, path: "/data" }],
});volumes.list()
volumes.list(): Promise<VolumeView[]>Lists the org’s volumes, newest first.
Returns: Promise<VolumeView[]>
Example:
for (const v of await client.volumes.list()) console.log(v.volumeId, v.name);volumes.get()
volumes.get(volumeId: string): Promise<VolumeView>Fetches one volume’s metadata.
Parameters:
volumeIdstring: e.g.vol_abc123.
Returns: Promise<VolumeView>
Example:
const vol = await client.volumes.get("vol_abc123");volumes.delete()
volumes.delete(volumeId: string): Promise<void>Deletes a volume’s metadata. Idempotent.
Parameters:
volumeIdstring: the volume id.
Returns: Promise<void>
Example:
await client.volumes.delete("vol_abc123");Sandbox
A live headless session. Construct via SandboxClient.create().
Properties
idstring: the session id.sandboxIdstring: alias ofid.controlUrlstring:wss://JSON-RPC control channel.expiresAtstring: ISO 8601 expiry.connectedboolean: whether the control channel is open.
Channel
connect()
connect(): Promise<void>Opens the control WebSocket. Idempotent. Call it before any control-channel method — files.*, runCode(), pty.create(), git.*, env(), volumes.mount(), and commands.start(). These do not open the channel for you; they throw ConnectionError if it is not open.
Returns: Promise<void>
Example:
const sbx = await client.create({ template: "base" });
await sbx.connect();
await sbx.files.write("/tmp/note.txt", "hi");commands.run() (no streaming callbacks, not background, no per-command env/user) runs over a warm HTTP fast path and needs no open channel — which is why the quickstart can call it right after create(). Every other control-channel method, and commands.run() once the channel is already open, requires connect() first.reconnect()
reconnect(): Promise<void>Re-opens the control socket after a drop.
Returns: Promise<void>
Example:
if (!sbx.connected) await sbx.reconnect();close()
close(): voidCloses the control channel locally. Does not release the remote session. Use kill() for that.
Returns: void
Example:
sbx.close(); // session keeps running until its timeoutCommands
commands.run()
commands.run(cmd: string, opts?: CommandOptions): Promise<CommandResult>Runs a command to completion and returns its exit code and captured output.
Parameters:
cmdstring: the program to run.opts?CommandOptions: see CommandOptions.
Returns: Promise<CommandResult>: exitCode, stdout, stderr. A non-zero exit resolves; it does not throw.
Example:
const r = await sbx.commands.run("ls", { args: ["-la", "/tmp"] });
console.log(r.exitCode, r.stdout);
// stream output as it arrives
await sbx.commands.run("npm", {
args: ["install"],
cwd: "/app",
onStdout: (d) => process.stdout.write(d),
});cmd is executed directly with args, not through a shell. Pipes, globs, and && will not expand. For shell syntax use run("sh", { args: ["-c", "…"] }).commands.start()
commands.start(cmd: string, opts?: CommandOptions): Promise<CommandHandle>Starts a command and returns a handle immediately, without waiting for exit. Use it for interactive or long-running processes.
Parameters:
cmdstring: the program to run.opts?CommandOptions: see CommandOptions.
Returns: Promise<CommandHandle>: cmdId, stdin(), onData(), wait(), kill().
Example:
const proc = await sbx.commands.start("python3", { args: ["-u", "worker.py"] });
proc.onData((c) => console.log(c.stream, c.data));
await proc.stdin("input\n");
const exitCode = await proc.wait();commands.connect()
commands.connect(): Promise<void>Re-opens the control channel so command frames flow again. An alias of reconnect().
Returns: Promise<void>
Example:
if (!sbx.connected) await sbx.commands.connect();pty.create()
pty.create(opts: PtyOptions): Promise<PtyHandle>Opens a pseudo-terminal (a real TTY), so interactive programs and curses UIs behave normally.
Parameters:
opts.colsnumber,opts.rowsnumber: required terminal size.opts.cmd?string: program to run; defaults to the guest shell.opts.cwd?string,opts.env?Record<string, string>.
Returns: Promise<PtyHandle>: ptyId, write(), resize(), onData(), kill().
Example:
const pty = await sbx.pty.create({ cols: 80, rows: 24 });
pty.onData((bytes) => process.stdout.write(new TextDecoder().decode(bytes)));
await pty.write("ls -la\n");
await pty.kill();Code
runCode()
runCode(code: string, opts?: RunCodeOptions): Promise<RunCodeResult>Runs code in a stateful kernel. Rich outputs (PNG, HTML, JSON, structured charts) come back as results items.
Parameters:
codestring: source to execute.opts.language?CodeLanguage:python(default),javascript,typescript,bash,r.opts.contextId?string: kernel context to reuse; see createCodeContext().opts.onStdout?,opts.onStderr?(data: string) => void: streamed text.
Returns: Promise<RunCodeResult>: results, charts, optional error. A runtime error in the code lands in error; it does not throw.
Example:
const r = await sbx.runCode(`
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [4, 5, 6])
plt.title("demo")
plt.show()
`);
console.log(r.charts[0]?.type); // "line"
console.log(r.charts[0]?.title); // "demo"
const png = r.results.find((i) => i.png)?.png; // base64createCodeContext()
createCodeContext(language?: "python" | "javascript" | "typescript" | "bash" | "r"): Promise<string>Creates a fresh kernel context so state persists across runCode() calls, like a REPL.
Parameters:
language?CodeLanguage: default"python".
Returns: Promise<string>, the context id.
Example:
const ctx = await sbx.createCodeContext("python");
await sbx.runCode("x = 41", { contextId: ctx });
const r = await sbx.runCode("print(x + 1)", { contextId: ctx }); // 42Files
files.* moves bytes over the control channel. For large files prefer downloadUrl() / uploadUrl().
files.read() / files.readText()
files.read(path: string): Promise<Uint8Array>
files.readText(path: string): Promise<string>Reads a file’s bytes, or its UTF-8 decoded text.
Parameters:
pathstring: absolute in-guest path.
Returns: Promise<Uint8Array> / Promise<string>
Example:
const text = await sbx.files.readText("/etc/hostname");
const bytes = await sbx.files.read("/tmp/out.bin");files.write()
files.write(path: string, data: Uint8Array | string, mode?: number): Promise<void>Writes a file, creating or truncating it.
Parameters:
pathstring: absolute in-guest path.dataUint8Array | string: content.mode?number: permission bits, e.g.0o755.
Returns: Promise<void>
Example:
await sbx.files.write("/app/run.sh", "#!/bin/sh\necho hi\n", 0o755);files.list()
files.list(path: string): Promise<FsEntry[]>Lists a directory’s entries (non-recursive).
Parameters:
pathstring: directory path.
Returns: Promise<FsEntry[]>: each with name, dir, size.
Example:
for (const e of await sbx.files.list("/app")) {
console.log(e.dir ? "d" : "-", e.name, e.size);
}files.stat()
files.stat(path: string): Promise<FsStat>Returns one entry’s metadata.
Parameters:
pathstring: file or directory path.
Returns: Promise<FsStat>: name, dir, size, mode, modTimeMs.
Example:
const st = await sbx.files.stat("/app/run.sh");
console.log(st.size, st.mode.toString(8), st.modTimeMs);files.rename()
files.rename(from: string, to: string): Promise<void>Renames or moves a path.
Parameters:
fromstring,tostring: source and destination paths.
Returns: Promise<void>
Example:
await sbx.files.rename("/tmp/a.txt", "/tmp/b.txt");files.remove()
files.remove(path: string, recursive?: boolean): Promise<void>Deletes a file or directory.
Parameters:
pathstring: path to delete.recursive?boolean: defaultfalse; required for non-empty directories.
Returns: Promise<void>
Example:
await sbx.files.remove("/tmp/build", true);files.mkdir()
files.mkdir(path: string): Promise<void>Creates a directory.
Parameters:
pathstring: directory to create.
Returns: Promise<void>
Example:
await sbx.files.mkdir("/app/data");files.search()
files.search(path: string, query: string, maxResults?: number): Promise<FsSearchMatch[]>Recursively greps for query under path.
Parameters:
pathstring: root to search.querystring: the pattern.maxResults?number: cap on matches.
Returns: Promise<FsSearchMatch[]>: each with path, line, text.
Example:
for (const m of await sbx.files.search("/app", "TODO", 20)) {
console.log(`${m.path}:${m.line}: ${m.text}`);
}files.watch()
files.watch(path: string, cb: (ev: FsWatchEvent) => void, recursive?: boolean): Promise<() => Promise<void>>Watches a path for changes. Returns an unwatch function. Call it to stop.
Parameters:
pathstring: path to watch.cb(ev: FsWatchEvent) => void: invoked per event withtypeandpath.recursive?boolean: defaultfalse.
Returns: Promise<() => Promise<void>>, the unwatch function.
Example:
const unwatch = await sbx.files.watch("/app", (ev) => {
console.log(ev.type, ev.path);
}, true);
await unwatch();files.upload() / files.download()
files.upload(path: string, data: Uint8Array | string): Promise<void>
files.download(path: string): Promise<Uint8Array>Transfer a file over the control channel. Same bytes as write() / read().
Parameters:
pathstring: in-guest path.dataUint8Array | string: upload content.
Returns: Promise<void> / Promise<Uint8Array>
Example:
await sbx.files.upload("/app/data.csv", csvString);
const out = await sbx.files.download("/app/result.json");downloadUrl()
downloadUrl(path: string): Promise<{ url: string; expiresAt?: string }>Signed, time-limited URL to download an in-guest file directly over HTTP, bypassing the control channel. Use for large files.
Parameters:
pathstring: in-guest file path.
Returns: Promise<{ url: string; expiresAt?: string }>
Throws: if the handle was not created by a client.
Example:
const { url } = await sbx.downloadUrl("/app/big.tar.gz");
const res = await fetch(url);uploadUrl()
uploadUrl(path?: string): Promise<{ url: string; expiresAt?: string }>Signed, time-limited URL to upload a file into the guest directly over HTTP.
Parameters:
path?string: destination path; optional, some backends return a prefix.
Returns: Promise<{ url: string; expiresAt?: string }>
Throws: if the handle was not created by a client.
Example:
const { url } = await sbx.uploadUrl("/app/big.zip");
await fetch(url, { method: "PUT", body: bytes });Git
Every git.* call is a non-shell git invocation in the guest, with no injection surface. Requires git on PATH, which the base template ships.
git.clone()
git.clone(url: string, opts?: GitCloneOptions): Promise<void>Clones a repository into the guest.
Parameters:
urlstring: remote URL.opts.path?string: destination dir.opts.branch?string: branch or tag.opts.depth?number: shallow-clone depth.opts.username?,opts.password?string: basic auth for private HTTPS remotes.opts.cwd?string: working directory.
Returns: Promise<void>
Throws: Error with git’s stderr on a non-zero exit.
Example:
await sbx.git.clone("https://github.com/org/repo.git", {
path: "/app/repo",
branch: "main",
depth: 1,
});git.status()
git.status(cwd?: string): Promise<GitStatus>Parsed working-tree status.
Parameters:
cwd?string: repository directory.
Returns: Promise<GitStatus>: see GitStatus.
Example:
const st = await sbx.git.status("/app/repo");
console.log(st.branch, st.clean, st.ahead, st.modified);git.add()
git.add(paths: string[], cwd?: string): Promise<void>Stages paths. An empty array is a no-op.
Parameters:
pathsstring[]: use["."]for everything.cwd?string: repository directory.
Returns: Promise<void>
Example:
await sbx.git.add(["."], "/app/repo");git.commit()
git.commit(message: string, opts?: GitCommitOptions): Promise<{ hash: string }>Commits staged changes and returns the new hash. Set author/email. An ephemeral session has no git identity.
Parameters:
messagestring: commit message.opts.cwd?string: repository directory.opts.author?,opts.email?string: identity, scoped to this commit only.opts.all?boolean: stage all tracked modifications first.
Returns: Promise<{ hash: string }>
Throws: Error on a non-zero exit.
Example:
const { hash } = await sbx.git.commit("add feature", {
cwd: "/app/repo",
author: "CI Bot",
email: "ci@example.com",
});git.push() / git.pull()
git.push(opts?: GitRemoteOptions): Promise<void>
git.pull(opts?: GitRemoteOptions): Promise<void>Pushes to or pulls from a remote. Credentials are used for this one invocation and never persisted to the repo config.
Parameters:
opts.cwd?string: repository directory.opts.remote?string: default"origin".opts.branch?string: defaults to the current branch’s upstream.opts.username?,opts.password?string: one-off HTTPS auth.
Returns: Promise<void>
Example:
await sbx.git.push({
cwd: "/app/repo",
username: "x-access-token",
password: process.env.GITHUB_TOKEN!,
});git.checkout()
git.checkout(ref: string, opts?: { cwd?: string; create?: boolean }): Promise<void>Checks out an existing ref, or creates a branch.
Parameters:
refstring: branch, tag, or commit.opts.cwd?string: repository directory.opts.create?boolean: create the branch (-b).
Returns: Promise<void>
Example:
await sbx.git.checkout("feature/x", { cwd: "/app/repo", create: true });git.branches()
git.branches(cwd?: string): Promise<GitBranch[]>Lists local branches.
Parameters:
cwd?string: repository directory.
Returns: Promise<GitBranch[]>: each with name, commit, current.
Example:
for (const b of await sbx.git.branches("/app/repo")) {
console.log(b.current ? "*" : " ", b.name, b.commit);
}git.log()
git.log(opts?: GitLogOptions): Promise<GitCommit[]>Recent commits, newest first.
Parameters:
opts.cwd?string: repository directory.opts.maxCount?number: cap the number returned.
Returns: Promise<GitCommit[]>: each with hash, author, email, date, message.
Example:
const commits = await sbx.git.log({ cwd: "/app/repo", maxCount: 10 });Lifecycle & admin
env()
env(vars: Record<string, string>): Promise<void>Injects or replaces per-session environment variables in the guest.
Parameters:
varsRecord<string, string>: the variables to set.
Returns: Promise<void>
Example:
await sbx.env({ API_URL: "https://staging.example.com" });volumes.mount()
volumes.mount(volId: string, path: string): Promise<void>Mounts a persistent volume into the running guest. Prefer attaching at create time via create({ volumes }).
Parameters:
volIdstring: volume id.pathstring: absolute in-guest mount point.
Returns: Promise<void>
Example:
await sbx.volumes.mount("vol_abc123", "/data");metrics()
metrics(): Promise<MetricsResult>Live resource usage for this session.
Returns: Promise<MetricsResult>: cpuPct, memBytes, memTotalBytes, diskBytes.
Throws: if the handle was not created by a client.
Example:
const m = await sbx.metrics();
console.log(m.cpuPct, m.memBytes / m.memTotalBytes);snapshot()
snapshot(name?: string): Promise<string>Checkpoints this running session and returns the snapshot id. The session keeps running.
Parameters:
name?string: optional label.
Returns: Promise<string>, the snapshot id.
Throws: if the handle was not created by a client.
Example:
await sbx.commands.run("pip", { args: ["install", "pandas"] });
const snapId = await sbx.snapshot("deps-installed");
// boot future sandboxes from it
const fast = await client.create({ fromSnapshot: snapId });revert()
revert(snapshotId: string): Promise<void>Restores this session in place from a snapshot. The session id stays stable.
Parameters:
snapshotIdstring: snapshot to restore.
Returns: Promise<void>
Throws: if the handle was not created by a client.
Example:
await sbx.revert(snapId); // back to a known-good statepause()
pause(): Promise<void>Saves full RAM + disk state and closes the control channel. Resume later with resume().
Returns: Promise<void>
Throws: if the handle was not created by a client.
Example:
await sbx.pause(); // stops billing for compute
await sbx.resume(); // full state restoredresume()
resume(): Promise<void>Resumes a paused session and re-points the control channel at the fresh slot.
Returns: Promise<void>
Throws: if the handle was not created by a client.
Example:
await sbx.resume();
const r = await sbx.commands.run("cat", { args: ["/tmp/state"] });setTimeout()
setTimeout(timeoutMs: number): Promise<{ expiresAt: string }>Extends the rolling idle window. Every use of the session resets it.
Parameters:
timeoutMsnumber: new idle window in ms.
Returns: Promise<{ expiresAt: string }>
Throws: if the handle was not created by a client.
Example:
const { expiresAt } = await sbx.setTimeout(30 * 60_000); // 30 minpreviewUrl()
previewUrl(port: number): Promise<{ url: string; token?: string }>Resolves a public URL for a port listening inside the guest, e.g. a dev server.
Parameters:
portnumber: the in-guest port.
Returns: Promise<{ url: string; token?: string }>: token present when the gateway signs one.
Throws: if the handle was not created by a client.
Example:
await sbx.commands.start("python3", { args: ["-m", "http.server", "3000"] });
const { url } = await sbx.previewUrl(3000);kill()
kill(): Promise<void>Destroys the remote session and closes the channel. Idempotent.
Returns: Promise<void>
Example:
try {
await sbx.commands.run("./build.sh");
} finally {
await sbx.kill();
}Types
CreateSandboxOptions
template?string: e.g."base","code","python-kernel", or a promoted template id.cpu?number: vCPUs; the host clamps to slot capacity.memMb?number: memory in MiB.diskGb?number: disk in GiB.envs?Record<string, string>: per-session env.metadata?Record<string, string>: opaque labels, filterable on list().timeoutMs?number: idle window before auto-release.fromSnapshot?string: boot from a snapshot instead of the template.lifecycle?SandboxLifecycle:{ onTimeout: "pause" | "kill", autoResume?: boolean }.volumes?VolumeAttachment[]: each{ volumeId, path }, mounted before the session starts.
SandboxView
sandboxIdstring,kindSandboxKind,stateSandboxState.metadataRecord<string, string>,expiresAtstring.cpunumber,memMbnumber.
CommandOptions
args?string[]: arguments; no shell expansion.cwd?string,user?string,timeoutMs?number.env?Record<string, string>: per-command env.background?boolean: return immediately; output still streams via callbacks.onStdout?,onStderr?(data: string) => void: streamed output.
CommandResult
exitCodenumber,stdoutstring,stderrstring.
CommandHandle
cmdIdstring: the command id.stdin(data): write to the command’s stdin.onData(cb): subscribe to{ stream, data }chunks.wait():Promise<number>, resolves with the exit code.kill(signal?): signal the process; default SIGTERM.
PtyOptions / PtyHandle
PtyOptions:cols,rows(required),cmd?,cwd?,env?.PtyHandle:ptyId,write(data),resize(cols, rows),onData(cb),kill().
RunCodeResult
resultsCodeResultItem[]: each hastype(stdout/stderr/result) plus any oftext,png,jpeg,svg,html,latex,json,markdown,chart.chartsChart[]: every chart acrossresults, flattened.error?:{ name?, message?, traceback? }or a string.
Chart
typeChartType:line,scatter,bar,pie,box_and_whisker,composite,unknown.title?,xLabel?,yLabel?string.x?,y?ChartAxis:label,ticks,scale.elements?unknown[]: per-type data (points, bars, slices).
FsEntry / FsStat / FsSearchMatch / FsWatchEvent
FsEntry:namestring,dirboolean,sizenumber.FsStat:FsEntryplusmodenumber (permission bits) andmodTimeMsnumber (unix millis).FsSearchMatch:pathstring,linenumber,textstring.FsWatchEvent:typestring,pathstring.
GitStatus
branchstring: empty on a detached HEAD or a repo with no commits.detachedboolean,cleanboolean.ahead,behindnumber: relative to the upstream, when set.staged,modified,untrackedstring[].
MetricsResult
cpuPctnumber,memBytesnumber,memTotalBytesnumber,diskBytesnumber.
SnapshotView
idstring,parentstring | null,namestring | null.sizeBytesnumber,createdAtstring,kindSandboxKind,templatestring.
VolumeView
volumeIdstring,namestring,createdAtstring.sizeMb?number,metadata?Record<string, string>.
Errors
All extend SolariError. Gateway errors also carry status, code, and body.
| Class | Status | Meaning |
|---|---|---|
AuthError | 401 | API key missing, malformed, or rejected. |
PlanError | 402 | The plan does not allow this. |
ConcurrencyLimitError | 429 | Too many live sessions. |
NoCapacityError | 503 | No host available right now. |
GatewayError | other | Any other non-2xx response. |
ActionError | None | An RPC returned ok: false. Carries method. |
TimeoutError | None | No reply within the per-call timeout. Carries method, timeoutMs. |
ConnectionError | None | The control channel is not open. |
import { NoCapacityError, ConcurrencyLimitError } from "@solarisdk/sandbox";
try {
const sbx = await client.create({ template: "base" });
} catch (e) {
if (e instanceof NoCapacityError) await retryLater();
else if (e instanceof ConcurrencyLimitError) await waitForSlot();
else throw e;
}