Quickstart
Run code in a sandbox in three lines, then learn the primitives that make Isorun different.
You can run code in a fresh microVM sandbox in a few lines: install the SDK, set your API key, then create a sandbox and exec inside it.
Install
npm install isorunAPI key
Set ISORUN_API_KEY in your environment. Get one from the
dashboard.
export ISORUN_API_KEY=isorun_live_...Run your first sandbox
import { Isorun } from 'isorun'
const isorun = new Isorun()
const sandbox = await isorun.create({ image: 'python:3.12-slim' })
const { stdout } = await sandbox.exec("python3 -c 'print(sum(range(10**7)))'")
console.log(stdout) // 49999995000000
await sandbox.destroy()Each isorun.create() boots a microVM with its own kernel and defaults to
1 vCPU + 1 GiB RAM + a 4 GiB disk. Call sandbox.destroy() to free it, or
let the timeoutSec timer auto-destroy it.
Run any image
The image can be any OCI image: a Docker Hub tag like node:22 or
python:3.12-slim, a GHCR or private-registry reference, or one you built
yourself. The first time a runner sees an image it pulls and prepares it;
every boot after that is instant.
await isorun.create({ image: 'node:22' })
await isorun.create({ image: 'ghcr.io/your-org/agent-runtime:1.0' })Pin a real tag or digest. Floating tags like latest and lts are rejected
at create time, because they'd let an upstream republish silently change what
runs.
The primitives that make Isorun different
Most runtimes stop at "boot fast, run code, destroy." Isorun adds primitives that change what an agent can do inside a sandbox.
1. Forking: clone a running sandbox
const parent = await isorun.create({ image: 'python:3.12-slim' })
await parent.exec('pip install transformers torch') // setup once
// 5 forks inherit the loaded packages AND the model weights in
// memory, with no re-install and no re-load.
const children = await parent.fork(5)
await Promise.all(children.map((c) => c.exec('python3 evaluate_hypothesis.py')))Each child inherits the parent's filesystem state and running process state. This is the backtracking primitive an agent uses to explore a branch and roll back. Read more
2. Public URLs: expose any in-sandbox port
await sandbox.exec(
"nohup setsid jupyter notebook --port 8888 " +
"--no-browser --ip 0.0.0.0 --NotebookApp.token='' >/dev/null 2>&1 &"
)
console.log(sandbox.url(8888))
// → https://8888-<runID>.isorun.app/You get a public, WebSocket-aware URL. Vite HMR, Jupyter, and gradio all work. Read more
3. Hibernate / resume: persistent workspaces at zero idle cost
await sandbox.hibernate() // pause + release active runtime resources
// … hours later …
await sandbox.resume() // filesystem, memory, and processes intactTo the user it looks like a workspace that's always there, while the runner only spends resources when it's actively running. Filesystem, memory, and running processes all survive. Read more
4. Snapshot / restore: capture state, restart anywhere
const snap = await sandbox.snapshot()
await sandbox.destroy()
// Later, on any runner in the same region:
const restored = await isorun.restore(snap.id)
await restored.exec('node -v')
await restored.destroy()Use this to amortise expensive setup across many sandboxes. Read more
Next steps
- Create & execute covers the default create-run-destroy loop.
- TypeScript SDK reference lists every method and option.
- Authentication explains keys and regions.