offshoot

Branch SQLite like git.

Copy-on-write forks of stock SQLite files, on your local disk or S3 bucket — a real database per agent attempt, eval run, or test; promote the winner, let the rest expire.

v0.2.9 · apache-2.0 · linux/macos · go 1.25+

$ offshoot init
$ offshoot create app
$ sqlite3 "$(offshoot checkout app)" "CREATE TABLE users (name); INSERT INTO users VALUES ('ada');"
$ offshoot checkpoint app v1
$ offshoot fork app attempt-1 --ttl 2h   # copy-on-write branch, near-zero added storage
$ sqlite3 "$(offshoot checkout app@attempt-1)" "DELETE FROM users;"   # destructive experiment
$ offshoot rollback app@attempt-1 --to fork    # it went badly — undo the world
$ offshoot promote app@attempt-1 --onto main --force   # …or it went well — ship it
fork · promote · destroy — branches, like git main fork --at v1 promote --onto main attempt-1 fork --ttl 2h attempt-2 · ttl 2h ⏱ reaped → destroy v1

why branch a database?

New here? Read the introduction →

how it works

stock sqlite in, your storage out your app plain sqlite3 stock sqlite file writes checkout app.db + wal a real file on disk wal frames offshoot serve captures wal → ltx ltx segments your storage — local dir · s3 · minio main snapshot seg seg seg → head append-only · checksummed attempt-1 seg base ptr (cow) — shares the parent's chain

Read the architecture →

for agents & harnesses

daemon · live capture, writer never pauses

$ offshoot serve &
$ P=$(offshoot session open app)
$ sqlite3 "$P" "INSERT INTO t VALUES ('x');"
$ offshoot session flush app v1
$ offshoot session status  # durable txid

mcp · the agent branches on its own

$ claude mcp add offshoot -- offshoot mcp
# seven tools: list, checkout, checkpoint,
# fork, rollback, promote, destroy —
# agent forks default to a 24h TTL

The daemon captures every committed transaction while your agent keeps writing — a checkpoint never quiesces the database, -flush-every 30s bounds what a crash can lose, and -http adds /metrics, /healthz, /rpc, and an SSE /events stream. Python and TypeScript SDKs drive the same API: pytest fixtures and a vitest/jest testkit for seed-once, fork-per-test isolation.

Agents & MCP guide →

install

# homebrew
$ brew tap sricola/offshoot https://github.com/sricola/offshoot
$ brew install offshoot

# docker — images publish to ghcr on every tagged release; the store lives in /data
$ docker run --rm -v offshoot-data:/data ghcr.io/sricola/offshoot:latest init

# from source (go 1.25+, cgo)
$ go install github.com/sricola/offshoot/cmd/offshoot@latest

# same binary, any store
$ offshoot -store ./.offshoot init             # local directory (default)
$ offshoot -store s3://my-bucket/offshoot init # S3, MinIO

Prebuilt binaries (offshoot_vX_os_arch.tar.gz + .sha256) ship with every tagged release. Linux and macOS; on Windows, use WSL2. At attach time offshoot probes the store and refuses to run if conditional writes aren't enforced — fail-closed, never silently degraded.

Full install guide →

essential commands

create <db> [--from f]new database (branch main), or import a file
checkout <db>[@branch]materialize a working copy; prints its path
checkpoint <db>[@br] <name>snapshot the checkout as a named checkpoint
fork <db>[@br] <new> [--at cp] [--ttl d]branch from head or a checkpoint; copy-on-write
rollback <db>[@br] --to <cp>repoint a branch at a checkpoint
promote <db>@<src> --onto <target>repoint target at src's head (--force for protected)
destroy <db>[@br] [--force]delete a branch; children survive their parent
statusall branches: state, storage class, TTL

Full CLI reference →