DEV Community

Cover image for One Repo Became Three — Quietly, Then Publicl
Yuji Suzuki
Yuji Suzuki

Posted on

One Repo Became Three — Quietly, Then Publicl

One Repo Became Three — Quietly, Then Publicly

ai #docker #security #mcp

Previously

Back in February, I published AI Sandbox Environment + DockMCP — a single repo that isolated AI coding agents in a Docker container, hid .env files and secrets at the filesystem level, and gave AI a controlled path back out to other containers through an MCP server.

Structurally, though, it was three different jobs wearing one trench coat: a devcontainer template, a host-side MCP server, and an in-container script/tool discovery server. I said I'd eventually split them apart. What I didn't say at the time was what I was about to use the split version for.

The Quiet Part

Before any of this was public, I split ai-sandbox-dkmcp into three repos privately and used that setup to build and ship an actual product: とけるよ, an iOS app.

Building a real iOS app inside the sandbox — not a demo, not the SecureNote sample app — surfaced friction that a template alone never would have. Xcode builds and tests don't run inside a Linux container; they need the host OS. That meant the host-tools mechanism, which had been a minor feature for wrapping docker-compose up, suddenly had to carry real weight:

  • xcode-build.sh, xcode-test.sh, xcode-archive.sh — host tools that let AI kick off Xcode operations without leaving the sandbox
  • A per-tool timeout declaration (# @timeout: 600 in a script's header). The global timeout was 60 seconds, fine for something like docker-compose up — and xcode-test.sh blew right through it. The fix wasn't obvious on the first try; it took some back-and-forth with Claude Code, weighing "just raise the global default" against "let a tool declare its own ceiling," before landing on the per-tool declaration (still clamped by an admin-controlled max, so a script can't unilaterally claim an hour).
  • Generic docker-compose-up.sh / -down.sh / -build.sh wrappers, once one-off demo scripts, made reusable

None of this was designed up front. It's the residue of actually depending on the tool to ship something, not just to demo it. If you look at docs/host-access.md in the ai-sandbox repo today, the Xcode tools and the @timeout mechanism are still sitting there — leftovers from that period, kept because they turned out to be generally useful.

The app shipped. That felt like a natural stopping point.

The Public Part

With the app out, I published the three-way split for real:

Repo What it is Runs where
ai-sandbox The devcontainer template — secret hiding, project structure, slash commands Docker (VS Code / CLI)
hostmcp MCP server for host-side access — containers, host tools, host OS commands Host OS
sandbox-mcp Lightweight MCP server for script/tool discovery inside the container Inside the container (stdio)

DockMCP became HostMCP. The bundled tool-discovery layer became SandboxMCP. What's left of the original repo is just AI Sandbox — the template.

AI Sandbox (container)
  └─ SandboxMCP (stdio)          ← discovers .sandbox/scripts/ and .sandbox/tools/
  └─ hostmcp client (via HTTP)   ← talks to HostMCP on the host OS
        ↓
Host OS: HostMCP server → API container, DB container, host tools, …
Enter fullscreen mode Exit fullscreen mode

Publishing didn't stop the work, either. HostMCP picked up a proper installer (go install github.com/YujiSuzuki/hostmcp@latest), host-path masking so the home directory's username never leaks into what AI sees, a "dangerous mode" for read-only debugging commands that still respects blocked paths, and large-output handling so a runaway build log doesn't blow out the context window. SandboxMCP picked up nested-git-repo detection for multi-repo workspaces. It's settled into a steady state now, which is why this post exists.

Why Split at All

Independent installs. Someone with an existing devcontainer might want HostMCP for host access, or SandboxMCP for script discovery, without adopting the whole secret-hiding template. As one repo, that meant cloning the template and cherry-picking.

Independent release cadence. HostMCP being go install-able shouldn't be gated behind a template release. It's a HostMCP concern now, not an ai-sandbox concern.

Real usage exposes real seams. The Xcode host tools and per-tool timeouts didn't come from design — they came from hitting a wall while shipping an actual app. Having HostMCP as its own project made it obvious that "host tools" needed to support more than the couple of demo scripts it launched with.

What Didn't Change

Secrets are physically absent, not rule-blocked. .env files and private keys still don't exist in AI's filesystem — not hidden by a deny list, just not there.

AI observes, humans act on infrastructure. HostMCP still won't let AI rebuild an image or run docker-compose up directly on its own judgment; that has to go through an approved host tool, and approval is a human step.

Still just Docker + MCP. No lock-in to a specific AI tool. Claude Code, Gemini CLI, Claude Desktop via MCP — all of it works the same way it did as one repo.

Try It

  • Setting up a new project? Start with ai-sandbox — click "Use this template."
  • Already have a devcontainer and just want host access? hostmcp installs standalone.
  • Want AI to discover your own scripts and tools without re-explaining them every session? sandbox-mcp is a go install away.

Feedback and issues are welcome on any of the three repos.

Top comments (0)