Model or dataset
mattpocock/sandcastle avatar
mattpocock/sandcastle

Sandcastle puts each AI coding agent in a sandbox and on its own branch, then merges the commits back

Orchestrate sandboxed coding agents in TypeScript with sandcastle.run()

9,058 stars977 forksTypeScriptMIT

At a glance

What is it?
mattpocock/sandcastle is a TypeScript library and CLI that wraps a coding agent run in an OS, container or cloud sandbox and merges the resulting branch commits back. It fits developers running several unattended agents, provided they can live with a 0.x API that shipped two minor releases on 2026-11-02.
Who is it for?
Adopt Sandcastle if you already leave coding agents running unattended on macOS, Linux or WSL2 and want each run confined to a sandbox and a branch from a single TypeScript call. Skip it on plain Windows without WSL2 or a container runtime, and skip it if you need an API that holds still between minor versions.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • mattpocock/sandcastle9,058 ★ · +961
Star history
Repository2026-09-222026-11-13
mattpocock/sandcastle8.1k9.1k

961 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

One sandcastle.run() call covers sandbox, branch and merge

A coding agent left alone on your working tree can edit anything its shell can reach. Sandcastle answers that with a single function, `sandcastle.run()`, which does three things in order according to the README: it starts the agent inside a sandbox, it puts the agent's work on a branch chosen by a configurable branch strategy, and it merges the commits made on those branches back.

You drive this from TypeScript rather than from a YAML pipeline. The README aims it at "parallelizing multiple AFK agents", review pipelines, and orchestrating your own agents. Read plainly, that is a tool for people who already trust an agent enough to walk away from it and now want several copies working at once without trampling each other.

The npm package is `@ai-hero/sandcastle`. Its package.json also declares a `sandcastle` binary pointing at `dist/main.js`, so one install gives both a library and a CLI. The CLI commands have their own reference page at docs/guide/cli.md, and docs/guide/run.md covers `run()` next to a second entry point, `createSandbox()`, for code that wants a sandbox without the full run.

Bubblewrap, Seatbelt, a container, or a cloud VM

Sandcastle calls itself provider-agnostic, and the provider list is the main decision a new user makes. There are three tiers. Native providers use the operating system's own process sandbox: Bubblewrap on Linux and WSL2, Seatbelt on macOS. Image-based providers run the agent in Docker or Podman. Cloud providers hand the sandbox to Daytona, E2B, Fly.io Sprites, Modal or Vercel. You can also write your own.

Each provider is a separate subpath export in package.json: `@ai-hero/sandcastle/sandboxes/bwrap`, `@ai-hero/sandcastle/sandboxes/seatbelt`, `@ai-hero/sandcastle/sandboxes/docker`, `@ai-hero/sandcastle/sandboxes/e2b`, `@ai-hero/sandcastle/sandboxes/sprites` and so on. A project imports only the providers it uses.

The tiers trade different costs. Native providers need neither a container runtime nor a remote account, because the confinement mechanism already ships with the OS. Docker and Podman need an engine installed and an image to run. The cloud tier moves the agent off your machine entirely, which also means an account, credentials and a bill from whichever of those five vendors you pick.

Plain Windows has no native sandbox, and no-sandbox means what it says

The native list names Linux, WSL2 and macOS. A Windows developer working outside WSL2 has no native provider on that list, so the route in is WSL2, Docker or Podman, or one of the cloud vendors. Every one of those adds a dependency the macOS and Linux user does not carry, and it should be counted before choosing Sandcastle for a mixed team.

The second trap sits in package.json. Alongside the real sandboxes there is an export called `@ai-hero/sandcastle/sandboxes/no-sandbox`. The README's provider paragraph does not mention it. Its name is its documentation: an agent run through it gets the branch and merge machinery without process isolation. That has uses when you are debugging a prompt and want the agent to see your real environment. It is also the one setting that removes the reason to adopt the library, so a configuration that ends up shared across a team is worth checking for it before anyone runs an agent unattended.

Merge-back is where parallel agents collide

Step three of the README's summary is "The commits made on the branches get merged back." That sentence carries most of the risk when several agents run against the same repository. Two agents that rewrite the same module will produce commits that do not merge cleanly, and the README's summary does not say what Sandcastle does in that case.

The answer belongs to docs/guide/branch-strategies.md, which is the page to read before fanning out. The consequence of skipping it is concrete: you discover the merge policy at the end of a long unattended run, after the agents have spent their time, rather than at the start.

The documentation set has more control points than the README names in prose. There are separate pages for agent providers and agent sessions, for iterations, for structured output, for prompts, for hooks, for init and for run logs, with every term defined in docs/guide/glossary.md. The published copy lives at aihero.dev/sandcastle. For a review pipeline, the hooks and structured output pages are the ones that decide whether an agent's result can be checked by code before its commits land.

Building @ai-hero/sandcastle from source with tsup and vitest

Prerequisites and a quick start for using the library live in docs/guide/getting-started.md. The README itself gives the commands for working on Sandcastle from a clone of the repository:

bash
npm install
npm run build    # Bundle with tsup
npm test         # Run tests with vitest
npm run typecheck # Type-check

The first line installs dependencies from package-lock.json. The build step runs tsup, configured by tsup.config.ts, and writes the bundle to dist/, which is where `main`, `types` and the `sandcastle` binary point. The test step runs vitest, and the repository carries two configs for it, vitest.config.ts and vitest.local.config.ts. The last line type-checks the source without bundling.

One detail matters if a build fails. package.json defines a `postbuild` script that runs `node scripts/copy-templates.mjs && node scripts/check-public-types-effect-free.mjs` after tsup. If either script exits with an error, `npm run build` fails even though the bundle in dist/ was already written, so read the tail of the output rather than assuming tsup was the culprit.

Two minor releases in one day: the upgrade cost of 0.x

Sandcastle is under active development. The last push was on 2026-11-03, and the release list shows v0.12.0 on 2026-06-29, then v0.13.0 and v0.14.0 both on 2026-11-02, about eleven hours apart. package.json is at version 0.14.0.

For a dependency that sits between you and an agent with write access to your repository, that pace has a price. Semantic versioning makes no compatibility promise below 1.0, so a minor bump can change the API. npm's caret range also treats 0.x minors as breaking: `^0.13.0` will not resolve to 0.14.0, so upgrades happen only when someone edits package.json on purpose. That is the safer default, and it means you own the upgrade each time.

The repository gives you the means to see what changed. It uses changesets, with a .changeset/ directory and a CHANGELOG.md at the top level. It is also developed with agents itself: AGENTS.md, CLAUDE.md, .claude/, .agents/ and a .sandcastle/ directory all sit in the root. The licence is MIT, which permits commercial use and modification as long as the copyright and licence notice travel with the code.

Sandcastle versus a git worktree and a container you script yourself

The do-it-yourself version of Sandcastle is a git worktree per agent, a container started by hand around each one, and a script that merges the branches when the agents finish. A worktree gives each agent its own checkout and branch, but by itself it confines nothing: the agent still runs as your user with your filesystem and network. The container supplies the confinement, and the merge script is yours to write and maintain.

Sandcastle folds those three pieces into `sandcastle.run()` and adds the ability to swap the confinement layer without rewriting the orchestration, moving from Seatbelt on a laptop to Docker in CI or to a cloud provider by changing which subpath you import. The cost is that the merge policy and the branch strategy become Sandcastle's decisions, expressed through its options, rather than lines in a shell script you can read in one sitting.

If you run a single agent at a time on one machine, the hand-rolled version is small and transparent. The library starts to pay for itself once there are several agents and more than one place they need to run.

Editorial conclusion

Adopt Sandcastle if you already leave coding agents running unattended on macOS, Linux or WSL2 and want each run confined to a sandbox and a branch from a single TypeScript call. Skip it on plain Windows without WSL2 or a container runtime, and skip it if you need an API that holds still between minor versions. Before fanning several agents out over one repository, read docs/guide/branch-strategies.md to see how merge-back treats overlapping commits, and pin the exact version you test against, such as 0.14.0.

Frequently asked questions

How do you use Sandcastle (mattpocock/sandcastle)?

You call sandcastle.run() from TypeScript. Sandcastle starts the agent in a sandbox, puts its work on a branch according to the configured branch strategy, and merges the resulting commits back; the quick start is in docs/guide/getting-started.md.

What is Sandcastle by Matt Pocock?

Sandcastle is an MIT-licensed TypeScript library and CLI, published on npm as @ai-hero/sandcastle, for orchestrating AI coding agents in isolated sandboxes. It is meant for running several unattended agents in parallel, building review pipelines, or orchestrating your own agents.

Which sandbox providers does Sandcastle support?

Native providers use Bubblewrap on Linux and WSL2 and Seatbelt on macOS, image-based providers cover Docker and Podman, and cloud providers cover Daytona, E2B, Fly.io Sprites, Modal and Vercel. You can also create your own provider.

Official sources

  1. Issues
  2. License: MIT
  3. mattpocock/sandcastle on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mattpocock-sandcastle.svg)](https://hysenlabs.com/projects/mattpocock-sandcastle)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/mattpocock-sandcastle.svg)](https://hysenlabs.com/projects/mattpocock-sandcastle)

Was this useful?