Guide
Advanced Topics
Deeper tooling for sandboxes, file sets, and power-user workflows.
Sandbox
A sandbox is an ephemeral container that runs a single command
and is discarded as soon as it exits. It is the same machinery Overplane uses
internally for agent runs, exposed directly through the
overplane sandbox run command so you can run ad-hoc commands inside
your project's image — or any image — without writing a script or remembering
long docker/podman invocations.
The sandbox abstracts over both Docker and Podman, so the same command behaves identically on either engine. Every run is fresh and isolated: there is no shared state between runs, and the container is removed when the command finishes.
Always-on guarantees
These mounts are applied to every sandbox run:
- The project repository is mounted read-only at
/project. Commands can read your project tree but cannot mutate the host. In a project sandbox, the specs directory is also mounted read-only at/specs. - Two fresh read-write scratch directories are mounted at
/outputand/error. Each run gets new, empty ones; the container's working directory defaults to/output. Files a command writes there are captured when it exits, and--output DIR/--error DIRextract them to host directories after a successful run. - The
overplanebinary is mounted at/usr/local/bin/overplane. The exact binary you invoked is onPATHinside the container — no image rebuild needed — so tooling that shells out tooverplanejust works.
Running ad-hoc commands
By default, sandbox run uses your project's built image (overplane-<project>:latest) and the runtime configured in
overplane.yaml, so sandbox build must have built the
image first. The command's output is streamed through, and its exit code becomes
overplane's exit code.
# Run a command in the project image. The natural form needs no '--':
# flag parsing stops at the first non-flag token, so '-l' is ls's flag.
overplane sandbox run ls -l
# Use '--' when the command itself starts with a dash.
overplane sandbox run -- some-tool --version
With --image (and optionally --runtime), the
sandbox runs against any image and does not require a project:
overplane sandbox run --image debian:bookworm-slim -- cat /etc/os-release
overplane sandbox run --image alpine --runtime podman -- sh -c 'echo hi' Customizing the environment
sandbox run exposes a flag for every option of the underlying abstraction:
-
--image REF— run this image instead of the project image (no project required). -
--runtime docker|podman— pick the container engine (defaults to the project runtime, else docker). -
--env KEY=VALUE— set an environment variable (repeatable). -
--env-from-host KEY— copy a variable from your host environment (repeatable). -
--mount HOST:CONTAINER[:ro|rw]— bind-mount extra host paths (repeatable; defaults torw). -
--network MODE— set the network mode, e.g.hostornone. -
--user UID:GID— override the run identity (defaults to your current host uid/gid). -
--workdir DIR— set the container working directory (defaults to/output). -
--project DIR— choose which host directory is mounted read-only at/project(defaults to the project root). -
--output DIR— extract captured/outputfiles to this host directory after a successful run. -
--error DIR— extract captured/errorfiles to this host directory after a successful run. -
--no-self-mount— do not mount theoverplanebinary into the container. -
--json— emit a structured result instead of streaming output.
overplane sandbox run \
--env CI=1 \
--env-from-host HOME \
--mount ./data:/data:ro \
--network none \
-- ./build.sh Structured output
Pass --json to capture the result instead of streaming it. The object
carries the exit code, engine, image, wall-clock duration, optional memory/CPU
usage, and base64-encoded stdout/stderr — so binary
output and separate streams survive intact.
{
"cpu_ms": ..., // omitted when the engine cannot report it
"engine": "docker",
"exit_code": 0,
"image": "overplane-myproject:latest",
"max_rss_bytes": ..., // omitted when unavailable
"stderr": "ZXJyCg==", // base64("err\n")
"stdout": "b3V0Cg==", // base64("out\n")
"wall_ms": 84
}