Skip to content

Releases: mattpocock/sandcastle

v0.5.10

08 May 08:11
9100690

Choose a tag to compare

Patch Changes

  • 95d63a4: Apply :z SELinux label by default on Docker bind mounts, matching the existing Podman behavior. Adds selinuxLabel option to DockerOptions ("z" | "Z" | false, default "z"). Extracts shared formatVolumeMount from Podman provider into src/mountUtils.ts so both providers use the same volume-mount formatter.
  • 9bf43df: Auto-create parent directories for file-target bind mounts under /home/agent. When a user mount targets a single file whose sandbox-side parent directory may not exist in the image (e.g. /home/agent/.codex/auth.json), both Docker and Podman providers now run mkdir -p + chown on the parent at container start. File mounts whose parent is outside /home/agent fail at config time with a clear error and remediation guidance.
  • adbb3cc: Add variant option to the opencode agent provider for controlling reasoning effort via opencode's --variant CLI flag.

v0.5.8

06 May 13:18
b9f7ca4

Choose a tag to compare

Patch Changes

  • 7400ead: Add a short hint to the parallel-planner and parallel-planner-with-review plan prompts noting that the issues list is already filtered, so the planner agent is less likely to requery and pick up issues outside the configured filter.
  • 21b6442: Fix Windows hosts emitting backslash separators for in-container paths during session capture/resume and copyPaths. sandboxSessionStore, defaultSessionPathsLayer, and startSandbox's copyPaths now use POSIX joins for paths that target the Linux container, so docker cp / podman cp no longer reject them on Windows.

v0.5.7

01 May 13:15
20cb608

Choose a tag to compare

Patch Changes

  • 904ad82: Fix PromptError: Prompt argument "{{TASK_ID}}" has no matching value in promptArgs thrown on every iteration of the simple-loop, sequential-reviewer, and parallel-planner* merge flows after sandcastle init. The VIEW_TASK_COMMAND and CLOSE_TASK_COMMAND registry values used to embed {{TASK_ID}}, which got baked into prompts whose runtime promptArgs do not include TASK_ID. They now use a plain <ID> placeholder for the agent to fill in from surrounding context.

v0.5.6

29 Apr 20:22
e640931

Choose a tag to compare

Patch Changes

  • 54b5111: Add timeouts.copyToWorktreeMs option to override the host-to-worktree copy timeout (default: 60 000 ms).
  • d8484ca: Surface fallback cp -R failures from copyToWorktree as a typed CopyToWorktreeError instead of silently swallowing them
  • b6cc84f: Fix WorktreeManager.pruneStale deleting active worktrees when .sandcastle (or any ancestor of the repo directory) is a symlink. git worktree list returns canonicalized paths, so the un-canonicalized prefix never matched the active set and parallel createSandbox() calls would wipe each other's worktrees mid-run, surfacing as spawn /bin/sh ENOENT.
  • 26920ca: Fix branchStrategy.baseBranch being silently dropped when calling sandcastle.run() with a worktree-based sandbox. New branches now correctly fork from the requested baseBranch instead of the host's HEAD.
  • bbb0f39: Fix encodeProjectPath to handle Windows paths by replacing backslashes with hyphens and stripping drive-letter colons, producing a valid single directory-name component on Windows.
  • b2123e4: Add optional timeoutMs field to hook objects, allowing per-hook timeout overrides with fallback to the default 60s
  • a658fcc: Update Quick Start install command to recommend --save-dev and note that Sandcastle is a dev/CI tool
  • 425b77e: Use APFS clonefile (cp -cR) on macOS for copy-to-worktree instead of GNU --reflink=auto, giving Mac users instant copy-on-write on APFS volumes

v0.5.5

27 Apr 08:03
972e266

Choose a tag to compare

Patch Changes

  • e868d2d: Fix createWorktree failing with "already exists" when reusing a preserved mid-rebase worktree. Collision detection now also matches by target path, covering the detached-HEAD state during an in-progress rebase.

v0.5.4

24 Apr 19:25
0ade9bb

Choose a tag to compare

Patch Changes

  • 9c8516d: Surface agent error details in AgentError when stderr is empty. Error events emitted to stdout by Codex and Pi, plus OpenCode's result text, are now parsed and included in the error message instead of being dropped.

  • b2cc893: Show context window size per iteration in the run summary. Each iteration with usage data emits a Context window: NNNk line (tokens rounded up to the nearest 1000) in both terminal and log-to-file mode.

  • 2843c1b: Support baseBranch when creating sandboxes, so new branches can be forked from a specified ref. Available both on createSandbox and in the named branch strategy.

  • d860e84: Fix Beads Dockerfile build failure on arm64 hosts (e.g. Apple Silicon). The image now builds on both amd64 and arm64.

  • fdd9b9e: Fix built-in review prompt templates so they respect the configured source branch instead of always diffing against main.

  • cfbeb67: Fix parallel-planner-with-review template to capture reviewer result and merge commits from both implementer and reviewer runs

  • eb03260: Fix transient worktree creation failure when branch.autoSetupMerge or push.autoSetupRemote is enabled globally

  • 4032e64: Inline prompts (prompt: "...") are now passed to the agent literally — no {{KEY}} substitution, no !`command` expansion, no built-in {{SOURCE_BRANCH}} / {{TARGET_BRANCH}} injection. Fixes #453: callers that build inline prompts from arbitrary content (issue bodies, PR descriptions) no longer fail when that content happens to contain {{...}}. Passing promptArgs alongside an inline prompt is now an error; use promptFile to opt into template behavior.

  • 6bc4d74: Fix PromptPreprocessor executing !`...` patterns that arrive via promptArgs substitution. Argument values are now treated as inert data: only shell blocks written in the raw template are executed. Previously, any caller passing text through promptArgs (issue titles, bodies, docs excerpts, etc.) could hit spurious command execution — or, with untrusted inputs, remote shell execution — because the preprocessor scanned the fully-assembled prompt after substitution.

  • 359907e: Add onAgentStreamEvent option to logging in log-to-file mode. The callback receives each text chunk and toolCall emitted by the agent, with the iteration number and a timestamp, so callers can forward the agent's output stream to an external observability system. Errors thrown by the callback are swallowed so a broken forwarder cannot kill the run.

  • ce1bf1b: Support tilde expansion in sandboxPath for Docker and Podman mount configs.

    Users can now write sandboxPath: "~/.npm" and it expands to /home/agent/.npm inside the sandbox. The expansion uses the provider's declared sandboxHomedir ("/home/agent" for Docker and Podman). Using ~ in sandboxPath with a provider that has no sandboxHomedir throws a descriptive error at mount resolution time.

v0.5.1

21 Apr 19:43
308b6a7

Choose a tag to compare

Patch Changes

  • ba6121e: Add a cwd option to createSandbox(), createWorktree(), run(), and interactive(). When provided, cwd replaces process.cwd() as the host repo directory used for worktrees, .sandcastle/.env, logs, patches, and git operations, letting you drive Sandcastle from outside the target repo. Relative paths resolve against process.cwd(); absolute paths pass through. A CwdError is raised when the path does not exist or is not a directory.
  • f872268: Fix session capture, which always failed with "Could not find the file". Sandcastle was looking for session JSONLs under a sessions/ subdirectory that Claude Code does not actually use.

v0.5.0

21 Apr 17:14
e9fb01b

Choose a tag to compare

Minor Changes

  • 800e743: Restructure hooks API to group by execution location (host vs sandbox). The old flat hooks: { onSandboxReady } shape is replaced with hooks: { host?: { onWorktreeReady?, onSandboxReady? }, sandbox?: { onSandboxReady? } }. Host hooks run on the developer's machine; sandbox hooks run inside the container. Breaking change (pre-1.0).

Patch Changes

  • 4515aa9: Add copyFileIn and copyFileOut methods to BindMountSandboxHandle for moving individual files between the host and the sandbox. Docker uses docker cp, Podman uses podman cp, and the new testBindMount() provider uses a plain filesystem copy.
  • 3aa9d9a: Fix Podman sandbox failing on macOS when host UID differs from 1000 by chowning /home/agent to the host UID:GID after container start, matching Docker provider behavior.
  • 0a84413: Breaking: Replace RunResult.iterationsRun with RunResult.iterations: IterationResult[]. Each IterationResult carries an optional sessionId extracted from Claude Code's stream-json init line. Consumers needing the iteration count should read iterations.length. Non-Claude agent providers produce sessionId: undefined. The same change applies to OrchestrateResult, SandboxRunResult, and WorktreeRunResult.
  • 85eb071: Add session capture and resume for Claude Code:
    • Capture: after each iteration, the agent's session is saved to the host at ~/.claude/projects/<encoded>/sessions/<id>.jsonl so it can be replayed or inspected locally with Claude Code's usual tooling. Adds captureSessions option to claudeCode() (default true) and sessionFilePath to IterationResult.
    • Resume: adds resumeSession option to run() for continuing a prior Claude Code conversation in a new sandbox run. Incompatible with maxIterations > 1.
    • Exposes the underlying SessionStore interface and transferSession helper for users who want to move sessions between the host and a sandbox directly.

v0.4.8

17 Apr 12:11
1fba706

Choose a tag to compare

Patch Changes

  • c8cfcc6: Add timeout to the isolated provider copyPaths loop in startSandbox. The entire copy loop is now wrapped with withTimeout (120s), producing a CopyToWorktreeTimeoutError on expiry, consistent with the per-step timeout pattern used elsewhere in the sandbox lifecycle.
  • bab11e9: Add network option to Docker and Podman sandbox providers for custom container networking
  • a2c580f: Make Dockerfile generation aware of the selected backlog manager. When "beads" is chosen, the Dockerfile installs beads CLI tools instead of GitHub CLI.
  • a2fd5ad: Generate .env.example dynamically during sandcastle init based on selected agent and backlog manager instead of copying a static file from the template directory.
  • 20741fe: Fix parallel-planner templates to use {{CLOSE_TASK_COMMAND}} placeholder instead of hardcoded "close the issue" language, and replace "GitHub issue" with backlog-agnostic wording
  • b7880ec: Make prompt/promptFile optional in interactive() — when neither is provided, the agent TUI launches with no initial prompt (the full prompt pipeline is skipped).
  • aea1131: Add per-step timeouts across the sandbox lifecycle. Every lifecycle step is now wrapped with Effect.timeoutFail via a withTimeout utility, producing a step-specific tagged error on expiry. Breaking: TimeoutError renamed to AgentIdleTimeoutError with timeoutMs field replacing idleTimeoutSeconds.
  • c261079: Support relative paths in MountConfig for bind-mount sandbox providers. hostPath relative paths resolve from process.cwd(), and sandboxPath relative paths resolve from the sandbox repo directory.
  • d13acc3: Remove unnecessary copyToWorktree and branchStrategy from planner and merger agents in parallel planner templates. These lightweight agents (maxIterations: 1) now default to head mode, avoiding the overhead of copying node_modules into worktrees.
  • 0f8a99a: Remove semaphore concurrency limiter from parallel-planner-with-review template. Issue pipelines now run concurrently via Promise.allSettled without a concurrency cap, matching the parallel-planner template.
  • bf23e83: Rename workspace terminology back to worktree across the codebase. All public API types and functions renamed from Workspace* to Worktree* (e.g. createWorktree(), Worktree, WorktreeBranchStrategy). copyToWorkspace renamed to copyToWorktree. sandboxWorkspacePath renamed to sandboxRepoPath and SANDBOX_WORKSPACE_DIR to SANDBOX_REPO_DIR for sandbox-internal paths. Source files renamed accordingly (WorktreeManager.ts, CopyToWorktree.ts, createWorktree.ts).

v0.4.7

15 Apr 10:13
bbe1776

Choose a tag to compare

Patch Changes

  • 6d0c1fb: Make sandbox optional in InteractiveOptions, defaulting to noSandbox()