Skip to content

Sandbox

Compare mikan's supported host, container, image, microVM, Firecracker, and Cloudflare sandbox modes.

Local development

host has the least setup and does not inject vault env. It cannot provide an isolated conversation office, so it also needs an explicit trusted door policy.

Mainline isolation

image:<image> lets mikan manage lifecycle, workspace mounts, vault env, and resource limits.

Gondolin preview

gondolin:default runs a local Gondolin/QEMU microVM in mikan’s own process and is the planned successor to managed image:* sandboxes.

ModeExecution locationVault env injectionVault keyNotes
hosthost machinenot injectedderived from the platform userLocal development only; needs an explicit trusted door policy
container:<name>existing Docker containerinjectedderived from the container nameone container one vault; multiple people sharing one container also share its vault
image:<image>Docker managed by mikaninjectedthe office keyCurrent recommended isolation mode; 1 conversation = 1 vault = 1 container
gondolin:defaultlocal Gondolin/QEMU VMinjectedthe office keyPreview; single-host, in mikan’s own process; requires Node.js >=23.6 and QEMU
firecracker:<vm-id>:<host-path>[:<ssh-user>[:<ssh-port>]]Firecracker VMinjectedthe office keyVery early alpha; you must start the VM and mount workspace at /workspace; not recommended yet
cloudflare:<sandbox-id>Cloudflare Workerinjectedthe office keyUnder construction; requires your own @cloudflare/sandbox bridge; host workspace is not synced

The office key is the versioned v1-<platform>-<readable-id>-<hash> segment that also names the conversation’s directory under the workspace. See Conversation offices.

Each conversation owns one directory under the workspace root — its office — named by office key rather than by the platform’s raw conversation id. Sandbox mounts follow that directory, so inside a runtime the office is at /workspace/<office-key>.

Which parts of the workspace a runtime sees is the door policy, a sandbox.workspace setting the admin portal can set globally or per conversation (the /pi-sandbox door chat command does the same for one conversation, but only under image:* and gondolin:*):

Door policy / layoutMounted under /workspace
isolated (default)only <office-key>/
trusted / shared-support<office-key>/ plus the shared MEMORY.md, skills/, and events/
trusted / fullthe entire workspace root

Only image:* and gondolin:default can enforce the isolated projection. The other modes report managedProjection: false, and because isolated is the default, they refuse to start a run until someone explicitly chooses a trusted policy for that office. Field semantics and the legacy sandbox.image.workspaceMount translation are documented in Configuration.

Workspaces created before the office layout hold directories named by raw conversation id. Every boot migrates them — workspace directories, conversation vault keys, and per-conversation host state — journaling each move so an interrupted run resumes instead of losing a conversation.

Two situations stop boot deliberately rather than guessing:

  • Unowned directories. With several platforms enabled, mikan cannot tell which one owns a raw directory. Name the owner with mikan office claim <conversationId> <platform> (daemon stopped); the next start performs the move.
  • Conflicts, where both the legacy and the office-key directory already exist. These are reported for manual merge and never clobbered.

Managed containers survive the rename: their binds are translated onto a snapshot of the running container, so the writable layer is preserved rather than rebuilt from the base image.

image:<image> recommended is the primary developed and recommended sandbox mode today; the other modes are kept for local development, compatibility, or experiments, and some capabilities will not be filled in.

Capabilityhostcontainer:<name>image:<image>gondolin:defaultfirecracker:*cloudflare:*
command execution
mikan-managed runtime lifecyclenot applicable✅ process-owned
per-conversation container / runtimeself-managedbridge-derived id
per-conversation vault env
automatic vault file projection / bind mount
automatic workspace mounthostself-managedself-managed
isolated conversation office
idle auto-stop / recreatenot applicable
default CPU / memory limits
/pi-sandbox boost
agent sandbox tool sets limits
recommendation levellocal devlegacy / compatibilitymainlinepreviewalphaunder construction

Both ❌ rows above are refusals rather than silent downgrades. A mode that cannot enforce the isolated projection raises Sandbox '<type>' cannot provide an isolated conversation office instead of mounting more than the policy asked for, and a mode that cannot mount vault files raises Sandbox type "<type>" does not support vault file mounts instead of running without the credential. On the modes that cannot project files, keep vault credentials in env only.