overview

ix is version control for sandboxes. you can fork, snapshot, and resume VMs similar to how you branch, commit, and checkout in git.

a Commit captures the full state of a VM, including disk and process memory, at a point in time. commits are immutable and form a DAG. a Branch points to the tip of a commit chain and advances automatically as you run commands. an agent might produce thousands of commits in minutes.

○──○──○──○──○──○──○──○    main
            
            └──○──○──○──○──○    fork-a
                     
                     └──○──○    fork-b

forking creates a new branch from any existing commit. both branches share all prior state, and only new writes allocate additional storage.

why we built this

we run agents that make hundreds of changes per day against a production stack with postgres, VMs, and distributed storage. the fastest way to know if a change works is to run it against production. ix lets agents test against a fork of production without breaking anything. no existing provider was sufficient, so we built our own.

api

most operations return a Branch or a Commit. both are UUIDv7 references that sort by creation time and always resolve to the same state. ix.describe attaches a human-readable label to any entity (Branch, Commit, Fs).

1 ix.spawn(sync, from): Branch u128
2 ix.fork(branch): Branch u128
3 ix.head(branch): Commit u128
4 ix.exec(branch, cmd, cwd): Proc
5 ix.eval(fs, cmd, cwd, seed): Proc
6 ix.fs(commit): Fs u128
7 ix.filter(fs, globs): Fs u128
8 ix.merge(base, left, right): Fs u128  PLANNED
9 ix.describe(entity, text)

proc

ix.exec returns a Proc, a handle to a running process inside a branch that mirrors std::process::Child in rust.

1 proc.stdout: Stream
2 proc.stderr: Stream
3 proc.wait(): ExitCode
4 proc.output(): Output
5 proc.pre: Commit u128
6 proc.post: Commit u128

you can stream stdout and stderr while the process runs, or call output() to wait and collect everything at once. pre and post are commits of the branch state before and after execution, so you can spawn from either to roll back or replay.

shell

shell sessions persist across disconnects. an agent can run for hours while your machine is off, and the session resumes exactly where you left it.

$ ix shell my-branch claude
$ ix shell my-branch -a my-claude-session

the shell exposes a raw PTY stream with an async reader and writer. you can pipe it into any terminal emulator or use libghostty, which supports native and browser rendering via WASM.

anti-captcha

environment egress can be routed through residential proxies to avoid rate limits and IP blocks.

sdks

sdks are available for typescript (node and browser via WASM), python, rust, and swift, plus a cli. all sdks are compiled from a single Rust crate, so every language has the same capabilities and types. native sdks can optionally mount local folders into a branch, so a remote agent can work on your code as if it were local.

// typescript
import { Ix } from "@ix/sdk"

const ix = await Ix.connect()

// spawn from an OCI image, fork it
const main = await ix.spawn("ubuntu:24.04")
const exp  = await ix.fork(main)

// run commands, read output
await ix.exec(exp, "echo hello > /tmp/hi")
const out = await ix.exec(exp, "cat /tmp/hi")
console.log(await out.output())
# install
$ bun add @ix/sdk

nix

every VM mounts a global /nix store with major packages custom compiled for znver5 (EPYC gen 5). packages are shared across all VMs and available instantly without per-branch installs. every VM ships with claude, codex, rg, fd, and other common tools by default. this does not require NixOS or nix as your package manager. VMs can run ubuntu or any other linux distro alongside the mounted store.

cached execution PLANNED

ix.eval boots an ephemeral VM from an input Fs and returns a Proc. the same Fs + cmd + seed always returns the cached result. pass seed 0 to bypass the cache.

ix traces syscalls during execution to record which files were actually read. file timestamps are zeroed so cache lookups depend only on content, not modification time. caching is recursive across the entire process tree. each child process gets its own cache entry based on its true inputs.

cargo build
├── rustc src/lib.rs      cached
├── rustc src/main.rs     re-run
   └── link main         re-run
└── rustc src/utils.rs    cached

on subsequent runs with the same inputs, the cached result is returned instantly and streams replay all at once. the cache is content-addressed and global, so two branches with identical file contents share results even across different VMs and users.

the API is remote-execution compatible, but also works for ordinary commands like cargo build without requiring bazel or buck2 setup.

merge PLANNED

ix.merge performs a three-way merge of two filesystems against a common base. merge conflicts are tracked as xattrs native to the filesystem.

faq

how are git and ix commits different?

ix commits are continuous and automatic, closer to jj than git. every mutation creates a commit, so the full history of a branch is preserved without explicit save points. you can revert to any point in a branch's history, not just the commits you remembered to make.

what about platform-specific files during sync?

add a .ixignore file to control which files are excluded from sync. if none exists, it falls back to .gitignore. this is where you would exclude platform-specific directories like target/ or node_modules/.

how does syncing work with large files?

ix mounts a custom filesystem where files are read lazily on demand. only the files your tools actually access are fetched. previously read files remain available offline.

what are costs like?

we aim to be competitive but are too early to publish fixed pricing. we will work with you to find something that fits.

where are servers located?

hillsboro, oregon and silicon valley, california. us east is planned.

what images can i use?

any OCI or Docker image works. you do not need to provide a kernel. ix runs a custom linux 6.19 kernel and boots your image as a guest filesystem on top of it.

what about macOS or windows VMs?

these are on our radar but not prioritized unless customers need them. let us know if they matter for you.

more questions?

email andrew@ix.dev.