uv add ix-sdkReads IX_TOKEN from the environment. Override with token=....
Note
Async-first. Python >= 3.11. Sync shim is minimal.
from ix_sdk import Sandbox
async with await Sandbox.oci("docker.io/library/python:3.12") as sbx:
await sbx.exec(["ls", "-la"]) # fire-and-forgetFactories:
Sandbox.oci(image, **opts) |
Fully-qualified OCI image reference |
Sandbox.ubuntu(version="24.04", **opts) |
Ubuntu shorthand |
Sandbox.attach(vm_id, **opts) |
Adopt an existing VM |
Options: token, base_url, region, env, name, ipv4, l7_proxy_ports. Env fallbacks: IX_TOKEN / IX_API_KEY, IX_API_BASE_URL, IX_REGION.
Sandbox.oci() expects a fully-qualified OCI reference such as docker.io/library/python:3.12, ghcr.io/owner/image:tag, or registry.example.com/team/app@sha256:....
Stateful. Variables, cwd, env persist across exec calls. Independent handles do not share state.
async with await Sandbox.oci("docker.io/library/python:3.12") as sbx:
async with await sbx.repl("python") as py:
await py.exec("x = 42")
await py.exec("print(x)") # sees x
async with await sbx.repl("python") as py2:
await py2.exec("print(x)") # NameErrorLanguages: "bash", "python", "node", "bun", "typescript".
async with await sbx.repl("bash") as sh:
await sh.exec("cd /tmp && export FOO=1")
await sh.exec("pwd; echo $FOO") # /tmp \n 1ReplResult has output: str (combined stdout+stderr) and exit_code: int.
child = await sbx.fork("child-1") # memory + disk, penniesawait sbx.write("/tmp/x", "hi")
text = await sbx.read("/tmp/x")
entries = await sbx.list("/tmp")
await sbx.write_bytes("/tmp/bin", b"\x01\x02\x03")
data = await sbx.read_bytes("/tmp/bin")async with deletes the VM on scope exit. Use await sbx.close() to manage the lifetime yourself.
Client / Branch expose the full API (regions, billing, tokens, volumes, migrations, observability). Reach for it when Sandbox is not enough.
from ix_sdk import Client
ix = Client(token=os.environ["IX_TOKEN"])