Releases: torkbot/sandbox
Release list
v0.14.0
Additional process pipes
Sandbox.spawn() can now expose caller-selected file descriptors as full-duplex streams. This makes it possible to run tools that use a dedicated control or protocol channel without mixing structured traffic into standard input, output, or error streams.
const child = sandbox.spawn("my-tool", [], {
pipes: [3],
});
const channel = child.pipes.get(3)!;
await channel.input.getWriter().write(request);
const response = await readResponse(channel.output);Requested descriptors must be unique integers numbered 3 or higher. Each descriptor is inherited by the guest process and is available through child.pipes using the same number. The input and output sides close independently, so protocols can continue sending requests after the guest has finished writing responses.
v0.13.2
This release tightens the sandbox exec path for short-lived commands.
Commands now carry their working directory through the guest control protocol, and sandbox-init applies it directly before starting the process. The TypeScript host no longer rewrites exec requests through a shell just to change directories, so the command that runs in the VM more closely matches the argv, environment, and cwd that callers requested.
The guest exec supervisor also does less work on the normal path. It waits directly for the child process, and timeout handling only activates when a timeout is requested.
There are no API changes required for existing callers.
v0.13.1
External image boot fixes
This release fixes the boot path introduced with external image packages in v0.13.0.
Applications can continue to choose and pin a rootfs image package separately from @torkbot/sandbox:
npm install @torkbot/sandbox@0.13.1 @torkbot/sandbox-image-alpine-3.23-agentimport { sandbox } from "@torkbot/sandbox";
import { image } from "@torkbot/sandbox-image-alpine-3.23-agent";
const vm = await sandbox({ rootfs: image }).boot();The kernel and initramfs are still owned by the core library, but the initramfs boot handoff now works correctly with rootfs images that do not contain Sandbox's init binary. That keeps image packages focused on the Linux filesystem contents while the library owns the VM launch contract.
More reliable minimal images
Sandbox now creates the small runtime files it owns, such as /etc/hosts, /etc/hostname, and /etc/resolv.conf, even when a minimal rootfs does not already contain those parent directories.
This makes slim images easier to use successfully: the image package can stay small, and Sandbox still installs the runtime configuration needed for hostname, DNS, and loopback behavior during boot.
Publishable image set
The source image suite now focuses on variants that fit the npm package model:
@torkbot/sandbox-image-alpine-3.23-agent@torkbot/sandbox-image-alpine-3.23-slim@torkbot/sandbox-image-debian-13-slim@torkbot/sandbox-image-ubuntu-26.04-slim
The oversized Debian and Ubuntu agent variants were removed from the source image set. For agent-ready environments today, use the Alpine agent image. For Debian or Ubuntu, start from the slim image and add the tools your workload needs in your own image build.
Better local validation
The lifecycle benchmark and repro tools now use the same local image artifact layout as the real image release pipeline.
For maintainers, this means the fast path is:
npm run images:build-local -- --image alpine-3.23-agent --architecture arm64
node --run benchmark:e2e:lifecycle -- --iterations 100 --warmups 2That benchmark now exercises the same external-image boot path that users get from published image packages, so local failures are much closer to release failures.
Local image publishing support
The local image publishing helper now supports the practical npm bootstrap workflow, including interactive publishing and package setup checks. This is mostly maintainer-facing, but it makes the image package lifecycle easier to keep aligned with the library release model.
Full Changelog: v0.13.0...v0.13.1
v0.13.0
External images
Sandbox no longer treats the default Linux machine image as part of the core library. Applications now install the VM runtime separately from the rootfs image they want to boot.
This makes image choice explicit:
npm install @torkbot/sandbox @torkbot/sandbox-image-alpine-3.23-agentimport { sandbox } from "@torkbot/sandbox";
import { image } from "@torkbot/sandbox-image-alpine-3.23-agent";
const vm = await sandbox({ rootfs: image }).boot();The immediate benefit is a much smaller base install for applications that only need the library API and runtime. Image bytes now live in image packages, so users can choose and pin the machine environment independently from @torkbot/sandbox.
More controlled machine environments
This release introduces separately versioned image packages for common starting points:
@torkbot/sandbox-image-alpine-3.23-agent@torkbot/sandbox-image-alpine-3.23-slim@torkbot/sandbox-image-debian-13-slim@torkbot/sandbox-image-ubuntu-26.04-slim
Use the agent image when you want a ready-to-use environment with common CLI tools for automated work. Use slim images when you want tighter control over what is installed and plan to add only the tools your workload needs.
Because image packages are normal npm dependencies, applications can pin them, upgrade them separately from the library, and review image changes like any other dependency update.
Runtime-owned boot path
The kernel and initramfs now belong to the core library instead of the selected rootfs image. This keeps the boot contract stable while image packages focus on the Linux filesystem contents.
For library users, this means image packages are simpler: they provide a concrete rootfs descriptor and facts about the environment. Sandbox still owns the VM launch path, init flow, networking, block storage, and writable overlay behavior.
Writable state still works the same way
The image package supplies the read-only starting machine. Existing writable rootfs APIs still control where changes go:
rootfs.cow(...)stores machine changes in caller-owned block storage.rootfs.persistent(...)stores machine changes in a local persistent overlay file.rootfs.flatten(...)can turn a configured machine state into a new standalone image.
This keeps the important workflow intact: start from a pinned base image, let an agent mutate its machine state, and save only the deltas outside the base image.
Breaking change
The old built-in image API has been removed. Applications should depend on an image package and pass its exported image descriptor to Sandbox instead.
This avoids coupling application behavior to whatever image happened to ship with a particular library version, and it avoids reinstalling large image contents when only the core library changes.
Full Changelog: v0.12.0...v0.13.0
ubuntu-26.04-slim 0.1.0-image.20260624T002048Z.shaeb556d79c8dd
Image: ubuntu-26.04-slim
Version: 0.1.0-image.20260624T002048Z.shaeb556d79c8dd
Release digest: sha256:eb556d79c8dd15c07b72baca337b1a3d43a551e5e94ca7d122bb11be21aef393
x64 rootfs digest: sha256:82b9c22ed87d5d5ab6b1aeb675e4ca24e687bc5d5e9c44b3bff234957d168645
arm64 rootfs digest: sha256:33eb53dbe8cac55eb918bdf773e5cd69273c6c073e8a5895f0668dc1dac9d1cb
ubuntu-26.04-agent 0.1.0-image.20260624T002047Z.sha1ff6791ad5e6
Image: ubuntu-26.04-agent
Version: 0.1.0-image.20260624T002047Z.sha1ff6791ad5e6
Release digest: sha256:1ff6791ad5e6d6c73e417b6edc51180baebb8152e2eeaf0815609d405faca33c
x64 rootfs digest: sha256:cf87ab32a743e5e4252d5fa46ca20a9149d7ea04ab6ce7aa0a3e77629c77f167
arm64 rootfs digest: sha256:9a4f3b3f4cf26c55fb57e6e268be070e6bb80b8ab17ae29752a63a28135c0c88
debian-13-slim 0.1.0-image.20260624T002051Z.sha13a6b81114d9
Image: debian-13-slim
Version: 0.1.0-image.20260624T002051Z.sha13a6b81114d9
Release digest: sha256:13a6b81114d906478cc258512f9611ac6e7dd4ada1e2a823d8ac64b1d9999288
x64 rootfs digest: sha256:586e2267dc3d9a0c9d6e6df1acf52ce142c1b99fee5c7a5919bb64d6ac3b2765
arm64 rootfs digest: sha256:d81457362586c28e686abd187d068bfaf68993090feb3b80c186a078ae088476
debian-13-agent 0.1.0-image.20260624T002047Z.sha30ae14883da8
Image: debian-13-agent
Version: 0.1.0-image.20260624T002047Z.sha30ae14883da8
Release digest: sha256:30ae14883da8660360faf839f6920044b87c4d987198cb3d3c9e48435886eec2
x64 rootfs digest: sha256:367f4e03f59e2a6c4609b4958345f41878ebaba7c64e8f8706e10ca0a5d1a5f6
arm64 rootfs digest: sha256:6c18e3ad57eeab64ed2c7f7f091901b77117a63db6a69a84f32c9befe627f1fc
alpine-3.23-slim 0.1.0-image.20260624T002044Z.sha57c1eece389c
Image: alpine-3.23-slim
Version: 0.1.0-image.20260624T002044Z.sha57c1eece389c
Release digest: sha256:57c1eece389cba0bc4d52d8a1f239e7a5ddf98514224518aad85737d3202db11
x64 rootfs digest: sha256:85239b0d6d1c1db1c54f61880b3077382c14744447167f306b0d9fbefb73a093
arm64 rootfs digest: sha256:2a9233cff48706ad286843194b9a6d2ae4e8a32083f740b56e69cb8f1e66c567
alpine-3.23-agent 0.1.0-image.20260624T002042Z.sha7133fe4f9f2e
Image: alpine-3.23-agent
Version: 0.1.0-image.20260624T002042Z.sha7133fe4f9f2e
Release digest: sha256:7133fe4f9f2e10580e6bf47618a287dc0123bdb967dcbcd1f3b91646944dcd92
x64 rootfs digest: sha256:ff4ce349de5ea02637755216e6175c005f58468fab3f8091e895eab5533cae14
arm64 rootfs digest: sha256:5a58eab3a92ef9efc30f1bcf7a244f060838605a6f2d0211160d0c069ad1d59d