SETUP · MACOS
A Mac is the quickest place to try SUB/WAVE: the CLI ships a native darwin binary, the core images are multi-arch, and Docker Desktop already wires up the one bit of host networking the stack needs. This page is the Quick Start with the Mac-shaped details filled in — which runtime, how much memory, and what changes on Apple Silicon.
STEP BY STEP
Anything that gives you docker and docker compose works. Docker Desktop ↗ is the default choice; OrbStack ↗ is lighter on battery and RAM. Colima works too if you prefer a CLI-only VM. Whichever you pick, it has to be running before any subwave command — everything below is Docker underneath.
docker compose versionYou want Compose v2 (the space-separated form, printed as v2.x). If that command errors, the runtime isn't up yet.
On a Mac every container runs inside a Linux VM with a fixed slice of your RAM, so this is the one dial worth checking before you start. Docker Desktop → Settings → Resources:
tts-heavy voice sidecar. Their compose memory ceilings are 6g and 10g respectively, and a VM smaller than that just OOM-kills them mid-load.Disk: budget ~3 GB for the core images, another ~2 GB if you pull a heavy flavour, plus whatever the stem cache is set to (off by default).
The installer detects darwin-arm64 or darwin-x64 and drops a single binary in /usr/local/bin (it will ask for sudo; pass --dir ~/.local/bin to avoid that). Then it offers to scaffold and start.
curl -fsSL https://cli.getsubwave.com | shsubwave setupinit writes the install to ~/subwave and brings the stack up; setup asks for Navidrome, your LLM, and the DJ persona, then renders the jingles. Full walkthrough on Quick Start.
open http://localhost:7700Port 7700 is the only host port the prod stack binds. If you remap it with CADDY_PORT, steer clear of 5000 and 7000 — macOS AirPlay Receiver squats on both, and the failure looks like a broken container rather than a taken port.
subwave doctorThe full diagnostic sweep: containers, Navidrome reachability, the LLM, and whether the stream is actually on air.
APPLE SILICON
The station itself is native on M-series Macs. Only the two optional PyTorch images are x86-only, because their upstream wheels are:
| Image | Arch | On Apple Silicon |
|---|---|---|
| broadcast · controller · web · caddy | amd64 + arm64 | Native |
analyzer (lean — bpm, key, loudness, outro) | amd64 + arm64 | Native |
analyzer-heavy (CLAP + Demucs) | amd64 only | Emulated — slow |
tts-heavy (Chatterbox + PocketTTS) | amd64 only | Emulated — slow |
The tts-heavy service carries its own platform: linux/amd64 pin, so it needs no platform setting of its own — but it is profile-gated and stays down until you ask for it by name with docker compose --profile tts-heavy up -d (or COMPOSE_PROFILES=tts-heavy in .env). The heavy analyzer is the other way round — it replaces a service that is already running, so it needs both the opt-in and the platform default:
# .env
ANALYZER_HEAVY=1
DOCKER_DEFAULT_PLATFORM=linux/amd64Docker Desktop → Settings → General → Use Rosetta for x86/amd64 emulation. Without it the emulated images fall back to QEMU, which is several times slower again. Even with it, a full CLAP + Demucs pass over a large library is an overnight job on a laptop. Leave the analyzer lean unless you want “sounds-like” search and vocal-aware transitions.
MAC-SPECIFIC GOTCHAS
Inside a container, localhost is the container. Point the wizard at http://host.docker.internal:4533 instead — every compose file already maps that name to the host gateway. Same rule for an Ollama box running on the Mac: http://host.docker.internal:11434.
The stream stops when the machine sleeps, and listeners get a dropped connection rather than silence. For a Mac mini acting as the station box, set System Settings → Displays → Advanced → Prevent automatic sleeping. On a laptop, keep it plugged in, or wrap long sessions in caffeinate:
caffeinate -di &state/ holds library.db, a SQLite database in WAL mode. Put it on an SMB or NFS share and file locking gets unreliable; put it outside your home directory and Docker Desktop needs the path added under Settings → Resources → File sharing before the bind mount will work. The default ~/subwave/state avoids both.
Every service is restart: unless-stopped, so the station comes back by itself — as long as Docker does. Tick Start Docker Desktop when you log in in Settings → General and the box recovers from a reboot unattended.
DAY TO DAY
The CLI works from any directory once installed — no cd into the install dir.
subwave statusStack + now-playing snapshot.
subwave logs controllerTail a service. Omit the name for everything.
subwave listenOpen the player in your browser.
subwave updatePull new images, recreate only what changed.
Hacking on the source rather than running a release? The dev compose file is the Mac smoke-test path — Development covers it. Something not right? Updates & Help has the troubleshooting checklist.