sandcastle

Execution layer — a runtime, not a process framework. It decides where and how an agent runs, not what it does; it therefore implements no SDLC stage and connects to the ontology only through the patterns it provides as substrate.

flowchart LR
    R["run()"] --> WT["create worktree<br/>+ sandbox"]
    WT --> H["setup hooks<br/>(deps / env)"]
    H --> IT["agent iterations<br/><i>AFK: maxIterations +<br/>completionSignal</i>"]
    IT --> C["collect commits"]
    C --> M["merge / branch<br/>per strategy"]
    M --> CL["cleanup<br/>(preserve if dirty)"]

Sandcastle (Matt Pocock, @ai-hero/sandcastle, MIT) is a TypeScript library for orchestrating AI coding agents in isolated sandboxes. The whole idea is three lines: you invoke an agent with a single sandcastle.run(), Sandcastle sandboxes it with a configurable branch strategy, and the commits made on the branch get merged back. It is provider-agnostic and explicitly built for “parallelizing multiple AFK agents, creating review pipelines, or orchestrating your own agents.” Unlike every framework in this wiki — which ships opinions about what an agent should do at each lifecycle stage — Sandcastle ships opinions about isolation, branching, iteration, and lifecycle. It is the embeddable / library pole of the runtime layer; its counterpart warren is the self-hosted-platform pole.

What it orchestrates (not what it builds)

  • Sandbox providers — pluggable isolation. Built-ins: Docker and Podman (bind-mount), Vercel (isolated Firecracker microVMs), and noSandbox() (run on the host, no isolation). Custom providers via createBindMountSandboxProvider / createIsolatedSandboxProvider.
  • Branch strategies — how agent commits relate to the repo: head (direct filesystem writes, fastest, bind-mount only), merge-to-head (temporary branch auto-merged back), and branch (an explicit named branch that persists and can be reused across runs).
  • Agent providers — harness-agnostic: Claude Code, Codex, pi, Cursor, OpenCode, GitHub Copilot, each with provider options (e.g. reasoning effort).

API primitives

Documented here as the runtime’s “capabilities” — but note these are orchestration verbs, not SDLC work:

  • run() — one-shot: create worktree/sandbox → run hooks → execute the agent → collect commits → merge back → clean up. Returns iterations, matched completionSignal, commits, and target branch.
  • createSandbox() — a reusable warm container: call sandbox.run() many times on one branch (dependencies/build artifacts persist between runs). sandbox.exec() runs shell commands in the same warm sandbox — e.g. gate an implement step on npm test before dispatching a review run. This is how the built-in implement-then-review pipeline works.
  • createWorktree() — worktree lifecycle separated from sandboxing, enabling the “interactive exploration → hand the worktree to AFK automation” workflow.
  • interactive() — a real-time human-in-the-loop TUI session (the only HITL affordance; there is no mid-run steering of an already-launched AFK run).

AFK (away-from-keyboard) handling

The runtime’s reason for existing, and the direct answer to the question that motivated this page. An unattended run is bounded and self-terminating by three knobs: maxIterations (loop cap), completionSignal (a string like <promise>COMPLETE</promise> the agent emits to end early), and two timeouts — idleTimeoutSeconds (resets on any output; genuinely-stuck agents fail) and completionTimeoutSeconds (a grace window for a “hanging process” that signalled done but keeps stdout open, e.g. a spawned gh/MCP child). Session capture & resume (resumeSession) and session forking let a multi-step or fanned-out workflow recover and branch. Structured output (Output.object() + a Zod schema, with optional retry-on-invalid) turns a run into a typed function call.

Orchestration profile

ConcernSandcastle
Isolationcontainer bind-mount (Docker/Podman) · isolated microVM (Vercel) · noSandbox() · git worktree per branch strategy
Parallelismyou script it — multiple AFK run()s in parallel; session forking for fan-out
Autonomy / AFKfirst-classmaxIterations + completionSignal + idle/completion timeouts
Steering (HITL)interactive() TUI before handoff; no mid-run steering of an AFK run
Persistence / memorysession capture + resume + fork; no cross-run memory store
Provider-agnosticClaude Code · Codex · pi · Cursor · OpenCode · Copilot
Branch → PRbranch strategies + merge-back; opening the PR is your script’s job (e.g. gh in the prompt)
Topologya library you embed — runs wherever your Node process + chosen provider run (local or Vercel cloud)
Distributionlibrary / SDK

Distinctive contribution

Sandcastle is the wiki’s first pure execution-layer artifact and the library pole of that layer: it hands you orchestration primitives and expects you to write the TypeScript that composes them, rather than running as a service. Its signature moves are the warm reusable sandbox (createSandbox + exec-gated multi-run pipelines like implement→verify→review on one branch), the worktree/sandbox split that supports “explore interactively, then hand off to AFK,” and schema-validated structured output that makes an agent run behave like a typed function. It ships example templates — simple-loop, sequential-reviewer, parallel-planner — that are recognisably the infrastructure under process-layer skills like lfg (autonomous pipeline) and sp-dispatching-parallel-agents (concurrent fan-out).

Patterns enabled

See Also