Container topology
Speedwave runs every project as a set of containers inside a small Linux VM, keeping all of it off your host machine.
The VM
Section titled “The VM”Speedwave skips Docker Desktop. Instead it runs its own Linux VM and puts the container runtime inside it.
Speedwave runs a Lima VM on Apple’s Virtualization Framework. Lima ships bundled inside the app, isolated from any other Lima install on your machine.
The VM is sized from your hardware: half your host RAM, clamped between 4 GiB and 32 GiB. A 16 GiB Mac gets an 8 GiB VM.
Speedwave runs a dedicated WSL2 distribution named Speedwave, using Hyper-V, provisioned by the Setup Wizard on first run with an offline installer fallback. On every start, Speedwave warn-checks two invariants: pinning the in-distro nerdctl version and fixing drvfs mount options so the container’s uid doesn’t hit permission errors on boot.
WSL2 manages its own memory and CPU, and Speedwave leaves those alone. It does write VPN-compatibility keys to your shared .wslconfig, so VPN-routed services stay reachable from inside the distro, active after a wsl --shutdown that Speedwave prompts for.
Both platforms need at least 16 GiB of RAM. macOS checks this at startup and warns you if you’re under it; Windows can’t always read host RAM, so the warning may not appear there, but the requirement still applies.
Speedwave also translates Windows host paths for containers: a drive letter like C:\Users\... becomes /mnt/c/Users/..., and a WSL UNC path into Speedwave’s own distro maps straight through. A path into a different distro or a network share is rejected, with guidance to fix it.
Containers per project
Section titled “Containers per project”Each project runs on its own network, named speedwave_<project>_network, never seeing another project’s containers. On it, Speedwave runs:
speedwave_<project>_claude: runs Claude Code. Holds no tokens, has no container socket.speedwave_<project>_proxy: a first-party forwarder for LLM traffic.speedwave_<project>_mcp_hub: the MCP Hub, the only MCP server Claude sees.speedwave_<project>_mcp_<service>: one container per connected integration.
flowchart TB
subgraph VM["Linux VM (Lima on macOS / WSL2 on Windows)"]
subgraph NET["speedwave_<project>_network"]
Claude["claude<br/>no tokens, no socket"]
Proxy["proxy<br/>port 4000"]
Hub["mcp_hub<br/>port 4000, zero tokens"]
W1["mcp_<service> worker<br/>/tokens:ro"]
W2["mcp_<service> worker<br/>/tokens:ro"]
Claude -->|"LLM traffic"| Proxy
Claude -->|"tools"| Hub
Hub --> W1
Hub --> W2
end
end
The Claude container reaches only two places: the proxy, for LLM traffic, and the MCP Hub, for tools. It never talks to a service directly. Each worker mounts only its own service’s credentials, read-only, and the hub holds no tokens. That’s the boundary described in full on Isolation model; for what a worker does with a request, see Workers.
Same container, different platform
Section titled “Same container, different platform”The container images are identical on macOS and Windows. Only the VM underneath changes.