Sandcastle

repository·main·Indexed 24 days ago

https://github.com/mattpocock/sandcastle

A TypeScript library for orchestrating AI coding agents within isolated sandbox environments such as Docker, Podman, or Vercel. Sandcastle automates sandboxing, agent execution via a JS API, and merging code changes back to the host. It features configurable branch strategies (Head, Merge-to-head, Branch), support for dynamic prompt context using !`command` expressions and {{KEY}} substitutions, and tools for managing reusable sandboxes and independent git worktrees.

Tokens
18.7K
Snippets
26
Records
109
Agent score
92%

What's inside @ai-hero/sandcastle

  1. Overview of Sandcastle

    main

    Sandcastle is a TypeScript library designed to orchestrate AI coding agents within isolated sandboxes. It simplifies agent execution by:

    1. Invoking agents via a single run() call.
    2. Automatically handling sandboxing using a configurable branch strategy.
    3. Merging commits made on the sandbox branches back into the main codebase.

    It is provider-agnostic and supports Docker, Podman, and Vercel, or custom providers.

  2. Understand Sandcastle Core Concepts

    main

    Sandcastle is a TypeScript CLI tool that orchestrates an agent inside a sandbox. To use the tool effectively, understand these key entities:

    • Sandcastle: The CLI tool itself.
    • Sandbox: The isolation boundary (container, VM, etc.) that constrains the agent's access.
    • Host: Your local machine where the real git repository and Sandcastle reside.
    • Agent: The AI coding tool running inside the sandbox (e.g., Claude Code, Codex).
    • Agent Provider: A pluggable implementation that builds commands and parses output for a specific agent.
    • Sandbox Provider: A pluggable implementation that creates and manages the sandbox environment.
  3. Understand Sandcastle key concepts

    main

    To use Sandcastle effectively, understand these core components:

    • Sandbox: An isolated environment (either a Docker container or a local directory) where the agent executes code.
    • Host: Your local machine where Sandcastle is running and where the actual git repository resides.
    • Agent: The AI coding tool (such as Claude Code) that is invoked inside the sandbox.
    • Iteration: A single invocation of the agent, which results in at most one commit.
  4. Configure Claude Code as an Agent Provider

    main

    Claude Code is the default agent provider in Sandcastle. It uses Claude Code as the AI coding agent inside the sandbox. To use it, you must provide either an OAuth token or an Anthropic API key, along with a GitHub token.

    To get a CLAUDE_CODE_OAUTH_TOKEN, run claude setup-token on your host machine. This allows the agent to use your existing Claude subscription.

    # Required Environment Variables
    
    # One of these:
    CLAUDE_CODE_OAUTH_TOKEN
    ANTHROPIC_API_KEY
    
    # Plus:
    GH_TOKEN
  5. Use Prompts and Prompt Templates

    main

    Sandcastle supports different ways to provide instructions to the agent:

    • Inline prompt: A raw string provided via the prompt option. No substitution or expansion is performed.
    • Prompt template: A file sourced via the promptFile option. It supports:
      • Prompt argument substitution: Replacing {{KEY}} placeholders with values from promptArgs.
      • Prompt expansion: Evaluating shell expressions (marked with !`command`) by replacing them with the command's stdout inside the sandbox.
  6. Fix Git worktree mount issues on Windows hosts

    main

    When running a sandbox inside a Linux container on a Windows host, Git worktree mounts can break because the .git file contains Windows-native paths (e.g., C:\Users\...) that cannot be resolved inside the Linux environment. Additionally, the parent .git directory may not have a valid sandbox path.

    Sandcastle resolves this by using patchGitMountsForWindows to perform pre-start patching. This process:

    1. Mounts the parent .git directory at a deterministic POSIX path: /.sandcastle-parent-git.
    2. Rewrites the worktree's .git file to use the new gitdir: path (e.g., gitdir: /.sandcastle-parent-git/worktrees/abc).
    3. Uses a Docker overlay mount to place the corrected .git file at SANDBOX_REPO_DIR/.git before the container starts.

    This ensures that Git operations work immediately upon sandbox availability without needing post-start exec commands.

  7. Understand Worktree Reuse Behavior in the Branch Strategy

    main

    When using the branch strategy, Sandcastle manages worktrees at .sandcastle/worktrees/<name>/. If a worktree for a specific branch already exists, Sandcastle now reuses it by default instead of throwing an error.

    Worktree States and Handling

    • Clean Worktree (no staged, unstaged, or untracked changes): Sandcastle reuses the worktree and attempts to fast-forward it from origin. If the local branch is strictly behind origin/<branch>, it performs a git fetch origin <branch> followed by git merge --ff-only.
    • Dirty Worktree (contains uncommitted changes): Sandcastle reuses the worktree as-is and emits a warning. The agent starts with the existing uncommitted state.
    • Diverged Worktree (contains unpushed commits): If the branch has diverged from origin and cannot be fast-forwarded, Sandcastle reuses the worktree exactly as it is to avoid clobbering unpushed work.

    Automatic Refresh Logic

    The automatic refresh from origin only occurs if the worktree is clean AND a fast-forward is possible. If the fetch fails (e.g., due to being offline), the refresh is skipped, but the run is not aborted.

  8. Calculate context window usage percentage from IterationResult.usage

    main

    The IterationResult.usage object provides raw token counts but does not include the model's context window size or the percentage of the window used. To calculate the percentage of the context window consumed, you must manually provide the model's context limit and use the raw token counts provided in IterationResult.usage.

    Available raw token fields in IterationResult.usage:

    • inputTokens
    • cacheCreationInputTokens
    • cacheReadInputTokens
    • outputTokens
  9. Align Docker image UID/GID with host via `sandcastle docker build-image`

    main
    To avoid EACCES permission errors on Linux hosts where the user UID/GID is not 1000, you should rebuild your agent images using the sandcastle docker build-image command. This command automatically detects your host's UID and GID (via process.getuid() and process.getgid()) and injects them into the image as AGENT_UID and AGENT_GID build arguments.
    sandcastle docker build-image
  10. Understand prompt interpolation behavior for inline vs template prompts

    main

    Sandcastle distinguishes between inline prompts (passed via the prompt string) and template prompts (sourced via promptFile).

    • Inline Prompts (prompt: "..."): These are delivered to the agent verbatim. Sandcastle does not perform argument substitution, prompt expansion, or injection of built-in variables like {{SOURCE_BRANCH}} or {{TARGET_BRANCH}}. If your inline prompt contains {{...}} sequences, they will be passed to the agent literally and will not be processed.
    • Template Prompts (promptFile): These are processed through the full interpolation pipeline, supporting {{KEY}} substitution and `!command` execution.

    Important: If you need to include dynamic context (like branch names) in an inline prompt, you must perform the interpolation in your JavaScript code using template literals rather than relying on Sandcastle's built-in arguments.