bots-garden/mini-mepublic Fork
⑂ v0.1.8
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 v0.1.8 · k33g · 27d ago
run-in-a-docker-sandbox.md · 179 lines · 14.8 KBmarkdown
Blame HistoryOpen raw

Faire tourner mini-me dans un Docker Sandbox

Ce guide montre comment exécuter mm dans un Docker Sandbox, pour que chaque commande lancée par le modèle et chaque fichier qu'il modifie le soient dans un conteneur, sur votre projet monté. Il couvre les deux usages : le mode fenêtre dans votre terminal, et depuis un éditeur via l'Agent Client Protocol. Il suppose Docker Desktop avec la commande sbx, et un serveur de modèles (Docker Model Runner ou llama-server) qui tourne sur votre machine.

Tout est sous docker-sbx/ dans le dépôt :

Élément Ce que c'est
template/Dockerfile Le template : l'image shell de Docker Sandboxes avec mm compilé depuis ce dépôt, plus les deux points d'entrée ci-dessous.
kits/mm-tui/spec.yaml Un kit sandbox : sbx run dessus ouvre le mode fenêtre de mm sur l'espace de travail.
kits/mm-acp/spec.yaml Un kit sandbox pour un éditeur : créé une fois avec sbx create, l'éditeur y lance ensuite mm -acp.
build.sh Construit l'image du template, k33g/mm-sandbox:<version> ; PUSH=1 la construit pour linux/amd64 et linux/arm64 et la pousse.
sync-kits.sh, push-kits.sh Alignent les kits sur une image, et les publient sur Docker Hub comme artefacts OCI de kit.

Utiliser les kits publiés

Chaque release publie l'image et les deux kits sur Docker Hub à la version de mm — k33g/mm-sandbox:0.1.7, k33g/mm-tui:0.1.7, k33g/mm-acp:0.1.7 — le chemin le plus court ne demande donc aucune construction. Docker Hub est une source de kits autorisée par défaut (sbx settings get kit.allowedSources montre docker.io/), et une référence avec un / mais sans hôte de registre est lue comme docker.io/… :

cd /chemin/de/votre/projet
sbx run k33g/mm-tui:0.1.7 . -- agent.dmr.yaml

pour le mode fenêtre, et pour un éditeur :

sbx create --name mm-acp k33g/mm-acp:0.1.7 . --kit-arg config=agent.dmr.yaml

puis la déclaration dans l'éditeur de l'étape 3 ci-dessous. Pas de --pull never : le kit nomme k33g/mm-sandbox:0.1.7 et sbx la télécharge. sbx kit inspect k33g/mm-tui:0.1.7 montre ce qu'un kit déclare avant de le lancer. Les étapes qui suivent construisent la même chose en local, pour un mm en cours de travail.

Étapes

1. Construire le template

Depuis la racine du dépôt :

./docker-sbx/build.sh

Cela lit le tag de mm dans release.env (v0.1.7) et construit k33g/mm-sandbox:0.1.7 : le tag de l'image est la version sans le v, comme les binaires de release, et le mm à l'intérieur est estampillé avec le tag — mm --version est exécuté dans l'image comme preuve. Le script réécrit ensuite la valeur par défaut de l'argument tag des kits à 0.1.7, pour que kits et image avancent ensemble. ./docker-sbx/build.sh v0.1.5 construit une autre version ; une image antérieure reste joignable avec --kit-arg tag=0.1.4.

L'image est dans votre store d'images Docker local : chaque sbx run ou sbx create sur ces kits prend --pull never tant qu'elle n'est pas poussée (docker push k33g/mm-sandbox:0.1.7), sinon sbx tente de la télécharger et échoue. Si sbx tourne sur une autre machine, EXPORT=1 ./docker-sbx/build.sh écrit aussi tmp/mm-sandbox-0.1.7.tar, à charger là-bas avec sbx template load.

2. Mode fenêtre dans le terminal (kit mm-tui)

Depuis le projet sur lequel mm doit travailler :

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

La première fois, sbx crée le sandbox, monte le répertoire courant comme espace de travail et s'y attache ; puis il lance le point d'entrée du kit avec ce qui suit -- en arguments — ici mm -tui agent.dmr.yaml, dans l'espace de travail. N'importe quel drapeau de mm passe de la même façon : -- -config autre.yaml.

Sans rien après --, mm lit l'argument config du kit, puis ./agent.yaml dans l'espace de travail, puis ses valeurs par défaut :

sbx run --pull never ./docker-sbx/kits/mm-tui . --kit-arg config=agent.dmr.yaml
--kit-arg Défaut Effet
config=<chemin> vide Le fichier de configuration, comme AGENT_CONFIG de mm : relatif à l'espace de travail, ou absolu dans le sandbox.
tag=<version> la dernière version construite (0.1.7) L'image k33g/mm-sandbox:<version> dont le sandbox est fait.

Le sandbox garde son nom (mm-tui-<répertoire> sauf --name) ; sbx run --name <nom> s'y rattache plus tard. À l'intérieur, la fenêtre est celle décrite dans Utiliser le mode fenêtre. Les sessions, quand sessions.enabled est actif, sont écrites sous .mm/sessions dans l'espace de travail — c'est votre répertoire hôte, elles survivent donc au sandbox.

3. Depuis un éditeur (kit mm-acp)

Un éditeur parle à mm -acp sur l'entrée et la sortie standard brutes de l'agent. sbx run ne peut pas porter cela : il alloue toujours un terminal. Le sandbox est donc créé une fois sans s'y attacher, et l'éditeur y lance mm avec sbx exec -i, qui transmet stdin et stdout tels quels.

  1. Depuis le projet que l'éditeur ouvrira, créez le sandbox avec le fichier de configuration intégré (. est l'espace de travail, sbx le rend absolu ; le chemin du kit doit être explicite : ./, ../ ou absolu) :

    cd /chemin/de/votre/projet
    sbx create --pull never --name mm-acp /chemin/de/mini-me/docker-sbx/kits/mm-acp . \
        --kit-arg config=agent.dmr.yaml
    

    Un chemin d'espace de travail qui n'existe pas sur votre machine fait demander à sbx « The selected workspace does not exist. Would you like to create it? » — répondez N et corrigez le chemin.

    --kit-arg config devient l'AGENT_CONFIG du conteneur, relatif à l'espace de travail parce que c'est là que sbx exec démarre mm. L'espace de travail est fixé à la création : un sandbox par projet, chacun avec son --name.

  2. Déclarez-le dans l'éditeur. Dans le settings.json de Zed :

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

    Par rapport à la configuration côté hôte, la commande est sbx et aucun env n'est nécessaire : AGENT_CONFIG est déjà dans le conteneur. Si l'éditeur ne trouve pas sbx, mettez le chemin absolu donné par which sbx dans "command".

  3. Ouvrez le panneau agent et choisissez mini-me (sandbox). L'éditeur lance mm -acp dans le sandbox à chaque conversation ; sbx exec démarre d'abord le sandbox s'il est arrêté. Appels d'outils, dialogues de permission, mentions @fichier et menu des commandes fonctionnent comme sur l'hôte — la différence est l'endroit où les commandes s'exécutent.

S'attacher à ce sandbox avec sbx run --name mm-acp ne lance pas mm : son point d'entrée affiche le câblage ci-dessus avec le vrai nom et les vrais chemins du sandbox, puis ouvre un shell à l'intérieur. sbx exec -it mm-acp bash est le chemin le plus court vers ce shell.

Le serveur de modèles reste sur l'hôte

Dans un sandbox, localhost est le sandbox lui-même. Votre serveur de modèles continue de tourner sur votre machine et se joint par host.docker.internal, que le proxy du sandbox fait pointer vers le localhost de l'hôte.

  • Docker Model Runner — rien à changer : agent.dmr.yaml a déjà fallback: http://host.docker.internal:12434/engines/v1, et mm bascule dessus quand localhost:12434 ne répond pas (la bannière dit quelle URL a gagné).
  • llama-server — agent.llamacpp.yaml n'a pas de fallback. Soit vous changez son baseUrl en http://host.docker.internal:8080/v1, soit vous passez --env AGENT_BASE_URL=http://host.docker.internal:8080/v1 à sbx run / sbx create (voir Faire tourner sur llama.cpp).

Les deux kits autorisent les ports 12434 et 8080 de l'hôte dans la politique réseau du sandbox. Pour un autre port : sbx policy allow network host.docker.internal:<port>.

Publier une version

La publication est une étape manuelle, depuis une machine avec Docker Desktop (buildx et la CLI sbx) ; le workflow Release ne construit que les binaires. Un script construit l'image pour linux/amd64 et linux/arm64, la pousse, puis valide et pousse les deux kits, le tout au tag de mm :

export DOCKER_HANDLE=k33g          # le compte Docker Hub, aussi propriétaire de l'image
export DOCKER_PAT=dckr_pat_…       # un jeton d'accès en lecture/écriture
./docker-sbx/publish.sh            # TAG depuis release.env : v0.1.7 → k33g/mm-sandbox:0.1.7, k33g/mm-tui:0.1.7, k33g/mm-acp:0.1.7

Avec les deux variables, le script se connecte avec elles et se déconnecte à la fin ; sans elles, il réutilise votre docker login existant. Ses deux moitiés se lancent seules : PUSH=1 ./docker-sbx/build.sh v0.1.7 (l'image) et ./docker-sbx/push-kits.sh v0.1.7 (les kits, SBX=/chemin/vers/sbx si la CLI n'est pas sur le PATH). Les deux appellent d'abord sync-kits.sh, qui réécrit version, le tag par défaut et le propriétaire de l'image des kits, de sorte qu'un kit publié nomme toujours l'image poussée avec lui — commitez ensuite les deux spec.yaml. sbx kit push parle directement au registre et s'authentifie depuis le magasin d'identifiants Docker, sans démon sandbox. IMAGE_OWNER=<compte> publie sous un autre compte.

Serveurs MCP via la passerelle sbx (exemple : GitHub)

Dans un sandbox, mm ne parle pas lui-même aux serveurs MCP et ne détient aucun jeton. sbx démarre une passerelle MCP par sandbox, sur l'hôte. À la création du sandbox, il inscrit deux variables dans le conteneur : MCP_GATEWAY_URL (http://mcp-gateway.docker.internal/mcp) et MCP_SENTINEL_TOKEN_NAME, un substitut que le proxy du sandbox remplace par le vrai identifiant. Quand mm trouve MCP_GATEWAY_URL et mcp.enabled: true, il ajoute un serveur nommé sbx-gateway, dont les outils apparaissent sous la forme sbx-gateway_<outil>. Le kit n'a besoin d'aucune règle réseau pour cela, car le proxy route cet hôte lui-même.

  1. Enregistrez une fois, sur l'hôte, le serveur officiel de GitHub via docker-sbx/mcp/github-mcp.sh. Le script lance ghcr.io/github/github-mcp-server dans Docker avec votre jeton. sbx l'exécute comme enfant de sandboxd, qui ne voit pas les variables de votre shell. Rangez donc le jeton une fois dans le trousseau macOS, sous le service github-mcp. Le script accepte aussi GITHUB_PERSONAL_ACCESS_TOKEN, GITHUB_OAUTH_TOKEN ou un gh connecté. sbx l'exécute sur l'hôte, donc le jeton n'entre jamais dans le sandbox. Par défaut, il expose 25 outils en lecture seule, dont get_me et get_teams. Pour en avoir plus, définissez GITHUB_READ_ONLY=0 et un GITHUB_TOOLSETS plus large dans l'environnement du script.

    security add-generic-password -U -a "$USER" -s github-mcp -w   # demande le jeton
    sbx mcp rm github 2>/dev/null               # un ancien "github" est le serveur ARCHIVÉ du catalogue
    sbx mcp add github-mm --command "$PWD/docker-sbx/mcp/github-mcp.sh"
    sbx mcp ls                                  # github-mm doit être prêt
    

    N'utilisez pas le nom github seul. Le catalogue Docker MCP le résout en « GitHub (Archived) », l'ancien serveur npm, qui n'a pas get_me et propose d'autres outils. L'entrée github-official du catalogue ne convient pas non plus en mode local. Là, une image du catalogue est lancée par un simple docker run, sans environnement, donc sans jeton.

  2. Créez un nouveau sandbox avec ce serveur dans son ensemble fixe. --static-mcp est une option de sbx : elle se place avant --, car tout ce qui suit -- va à mm. Elle ne s'applique qu'à la création, donc supprimez d'abord un ancien sandbox du même nom :

    cd /chemin/du/projet
    sbx rm mm-mcp-github 2>/dev/null
    sbx run --name mm-mcp-github --static-mcp github-mm k33g/mm-tui:<version> . -- agent.dmr.sbx.yaml
    
  3. La configuration doit seulement activer MCP. demo/agent.dmr.sbx.yaml contient :

    mcp:
      enabled: true
      permissions: ask
      discoveryTimeout: 10s
      servers: []        # mm ajoute la passerelle quand MCP_GATEWAY_URL est défini
    

    La bannière liste alors sbx-gateway_get_me, sbx-gateway_list_issues, etc. dans tools:.

Une image de kit construite avant ce changement ne peut pas utiliser la passerelle. Elle ne découvre rien et affiche method "tools/list" is invalid during session initialization. La passerelle suit strictement le transport Streamable HTTP de MCP : elle exige d'abord initialize, puis le Mcp-Session-Id renvoyé sur chaque requête. L'ancien mm sautait les deux. C'était sans effet face à api.githubcopilot.com, mais bloquant ici. Reconstruisez et republiez le kit après la mise à jour.

Si la bannière ne liste aucun outil sbx-gateway_*, vérifiez l'enregistrement avec sbx mcp inspect github-mm, puis lisez le journal MCP de sbx, mcp/mcp.log dans son répertoire d'état. github-mcp: no token dans ce journal signifie que le script n'a trouvé aucun jeton : vérifiez l'entrée du trousseau avec security find-generic-password -s github-mcp. L'endpoint distant https://api.githubcopilot.com/mcp/ est une autre voie, mais seulement avec une OAuth App GitHub. GitHub ne propose pas l'enregistrement dynamique de client, donc en mode local sbx mcp add le refuse sans --client-id, même avec un en-tête Authorization.

Nommez le dépôt dans vos demandes, par exemple « liste les issues ouvertes de k33g/mon-depot ». Un petit modèle à qui l'on dit seulement « mon organisation » invente un propriétaire et un dépôt, et chaque appel revient en Not Found.

Variantes

  • Une autre configuration pour une session d'éditeur. Ajoutez "-e", "AGENT_CONFIG=agent.lsp.yaml" avant le nom du sandbox dans "args" ; sbx exec -e remplace la valeur intégrée pour cette exécution seulement.
  • Skills. skillsDir est relatif au répertoire où mm tourne, c'est-à-dire l'espace de travail dans les deux kits — la même règle que sur l'hôte.
  • Docker dans le sandbox. Construisez le template sur le shell Docker-in-Docker : SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx/build.sh.
  • Lire les logs. En mode fenêtre ils sont à l'écran ; en ACP ils vont sur stderr, que Zed montre sous dev: open acp logs.
  • Supprimer un sandbox. sbx rm mm-acp. Le répertoire du projet est un montage et n'est pas touché.

Voir aussi

  • Le format suivi par ces deux fichiers : la spécification des kits de Docker Sandboxes (schemaVersion: "2"), livrée avec les sources de sbx.
  • Ce que mm -acp expose à l'éditeur : référence ACP.
  • Les drapeaux et variables d'environnement que mm lit : référence de la ligne de commande.
  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
# Faire tourner mini-me dans un Docker Sandbox

Ce guide montre comment exécuter `mm` dans un [Docker Sandbox](https://docs.docker.com/ai/sandboxes/), pour que chaque commande lancée par le modèle et chaque fichier qu'il modifie le soient dans un conteneur, sur votre projet monté. Il couvre les deux usages : le mode fenêtre dans votre terminal, et depuis un éditeur via l'Agent Client Protocol. Il suppose Docker Desktop avec la commande `sbx`, et un serveur de modèles (Docker Model Runner ou llama-server) qui tourne sur votre machine.

Tout est sous [`docker-sbx/`](../../../docker-sbx/README.md) dans le dépôt :

| Élément | Ce que c'est |
|---|---|
| `template/Dockerfile` | Le **template** : l'image `shell` de Docker Sandboxes avec `mm` compilé depuis ce dépôt, plus les deux points d'entrée ci-dessous. |
| `kits/mm-tui/spec.yaml` | Un **kit sandbox** : `sbx run` dessus ouvre le mode fenêtre de `mm` sur l'espace de travail. |
| `kits/mm-acp/spec.yaml` | Un **kit sandbox** pour un éditeur : créé une fois avec `sbx create`, l'éditeur y lance ensuite `mm -acp`. |
| `build.sh` | Construit l'image du template, `k33g/mm-sandbox:<version>` ; `PUSH=1` la construit pour linux/amd64 et linux/arm64 et la pousse. |
| `sync-kits.sh`, `push-kits.sh` | Alignent les kits sur une image, et les publient sur Docker Hub comme artefacts OCI de kit. |

## Utiliser les kits publiés

Chaque release publie l'image et les deux kits sur Docker Hub à la version de mm — `k33g/mm-sandbox:0.1.7`, `k33g/mm-tui:0.1.7`, `k33g/mm-acp:0.1.7` — le chemin le plus court ne demande donc aucune construction. Docker Hub est une source de kits autorisée par défaut (`sbx settings get kit.allowedSources` montre `docker.io/`), et une référence avec un `/` mais sans hôte de registre est lue comme `docker.io/…` :

```bash
cd /chemin/de/votre/projet
sbx run k33g/mm-tui:0.1.7 . -- agent.dmr.yaml
```

pour le mode fenêtre, et pour un éditeur :

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

puis la déclaration dans l'éditeur de l'étape 3 ci-dessous. Pas de `--pull never` : le kit nomme `k33g/mm-sandbox:0.1.7` et sbx la télécharge. `sbx kit inspect k33g/mm-tui:0.1.7` montre ce qu'un kit déclare avant de le lancer. Les étapes qui suivent construisent la même chose en local, pour un mm en cours de travail.

## Étapes

### 1. Construire le template

Depuis la racine du dépôt :

```bash
./docker-sbx/build.sh
```

Cela lit le tag de mm dans `release.env` (`v0.1.7`) et construit `k33g/mm-sandbox:0.1.7` : le tag de l'image est la version sans le `v`, comme les binaires de release, et le `mm` à l'intérieur est estampillé avec le tag — `mm --version` est exécuté dans l'image comme preuve. Le script réécrit ensuite la valeur par défaut de l'argument `tag` des kits à `0.1.7`, pour que kits et image avancent ensemble. `./docker-sbx/build.sh v0.1.5` construit une autre version ; une image antérieure reste joignable avec `--kit-arg tag=0.1.4`.

L'image est dans votre store d'images Docker local : chaque `sbx run` ou `sbx create` sur ces kits prend `--pull never` tant qu'elle n'est pas poussée (`docker push k33g/mm-sandbox:0.1.7`), sinon `sbx` tente de la télécharger et échoue. Si `sbx` tourne sur une autre machine, `EXPORT=1 ./docker-sbx/build.sh` écrit aussi `tmp/mm-sandbox-0.1.7.tar`, à charger là-bas avec `sbx template load`.

### 2. Mode fenêtre dans le terminal (kit `mm-tui`)

Depuis le projet sur lequel `mm` doit travailler :

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

La première fois, `sbx` crée le sandbox, monte le répertoire courant comme espace de travail et s'y attache ; puis il lance le point d'entrée du kit avec ce qui suit `--` en arguments — ici `mm -tui agent.dmr.yaml`, dans l'espace de travail. N'importe quel drapeau de `mm` passe de la même façon : `-- -config autre.yaml`.

Sans rien après `--`, `mm` lit l'argument `config` du kit, puis `./agent.yaml` dans l'espace de travail, puis ses valeurs par défaut :

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

| `--kit-arg` | Défaut | Effet |
|---|---|---|
| `config=<chemin>` | vide | Le fichier de configuration, comme `AGENT_CONFIG` de `mm` : relatif à l'espace de travail, ou absolu dans le sandbox. |
| `tag=<version>` | la dernière version construite (`0.1.7`) | L'image `k33g/mm-sandbox:<version>` dont le sandbox est fait. |

Le sandbox garde son nom (`mm-tui-<répertoire>` sauf `--name`) ; `sbx run --name <nom>` s'y rattache plus tard. À l'intérieur, la fenêtre est celle décrite dans [Utiliser le mode fenêtre](use-the-window-mode.md). Les sessions, quand `sessions.enabled` est actif, sont écrites sous `.mm/sessions` dans l'espace de travail — c'est votre répertoire hôte, elles survivent donc au sandbox.

### 3. Depuis un éditeur (kit `mm-acp`)

Un éditeur parle à `mm -acp` sur l'entrée et la sortie standard brutes de l'agent. `sbx run` ne peut pas porter cela : il alloue toujours un terminal. Le sandbox est donc créé une fois sans s'y attacher, et l'éditeur y lance `mm` avec `sbx exec -i`, qui transmet stdin et stdout tels quels.

1. Depuis le projet que l'éditeur ouvrira, créez le sandbox avec le fichier de configuration intégré (`.` est l'espace de travail, sbx le rend absolu ; le chemin du kit doit être explicite : `./`, `../` ou absolu) :

   ```bash
   cd /chemin/de/votre/projet
   sbx create --pull never --name mm-acp /chemin/de/mini-me/docker-sbx/kits/mm-acp . \
       --kit-arg config=agent.dmr.yaml
   ```

   Un chemin d'espace de travail qui n'existe pas sur votre machine fait demander à sbx « The selected workspace does not exist. Would you like to create it? » — répondez `N` et corrigez le chemin.

   `--kit-arg config` devient l'`AGENT_CONFIG` du conteneur, relatif à l'espace de travail parce que c'est là que `sbx exec` démarre `mm`. L'espace de travail est fixé à la création : un sandbox par projet, chacun avec son `--name`.

2. Déclarez-le dans l'éditeur. Dans le `settings.json` de Zed :

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

   Par rapport à [la configuration côté hôte](use-from-an-editor.md), la commande est `sbx` et aucun `env` n'est nécessaire : `AGENT_CONFIG` est déjà dans le conteneur. Si l'éditeur ne trouve pas `sbx`, mettez le chemin absolu donné par `which sbx` dans `"command"`.

3. Ouvrez le panneau agent et choisissez **mini-me (sandbox)**. L'éditeur lance `mm -acp` dans le sandbox à chaque conversation ; `sbx exec` démarre d'abord le sandbox s'il est arrêté. Appels d'outils, dialogues de permission, mentions `@fichier` et menu des commandes fonctionnent comme sur l'hôte — la différence est l'endroit où les commandes s'exécutent.

S'attacher à ce sandbox avec `sbx run --name mm-acp` ne lance pas `mm` : son point d'entrée affiche le câblage ci-dessus avec le vrai nom et les vrais chemins du sandbox, puis ouvre un shell à l'intérieur. `sbx exec -it mm-acp bash` est le chemin le plus court vers ce shell.

## Le serveur de modèles reste sur l'hôte

Dans un sandbox, `localhost` est le sandbox lui-même. Votre serveur de modèles continue de tourner sur votre machine et se joint par `host.docker.internal`, que le proxy du sandbox fait pointer vers le `localhost` de l'hôte.

- **Docker Model Runner** — rien à changer : `agent.dmr.yaml` a déjà `fallback: http://host.docker.internal:12434/engines/v1`, et `mm` bascule dessus quand `localhost:12434` ne répond pas (la bannière dit quelle URL a gagné).
- **llama-server** — `agent.llamacpp.yaml` n'a pas de fallback. Soit vous changez son `baseUrl` en `http://host.docker.internal:8080/v1`, soit vous passez `--env AGENT_BASE_URL=http://host.docker.internal:8080/v1` à `sbx run` / `sbx create` (voir [Faire tourner sur llama.cpp](run-with-llama-cpp.md)).

Les deux kits autorisent les ports 12434 et 8080 de l'hôte dans la politique réseau du sandbox. Pour un autre port : `sbx policy allow network host.docker.internal:<port>`.

## Publier une version

La publication est une étape manuelle, depuis une machine avec Docker Desktop (buildx et la CLI `sbx`) ; le workflow Release ne construit que les binaires. Un script construit l'image pour linux/amd64 et linux/arm64, la pousse, puis valide et pousse les deux kits, le tout au tag de mm :

```bash
export DOCKER_HANDLE=k33g          # le compte Docker Hub, aussi propriétaire de l'image
export DOCKER_PAT=dckr_pat_…       # un jeton d'accès en lecture/écriture
./docker-sbx/publish.sh            # TAG depuis release.env : v0.1.7 → k33g/mm-sandbox:0.1.7, k33g/mm-tui:0.1.7, k33g/mm-acp:0.1.7
```

Avec les deux variables, le script se connecte avec elles et se déconnecte à la fin ; sans elles, il réutilise votre `docker login` existant. Ses deux moitiés se lancent seules : `PUSH=1 ./docker-sbx/build.sh v0.1.7` (l'image) et `./docker-sbx/push-kits.sh v0.1.7` (les kits, `SBX=/chemin/vers/sbx` si la CLI n'est pas sur le PATH). Les deux appellent d'abord `sync-kits.sh`, qui réécrit `version`, le `tag` par défaut et le propriétaire de l'image des kits, de sorte qu'un kit publié nomme toujours l'image poussée avec lui — commitez ensuite les deux `spec.yaml`. `sbx kit push` parle directement au registre et s'authentifie depuis le magasin d'identifiants Docker, sans démon sandbox. `IMAGE_OWNER=<compte>` publie sous un autre compte.

## Serveurs MCP via la passerelle sbx (exemple : GitHub)

Dans un sandbox, `mm` ne parle pas lui-même aux serveurs MCP et ne détient aucun jeton. `sbx` démarre une passerelle MCP par sandbox, sur l'hôte. À la création du sandbox, il inscrit deux variables dans le conteneur : `MCP_GATEWAY_URL` (`http://mcp-gateway.docker.internal/mcp`) et `MCP_SENTINEL_TOKEN_NAME`, un substitut que le proxy du sandbox remplace par le vrai identifiant. Quand `mm` trouve `MCP_GATEWAY_URL` et `mcp.enabled: true`, il ajoute un serveur nommé `sbx-gateway`, dont les outils apparaissent sous la forme `sbx-gateway_<outil>`. Le kit n'a besoin d'aucune règle réseau pour cela, car le proxy route cet hôte lui-même.

1. Enregistrez une fois, sur l'hôte, le serveur officiel de GitHub via `docker-sbx/mcp/github-mcp.sh`. Le script lance `ghcr.io/github/github-mcp-server` dans Docker avec votre jeton. sbx l'exécute comme enfant de sandboxd, qui ne voit pas les variables de votre shell. Rangez donc le jeton une fois dans le trousseau macOS, sous le service `github-mcp`. Le script accepte aussi `GITHUB_PERSONAL_ACCESS_TOKEN`, `GITHUB_OAUTH_TOKEN` ou un `gh` connecté. sbx l'exécute sur l'hôte, donc le jeton n'entre jamais dans le sandbox. Par défaut, il expose 25 outils en lecture seule, dont `get_me` et `get_teams`. Pour en avoir plus, définissez `GITHUB_READ_ONLY=0` et un `GITHUB_TOOLSETS` plus large dans l'environnement du script.

   ```bash
   security add-generic-password -U -a "$USER" -s github-mcp -w   # demande le jeton
   sbx mcp rm github 2>/dev/null               # un ancien "github" est le serveur ARCHIVÉ du catalogue
   sbx mcp add github-mm --command "$PWD/docker-sbx/mcp/github-mcp.sh"
   sbx mcp ls                                  # github-mm doit être prêt
   ```

   N'utilisez pas le nom `github` seul. Le catalogue Docker MCP le résout en « GitHub (Archived) », l'ancien serveur npm, qui n'a pas `get_me` et propose d'autres outils. L'entrée `github-official` du catalogue ne convient pas non plus en mode local. Là, une image du catalogue est lancée par un simple `docker run`, sans environnement, donc sans jeton.

2. Créez un **nouveau** sandbox avec ce serveur dans son ensemble fixe. `--static-mcp` est une option de `sbx` : elle se place **avant** `--`, car tout ce qui suit `--` va à `mm`. Elle ne s'applique qu'à la création, donc supprimez d'abord un ancien sandbox du même nom :

   ```bash
   cd /chemin/du/projet
   sbx rm mm-mcp-github 2>/dev/null
   sbx run --name mm-mcp-github --static-mcp github-mm k33g/mm-tui:<version> . -- agent.dmr.sbx.yaml
   ```

3. La configuration doit seulement activer MCP. `demo/agent.dmr.sbx.yaml` contient :

   ```yaml
   mcp:
     enabled: true
     permissions: ask
     discoveryTimeout: 10s
     servers: []        # mm ajoute la passerelle quand MCP_GATEWAY_URL est défini
   ```

   La bannière liste alors `sbx-gateway_get_me`, `sbx-gateway_list_issues`, etc. dans `tools:`.

Une image de kit construite avant ce changement ne peut pas utiliser la passerelle. Elle ne découvre rien et affiche `method "tools/list" is invalid during session initialization`. La passerelle suit strictement le transport Streamable HTTP de MCP : elle exige d'abord `initialize`, puis le `Mcp-Session-Id` renvoyé sur chaque requête. L'ancien `mm` sautait les deux. C'était sans effet face à `api.githubcopilot.com`, mais bloquant ici. Reconstruisez et republiez le kit après la mise à jour.

Si la bannière ne liste aucun outil `sbx-gateway_*`, vérifiez l'enregistrement avec `sbx mcp inspect github-mm`, puis lisez le journal MCP de sbx, `mcp/mcp.log` dans son répertoire d'état. `github-mcp: no token` dans ce journal signifie que le script n'a trouvé aucun jeton : vérifiez l'entrée du trousseau avec `security find-generic-password -s github-mcp`. L'endpoint distant `https://api.githubcopilot.com/mcp/` est une autre voie, mais seulement avec une OAuth App GitHub. GitHub ne propose pas l'enregistrement dynamique de client, donc en mode local `sbx mcp add` le refuse sans `--client-id`, même avec un en-tête `Authorization`.

Nommez le dépôt dans vos demandes, par exemple « liste les issues ouvertes de k33g/mon-depot ». Un petit modèle à qui l'on dit seulement « mon organisation » invente un propriétaire et un dépôt, et chaque appel revient en `Not Found`.

## Variantes

- **Une autre configuration pour une session d'éditeur.** Ajoutez `"-e", "AGENT_CONFIG=agent.lsp.yaml"` avant le nom du sandbox dans `"args"` ; `sbx exec -e` remplace la valeur intégrée pour cette exécution seulement.
- **Skills.** `skillsDir` est relatif au répertoire où `mm` tourne, c'est-à-dire l'espace de travail dans les deux kits — la même règle que sur l'hôte.
- **Docker dans le sandbox.** Construisez le template sur le shell Docker-in-Docker : `SHELL_TEMPLATE=docker/sandbox-templates:shell-docker ./docker-sbx/build.sh`.
- **Lire les logs.** En mode fenêtre ils sont à l'écran ; en ACP ils vont sur stderr, que Zed montre sous `dev: open acp logs`.
- **Supprimer un sandbox.** `sbx rm mm-acp`. Le répertoire du projet est un montage et n'est pas touché.

## Voir aussi

- Le format suivi par ces deux fichiers : la spécification des kits de Docker Sandboxes (`schemaVersion: "2"`), livrée avec les sources de `sbx`.
- Ce que `mm -acp` expose à l'éditeur : [référence ACP](../reference/acp.md).
- Les drapeaux et variables d'environnement que `mm` lit : [référence de la ligne de commande](../reference/cli.md).