Operations Tooling
Sanctum ships with a set of operational scripts in ~/.sanctum/scripts/ that automate the most common maintenance tasks. These are designed to be run from the Mac Mini hub.

Your house has a health check suite, a sync pipeline, an auto-healing watchdog, and a diagnostic tool. There are Fortune 500 companies with worse observability. We’re not going to dwell on what that says about the state of enterprise software or the mental state of people who build home intelligence platforms. We’re just going to document the tools.
sanctum-status.sh
Section titled “sanctum-status.sh”The big picture. One command, every service, everything you need to know about whether your house is alive and well or quietly falling apart.
~/.sanctum/scripts/sanctum-status.shWhat it checks:
- Mac services: Cloudflare Tunnel, Home Assistant, LM Studio, Docker
- VM services: health ingester, Graphiti, Neo4j, OpenClaw gateway
- External access: ha.nepveu.name, health.nepveu.name, sanctum.haus (with CF Access token test)
- Tailscale: connection status, peer count
- Keychain: all critical keys present (account:
sanctum) - Git repos: 8 Mac repos + VM repo (dirty files, unpushed commits)
- Disk usage: Mac and VM
Flags:
| Flag | Effect |
|---|---|
--quiet | Only show problems. Exit code = number of issues. |
Use --quiet in cron jobs or post-boot checks to get a pass/fail result. No news is good news. Literally — silence means everything is fine.
sanctum-sync.sh
Section titled “sanctum-sync.sh”One command to check, commit, and push every Sanctum git repository. Including the VM repo, which requires a bundle proxy because — and this never stops being fun to explain — the VM has no internet access.
~/.sanctum/scripts/sanctum-sync.shRepos synced:
sanctum-config(~/.sanctum)command-center,health-center,openclaw-skills,sanctum-docsyoda-voice-agent,genome-mcp,icloud-organizermanoir-nepveu(VM, via bundle proxy)
Dirty files are auto-committed with a generated message describing the changes. The VM repo is pushed through the Mac using vm-push.sh under the hood, which creates a git bundle, sneaks it across the bridge network like contraband, and pushes it to GitHub on the VM’s behalf.
Flags:
| Flag | Effect |
|---|---|
--dry-run | Show what would be done without making changes |
--force | Commit and push without prompting |
sanctum-doctor.sh
Section titled “sanctum-doctor.sh”The thing you run when something feels wrong but you don’t know what. It checks file permissions, port conflicts, stale processes, config cache, Docker health, keychain integrity, firewall state, and VM connectivity. Then it tells you what’s broken. And if you ask nicely — with --fix — it’ll try to repair things too.
# Diagnose only~/.sanctum/scripts/sanctum-doctor.sh
# Diagnose and auto-fix~/.sanctum/scripts/sanctum-doctor.sh --fixWhat it checks and fixes:
| Check | Auto-fix |
|---|---|
| Config cache stale | Regenerates .instance.json |
| File permissions drifted | Restores 700/600 as needed |
| Scripts not executable | chmod 700 |
| Duplicate cloudflared processes | Kills extras, keeps oldest |
| Zombie Docker containers | docker container prune |
Stale sanctum keychain entries | Reports (manual cleanup) |
| Missing critical keychain keys | Reports |
| pf firewall anchor not loaded | Reloads anchor |
| Stopped Docker containers | docker start |
| LaunchAgents not loaded | launchctl bootstrap |
| VM SOPS vault integrity | Reports |
vm-push.sh
Section titled “vm-push.sh”Push the VM git repository to GitHub via the Mac. The VM runs on a host-only network with no internet access, so this script creates a git bundle on the VM, transfers it to the Mac, merges it with the GitHub remote, and pushes.
It’s a Rube Goldberg machine for git push, and it works flawlessly.
# Push current VM state~/.sanctum/scripts/vm-push.sh
# Commit all dirty files on VM first, then push~/.sanctum/scripts/vm-push.sh --commit "Updated health ingester config"Merge conflicts are resolved automatically by favoring the VM version (since the VM is the source of truth for its own repo).
rotate-cf-service-token.sh
Section titled “rotate-cf-service-token.sh”Rotate the Cloudflare Access service token used by Health Auto Export to authenticate with the health ingester. This should be run before the current token expires (check sanctum-status.sh for expiry warnings).
~/.sanctum/scripts/rotate-cf-service-token.shWhat it does:
- Creates a new service token via CF API (1-year expiry)
- Updates the CF Access policy for
health.nepveu.name - Deletes the old service token
- Updates the Mac Keychain with new credentials
- Regenerates the Health Auto Export import file
- Verifies the new token works end-to-end
After running, you need to update Health Auto Export on the iPhone with the new CF-Access-Client-Id and CF-Access-Client-Secret headers (or re-import the regenerated config from iCloud).
Yes, the last step is manual. On your phone. With your thumbs. Welcome to the limits of automation.
generate-hae-config.sh
Section titled “generate-hae-config.sh”Generate a Health Auto Export importable .json file for this Sanctum instance. Reads tokens from Keychain and VM SOPS, and produces a file ready to AirDrop to an iPhone.
# Generate on Desktop (default)~/.sanctum/scripts/generate-hae-config.sh
# Generate to specific path~/.sanctum/scripts/generate-hae-config.sh ~/Desktop/my-health-config.jsonThe generated config includes the correct endpoint URL, all three authentication headers (base64-encoded), and the 16 health metrics that the ingester processes. After AirDropping to the iPhone, open the file in Health Auto Export and tap Import.
generate-instance.sh
Section titled “generate-instance.sh”Interactive wizard that creates a new instance.yaml for a fresh Sanctum installation. Asks about your household, network, optional services, and notifications, then generates a complete config file.
~/.sanctum/scripts/generate-instance.shThe wizard:
- Auto-detects your macOS username, home directory, and LAN IP
- Picks up Tailscale hostname and IP if installed
- Generates a URL slug from your household name
- Asks which optional services to enable (Firewalla, voice agent, Cloudflare, health, Tailscale)
- Configures Cloudflare domain and tunnel name if enabled
- Sets up notification preferences (Signal)
- Produces a properly formatted
instance.yamlwith600permissions
After generating, review the file, fill in any hardware-specific values (UTM VM UUID, Firewalla MAC address, HA entity IDs), then run generate-plists.sh to create the LaunchAgents.