Add Dockerfile, docker-compose.yml, docker-entrypoint.sh, and .dockerignore so the bot runs detached and survives reboots, replacing the foreground venv run. The image is generic (no secrets/deployment specifics baked in): host networking reaches both Synapse and the Mac; .env, config.toml, and the SSH key are mounted read-only. The entrypoint is the container's environment seam (D4 analog of launch-claude.sh) — it generates ~/.ssh/config for the mac-bridge alias from config.toml [mac] (new hostname/user fields) so the bot's `ssh mac-bridge` stays unchanged. SSH key mounted not baked; first connect uses accept-new host trust. Proven live on the Spark: container connects to Synapse and real messages launched drivable sessions on the phone across 2 rooms via the full chain.
matrix-bridge
A single-user Matrix → Claude Code bridge. Send a message in a project's Matrix room and a Claude Code session launches on the Mac in that project's repo, then surfaces to your phone via Claude Code Remote Control. The point: make the trigger for a coding session portable without moving execution off the Mac.
Runs as a small matrix-nio bot in a Docker container on a DGX Spark; a zsh wrapper on the
Mac (scripts/launch-claude.sh) is the only piece that knows the Mac's environment. Routing
is deterministic in v1 — the room you message in decides the repo (an explicit config map).
Status: scaffolded, pre–Phase 0. No bot code yet. See
AGENTS.md→## Current statefor the active milestone andROADMAP.mdfor the phase plan.
How it works (v1)
Matrix message in a project room
→ bot on the Spark maps room → repo
→ SSHes to the Mac, runs scripts/launch-claude.sh <repo_dir> <message>
→ wrapper cd's into the repo and launches `claude`
→ Remote Control notifies the phone; you drive the session there
Setup
TODO — filled in as Phase 0 is proven: Matrix onboarding (Element + the existing Synapse
homeserver, a bot user), the Mac wrapper, passwordless SSH from the Spark to the Mac, and the
first room→repo mapping. Copy config.example.toml to config.toml (gitignored) and fill in
real room IDs and repo paths. The original scoping docs (SPEC / DECISIONS / KICKOFF) hold the
full background.