How to run mini-me in a Docker Sandbox
This guide shows how to run mm inside a Docker Sandbox, so that every command the model runs and every file it edits happens in a container, on a mounted copy of your project. It covers the window mode in your terminal and an editor through the Agent Client Protocol. It assumes Docker Desktop with the sbx command, and a model server running on your machine.
Everything lives under demos/use-with-sbx/ in the repository. The kits follow the kit specification v3 (schemaVersion: "3"): one workload that runs mm, and mixins you add to it with --kit.
| Piece | Where | What it is |
|---|---|---|
mini-me |
bots-garden/mini-me-kit, directory mini-me/ |
The workload: Docker's shell template (Ubuntu, user agent) with the mm binary of a release (mm_version, default v0.3.0), downloaded from mini-me's release page. Entry point mm, default arguments -tui. Versioned by its own tags (v0.0.1). |
go-toolchain |
demos/use-with-sbx/kits/go-toolchain/ |
A mixin: Go (go_version, default 1.27.2), gofmt and gopls (gopls_version, default latest). Allows the module hosts at runtime: proxy.golang.org, sum.golang.org, github.com, golang.org. |
cli-tools |
demos/use-with-sbx/kits/cli-tools/ |
A mixin: rg, bat and eza as static binaries. No runtime network. |
agent.yaml, agent.lucy.yaml |
demos/use-with-sbx/ |
Two mm configurations for llmman (Jan-nano, Lucy). |
AGENTS.md |
demos/use-with-sbx/ |
Instructions for the agent working inside the sandbox (the tools installed, how to run Go): mm adds it to its system prompt when it runs in that directory — see How to give the agent your project's instructions. |
Steps
1. Allow the kit's source
The mini-me kit is referenced by git URL, a tag and its directory. Its host must be an allowed kit source, once:
sbx settings set kit.allowedSources '["docker.io/","git.rickub.com/bots-garden/"]'
2. Window mode in the terminal
From the directory you want mm to work on — demos/use-with-sbx/ itself, to use its configurations and its AGENTS.md:
cd demos/use-with-sbx
RELEASE=v0.0.1
REPOSITORY=git+https://git.rickub.com/bots-garden/mini-me-kit.git
sbx run --name mm-demo-remote "${REPOSITORY}#ref=${RELEASE}&dir=mini-me"
The first run builds the kit, creates the sandbox, mounts the current directory as its workspace and runs mm -tui, which reads ./agent.yaml. Add the mixins with --kit; what follows -- replaces the default arguments, so it is mm's whole command line:
sbx run --name mm-demo-remote "${REPOSITORY}#ref=${RELEASE}&dir=mini-me" \
--kit ./kits/go-toolchain --kit ./kits/cli-tools \
-- -tui -config agent.lucy.yaml
The sandbox keeps its name; sbx run --name mm-demo-remote attaches to it again later. The window is the one described in Use the window mode. Sessions, when sessions.enabled is on, are written under the workspace's .mm/sessions — your host directory — so they survive the sandbox.
To work on the kit itself, clone mini-me-kit and run it from its demo/ directory: sbx run --name mm-demo ../mini-me.
3. From an editor (ACP)
An editor talks to mm -acp over raw stdin and stdout, which sbx run cannot carry (it always allocates a terminal). Create the sandbox once without attaching, then let the editor start mm inside it with sbx exec -i:
-
From the project the editor will open, with the kit's remote reference:
RELEASE=v0.0.1 REPOSITORY=git+https://git.rickub.com/bots-garden/mini-me-kit.git sbx create --name mm-acp "${REPOSITORY}#ref=${RELEASE}&dir=mini-me" . \ --kit /path/to/mini-me/demos/use-with-sbx/kits/go-toolchainor with a local clone of mini-me-kit (a kit path must start with
./,../or/):git clone https://git.rickub.com/bots-garden/mini-me-kit.git /path/to/mini-me-kit sbx create --name mm-acp /path/to/mini-me-kit/mini-me . \ --kit /path/to/mini-me/demos/use-with-sbx/kits/go-toolchainThe workspace (
.) is fixed at creation: one sandbox per project, each with its own--name. -
Check it by hand:
sbx exec -i mm-acp mm -acp -config agent.lucy.yaml -
Register it in Zed's
settings.json:{ "agent_servers": { "mini-me (sandbox)": { "type": "custom", "command": "sbx", "args": ["exec", "-i", "mm-acp", "mm", "-acp", "-config", "agent.lucy.yaml"] } } }If the editor cannot find
sbx, put the absolute path fromwhich sbxin"command". Tool calls, permission dialogs,@filementions and the slash-command menu work as on the host; the difference is where the commands run. See Use mini-me from an editor for the host-side setup.
Generate a sbxenv.yaml with mm sbxinit
To describe the sandbox in a file, run this in your project's directory:
mm sbxinit
sbx env create --force
sbx env needs sbx 0.39.0 or newer, and docker.io/ among the allowed kit sources (step 1). The file names the latest mini-me-kit, and pullPolicy: always makes the sandbox fetch it at each creation. If that version cannot be read, for instance without network, mm says so and uses the tag latest. The sandbox is named after acp.name in agent.yaml, followed by -sbx; --name chooses another one.
To mount a sub-folder rather than the current directory:
mm sbxinit --workspace ./workspace
The file then holds the folder's absolute path. Create the folder yourself: mm warns you if it does not exist. To remove the sandbox, run sbx env rm --force.
All the flags are in the CLI reference.
When the agent file is outside the workspace
The sandbox only sees what is mounted. With --workspace ./workspace and an agent.yaml in the parent folder, mm in the sandbox cannot read that file. mm sbxinit warns you (agent.yaml is outside the workspace) and changes nothing else: the generated file only mounts the workspace.
You have two ways to solve it.
Put the agent file in the workspace. This is the simple way, and the file needs no change:
mv agent.yaml workspace/
The agent can then rewrite its own file, because the workspace is writable.
Mount the agent file's folder read-only. Choose this when the agent must not be able to change its own settings. Keep the agent file in its own folder, not in the parent of the workspace:
project/
├── sbxenv.yaml not mounted
├── agents/ agent.yaml, mounted read-only
└── workspace/ the code, mounted read-write
Then add this to sbxenv.yaml by hand:
additionalWorkspaces:
- path: ./agents
readOnly: true
# The folder of this file, as the sandbox sees it.
args:
PROJECT_DIR:
required: true
env:
# mm reads this agent file instead of ./agent.yaml.
AGENT_CONFIG: ${{ env.args.PROJECT_DIR }}/agents/agent.yaml
Every sbx env command now needs the argument:
sbx env create --force --env-arg PROJECT_DIR="$PWD"
sbx env rm --force --env-arg PROJECT_DIR="$PWD"
mm sbxinit does not generate this form, because it makes the file longer for a case most projects do not have. Running mm sbxinit again and answering yes replaces these additions. demos/dev.team/sbxenv.yaml is a complete example.
The model server stays on the host
Inside a sandbox localhost is the sandbox itself. Your model server keeps running on your machine and is reached through host.docker.internal, which the sandbox proxy maps to your host.
-
The
mini-mekit's network policy allowshost.docker.internal:12434(Docker Model Runner),:11434(Ollama) and:17434(llmman).agent.dmr.yamlalready falls back tohttp://host.docker.internal:12434/engines/v1; the configurations shipped indemos/use-with-sbx/use llmman (fallback: http://host.docker.internal:17434/v1). -
For another port — llama-server's
8080, for instance — add it to the kit'snetwork-policycapability, or allow it for one sandbox:sbx policy allow network host.docker.internal:8080sbx policy logshows what was blocked.
Change a version
- mm: the
defaultofmm_versioninmini-me/mini-me.yamlof the mini-me-kit repository — a release tag such asv0.3.0; the kit's own tag (RELEASEabove) then names the new kit. The build downloadshttps://rickub.com/bots-garden/mini-me/releases/download/<tag>/mm-<version>-linux-<arch>; a tag with no such release fails the build. - Go, gopls, rg, bat, eza: the
defaultof the matching argument in the mixin's YAML (go_version,gopls_version,rg_version,bat_version,eza_version); each one has apatternthat refuses a malformed version.
MCP servers through the sbx gateway
Inside a sandbox, mm does not talk to MCP servers itself and holds no token. sbx runs one MCP gateway per sandbox, on the host, and bakes MCP_GATEWAY_URL into the container. When mm finds MCP_GATEWAY_URL and mcp.enabled: true, it adds a server called sbx-gateway, and its tools show up as sbx-gateway_<tool>:
mcp:
enabled: true
permissions: ask
discoveryTimeout: 10s
servers: [] # the gateway is added by mm when MCP_GATEWAY_URL is set
Register the server on the host (sbx mcp add <name> --command <script>), then create a new sandbox with it in its fixed set — --static-mcp <name> is an sbx flag and goes before --. If no sbx-gateway_* tool appears in the banner, sbx mcp inspect <name> and sbx's mcp/mcp.log say why.
Variants
- Skills.
skillsDiris relative to the directorymmruns in — the workspace — as on the host. - Read the logs. In the window mode they are on screen; over ACP they go to stderr, which Zed shows under
dev: open acp logs. - A shell in the sandbox.
sbx exec -it mm-acp bash. - Remove a sandbox.
sbx rm mm-acp. The project directory is a bind mount and is not touched.
See also
- The kit format: specification v3.
- What
mm -acpexposes to the editor: ACP reference. - The flags and environment variables
mmreads: command line reference.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
|