Skip to content

Architecture Overview

Sanctum Anatomy — a cinematic cross-section of the haus, circuits glowing beneath the skin, teal along the bones and amber through the flesh

At 02:47 on a Tuesday in April, an Xbox in the basement quietly joined the Wi-Fi. By 02:47:03, it was blocked at the router, a Signal message was sitting on a phone nine hundred kilometres away, a curfew violation was recorded in a SQLite database in a service named after the Sermon on the Mount, and a dashboard banner was already glowing amber. Nobody woke up. The haus, as of that moment, had noticed.

That is Sanctum working correctly. Thirty-eight services, two machines, one private bridge, and an ethos that matters more than any individual technical choice: we are building this like a body. It has bones — the parts that have stopped changing. It has flesh — the parts still growing new capabilities every week. It has nerves between the two, senses pointed at the outside world, and an immune response that sometimes wakes you up gently and sometimes does not wake you up at all. The docs below are the anatomy chart.

Physically, Sanctum is a Mac Mini M4 Pro and a QEMU-headless Ubuntu VM running on it, connected by a private bridge100 interface on 10.10.10.0/24. The Mac is where hardware lives: Apple Silicon inference, Sonos bridging, Signal, HomeKit, and everything that has to touch a USB port or a microphone. The VM is where the agent cluster lives: six to nine specialized intelligences with no direct route to the internet. If the VM wants to reach the outside world, it asks the Mac nicely, and the Mac decides whether the request is reasonable. It is an air-gapped tenant with an indoor-plumbing privilege.

Sanctum network topology — Mac Mini host and Ubuntu VM connected via bridge100, with Cloudflare Tunnel and Tailscale as the two external on-ramps
🔍 Hover to zoom

Conceptually, though, the physical diagram is the least interesting view. What makes Sanctum work is what runs inside those two boxes and how the pieces relate to each other — which is where the body metaphor becomes less cute and more operationally useful.

There’s also a less-physical principle that runs through the rest of this anatomy: the Council is plural on purpose. Each Jedi runs on a different model family by default — Yoda and Mundi on Claude Opus 4.7 via the haus’s Max subscription bridge, Qui-Gon on Qwen2.5-Coder-14B, Windu on Gemini 3.1 Pro, the privacy-critical seats (Cilghal, Mothma, Jocasta) on the local Qwen3.6 — because a council of one model wearing five robes returns one kind of answer regardless of who asks. See (Neuro)diversity is Paramount for the full doctrine and Principle 10 in The Living Force for the canonical short version.

The Bones — a pencil-sketch anatomical plate of Sanctum's Rust services laid out as a load-bearing skeletal frame, each vertebra labelled with a service name, faint teal halo along the spine

The bones are written in Rust and live in the sanctum-rs workspace. They are the parts of the system that have stopped redesigning themselves. Once a service crosses from the Python side of the haus — where features still sprout new limbs every week — into sanctum-rs/services/ and is built and deployed as the running launchd unit, it becomes structural: a single deploy binary, compile-time guarantees on its interfaces, and a slot that either holds or doesn’t.

As of this writing, two services actually meet that bar:

BonePortWhat It Holds Up
sanctum-watchdogThe Living Force incarnate. Checks every service every ten minutes, self-heals the ones it can, escalates the ones it can’t.
sanctum-proxy4040The cloud-tier model router. Classifies requests, applies daily cost caps, falls back through a configured chain before giving up.

Several more services have Rust source scaffolded in sanctum-rs/services/sanctum-firewalla, sanctum-tts, sanctum-mlx, sanctum-memory, sanctum-server, sanctum-idle — but their runtimes are still the original Node or Python implementations on the ports you’d expect (:1984, :8008, :1337, :42069). The tools/rust_readiness.py harness tracks them honestly under the porting stage — it will not honour a graduated claim unless the binary actually exists at sanctum-rs/target/release/<name> on disk. Bones must be earned.

The Flesh — a pencil-sketch anatomical plate of Sanctum's Python services drawn as musculature wrapped around the skeleton, a warm amber halo through the fibres showing active feature growth

The flesh is Python. It is how we find out what the service is before we carve it in Rust. Every service that currently sits in ~/.sanctum/force-flow/ or in the sanctum-screen-time repo is there because its feature shape is still moving — new credit mechanisms, new curfew edge cases, new channels added to the notification fan-out, a homework mode that keeps acquiring exemptions. Writing that in Rust would mean shipping less, slower, with fewer features that our family actually needs.

MusclePortWhat It’s Still Figuring Out
force-flow4077The unified notification hub. iPhone push, Sonos TTS, Signal via signal-cli daemon, dashboard banners, macOS Notification Center. The channel list keeps gaining members.
screen-timeCurfew, wind-down, homework mode, credits, guests. Deployed alongside force-flow. The rules here change whenever a teenager finds a loophole.
memory-vault-mcpMCP server in front of sanctum-memory. The consolidation pass is still tuning its heuristics.

Flesh hardens. The rust_readiness tool exists specifically so we can tell when a muscle has stopped twitching long enough to become a bone. The current readout (python3 tools/rust_readiness.py) puts force-flow and memory-vault-mcp in the hardening stage — feature velocity is slowing, but not zero. screen-time is still firmly organic. It will cross when the guest-approval flow stabilises, and not a day before.

Between bones and flesh runs a network of private pathways — bridge100 on the Mac–VM axis, and a short list of well-known local ports that services use to find each other without DNS. The rule is simple: no service reaches across the bridge for a remote HTTP call if there’s a local one that does the same job. Every cross-service conversation in Sanctum is a few hundred microseconds on the loopback interface, which means nothing interesting depends on the router’s mood at 3 AM.

Mac Mini 10.10.10.1
├─ 1111 command-center
├─ 1234 LM Studio
├─ 1337 sanctum-mlx
├─ 1984 sanctum-firewalla
├─ 4040 sanctum-proxy
├─ 4077 force-flow
├─ 8008 sanctum-tts
├─ 8080 signal-cli daemon
└─ 42069 sanctum-memory
bridge100 10.10.10.0/24
Ubuntu VM 10.10.10.10
├─ openclaw-gateway (systemd)
├─ Yoda, Windu, Qui-Gon,
│ Cilghal, Mundi, Mothma
└─ outbound → 10.10.10.1 only

The VM has no independent route to the outside world. Any external dependency — an Anthropic API call, a Gemini image generation, a git pull — happens through a Mac-side proxy or a Tailscale tunnel. This is either excellent security architecture or the opening scene of a containment thriller. It has been both.

Each agent in the cluster is a specialized perception. Sanctum does not have one intelligence — it has a council of them, routed by the Smart Router to the model tier that fits their job. Cloud for long-horizon synthesis. Local-ops for tool use and code. Local-secure for anything that must never leave the machine.

AgentRoleModel Tier
YodaConsigliere — absorbs everyone else’s escalations, advises the Doncouncil-brain — Opus 4.7 by default; smart-routed to local council-mlx for general chat and Opus 4.7 --effort max (Claude Team) for deep reasoning
WinduSecurity master — Firewalla rules, PF policy, perimeter auditsCloud (Opus 4.7)
Qui-GonInfrastructure — Docker health, systemd units, recoveryLocal ops
CilghalHealth — Apple Health, sleep, cognitive scaffoldingLocal secure (Gemma4+LoRA)
Ki-Adi-MundiFinance — Triptyq deal flow, personal treasuryLocal secure
JocastaArchivist — CRM, communications, long memoryCloud
Mon MothmaOperations — Force Flow + Living Force orchestrationCloud
AhsokaSatellite — the agent that follows you when you leave the hausLocal ops
TommyGuardian Spirit — the dead cat with strong opinions about network segmentationspecial

The routing rule is not democratic. Code and security stay on Opus regardless of budget; general chat can be downgraded to a cheaper model mid-conversation; health and fund data never leave the Mac. The proxy’s JSONL usage log is the ground truth for what actually ran, because an agent doesn’t always know which tier served its last turn.

Infrastructure rots. Entropy is undefeated. The whole reason sanctum-watchdog exists — and the whole reason the Living Force doctrine exists around it — is that a running system in a haus is a continuous low-grade medical emergency, and somebody has to keep checking the vitals. Every ten minutes, the watchdog walks the service catalogue, probes each port, asks each service whether it is well, and either (a) believes the answer, (b) restarts the service, or (c) writes a Force Flow notification aimed at a human. The correct outcome most nights is (a).

When the save is clean — a probe catches a drifting last_active timestamp two minutes before it metastasises into a cascade, the anomaly detector pins a root cause on the first retry — the watchdog does what Patrick Roy did to Sandström in the Forum, Game 4, 1993: glove save, wink at the shooter, skate to the bench. The cascade never lands. The dashboard stays green. The haus sleeps.

When the answer is wrong in interesting ways, the notification fans out through force-flow: the severity decides whether it’s a silent dashboard banner, a Sonos announcement that wakes the haus at 7 AM, an iPhone push, or — for the critical tier — a Signal message from Yoda’s account to a phone in California. Windu runs a parallel perimeter check over the Firewalla log; Qui-Gon watches the infrastructure layer; Cilghal watches your vitals rather than the machine’s. The council is, structurally, a distributed set of specialised antibodies with overlapping coverage. Allez, les Boys.

The thing we have learned, building this: a living system cannot be rewritten all at once, and it cannot be frozen all at once either. Rust is brittle if you reach for it too early; Python is expensive if you reach for it too late. So Sanctum runs on two substrates at the same time, and we accept that. We write new things in Python, where iteration is cheap and the shape of the service is still negotiable. We port old things to Rust, where deploys are single binaries and compile-time guarantees pay rent every day. The rust_readiness harness tells us the transition date. The Living Force doctrine tells us how to keep the thing alive during the transition.

The practical rule is this: you cannot tell a service’s maturity from its function, only from its velocity. Force Flow is mission-critical and still Python. sanctum-tts is cosmetic voice synthesis and already Rust. What graduates a service is not how important it is — it is how settled it is. Hardened and flexible at the same time is the only configuration that survives contact with a real family living in a real haus in Québec for a real decade. Welcome to City Montreal. Where we’re going, we don’t need roads — we need launchd, age keys, and a watchdog that doesn’t lie.

The Living Force

The self-healing doctrine. Ten principles, eight phases, and the incident log that birthed them. Read this before touching anything critical.

Language Maturity

When to keep a service in Python, when to rust it, and the CLI that tells you which bone is next to calcify.

Force Flow

One service, one brain, every alert in the haus. The notification fan-out the whole council depends on.

Services

The full catalogue — 38 services, their ports, their LaunchAgent names, and the one-line commentary each port earned.