Skip to content
Migrate · CodeSandbox SDK

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
7

The 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
30

sbx 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 --yes

The 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/kvm for 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-sdk gives the same calls in snake_case, and sbx covers 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 updateTier resizes 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>.

All migration guides