finds.dev← search

// the find

mattpocock/sandcastle

★ 6,441 · TypeScript · MIT · updated Jun 2026

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

Sandcastle is a TypeScript library for running AI coding agents (currently Claude Code) inside isolated sandboxes — Docker, Podman, or Vercel microVMs — with git worktree management handled for you. It's aimed at teams that want to parallelize AFK agents or build CI pipelines where an agent implements and another reviews, without manually juggling branches and containers.

The branch strategy abstraction (head/merge-to-head/branch) is genuinely well-thought-out — the difference between bind-mount and isolated providers defaulting to different strategies reflects real operational semantics, not arbitrary API design. The `createSandbox()` + `await using` pattern for multi-step implement-then-review pipelines is clean and the split-ownership model between worktree and sandbox lifecycle is explicit rather than surprising. The repo eats its own cooking: the `.sandcastle/` workflows and GitHub Actions templates show real usage, not just hypothetical examples. The ADR directory is unusually thorough for a library this young — decisions like session storage ownership and fork-vs-resume semantics are documented with actual rationale.

Claude Code is the only real agent provider right now; the 'provider-agnostic' framing is aspirational — the auth setup (OAuth token via `claude setup-token`) bakes in Claude Code specifics from the first `init`. The bind-mount default for Docker means the agent writes directly to your host filesystem under `{ type: 'head' }`, which is a footgun for anyone who reads 'sandboxed' and assumes isolation. The session resume/fork feature requires filesystem-backed session files on the host, which breaks in any distributed or ephemeral CI environment. Error handling across container lifecycle steps is inconsistent — some failures throw, some return non-zero exit codes you're expected to check, and a broken `onAgentStreamEvent` callback is silently swallowed rather than surfaced.

View on GitHub →

// want more like this?

We dig through GitHub every week and send a few repos picked for what you actually care about — each with an honest take like this one.

Get finds in your inbox → Search again →