container runs every Linux
container in its own lightweight VM with its own kernel, on Apple silicon with
macOS 26 or later. AppleContainerRuntime connects to a container you
started and executes every captured line inside it; Mirage never starts,
stops, or deletes one. See the Sandbox overview
first for routing, the shared image, and how to serve workspace mounts inside
the sandbox.
Start the container
Install the tool and start its services once, then build the sandbox image from the Mirage repository root:--target fuse selects the Dockerfile’s FUSE build stage. -t mirage-python-fuse
assigns a local name to the resulting image, which contains Python, Mirage,
and FUSE (Filesystem in Userspace). FUSE makes workspace backends accessible
as ordinary files inside the container.
This example reuses Mirage’s shared Python image to serve the workspace
mounts. You can control it from the TypeScript SDK: the host SDK and the
Mirage implementation inside the container are independent. For a custom
image, see The sandbox image.
Create
sandbox.yaml with your backends and mount paths, following
The workspace inside the sandbox.
Then copy it into the container and start the workspace:
--volume; the guest otherwise sees nothing from the host filesystem. A
service on your Mac is not at 127.0.0.1 inside the container either; Apple’s
host integration guide
sets up a host.container.internal name for sandbox-side configs.
Connect from TypeScript
container CLI is the transport, so there is no SDK dependency. The
container config is the id the container was started with (its --name);
unknown config fields fail at construction. The first captured line checks
container inspect and accepts only running; a stopped container needs
container start. Stdin and stderr stay separate.
Differences from docker exec
Every captured command runs under a short sh prelude, so the image needs a
POSIX sh. The prelude evens out two ways container exec differs from
docker exec:
container exec -eappends to the image’s environment rather than replacing a variable the image already sets, so a program started directly would read the image’sPATH. Under the prelude the session’s value wins, as it does with Docker.container exec -wcreates a working directory that does not exist. Under the prelude, a cwd the container does not serve fails loudly (can't cd to /data) instead of running in an empty directory whose writes never reach the backend.
One container per agent
A line runs in its session’s container. List agents undercontainers,
keyed by the session id each agent’s session is created with; a session not
listed runs in container:
config: {container: my-sandbox, containers: {agent_a: sandbox-a, agent_b: sandbox-b}}.
Separate containers are separate
VMs, so agents share no files, processes, CPU or memory. Each container serves
its own view of the workspace: with Mirage inside it, make that agent’s rules
the default profile in its sandbox.yaml; with a mount over SFTP, bind the
container’s key to the agent’s profile
(Bind a key to a profile). A session
with no container of its own and no container fails with
apple_container has no container for session .... Each container is checked
with container inspect on its first line.
One container is one VM. Concurrent lines sent to the same container share
its filesystem and process table, so give agents that must not see each
other their own container.