---
title: "Sandbox"
description: "Compare mikan's supported host, container, image, and Cloudflare sandbox modes."
url: "https://geminixiang.github.io/sandbox/"
---

# Sandbox

`host` has the least setup and does not inject vault env. It cannot enforce an isolated
    office or read-only shared memory, so it needs an explicit trusted read-write policy when
    the platform-derived projection requests either boundary.
    `image:<image>` lets mikan manage lifecycle, workspace mounts, vault env, and resource limits.

  `docker:*` is not a supported mode; use `container:*` or `image:*` instead.

## Supported modes

| Mode                      | Execution location        | Vault env injection | Vault key                       | Notes                                                                                            |
| ------------------------- | ------------------------- | ------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------ |
| `host`                    | host machine              | not injected        | derived from the platform user  | Local development only; requires a trusted read-write projection                                 |
| `container:<name>`        | existing Docker container | injected            | derived from the container name | one container one vault; multiple people sharing one container also share its vault              |
| `image:<image>`           | Docker managed by mikan   | injected            | the office key                  | Current recommended isolation mode; `1 conversation = 1 vault = 1 container`                     |
| `cloudflare:<sandbox-id>` | Cloudflare Worker         | injected            | the office key                  | Under 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](#conversation-offices).

## 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:*`):

| Door policy / layout / visibility        | Mounted under `/workspace`                                                        |
| ---------------------------------------- | --------------------------------------------------------------------------------- |
| `isolated` / `conversation`              | only `<office-key>/`                                                              |
| `trusted` / `shared-support` / `public`  | `<office-key>/` plus shared `MEMORY.md`, `skills/`, and `events/`, all read-write |
| `trusted` / `shared-support` / `private` | the same support paths, but shared `MEMORY.md` is read-only                       |
| `trusted` / `full`                       | the entire workspace root                                                         |

Without an explicit workspace setting, recorded Slack public channels derive trusted/public shared
support, private channels derive trusted/private shared support, and DMs, external channels,
unknown kinds, and platforms without recorded visibility derive isolated. Only `image:*` can enforce
isolated projections or read-only shared memory. The other modes report `managedProjection: false`
and refuse those runs until an admin chooses `image:*` or an explicit trusted read-write policy.
Field semantics and the legacy `sandbox.image.workspaceMount` translation are documented in
[Configuration](/configuration/).

  Door policy decides which host directories are projected into the runtime. It is not an execution
  boundary: `host` mode runs tools directly on the host with no filesystem or process isolation
  whatever policy is chosen, and a `full` layout gives the runtime every conversation's office.

### Upgrading from the raw-id layout

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.

## Per-mode docs

<LinkCard
  title="Host sandbox"
  description="Run tools directly on the host; best for local development."
  href="host/"
/>
<LinkCard
  title="Container sandbox"
  description="Connect to an existing Docker container and reuse your own lifecycle management."
  href="container/"
/>
<LinkCard
  title="Image sandbox"
  description="Let mikan manage per-conversation containers and resource limits."
  href="image/"
/>
<LinkCard
  title="Cloudflare sandbox"
  description="Run tools through a Cloudflare Worker bridge; under construction."
  href="cloudflare/"
/>

## Capability differences

`image:<image>` <Badge text="recommended" variant="success" /> 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.

| Capability                                   | `host`         | `container:<name>`     | `image:<image>` | `cloudflare:*`     |
| -------------------------------------------- | -------------- | ---------------------- | --------------- | ------------------ |
| command execution                            | ✅             | ✅                     | ✅              | ✅                 |
| mikan-managed runtime lifecycle              | not applicable | ❌                     | ✅              | ❌                 |
| per-conversation container / runtime         | ❌             | ❌                     | ✅              | bridge-derived id  |
| per-conversation vault env                   | ❌             | ❌                     | ✅              | ✅                 |
| automatic vault file projection / bind mount | ❌             | ❌                     | ✅              | ❌                 |
| automatic workspace mount                    | host           | self-managed           | ✅              | ❌                 |
| isolated conversation office                 | ❌             | ❌                     | ✅              | ❌                 |
| read-only shared workspace memory            | ❌             | ❌                     | ✅              | ❌                 |
| idle auto-stop / recreate                    | not applicable | ❌                     | ✅              | ❌                 |
| default CPU / memory limits                  | ❌             | ❌                     | ✅              | ❌                 |
| `/pi-sandbox boost`                          | ❌             | ❌                     | ✅              | ❌                 |
| agent `sandbox` tool sets limits             | ❌             | ❌                     | ✅              | ❌                 |
| recommendation level                         | local dev      | legacy / compatibility | mainline        | under construction |

These ❌ rows are refusals rather than silent downgrades. A mode that cannot enforce an isolated
projection raises `Sandbox '<type>' cannot provide an isolated conversation office`; one that cannot
enforce private visibility raises `Sandbox '<type>' cannot enforce read-only shared workspace memory`.
A mode that cannot mount vault files raises `Sandbox type "<type>" does not support vault file mounts`
instead of running without the credential. On modes that cannot project files, keep vault credentials
in `env` only.
