How to run Bun code in a cloud sandbox
Bun 1.4.0 is preinstalled in every Runtime sandbox: write your file into the microVM and run bun on it, TypeScript and tests included.
On Runtime, Bun needs no install step, and the SDK runs on Bun too. Every sandbox is a Firecracker microVM with its own kernel and Bun 1.4.0 next to Node.js 24.21.0. A new sandbox answered its first command 351 ms after the request at the median on 24 September 2026 (speed). A 2 vCPU, 4 GiB sandbox costs $0.08 an hour with both CPUs busy and $0.03125 an hour while it waits, because Runtime bills the CPU your code uses (pricing).
Run a Bun script
TypeScriptimport { Sandbox } from "withruntime";const script = `const words = "the quick brown fox jumps over the lazy dog".split(" ");const longest: string = words.reduce((a, b) => (b.length > a.length ? b : a));console.log(longest, Bun.version);`;await using sbx = await Sandbox.create({ network: { internet: false }, timeoutSeconds: 300, onLeaseEnd: "stop",});await sbx.files.write("/workspace/job.ts", script);const run = await sbx.exec(["bun", "job.ts"], { timeoutMs: 20_000 });console.log(run.exitCode, run.stdout);Pythonfrom withruntime import Sandboxscript = """const words = "the quick brown fox jumps over the lazy dog".split(" ");const longest: string = words.reduce((a, b) => (b.length > a.length ? b : a));console.log(longest, Bun.version);"""with Sandbox.create(network={"internet": False}, timeout_seconds=300, on_lease_end="stop") as sbx: sbx.files.write("/workspace/job.ts", script) run = sbx.exec(["bun", "job.ts"], timeout_ms=20_000) print(run.exit_code, run.stdout)Bun "supports TypeScript and JSX with no configuration" and transpiles each
file before it runs (Bun). It does not
type-check; see TypeScript in a sandbox for tsc.
What is in the image
| Tool | Version or detail |
|---|---|
| Bun | 1.4.0 (bun) |
| Node.js | 24.21.0 (node, npm, npx) |
unzip |
In the image; Bun's own installer needs it on Linux |
| Build tools | gcc, g++, make |
| OS | Ubuntu 24.04.5 LTS (noble), amd64, 6.1 kernel |
Commands run as the user runtime with /workspace as home and working
directory, and sudo works without a password
(the sandbox environment).
Run a test suite with bun test
bun test is Bun's built-in, Jest-compatible runner. It finds files named
*.test.ts, *_test.ts, *.spec.ts and *_spec.ts (and the JavaScript
forms), and each test times out after 5,000 ms unless you pass --timeout
(Bun test).
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ timeoutSeconds: 1200, onLeaseEnd: "stop" });await sbx.files.upload("./my-app", "/workspace/app");await sbx.exec("cd app && bun install", { check: true, timeoutMs: 300_000 });await sbx.network.set({ internet: false }); // tests run with no networkconst run = await sbx.exec(["bun", "test", "--timeout", "20000"], { cwd: "/workspace/app", timeoutMs: 600_000, onStdout: (text) => process.stdout.write(text),});process.exitCode = run.exitCode ?? 1;Pythonimport sysfrom withruntime import Sandboxwith Sandbox.create(timeout_seconds=1200, on_lease_end="stop") as sbx: sbx.files.upload("./my-app", "/workspace/app") sbx.exec("cd app && bun install", check=True, timeout_ms=300_000) sbx.network.set(internet=False) # tests run with no network run = sbx.exec(["bun", "test", "--timeout", "20000"], cwd="/workspace/app", timeout_ms=600_000, on_stdout=sys.stdout.write) sys.exit(1 if run.exit_code is None else run.exit_code)A timeoutMs over 60 seconds streams the output, and the result keeps
everything the tests printed. Cutting the network after the install keeps a
test that calls out from reaching anything.
Serve a Bun app
Start a server with spawn, not exec: everything an exec starts ends
with its command. Then share the port as a private HTTPS
preview.
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ timeoutSeconds: 1800 });await sbx.files.write( "/workspace/server.ts", 'Bun.serve({ port: 3000, fetch: () => new Response("hello from bun") });',);const server = await sbx.spawn(["bun", "server.ts"]);await sbx.exec("sleep 1 && curl -s localhost:3000", { check: true });console.log(server.id);A newer Bun, or the same Bun in every sandbox
Bun's installer puts Bun in ~/.bun/bin, takes a version as
bash -s "bun-v<version>", and needs unzip
(Bun installation). To pin one release
for every sandbox, run it in a custom image recipe with
BUN_INSTALL pointing at /usr/local, so bun lands on the sandbox user's
PATH:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "bun-app", recipe: { commands: ["curl -fsSL https://bun.com/install | BUN_INSTALL=/usr/local bash"], npm: ["zod"], },});await using sbx = await runtime.sandboxes.create({ image: "bun-app" });console.log((await sbx.exec(["bun", "--version"])).stdout);Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="bun-app", recipe={ "commands": ["curl -fsSL https://bun.com/install | BUN_INSTALL=/usr/local bash"], "npm": ["zod"],})with runtime.sandboxes.create(image="bun-app") as sbx: print(sbx.exec(["bun", "--version"]).stdout)Recipe commands run as root in /workspace. Building an image is free; a
stored image is charged on its size.
Drive sandboxes from Bun
The withruntime package supports Bun as well as Node 22 or later, and
await using works on Bun, so a Bun service can create, run and stop
sandboxes with the samples above unchanged (JavaScript SDK).
Terminalbun add withruntimeRelated
- Run TypeScript code in a sandbox
- Run JavaScript and Node.js code in a sandbox
- Preview apps an agent built
- Run agent evals and SWE-bench
New accounts get 50 free sandbox hours, no card:
Terminalnpx withruntime sandbox run --trial -- bun --versionSources
- Bun runtime: https://bun.com/docs/runtime (read 25 September 2026)
- Bun test runner: https://bun.com/docs/test (read 25 September 2026)
- Bun installation: https://bun.com/docs/installation (read 25 September 2026)
bun add: https://bun.com/docs/cli/add (read 25 September 2026)
Facts on this page were checked on 25 September 2026.