TypeScript SDK

Sandbox

Create, list, inspect, and manage sandboxes with @tektona/sdk.

tek.sandbox manages sandboxes. create, get, and list return a Sandbox instance bound to the client; per-sandbox actions are also available as methods on that instance.

Create

The request body is the generated create type (snake_case fields). org and project are optional here — omit them to inherit the client's default scope (new Tektona({ org, project })). resources are in GiB (and CPU cores):

const tek = new Tektona({ apiKey, org: 'my-org', project: 'my-project' });

const sandbox = await tek.sandbox.create({
  image: 'ghcr.io/tektona-ai/desktop-x11:0.4.3',
  egress_network_policy: 'tektona/open',
  // org / project inherited from the client scope above (pass them to override)
  // resources: { cpu: 2, memory: 4, disk: 20 },  // cores, GiB, GiB
  // env: { FOO: 'bar' },
  // public: true,
});

create returns the rich Sandbox instance (its instance fields stay camelCase: id, state, image, project, org, resources, egressNetworkPolicy, public). Pass a request timeout via the optional second argument: create(body, { timeoutMs }).

List

list is scoped to an org (from the client default or per-call org), optionally narrowed to a project. It returns one Page:

const page = await tek.sandbox.list({ limit: 50 });           // org from client scope
const mine = await tek.sandbox.list({ scope: 'mine' });
for await (const sb of tek.sandbox.listAll()) console.log(sb.id);

Get

const sandbox = await tek.sandbox.get('01J5K9M2XR');

Delete

await tek.sandbox.delete('01J5K9M2XR'); // idempotent: a missing sandbox resolves cleanly

Preview URLs

Expose a sandbox port publicly, optionally bounded by a TTL:

const preview = await sandbox.preview.create(8080, { ttl: '1h' });
if (preview.kind === 'public') {
  console.log(preview.url);
} else {
  console.log(preview.url, preview.token, preview.expiresAt);
}

await sandbox.preview.revoke(preview.token); // idempotent

ttl accepts a Go-style duration ('1h', '15m') or milliseconds; it must be between 60 seconds and 24 hours. Out-of-range values throw InvalidArgumentError before the network call.

Lifecycle

Every method below is available both as tek.sandbox.<op>(id, …) and as an instance method on a Sandbox.

await sandbox.pause({ mode: 'hibernate' }); // or 'suspend'; -> { id, state }
await sandbox.resume();
await sandbox.reboot();                     // orderly cold reboot; recent writes are flushed first

const fork = await sandbox.fork({ mode: 'full' }); // 'filesystem' | 'full'
// -> { id, state, cache_key, image_ref }

const resize = await sandbox.resize({ cpu: 4, memory: 8, force: true });
// -> { id, before, after, appliesImmediately, note }

resize applies immediately when possible, otherwise on the next start/resume (appliesImmediately: false). force is required to downsize memory.

Access & desktop

SSH, VNC, and desktop control are grouped into sub-namespaces on the instance:

const ssh = await sandbox.ssh.access();
// -> { url, token, ssh_host, ssh_port, ssh_ports? }

const vnc = await sandbox.vnc.access({ start_desktop: true });
// -> { url, token, expires_at }

await sandbox.desktop.start(); // -> { status }
await sandbox.desktop.stop();  // -> { status }

const pngBase64 = await sandbox.desktop.screenshot(); // base64-encoded PNG

Observability

const page = await sandbox.listTransitions({ limit: 20 }); // -> Page<TransitionResponse>
for await (const t of sandbox.listAllTransitions()) console.log(t.to_state);

const ports = await sandbox.listPorts(); // [{ port, process, protocol }]
const rules = await sandbox.listEgressInjectionRules(); // [{ domain_pattern, path_match?, secret_refs }]

const lifecycle = await sandbox.getLifecycleConfig();
// -> { auto_delete_after, auto_pause_after, auto_pause_mode, auto_resume }
await sandbox.updateLifecycleConfig({ auto_pause_after: '15m', auto_resume: true });

Lifecycle durations are Go-style strings; pass an empty string to disable a timer.

Sharing

await sandbox.share({ share_type: 'use' });   // 'use' | 'manage' -> { id, share_type }
await sandbox.unshare();                        // back to private
await sandbox.transfer({ to: 'user@example.com', reason: 'handover' });
// -> { id, owner_user_id }

On this page