Sandcastle resumeSession Constraints: Validation Rules and File Requirements
The resumeSession feature in Sandcastle requires maxIterations to be set to 1 and mandates that the session JSONL file exists on the host filesystem at ~/.claude/projects/<encoded>/<id>.jsonl before the agent can resume the Claude Code session.
The resumeSession feature in mattpocock/sandcastle allows you to continue a previously saved Claude Code agent run inside a sandboxed environment. Before invoking this capability, the framework enforces specific constraints to ensure session integrity and prevent iteration conflicts.
Validation Constraints for resumeSession
The run function in src/run.ts enforces two hard constraints before allowing a session to resume.
maxIterations Must Equal 1
The resume logic only applies to the first iteration of the agent loop. In src/run.ts lines 52-58, the code validates that maxIterations is explicitly set to 1. This constraint exists because the session restoration hook executes only at the beginning of the first iteration, and multi-iteration runs could lead to undefined behavior when combined with resumed state.
Session File Must Exist on Host
The framework validates that the referenced session file exists on the host filesystem before attempting to transfer it to the sandbox. In src/run.ts lines 76-84, the code checks for the presence of the JSONL file at ~/.claude/projects/<encoded>/${resumeSession}.jsonl. If the file is missing, the function throws an Error with a clear message before any sandbox operations begin.
How Session Transfer Works
Once validation passes, Sandcastle coordinates the movement of session data between the host and the sandbox environment.
Host and Sandbox Session Stores
In src/SessionStore.ts, the transferSession(from, to, id) function (lines 20-70 and 119-136) handles the actual file movement. The implementation defines two concrete stores:
- hostSessionStore: Reads and writes JSONL files in
~/.claude/projects/<encoded>/on the host machine - sandboxSessionStore: Copies files through the bind-mount sandbox handle or via
docker cp/podman cpfor isolated environments
Orchestrator Execution
In src/Orchestrator.ts lines 79-99, the per-iteration loop constructs both stores and invokes transferSession when i === 1 and a resumeSession ID is present. This copies the JSONL file into the sandbox's ~/.claude/projects/<encoded>/ directory before the agent starts.
CLI Flag Injection
After transferring the session file, Sandcastle must instruct Claude Code to load it. In src/AgentProvider.ts lines 70-74, the buildPrintCommand method appends the --resume <id> flag to the CLI command. This instructs the agent to restore its internal conversation state, tool call history, and token usage from the supplied JSONL file.
Error Handling
The feature implements specific error handling for constraint violations:
- Missing file: If the session file does not exist during validation,
src/run.tsthrows a standardError(lines 77-84) - Transfer failure: If the file copy fails due to permissions or network issues, the Orchestrator wraps the error in a
SessionCaptureError(lines 92-98 insrc/Orchestrator.ts)
Usage Example
import { run } from "./src/run.js";
import { claudeCode } from "./src/AgentProvider.js";
import { docker } from "./src/SandboxFactory.js";
await run({
agent: claudeCode("claude-opus-4-7"),
sandbox: docker({ imageName: "sandcastle:myrepo" }),
cwd: "/my/project",
prompt: "Continue the previous analysis from where we left off",
resumeSession: "abc-123", // File must exist at ~/.claude/projects/<encoded>/abc-123.jsonl
maxIterations: 1, // Required constraint
});
Running this script validates the constraints, transfers the session file into the sandbox, and launches claude --resume abc-123 to continue the previous conversation exactly where it paused.
Summary
- Set
maxIterations: 1when usingresumeSessionto satisfy the validation logic insrc/run.ts - Verify file existence at
~/.claude/projects/<encoded>/<id>.jsonlbefore running, or the framework throws an error - Transfer mechanism uses
SessionStore.transferSessioncalled by the Orchestrator at the first iteration only - CLI integration occurs via
AgentProvider.tswhich appends the--resume <id>flag to the Claude Code command - Error types include standard
Errorfor missing files andSessionCaptureErrorfor failed transfers
Frequently Asked Questions
What happens if I set maxIterations greater than 1 with resumeSession?
The validation logic in src/run.ts lines 52-58 will throw an error preventing execution. The resume hook is designed to run only once at the start of the first iteration, making multi-iteration resumes architecturally incompatible with the current implementation.
Where does Sandcastle look for the session file?
According to the source code in src/run.ts lines 76-84, Sandcastle expects the file at ~/.claude/projects/<encoded>/${resumeSession}.jsonl on the host filesystem, where <encoded> represents the encoded project path. The file must exist before the run function executes.
Can I resume a session in an isolated sandbox without bind mounts?
Yes. While bind-mount providers allow direct file access, isolated sandboxes use the sandboxSessionStore implementation which transfers files via docker cp or podman cp mechanisms. The transferSession abstraction in src/SessionStore.ts handles both transparently.
What error occurs if the session file is missing?
If the JSONL file does not exist at the expected path, src/run.ts throws an Error with a descriptive message explaining that the session file could not be found. This validation occurs before any sandbox container operations, preventing wasted resources on failed runs.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →