bots-garden/mini-mepublic Fork
⑂ feature/mini-mes
Commits
⬇ Clone ▾
git clone https://git.rickub.com/bots-garden/mini-me.git
git clone ssh://git@rickub.com/bots-garden/mini-me.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP
📦 Mini Me 460cf23 · on feature/mini-mes · k33g · 27d ago
README.md · 208 lines · 11.2 KBmarkdown
Blame HistoryOpen raw

mm in a Docker Sandbox

Everything needed to run mm inside a Docker Sandbox: a template (the shell sandbox image with mm installed) and two kits that start it — one for the window mode in your terminal, one for an editor that speaks the Agent Client Protocol.

The full guide, with the reasoning, is in docs/en/how-to/run-in-a-docker-sandbox.md (français). This page is the short version.

docker-sbx/
├── publish.sh               build + push the image, then publish the kits — the one command to release
├── build.sh                 builds the template image, k33g/mm-sandbox:<version> (PUSH=1: multi-arch, pushed)
├── sync-kits.sh             points the kits at one image: owner + version
├── push-kits.sh             publishes the kits to Docker Hub as OCI artifacts (sbx kit push)
├── template/
│   ├── Dockerfile           docker/sandbox-templates:shell + mm (built from this checkout)
│   ├── mm-tui               entry point of the mm-tui kit: `mm -tui "$@"`
│   └── mm-acp-info          entry point of the mm-acp kit: prints the editor wiring, opens a shell
└── kits/
    ├── mm-tui/spec.yaml     kind: sandbox — `sbx run` opens mm's window on the workspace
    └── mm-acp/spec.yaml     kind: sandbox — `sbx create` once, the editor runs `sbx exec -i … mm -acp`

0. Use the published kits (no build)

Every release publishes the image and the two kits to Docker Hub at mm's version:

On Docker Hub What it is
k33g/mm-sandbox:0.1.7 The template image. You never name it yourself: each kit pulls it.
k33g/mm-tui:0.1.7 The window-mode kit, for sbx run.
k33g/mm-acp:0.1.7 The editor kit, for sbx create + sbx exec -i … mm -acp.

Nothing to build, no --pull never, and no setting to change: Docker Hub is an allowed kit source out of the box (sbx settings get kit.allowedSources shows docker.io/), and a reference with a / but no registry host is read as docker.io/…. Only Docker Desktop with the sbx command, and a model server on your machine, are needed.

Look before you run. sbx kit inspect reads the kit from the Hub without creating anything: its image, its entry point, its arguments and their defaults, the ports it allows.

sbx kit inspect k33g/mm-tui:0.1.7

Window mode. From the project you want mm to work on:

cd /path/to/your/project
sbx run k33g/mm-tui:0.1.7 . -- agent.dmr.yaml

The first run pulls the kit and the image, creates the sandbox mm-tui-<directory>, mounts the current directory as its workspace and opens mm -tui agent.dmr.yaml in it. What follows -- is mm's own command line, so -- -config other.yaml works too. Without anything after --, mm reads the kit's config argument, then ./agent.yaml in the workspace:

sbx run k33g/mm-tui:0.1.7 . --kit-arg config=agent.dmr.yaml

Later, sbx run --name mm-tui-<directory> re-attaches to that sandbox; sbx ls lists them.

From an editor. Create the sandbox once, from the project the editor will open, with the configuration file baked in:

cd /path/to/your/project
sbx create --name mm-acp k33g/mm-acp:0.1.7 . --kit-arg config=agent.dmr.yaml

#sbx create  k33g/mm-acp:0.1.7 . --name sbx-mm-acp

then register it in the editor — in Zed's settings.json:

{
  "agent_servers": {
    "mini-me (sandbox)": {
      "type": "custom",
      "command": "sbx",
      "args": ["exec", "-i", "mm-acp", "mm", "-acp"]
    }
  }
}

The editor starts mm -acp inside the sandbox for every conversation; sbx exec starts the sandbox first when it is stopped, and runs mm in the workspace with the baked-in AGENT_CONFIG. One sandbox per project, each with its own --name and its own editor entry. Section 3 has the details (another config for one session, where the logs are, why sbx exec -i and not sbx run).

Kit arguments. Both kits take the same two, passed with --kit-arg name=value (repeatable) to sbx run or sbx create:

--kit-arg Default Effect
config=<path> empty The file mm reads (its AGENT_CONFIG): relative to the workspace, or absolute inside the sandbox. Empty: ./agent.yaml, then the built-in defaults.
tag=<version> the kit's own version (0.1.7) Which k33g/mm-sandbox:<version> image to use. Normally left alone: a kit and its image share a version.

Other versions. Replace 0.1.7 with the release you want, in the kit reference only — the kit brings the matching image. A kit can also be pinned by digest, k33g/mm-tui@sha256:…, the digest being what sbx kit inspect or the Hub page shows.

If sbx refuses the source. A message like its source is not in your allowlist means kit.allowedSources was narrowed on this machine; sbx settings set kit.allowedSources '["docker.io/"]' restores the default, or add docker.io/k33g/ to your list.

Sections 1–3 are the same flow with a template and kits built locally, for a work-in-progress mm.

1. Build the template

From the repository root:

./docker-sbx/build.sh            # TAG from release.env: v0.1.7 → k33g/mm-sandbox:0.1.7
./docker-sbx/build.sh v0.1.5     # → k33g/mm-sandbox:0.1.5

The image tag is mm's tag without the v, the same rule as the release assets, and the script rewrites the kits' default tag argument to the version it built, so the kits always name the image just built. The image lands in the local Docker image store: every sbx run / sbx create below carries --pull never until you docker push k33g/mm-sandbox:0.1.7. If sbx runs on another machine, EXPORT=1 ./docker-sbx/build.sh also writes tmp/mm-sandbox-<version>.tar; load it there with sbx template load.

2. Window mode in the terminal — kit mm-tui

From the project you want mm to work on:

sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml

What follows -- reaches mm as its own arguments, so this runs mm -tui agent.dmr.yaml in the workspace. Any mm flag passes through the same way (-- -config other.yaml). Two kit arguments exist as well:

--kit-arg Default Effect
config=<path> empty The file mm reads when nothing follows -- (its AGENT_CONFIG). Relative to the workspace, or absolute. Empty: ./agent.yaml, then the built-in defaults.
tag=<version> the version last built (0.1.7) Which k33g/mm-sandbox:<version> image to use.

sbx run --name <name> re-attaches to a sandbox that already exists. Sessions, when enabled in the YAML, are written under the workspace's .mm/sessions, which is your host directory.

3. From an editor (ACP) — kit mm-acp

Create the sandbox once, without attaching, from the project the editor will open. . is the workspace; sbx makes it absolute. A path that does not exist on your machine makes sbx ask "The selected workspace does not exist. Would you like to create it?" — answer N and fix the path. The kit path must be explicit: ./, ../ or absolute.

cd /path/to/your/project
sbx create --pull never --name mm-acp ./docker-sbx/kits/mm-acp . \
    --kit-arg config=agent.dmr.yaml

# once the image is pushed (docker push k33g/mm-sandbox:0.1.7), --pull never is not needed:
sbx create --name mm-acp ./docker-sbx/kits/mm-acp . \
    --kit-arg config=agent.dmr.yaml

Then register it in the editor. In Zed's settings.json:

{
  "agent_servers": {
    "📦 mini-me (dmr sbx)": {
      "type": "custom",      
      "command": "sbx",
      "args": ["exec", "-i", "mm-acp", "mm", "-acp"],
    },    
  }
}

Or:

sbx create --pull never --name mm-acp-2 ./docker-sbx/kits/mm-acp . 

And:

{
  "agent_servers": {  
    "😄 mini-me (dmr sbx)": {
      "type": "custom",      
      "command": "sbx",
      "args": ["exec", "-i", "mm-acp-2", "mm", "-acp"],
      "env": { "AGENT_CONFIG": "/Users/k33g/kDrive/Rickub/bots-garden/mini-me/demo/agent.dmr.yaml" }
    },     
  }
}

The editor starts mm -acp inside the sandbox for every conversation; sbx exec starts the sandbox first when it is stopped, and runs mm in the workspace with the AGENT_CONFIG baked in by --kit-arg config. Everything the model does — commands, file edits — happens inside the sandbox, on the mounted project.

Why sbx exec -i and not sbx run: an ACP client speaks JSON-RPC on the agent's raw stdin/stdout, and sbx run always allocates a terminal. Attaching to this sandbox with sbx run --name mm-acp is still useful: its entry point prints the wiring above with the sandbox's real name, then opens a shell.

  • One sandbox per project: the workspace is fixed at creation. Give each one its own --name and its own entry in the editor.
  • Another configuration file for one session: "args": ["exec", "-i", "-e", "AGENT_CONFIG=agent.lsp.yaml", "mm-acp", "mm", "-acp"].
  • sbx not found by the editor: use the absolute path printed by which sbx as "command".
  • Logs: in Zed, dev: open acp logs shows mm's banner, warnings and [acp] … trail.

4. Publishing a version

Publishing is done by hand, from a laptop with Docker Desktop (buildx and the sbx CLI). One command builds the image for linux/amd64 and linux/arm64, pushes it, then validates and pushes the two kits, all at mm's tag:

export DOCKER_HANDLE=k33g          # the Docker Hub account, also the image owner
export DOCKER_PAT=dckr_pat_…       # an access token with read/write scope
./docker-sbx/publish.sh            # TAG from release.env: v0.1.7 → k33g/mm-sandbox:0.1.7, k33g/mm-tui:0.1.7, k33g/mm-acp:0.1.7
./docker-sbx/publish.sh v0.1.5     # another tag

With the two variables set, the script logs in with them and logs out at the end; with neither, it reuses the docker login you already have. It is two steps you can also run alone:

PUSH=1 ./docker-sbx/build.sh v0.2.3     # buildx multi-arch, pushed; proof: `imagetools inspect` lists both platforms
./docker-sbx/push-kits.sh v0.1.7        # sbx kit validate + sbx kit push, for each kit

Both call sync-kits.sh first, so the published kits always name the image just pushed, and the kits' spec.yaml end up saying the new version — commit them. sbx kit push talks to the registry directly and authenticates from the Docker credential store; no sandbox daemon is involved. IMAGE_OWNER=<handle> publishes under another account. Nothing in CI publishes to the Hub: the Release workflow only builds the binaries.

The model server stays on the host

Inside a sandbox localhost is the sandbox itself. Docker Model Runner and llama-server keep running on your machine and are reached through host.docker.internal, which the sandbox proxy maps to your host's localhost:

  • agent.dmr.yaml already has fallback: http://host.docker.internal:12434/engines/v1 — nothing to change.
  • agent.llamacpp.yaml has no fallback: pass --env AGENT_BASE_URL=http://host.docker.internal:8080/v1 to sbx run / sbx create, or edit its baseUrl.

Both kits allow ports 12434 (Docker Model Runner) and 8080 (llama-server) on the host. Another port: sbx policy allow network host.docker.internal:<port>.

  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
207
208
# mm in a Docker Sandbox

Everything needed to run `mm` inside a [Docker Sandbox](https://docs.docker.com/ai/sandboxes/): a **template** (the `shell` sandbox image with `mm` installed) and two **kits** that start it — one for the window mode in your terminal, one for an editor that speaks the Agent Client Protocol.

The full guide, with the reasoning, is in [`docs/en/how-to/run-in-a-docker-sandbox.md`](../docs/en/how-to/run-in-a-docker-sandbox.md) ([français](../docs/fr/how-to/run-in-a-docker-sandbox.md)). This page is the short version.

```
docker-sbx/
├── publish.sh               build + push the image, then publish the kits — the one command to release
├── build.sh                 builds the template image, k33g/mm-sandbox:<version> (PUSH=1: multi-arch, pushed)
├── sync-kits.sh             points the kits at one image: owner + version
├── push-kits.sh             publishes the kits to Docker Hub as OCI artifacts (sbx kit push)
├── template/
│   ├── Dockerfile           docker/sandbox-templates:shell + mm (built from this checkout)
│   ├── mm-tui               entry point of the mm-tui kit: `mm -tui "$@"`
│   └── mm-acp-info          entry point of the mm-acp kit: prints the editor wiring, opens a shell
└── kits/
    ├── mm-tui/spec.yaml     kind: sandbox — `sbx run` opens mm's window on the workspace
    └── mm-acp/spec.yaml     kind: sandbox — `sbx create` once, the editor runs `sbx exec -i … mm -acp`
```

## 0. Use the published kits (no build)

Every release publishes the image and the two kits to Docker Hub at mm's version:

| On Docker Hub | What it is |
|---|---|
| `k33g/mm-sandbox:0.1.7` | The template image. You never name it yourself: each kit pulls it. |
| `k33g/mm-tui:0.1.7` | The window-mode kit, for `sbx run`. |
| `k33g/mm-acp:0.1.7` | The editor kit, for `sbx create` + `sbx exec -i … mm -acp`. |

Nothing to build, no `--pull never`, and no setting to change: Docker Hub is an allowed kit source out of the box (`sbx settings get kit.allowedSources` shows `docker.io/`), and a reference with a `/` but no registry host is read as `docker.io/…`. Only Docker Desktop with the `sbx` command, and a model server on your machine, are needed.

**Look before you run.** `sbx kit inspect` reads the kit from the Hub without creating anything: its image, its entry point, its arguments and their defaults, the ports it allows.

```bash
sbx kit inspect k33g/mm-tui:0.1.7
```

**Window mode.** From the project you want mm to work on:

```bash
cd /path/to/your/project
sbx run k33g/mm-tui:0.1.7 . -- agent.dmr.yaml
```

The first run pulls the kit and the image, creates the sandbox `mm-tui-<directory>`, mounts the current directory as its workspace and opens `mm -tui agent.dmr.yaml` in it. What follows `--` is mm's own command line, so `-- -config other.yaml` works too. Without anything after `--`, mm reads the kit's `config` argument, then `./agent.yaml` in the workspace:

```bash
sbx run k33g/mm-tui:0.1.7 . --kit-arg config=agent.dmr.yaml
```

Later, `sbx run --name mm-tui-<directory>` re-attaches to that sandbox; `sbx ls` lists them.

**From an editor.** Create the sandbox once, from the project the editor will open, with the configuration file baked in:

```bash
cd /path/to/your/project
sbx create --name mm-acp k33g/mm-acp:0.1.7 . --kit-arg config=agent.dmr.yaml

#sbx create  k33g/mm-acp:0.1.7 . --name sbx-mm-acp
```

then register it in the editor — in Zed's `settings.json`:

```json
{
  "agent_servers": {
    "mini-me (sandbox)": {
      "type": "custom",
      "command": "sbx",
      "args": ["exec", "-i", "mm-acp", "mm", "-acp"]
    }
  }
}
```

The editor starts `mm -acp` inside the sandbox for every conversation; `sbx exec` starts the sandbox first when it is stopped, and runs mm in the workspace with the baked-in `AGENT_CONFIG`. One sandbox per project, each with its own `--name` and its own editor entry. Section 3 has the details (another config for one session, where the logs are, why `sbx exec -i` and not `sbx run`).

**Kit arguments.** Both kits take the same two, passed with `--kit-arg name=value` (repeatable) to `sbx run` or `sbx create`:

| `--kit-arg` | Default | Effect |
|---|---|---|
| `config=<path>` | empty | The file mm reads (its `AGENT_CONFIG`): relative to the workspace, or absolute inside the sandbox. Empty: `./agent.yaml`, then the built-in defaults. |
| `tag=<version>` | the kit's own version (`0.1.7`) | Which `k33g/mm-sandbox:<version>` image to use. Normally left alone: a kit and its image share a version. |

**Other versions.** Replace `0.1.7` with the release you want, in the kit reference only — the kit brings the matching image. A kit can also be pinned by digest, `k33g/mm-tui@sha256:…`, the digest being what `sbx kit inspect` or the Hub page shows.

**If sbx refuses the source.** A message like `its source is not in your allowlist` means `kit.allowedSources` was narrowed on this machine; `sbx settings set kit.allowedSources '["docker.io/"]'` restores the default, or add `docker.io/k33g/` to your list.

Sections 1–3 are the same flow with a template and kits built locally, for a work-in-progress mm.

## 1. Build the template

From the repository root:

```bash
./docker-sbx/build.sh            # TAG from release.env: v0.1.7 → k33g/mm-sandbox:0.1.7
./docker-sbx/build.sh v0.1.5     # → k33g/mm-sandbox:0.1.5
```

The image tag is mm's tag without the `v`, the same rule as the release assets, and the script rewrites the kits' default `tag` argument to the version it built, so the kits always name the image just built. The image lands in the local Docker image store: every `sbx run` / `sbx create` below carries `--pull never` until you `docker push k33g/mm-sandbox:0.1.7`. If `sbx` runs on another machine, `EXPORT=1 ./docker-sbx/build.sh` also writes `tmp/mm-sandbox-<version>.tar`; load it there with `sbx template load`.

## 2. Window mode in the terminal — kit `mm-tui`

From the project you want `mm` to work on:

```bash
sbx run --pull never ./docker-sbx/kits/mm-tui . -- agent.dmr.yaml
```

What follows `--` reaches `mm` as its own arguments, so this runs `mm -tui agent.dmr.yaml` in the workspace. Any `mm` flag passes through the same way (`-- -config other.yaml`). Two kit arguments exist as well:

| `--kit-arg` | Default | Effect |
|---|---|---|
| `config=<path>` | empty | The file `mm` reads when nothing follows `--` (its `AGENT_CONFIG`). Relative to the workspace, or absolute. Empty: `./agent.yaml`, then the built-in defaults. |
| `tag=<version>` | the version last built (`0.1.7`) | Which `k33g/mm-sandbox:<version>` image to use. |

`sbx run --name <name>` re-attaches to a sandbox that already exists. Sessions, when enabled in the YAML, are written under the workspace's `.mm/sessions`, which is your host directory.

## 3. From an editor (ACP) — kit `mm-acp`

Create the sandbox once, without attaching, **from the project the editor will open**. `.` is the workspace; sbx makes it absolute. A path that does not exist on your machine makes sbx ask "The selected workspace does not exist. Would you like to create it?" — answer `N` and fix the path. The kit path must be explicit: `./`, `../` or absolute.

```bash
cd /path/to/your/project
sbx create --pull never --name mm-acp ./docker-sbx/kits/mm-acp . \
    --kit-arg config=agent.dmr.yaml

# once the image is pushed (docker push k33g/mm-sandbox:0.1.7), --pull never is not needed:
sbx create --name mm-acp ./docker-sbx/kits/mm-acp . \
    --kit-arg config=agent.dmr.yaml
```

Then register it in the editor. In Zed's `settings.json`:

```json
{
  "agent_servers": {
    "📦 mini-me (dmr sbx)": {
      "type": "custom",      
      "command": "sbx",
      "args": ["exec", "-i", "mm-acp", "mm", "-acp"],
    },    
  }
}
```

Or:

```bash
sbx create --pull never --name mm-acp-2 ./docker-sbx/kits/mm-acp . 
```

And:

```json
{
  "agent_servers": {  
    "😄 mini-me (dmr sbx)": {
      "type": "custom",      
      "command": "sbx",
      "args": ["exec", "-i", "mm-acp-2", "mm", "-acp"],
      "env": { "AGENT_CONFIG": "/Users/k33g/kDrive/Rickub/bots-garden/mini-me/demo/agent.dmr.yaml" }
    },     
  }
}
```



The editor starts `mm -acp` inside the sandbox for every conversation; `sbx exec` starts the sandbox first when it is stopped, and runs `mm` in the workspace with the `AGENT_CONFIG` baked in by `--kit-arg config`. Everything the model does — commands, file edits — happens inside the sandbox, on the mounted project.

Why `sbx exec -i` and not `sbx run`: an ACP client speaks JSON-RPC on the agent's raw stdin/stdout, and `sbx run` always allocates a terminal. Attaching to this sandbox with `sbx run --name mm-acp` is still useful: its entry point prints the wiring above with the sandbox's real name, then opens a shell.

- One sandbox per project: the workspace is fixed at creation. Give each one its own `--name` and its own entry in the editor.
- Another configuration file for one session: `"args": ["exec", "-i", "-e", "AGENT_CONFIG=agent.lsp.yaml", "mm-acp", "mm", "-acp"]`.
- `sbx` not found by the editor: use the absolute path printed by `which sbx` as `"command"`.
- Logs: in Zed, `dev: open acp logs` shows `mm`'s banner, warnings and `[acp] …` trail.

## 4. Publishing a version

Publishing is done by hand, from a laptop with Docker Desktop (buildx and the `sbx` CLI). One command builds the image for linux/amd64 and linux/arm64, pushes it, then validates and pushes the two kits, all at mm's tag:

```bash
export DOCKER_HANDLE=k33g          # the Docker Hub account, also the image owner
export DOCKER_PAT=dckr_pat_…       # an access token with read/write scope
./docker-sbx/publish.sh            # TAG from release.env: v0.1.7 → k33g/mm-sandbox:0.1.7, k33g/mm-tui:0.1.7, k33g/mm-acp:0.1.7
./docker-sbx/publish.sh v0.1.5     # another tag
```

With the two variables set, the script logs in with them and logs out at the end; with neither, it reuses the `docker login` you already have. It is two steps you can also run alone:

```bash
PUSH=1 ./docker-sbx/build.sh v0.2.3     # buildx multi-arch, pushed; proof: `imagetools inspect` lists both platforms
./docker-sbx/push-kits.sh v0.1.7        # sbx kit validate + sbx kit push, for each kit
```

Both call `sync-kits.sh` first, so the published kits always name the image just pushed, and the kits' `spec.yaml` end up saying the new version — commit them. `sbx kit push` talks to the registry directly and authenticates from the Docker credential store; no sandbox daemon is involved. `IMAGE_OWNER=<handle>` publishes under another account. Nothing in CI publishes to the Hub: the Release workflow only builds the binaries.

## The model server stays on the host

Inside a sandbox `localhost` is the sandbox itself. Docker Model Runner and llama-server keep running on your machine and are reached through `host.docker.internal`, which the sandbox proxy maps to your host's `localhost`:

- `agent.dmr.yaml` already has `fallback: http://host.docker.internal:12434/engines/v1` — nothing to change.
- `agent.llamacpp.yaml` has no fallback: pass `--env AGENT_BASE_URL=http://host.docker.internal:8080/v1` to `sbx run` / `sbx create`, or edit its `baseUrl`.

Both kits allow ports 12434 (Docker Model Runner) and 8080 (llama-server) on the host. Another port: `sbx policy allow network host.docker.internal:<port>`.