AIHero

    Guides

    Configuration

    Edit this page on GitHub
    On this page

    Config directory (.sandcastle/)

    All per-repo sandbox configuration lives in .sandcastle/. Run sandcastle init to create it.

    Custom Dockerfile

    The .sandcastle/Dockerfile controls the sandbox environment. The default template installs:

    • Node.js 22 (base image)
    • git, curl, jq (system dependencies)
    • GitHub CLI (gh)
    • Claude Code CLI
    • A non-root agent user (required — Claude runs as this user)

    When customizing the Dockerfile, ensure you keep:

    • A non-root user (the default agent user) for Claude to run as
    • git (required for commits and branch operations)
    • gh (required for issue fetching)
    • Claude Code CLI installed and on PATH

    Add your project-specific dependencies (e.g., language runtimes, build tools) to the Dockerfile as needed.

    Hooks

    Hooks are grouped by where they run — host (on the developer's machine) or sandbox (inside the container):

    hooks: {
    host: {
    onWorktreeReady: [{ command: "cp .env.example .env" }],
    onSandboxReady: [{ command: "echo sandbox is up" }],
    },
    sandbox: {
    onSandboxReady: [
    { command: "npm install", timeoutMs: 300_000 },
    { command: "apt-get install -y ffmpeg", sudo: true },
    ],
    },
    }
    HookRuns onWhenWorking directory
    host.onWorktreeReadyHostAfter copyToWorktree, before sandbox startWorktree path (host repo root under head)
    host.onSandboxReadyHostAfter sandbox is upWorktree path (host repo root under head)
    sandbox.onSandboxReadySandboxAfter sandbox is upSandbox repo directory

    Ordering: copyToWorktree -> host.onWorktreeReady (sequential) -> sandbox created -> host.onSandboxReady + sandbox.onSandboxReady (parallel).

    • Host hooks accept { command: string; timeoutMs?: number } — no sudo, no cwd. Use cd or inline env in the command string.
    • Sandbox hooks accept { command: string; sudo?: boolean; timeoutMs?: number } — set sudo: true for elevated privileges.
    • timeoutMs overrides the default 60 s per-hook timeout. Useful for long-running setup commands like dependency installs (e.g. timeoutMs: 300_000 for 5 minutes).
    • Within each hook point, sandbox hooks run in parallel; host hooks within onSandboxReady also run in parallel with sandbox hooks. host.onWorktreeReady hooks run sequentially in declared order.
    • If any hook exits non-zero, setup fails fast.
    • When a signal is passed to run(), it is threaded to all hooks — aborting the signal cancels any in-flight hook commands.