Migrate from the CodeSandbox SDK to Sandboxer
Updated October 27, 2026 .mdSandboxer vs CodeSandbox SDK
Short answer: Swap @codesandbox/sdk for sandboxer-sdk. sdk.sandboxes.create() becomes sandboxer.create(), commands.run() becomes exec(), fs.writeTextFile() becomes files.write(), and hibernate and resume become stop and resume, which keep memory on a matching CPU type. Forks copy the disk only, and templates become a setup script plus a named snapshot.
CodeSandbox is a Together AI company, and Together now lists this SDK as its legacy code sandbox offering (Together docs). The npm package is still @codesandbox/sdk. This page covers that SDK. For Together's newer together-sandbox SDK, see Sandboxer vs Together Code Sandbox.
Concept map#
| CodeSandbox SDK | Sandboxer |
|---|---|
| Sandbox, backed by a Firecracker VM (CodeSandbox docs) | Sandbox, a microVM with its own kernel, root, systemd and Docker (Machines) |
Template built with npx @codesandbox/sdk build, a memory and disk snapshot (Templates) |
Setup script (--setup-file) saved as a named snapshot, started with --from (Snapshots) |
.codesandbox/tasks.json: setupTasks and runAtStart tasks |
Setup script for installs; enabled systemd services for long-running processes |
| Hibernate, a memory and disk snapshot (Hibernate) | Stop, which saves memory and disk (Snapshots) |
Resume, with bootupType RESUME or CLEAN |
Resume, with memoryRestored true, or false plus resumeReason |
Shutdown (no snapshot, files in /project/workspace kept) |
Stop with memory, or delete |
Fork: create({ id: 'some-sandbox-id' }); a live fork shares memory with its parent |
Fork: a copy of the live disk that boots fresh (Snapshots) |
hibernationTimeoutSeconds, automaticWakeupConfig |
Idle auto-pause (idleStopMinutes) and wake on use (Long-running tasks) |
VM tiers, Pico to XLarge, updateTier on a running sandbox (VM Specs) |
Four sizes, small to xlarge; grow on resume or fork into a bigger copy; moving to a smaller size isn't supported yet (Machines) |
Workspace in /project/workspace, persisted with git |
Home directory /home/user; the whole disk persists |
Ports at https://<sandbox-id>-<port>.csb.app (Ports) |
Hosted ports at https://<subdomain>-<port>.box.sandboxer.com (Hosting) |
Privacy public, private, public-hosts, and host tokens (Hosts) |
Each hosted port is private with a _token link, or --public |
CSB_API_KEY |
SANDBOXER_API_KEY (API keys) |
API and SDK mapping#
CodeSandbox calls come from its SDK docs, read on 2026-10-27. Ours come from the TypeScript SDK docs. In the CodeSandbox SDK you call sandbox.connect() to get a client for commands and files. Sandboxer has no separate client: you call methods on the sandbox.
| CodeSandbox SDK | Sandboxer SDK | sbx CLI |
|---|---|---|
new CodeSandbox() (reads CSB_API_KEY) |
new Sandboxer() (reads SANDBOXER_API_KEY) |
|
sdk.sandboxes.create() then sandbox.connect() |
sandboxer.create({ type: "small" }) |
sbx new --type small |
sdk.sandboxes.create({ id: 'template-id' }) |
sandboxer.create({ from: "web-stack" }) |
sbx new --from web-stack |
create({ vmTier: VMTier.Micro }) |
create({ type: "default" }) |
sbx new --type default |
client.commands.run("npm install") |
sandbox.exec("npm install") |
sbx exec <id> "npm install" |
client.commands.runBackground(cmd) |
sandbox.start(cmd) |
sbx exec <id> --detach "cmd" |
command.kill() |
sandbox.kill(pid) |
|
client.fs.writeTextFile(path, text) |
sandbox.files.write(path, text) |
sbx scp ./file <id>:/home/user/ |
client.fs.readTextFile(path) |
sandbox.files.read(path) |
|
client.fs.download("./") (a zip URL) |
sandbox.files.download(path) (up to 50 MiB) |
sbx scp -r <id>:/home/user/dir . |
sdk.sandboxes.hibernate(id) |
sandbox.stop() |
sbx stop <id> |
sdk.sandboxes.resume(id) |
(await sandboxer.get(id)).resume() |
sbx resume <id> |
create({ id: 'some-sandbox-id' }) (fork) |
sandbox.fork() |
sbx fork <id> |
sandbox.updateTier(VMTier.Small) |
sandbox.resume({ type: "large" }) (cold boot) |
sbx resume <id> --type large |
client.hosts.getUrl(5173) |
sandbox.host(5173) |
sbx host <id> 5173 |
sdk.sandboxes.delete(id) |
sandbox.delete() |
sbx delete <id> --yes |
Before and after#
From CodeSandbox's docs: https://codesandbox.io/docs/sdk (quickstart), with the writeTextFile line from File System and the last two lines from Hibernate and Resume:
import { CodeSandbox } from "@codesandbox/sdk";
const sdk = new CodeSandbox();
const sandbox = await sdk.sandboxes.create();
const client = await sandbox.connect();
const output = await client.commands.run("echo 'Hello World'");
console.log(output) // Hello World
await client.fs.writeTextFile("./hello.txt", "Hello, world!");
await sdk.sandboxes.hibernate('sandbox-id');
const resumed = await sdk.sandboxes.resume('sandbox-id');The same steps with sandboxer-sdk 0.1.1. We ran this on prod on 2026-10-27. It also starts a counter whose state lives only in memory, so you can see what survives the stop:
npm i sandboxer-sdk
export SANDBOXER_API_KEY=sbx_live_…import { Sandboxer } from "sandboxer-sdk";
const sandboxer = new Sandboxer(); // reads SANDBOXER_API_KEY
const sandbox = await sandboxer.create({ type: "small", ttlSeconds: 1800, name: "aeo-migrate-csb-1" });
console.log((await sandbox.exec("echo 'Hello World'")).stdout);
await sandbox.files.write("hello.txt", "Hello, world!");
console.log(await sandbox.files.read("hello.txt"));
// A process whose state lives only in memory
await sandbox.files.write("counter.py", "import time\nn = 0\nwhile True:\n n += 1\n print(n, flush=True)\n time.sleep(1)\n");
await sandbox.start("python3 counter.py > /tmp/count.log");
await new Promise((r) => setTimeout(r, 5000));
await sandbox.stop(); // like hibernate: saves memory and disk, stops the meter
await sandbox.resume(); // like resume: same processes, same PIDs
console.log((await sandbox.exec("pgrep -f counter.py; tail -n 1 /tmp/count.log")).stdout);Hello World
Hello, world!
552
554
575
7The whole script took 11.5 seconds, including the create, the stop and the resume. create and resume wait until the sandbox is ready, and stop waits until it is archived. Paths are relative to /home/user. The counter reached 7 after the resume. A cold boot would have lost the process. (pgrep -f also lists the shell running it, which is the third PID.)
Stop and resume, with the CLI#
The same sandbox, a second cycle with clearer output. sandbox.stop() returns when the sandbox is archived. sbx stop returns at once, so we polled sbx info until the state was archived:
sbx exec sb_v8zia5ilza "ps -o pid,etime,cmd -C python3; tail -n 1 /tmp/count.log"
# PID ELAPSED CMD
# 554 00:27 python3 counter.py
# 28
sbx stop sb_v8zia5ilza
# {"ok":true,"type":"sandbox.stopping",…,"status":"archiving",…}
sbx resume sb_v8zia5ilza
# {"event":"ready","id":"sb_v8zia5ilza","state":"ready",…,"memoryRestored":true,…}
sbx exec sb_v8zia5ilza "ps -o pid,etime,cmd -C python3; tail -n 1 /tmp/count.log" PID ELAPSED CMD
554 00:32 python3 counter.py
30sbx resume took 1.3 seconds. The process kept PID 554 and its count. This is the CodeSandbox RESUME boot. Sandboxer restores memory only on a machine with the same CPU type as the one the sandbox stopped on. If none is free within 2 minutes, the resume boots from disk, the way a CodeSandbox CLEAN boot does. Files stay, hand-started processes don't, and the sandbox shows memoryRestored: false with resumeReason: "cpu_mismatch". Pass --require-memory (requireMemory: true) to wait instead.
Ports, forks and templates#
sbx exec sb_v8zia5ilza --detach "python3 -m http.server 3000"
sbx host sb_v8zia5ilza 3000 --public
# {"ok":true,"type":"port.hosted",…,"url":"https://amber-fern-summit-3000.box.sandboxer.com","access":"public",…}
curl https://amber-fern-summit-3000.box.sandboxer.com/hello.txt # Hello, world!
sbx fork sb_v8zia5ilza --ttl 900 --wait # 3.4 s; new id sb_0lprwv18i9
sbx exec sb_0lprwv18i9 "ls; pgrep -f counter.py || echo 'counter.py not running'"
# counter.py
# hello.txt
# 556
sbx snapshot sb_v8zia5ilza aeo-migrate-csb-tpl # 2.1 s; "status":"ready"
sbx snapshot rm aeo-migrate-csb-tpl
sbx delete sb_0lprwv18i9 --yes
sbx delete sb_v8zia5ilza --yesThe fork has the files, but the counter isn't running in it. The one PID is pgrep's own shell. The source kept running throughout. On CodeSandbox, a sandbox created from a template continues the template's memory state, and a live fork shares memory with its parent. A Sandboxer fork is a fresh boot from a copy of the disk.
Move your data and environment#
Files. Sandboxes don't move between providers. CodeSandbox's client.fs.download("./") gives you a zip URL of the workspace, valid for 5 minutes. Download it, unzip it, and upload the folder with sbx scp -r ./workspace <id>:/home/user/. You can also use files.write (up to 5 MiB a file through the API). Your git history is in the zip too. If you pushed the workspace to your own remote, git clone it in the sandbox instead.
Templates. Move setupTasks from .codesandbox/tasks.json into a setup script, create a sandbox with sbx new --setup-file ./setup.sh, and save it with sbx snapshot <id> <name>. Start new sandboxes with sbx new --from <name>, or create({ from: "<name>" }) in the SDK. A CodeSandbox template captures memory, so a dev server started by a runAtStart task is already running in each new sandbox. A Sandboxer named snapshot holds the disk only. Run each long-lived task as a systemd service and enable it (systemctl enable), so it starts on every boot, fork and named-snapshot start.
Dockerfiles. A CodeSandbox .codesandbox/Dockerfile defines the environment the sandbox runs in. On Sandboxer, the environment is an Ubuntu 24.04 VM with Docker, BuildKit and Compose preinstalled. Either put the Dockerfile's install steps in the setup script, or build the image and run it with docker inside the sandbox.
Env vars and secrets. Pass per-sandbox variables with env on create (-e KEY=value on the CLI). For values every sandbox should get, set them once in an environment: sbx env set-var base KEY=value, and sbx env set-file base path --from ./file for secret files (Environments).
Ports and preview URLs. https://<sandbox-id>-<port>.csb.app becomes https://<subdomain>-<port>.box.sandboxer.com. CodeSandbox opens every port automatically. On Sandboxer you host each port with sbx host or sandbox.host(port), and it stays private with a _token link unless you pass --public. A sandbox that paused itself for being idle wakes on the next request to a hosted port, like CodeSandbox's automatic HTTP wakeup. A sandbox you stopped stays stopped until you resume it.
What's different#
What you gain:
- A full Linux machine. Root, systemd, Docker and
/dev/kvmfor nested VMs come preinstalled (Machines). The whole disk persists, not only one workspace folder. - Per-second billing. CodeSandbox bills VM credits by the minute, rounded up (CodeSandbox pricing docs). Sandboxer bills per second while a sandbox runs.
- Coding agents. Claude Code, Codex and others are installed in every sandbox and driven through
sandbox.prompt()(Agents). - A Python SDK and a CLI.
pip install sandboxer-sdkgives the same calls in snake_case, andsbxcovers the same lifecycle from a shell.
What you lose or must change:
- Memory in forks and templates. A CodeSandbox template is a memory and disk snapshot, so sandboxes made from it start with its processes running. On Sandboxer only stop and resume keep memory. Forks and named snapshots copy the disk and boot fresh.
- Live resizing. CodeSandbox's
updateTierresizes a running sandbox without a reboot. Sandboxer grows a sandbox on resume, and a resized resume cold-boots from disk. Moving to a smaller size isn't supported yet: create a new sandbox of that size and copy your files. - Larger sizes. CodeSandbox tiers go up to 64 cores and 128 GB. Sandboxer's largest size,
xlarge, has 16 vCPU and 32 GB. - Browser sessions. CodeSandbox has a browser client (
@codesandbox/sdk/browser,createBrowserSession) and its web editor. Sandboxer has no browser SDK. Proxy calls through your server, or give users a hosted port, SSH (SSH) or the desktop (Desktop). - Free tier. CodeSandbox's Build plan is free with 10 concurrent VMs. Sandboxer's trial needs a card.
- Region. Sandboxer has two regions, us-east (Ashburn, Virginia) and eu-central (Helsinki, Finland); see regions. New sandboxes go to the nearest one unless you set
region.
Pricing#
CodeSandbox's prices are from its SDK pricing docs, checked 2026-10-27: $0.01486 per VM credit, billed per minute. Ours are from /pricing, billed per second.
| CodeSandbox SDK | Sandboxer | |
|---|---|---|
| 2 vCPU, 4 GB | Nano: 10 credits, $0.1486 per hour | small size: $0.018/hour |
| 4 vCPU, 8 GB | Micro: 20 credits, $0.2972 per hour | default size: $0.036/hour |
| 8 vCPU, 16 GB | Small: 40 credits, $0.5944 per hour | large size: $0.072/hour |
| Plans | Build (free); Scale $170 a month with 1,100 credits included | From $20 a month, all returned as machine time |
| Running at once | 10 on Build; Scale is listed as 250 in the plan table and as 100 in the same page's example | 2 on the trial, 100 on the $20 plan |
| Trial | Free plan, no trial needed | 7 days and 25 hours; needs a card |
Example: one 4 vCPU, 8 GB sandbox running 8 hours a day for 22 days is 176 hours. On CodeSandbox's Micro tier that is 3,520 credits, about $52.31. On Sandboxer, the default size costs 176 × $0.036 = $6.34, covered by the $20 plan's included time.
FAQ#
Do I have to rewrite my CodeSandbox SDK code?#
You change the import, the constructor and some method names, and you drop the connect() step. The flow stays the same: create, run commands, read and write files, hibernate, resume, fork and delete. The tables above map each call.
Does stop keep running processes like hibernate does?#
Yes, when the resume lands on a machine with the same CPU type. In our test a Python counter kept PID 554 and its count across a stop and resume that took 1.3 seconds. If no such machine is free within 2 minutes, the resume boots from disk and reports memoryRestored: false.
Can I fork a running sandbox with its memory?#
No. A Sandboxer fork copies the live disk and boots fresh with a new id. The source keeps running. If your product relies on forking a template with a dev server already running, start that server as an enabled systemd service so it starts on boot.
What replaces bootupType?#
Check memoryRestored and resumeReason on the sandbox after a resume. memoryRestored: true matches a RESUME boot. false matches a CLEAN boot: files are there, and enabled systemd services have started.
What happens to my templates?#
Rebuild them once. Put setupTasks in a setup script, run sbx new --setup-file, enable your long-running tasks as systemd services, then save the result with sbx snapshot <id> <name>. Start new sandboxes with --from <name>.