from nullspace import Sandboxwith Sandbox.create( template="claude-code", envs={"ANTHROPIC_API_KEY": "..."},) as sb: sb.git.clone("https://github.com/acme/api", "/repo") sb.commands.run( 'claude -p "fix the failing auth test"', shell=True, cwd="/repo", ) print(sb.git.diff(path="/repo"))
One control plane, every client
Drive it from the tool you already use.
Reach the same lifecycle from a Python, TypeScript, or Go SDK, the nullspace CLI, a plain HTTP API, or MCP. Ready-made Claude Code and Codex skills let your coding agent drive Nullspace out of the box.
Python
from nullspace import Sandboxsandbox = Sandbox.create(template="base")result = sandbox.commands.run("uname -a", shell=True)print(result.stdout)
The primitives
Six explicit operations. Nothing hidden.
Each is a single API call — no orchestration config, no hidden control loop. Compose them however your agent needs.
The lifecycle above ships today. These show the direction we're building toward — richer hardware, scale, and safety primitives under one programmable surface. Speculative APIs are marked.
Composability
Any machine an agent needs, in code.
Specify hardware, image, files, tools, and env in one call — no stitched-together setup scripts.
Fan agents out across many sandboxes in parallel, or keep capacity warm so latency-sensitive loops start instantly.
Fan out
from concurrent.futures import ThreadPoolExecutorfrom nullspace import Sandbox# Explore many paths at once, one sandbox each.def evaluate(candidate: str) -> str: with Sandbox.create(template="base") as sb: sb.git.clone( "https://github.com/acme/evals", path="/workspace/evals", ) run = sb.commands.run( f"python eval.py --id {candidate}", shell=True, cwd="/workspace/evals", ) return run.stdoutcandidates = ["patch-001", "patch-002"] # ...with ThreadPoolExecutor(max_workers=100) as pool: results = list(pool.map(evaluate, candidates))
Stateful lifecycle
Pause, resume, fork, and snapshot — no context lost.
Stop work without throwing it away, branch a running machine, and turn prepared state into a reusable baseline.
Pause / Resume
from nullspace import Sandboxsandbox = Sandbox.create( template="base", vcpus=4, memory_mb=8192,)# The agent sets up useful state.sandbox.commands.run( "pip install -r requirements.txt", shell=True,)sandbox.commands.run( "python preprocess.py --in /data/raw", shell=True,)# Pause without losing work — full VM state.snapshot = sandbox.hibernate()# Later, wake exactly where it stopped.resumed = Sandbox.resume(snapshot.id)resumed.commands.run( "python continue.py --in /data/processed", shell=True,)
Safety
Powerful by default, contained by design.
Every sandbox is an isolated microVM. Cut off the network, scope what an agent can touch, and branch risky work off known-good state.
Isolation
from nullspace import Sandbox# Each sandbox is its own microVM — not a# shared container. Cut the network off for# untrusted code.sandbox = Sandbox.create( template="base", internet_access=False,)sandbox.files.write( "/workspace/generated.py", model_output,)run = sandbox.commands.run( "python /workspace/generated.py", shell=True,)print(run.exit_code, run.stdout)
Experience
Simple when you want it, deep when you need it.
Ask for a sandbox without learning the stack — then reach into the microVM runtime, snapshots, and lifecycle events when the workload demands it.
Simple by default
from nullspace import Sandbox# One line to a running, isolated machine.with Sandbox.create(template="base") as sandbox: result = sandbox.commands.run( "python agent_task.py", shell=True, ) print(result.stdout)
Give your agents real compute.
Boot your first microVM in about five minutes — or join the waitlist for hosted access.