Back to feed

mattpocock/sandcastle

mattpocock/sandcastle
3k
+293/day
267
TypeScript

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

From the README

What Is Sandcastle?

A TypeScript library for orchestrating AI coding agents in isolated sandboxes:

  1. You invoke agents with a single sandcastle.run().
  2. Sandcastle handles sandboxing the agent with a configurable branch strategy.
  3. The commits made on the branches get merged back.

Sandcastle is provider-agnostic — it ships with built-in providers for Docker, Podman, and Vercel, and you can create your own. Great for parallelizing multiple AFK agents, creating review pipelines, or even just orchestrating your own agents.

Prerequisites

  • Git
  • A sandbox provider — Sandcastle needs an isolated environment to run agents in. Built-in options:
    • Docker Desktop — most common for local development
    • Podman — rootless alternative to Docker
    • Vercel — cloud-based Firecracker microVMs via @vercel/sandbox
    • Or create your own using createBindMountSandboxProvider or createIsolatedSandboxProvider

Quick start

  1. Install the package:
npm install --save-dev @ai-hero/sandcastle
  1. Run sandcastle init. This scaffolds a .sandcastle directory with all the files needed.
npx sandcastle init
  1. Edit .sandcastle/.env and fill in your default values for ANTHROPIC_API_KEY. If you want to use your Claude subscription instead of an API key, see #191.
cp .sandcastle/.env.example .sandcastle/.env
  1. Run the .sandcastle/main.ts (or main.mts) file with npx tsx
npx tsx .sandcastle/main.ts
// 3. Run the agent via the JS API
import { run, claudeCode } from "@ai-hero/sandcastle";
import { docker } from "@ai-hero/sandcastle/sandboxes/docker";

await run({
  agent: claudeCode("claude-opus-4-6"),
  sandbox: docker(), // or podman(), vercel(), or your own provider
  promptFile: ".sandcastle/prompt.md",
});

Sandbox Providers

Sandcastle uses a SandboxProvider to create isolated environments. The sandbox option on run() and createSandbox() accepts any provider. A no-sandbox option is also available for interactive() and wt.interactive(). Built-in providers:

| Provider | Import path | Type | Accepted by | | ---------- | ------------------------------------------ | ---------- | --------------------------------------------- | | Docker | @ai-hero/sandcastle/sandboxes/docker | Bind-mount | run(), createSandbox(), interactive() | | Podman | @ai-hero/sandcastle/sandboxes/podman | Bind-mount | run(), createSandbox(), interactive() | | Vercel | @ai-hero/sandcastle/sandboxes/vercel | Isolated | run(), createSandbox(), interactive() | | No-sandbox | @ai-hero/sandcastle/sandboxes/no-sandbox | None | interactive(), wt.interactive() (default) |

Worktree methods (wt.run(), wt.interactive(), wt.createSandbox()) accept the same providers as their top-level counterparts. `wt.