Sandcastle
@ai-hero/sandcastle v0.9 — agent orchestration / 6 agent providers / sandbox isolation / branch strategy / session resume
Sandcastle は、AI コーディングエージェントを隔離された sandbox で動かし、変更を branch / worktree 経由で回収する TypeScript CLI / SDK。単発実行なら run()、長く使う環境なら createSandbox()、sandbox なしの探索から始めるなら createWorktree() が中心になる。
Sandcastle は「prompt を渡す」だけの薄いラッパーではない。sandbox を作る前に host 側で branch / worktree / env / prompt を解決し、sandbox 内で agent を起動し、最後に commit と session を host 側へ戻す。
単発の AFK agent 実行。sandbox lifecycle を自動管理し、iteration、completion signal、commit、log path を返す。
同じ sandbox と同じ branch を複数回使う。実装 → レビューのような multi-run pipeline 向き。
worktree を first-class に扱う。先に探索し、後で sandboxed AFK run に渡せる。
agent を対話モードで起動。noSandbox() を指定すれば host 上で直接実行できる。worktree の wt.interactive() は sandbox 未指定時に no-sandbox が既定。
import { run, claudeCode } from "@ai-hero/sandcastle";
import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
const result = await run({
agent: claudeCode("claude-opus-4-7"),
sandbox: docker(),
promptFile: ".sandcastle/prompt.md",
maxIterations: 3,
});
console.log(result.commits);
AgentProvider は sandbox 内で起動するコマンド組み立てと output parse を担う。factory 関数に model 文字列を渡して run() / createSandbox() / interactive() へ注入する。
| Factory | 例 | session capture |
|---|---|---|
claudeCode(model, opts?) | claudeCode("claude-opus-4-7", { effort: "high", permissionMode: "auto" }) | 既定 ON。v0.8+ で permissionMode により AFK run の tool approval を bypass 以外に切替可能。 |
codex(model, opts?) | codex("gpt-5.4", { approvalsReviewer: "auto_review" }) | 既定 ON。v0.8+ で approvalsReviewer: "auto_review" が reviewer agent 経由の approval を有効化。 |
pi(model, opts?) | pi("claude-sonnet-4-6", { thinking: "high" }) | 既定 ON |
cursor(model) | cursor("composer-2") | — |
opencode(model) | opencode("opencode/big-pickle") | — |
copilot(model) | copilot("claude-sonnet-4.5") | — |
<session-id>/subagents/agent-*.jsonl)も main session と一緒に capture する(個別失敗は warning、main session 失敗は run 失敗)。RunResult.resume() は同一 session を継続、RunResult.fork() は新 session ID で分岐。fork は session のみを分離し branch / worktree は分離しない(並行 fork には明示 branch が必要)。SandboxProvider は「どこで agent を動かすか」を差し替える小さな契約。built-in provider は実行場所だけでなく、使える branch strategy と同期方式も変える。
host の worktree を container へ mount。ローカルで最も一般的。
rootless 寄りのローカル provider。Docker と同じ型の境界で扱える。
cloud sandbox。code in / commits out の sync が必要な境界。
container を作らず host で agent を直接実行。run() / createSandbox() / interactive() すべてで指定可能。
@daytona/sdk 経由の cloud isolated sandbox。Vercel と同様に code in / commits out の sync が必要。
| Provider 型 | 実装者が満たす契約 | 設計上の意味 |
|---|---|---|
bind-mount | exec(), interactiveExec(), file copy, close() | host filesystem へ mount 経由で直接書く。sync が不要。 |
isolated | exec(), copyIn(), copyFileOut(), close() | sandbox 側 filesystem が独立。commit extraction が必要。 |
no-sandbox | host command execution | 隔離を省略したい run / interactive。worktree 探索の既定にも使われる。 |
Sandcastle の prompt system は薄く、強い workflow 意見を押し付けない。prompt は literal、promptFile は template として扱われる。この差が重要。
| 入力 | 処理 | 使いどころ |
|---|---|---|
prompt | そのまま agent へ渡す。promptArgs と併用不可。 | JavaScript 側で文字列を組む短い指示。 |
promptFile | {{KEY}} substitution と shell expression expansion を実行。promptArgs の null / undefined は v0.9 で PromptError として fail-fast。 | issue / branch / command output を混ぜる再利用 prompt。 |
completionSignal | agent output に含まれたら iteration loop を早期停止。既定は <promise>COMPLETE</promise>。 | タスク完了時に無駄な iteration を走らせない。 |
completionTimeoutSeconds | completion signal 検出後、process が exit しない「hanging process」に対する猶予(既定 60 秒)。 | signal 後の MCP / 子 process 残留でも commit を失わず成功扱いにできる。 |
output: Output.object() | prompt 内の XML tag から schema 検証済み JSON を抽出。maxIterations === 1 必須。 | 型付き結果を run の戻り値として受け取る。 |
resumeSession | host 上の session ファイルを sandbox へ移送し iteration 1 で resume。 | 前回会話を sandbox 内で継続。 |
branch strategy
head は host 作業ツリーへ直接、merge-to-head は一時 branch、branch は明示 branch。変更境界が用途で変わる。
worktree lock
named branch の worktree 共有を lock file で fail-fast。待機や retry ではなく「同じ branch を同時に使う caller error」と扱う。
idle / completion timeout
idleTimeoutSeconds(既定 600)は output 停止中の agent を fail-fast。completionTimeoutSeconds は signal 検出後の hanging process 用で、expire 時は warning 付き成功。
- README.md — Quick start、API、provider、session capture / resume / fork
- CHANGELOG.md — v0.9.0 subagent transcript capture、init / promptArgs 改善
- CONTEXT.md — 用語(completion timeout、hanging process、structured output)
- src/index.ts — 公開 export(6 agent / 5 sandbox factory)
- src/run.ts / src/createSandbox.ts / src/createWorktree.ts — 実行モデル
- docs/adr/0019-completion-timeout-for-hanging-process.md — completion timeout
- docs/adr/0018-fork-is-session-only.md — fork の branch 非分離
- GitHub: mattpocock/sandcastle — 本体リポジトリ
- npm: @ai-hero/sandcastle — package registry(v0.9.x)
- Docker / Podman / Vercel / Daytona — built-in sandbox provider の前提環境