Skip to content

sanctum CLI Reference

Sanctum CLI — a vintage Swiss Army knife laid open, distinct hand-tools fanned out from a single pivot, a teal beam catching the hinge at the center. One binary, every host.

sanctum is the operator surface for every Sanctum host — router, wizard, doctor in one Python binary (Typer + Rich). The public install path is the Homebrew tap ogilthorp3/sanctum (public), so brew install ogilthorp3/sanctum/sanctum-cli works directly — it auto-taps on first use. (On Bert’s own host it also exists as a dev install at ~/.local/bin/sanctum.) The everyday commands are below; a dozen deeper helpers sit one level down. sanctum --help is the canonical roster, and it moves faster than this page.

Terminal window
sanctum <command> [args]

Most commands read ~/.sanctum/instance.yaml and fail blunt when it’s missing or invalid. The errors are deliberately curt — Sanctum is for technical-friend haushelds, and we trust you with the real line.


The first command you run, the first when something’s wrong, and the first we’ll ask you to run when you reach out for help. It probes the three subsystems that must be healthy for the host to work.

Terminal window
sanctum doctor
sanctum doctor --full
sanctum doctor --json
Group Probe
LaunchAgents launchctl list, filtered to com.sanctum.*. Each row’s status is derived from its PID and last exit code
Providers Reachability + latency for each configured model provider (claude, gemini, mlx_local)
Backup repos restic snapshots against each configured repo (local SSD + cloud)

It’s brevity-gated — one OK line when green, the full tables only on a DEGRADED/FAILED row or --full. --json emits the whole report, for the menu-bar plugin and CI.

Code Meaning
0 Nothing worse than OPERATIONAL
1 At least one subsystem is DEGRADED or FAILED (or instance.yaml is missing)

The canonical health suite — tells you whether the install is still good after an update, a reboot, or a drift suspicion. Twelve probes, two tiers:

Terminal window
sanctum self-test
sanctum self-test --json
sanctum self-test --only cathedral
# Probe Verifies Tier
1 network reachability loopback + DNS resolve CLI
2 node binary identity /usr/local/bin/node is the signed Node.js Foundation binary CLI
3 sanctum config valid ~/.sanctum/instance.yaml parses and validates CLI
4 recent backup snapshot a restic snapshot exists and is recent (n/a on a fresh install) CLI
5 Yoda cathedral (:1337) TLS port reachable haus
6 Coder cathedral (:3301) TLS port reachable haus
7 proxyd routing (:4040) service alive (an HTTP 401 counts — it answered) haus
8 Force Flow (:4077) listening haus
9 chitti samskara (:2188) listening haus
10 TCC grants the expected automation grants are present haus
11 R2D2 supervisor heartbeat the auto-fix supervisor is beating, with a sane success rate haus
12 audit log within budget the audit log is under its size cap haus

The four CLI-tier probes run everywhere. The eight haus-tier probes only mean something once the haus services are up; on a CLI-only box they return n/a, not fail, and n/a doesn’t count.

No percentage threshold. The suite exits 0 iff every applicable probe passes; one real failure exits 1. n/a probes are skipped either way.

[ 6/12] Coder cathedral (:3301) ···· fail no response on :3301
1 probe(s) failed. 11/12 applicable probes passed in 185 ms. Each red
line above has the actionable detail.

sanctum logs self-test has the full transcript if a red line’s own detail isn’t enough. --only <substr> narrows to matching probe names; --json feeds the soak harness. Run it after install, a macOS major upgrade, or a reboot you’re unsure of, and weekly as hygiene — sanctum update runs it as the gate.


The thirty-second health glance — who am I, where’s my disk, when did I last back up, how busy have I been. The host’s own vital signs, no probes into other services. Run this if you run one command in the morning.

Terminal window
sanctum status
sanctum status --oneline
sanctum status --json
Field Source
instance / host instance.yaml (instance name, hostname)
default provider the router’s current default (e.g. claude)
disk df on /System/Volumes/Data; DEGRADED at >=85% used, FAILED at >=90%
backups restic snapshot count + age per repo (local SSD + cloud), oldest age wins
telemetry 7-day rollup: requests and errors

The default render is a set of Rich tables; --oneline collapses it to one line, what the menu-bar plugin and a morning glance want:

sanctum @ manoir.local · backup 7h / ? · router→claude · disk 76% (operational) · telemetry 32r/8e/7d

status answers “is this host okay right now?”; doctor is what you reach for when it shows red.


Upgrades the CLI via the Homebrew tap, then re-runs sanctum self-test as the gate. Run by hand on a new release; not (yet) wired into a launchd timer.

Terminal window
sanctum update
sanctum update --dry-run
sanctum update --skip-self-test

It runs brew update, then brew upgrade ogilthorp3/sanctum/sanctum-cli, then sanctum self-test as the gate — and refuses to call the upgrade “done” unless every probe still passes.

Flag Behavior
--dry-run Print every action without executing
--skip-self-test Skip the gate. Operator-grade — use when you know what you’re doing

brew upgrade exits 0 even when nothing changed, so an already-current install falls through harmlessly. If the gate fails after a real upgrade, the command exits non-zero and says so — investigate, then downgrade or fix forward.


Removes every operational artifact — LaunchAgents, Keychain credentials, the brew tap reference — but never your data. Pass --purge if you actually want the data gone too.

Terminal window
sanctum uninstall
sanctum uninstall --purge
sanctum uninstall --dry-run
  • Every com.sanctum.* LaunchAgent in ~/Library/LaunchAgents/ — bootout plus the plist renamed .plist.uninstalled-YYYY-MM-DD (orphan plists are worse than missing services). Discovered by glob, so it tracks the roster.
  • Every sanctum/* Keychain entry, revoked via security delete-generic-password.
  • The ogilthorp3/sanctum brew tap reference (a later brew install re-taps).
  • SanctumBridge.app + SanctumLauncher.app, renamed with the .uninstalled- suffix.

~/.sanctum/logs/ (audit), memory/ (agent memory + Memory Vault), backups/ (local snapshots), secrets/ (mode-600 files), and your cloud bucket — your R2/B2/gdrive target is untouched.

The ~/.sanctum/ data dirs above, renamed to ~/.sanctum.purged-<timestamp> rather than rm -rf’d — a fat-fingered purge gets a few seconds of grace. It never touches /usr/local/bin/node, the Apple Installer’s domain.


A typed shortcut around tail. Resolves a short name to its real path (some under ~/.sanctum/logs/, some ~/.openclaw/logs/) and streams it — follow, last 50 lines.

Terminal window
sanctum logs <service>
sanctum logs --list
sanctum logs proxyd --once -n 200

sanctum logs --list prints the canonical map — names, paths, which files exist — and won’t go stale:

Name File
r2d2 ~/.sanctum/logs/r2d2-audit.jsonl
kitchen-loop ~/.sanctum/logs/kitchen-loop.log
proxyd ~/.openclaw/logs/proxyd.log
yoda ~/.openclaw/logs/sanctum-mlx.log
coder ~/.openclaw/logs/sanctum-mlx-coder.log
cathedral both sanctum-mlx.log + sanctum-mlx-coder.log
bridge ~/.openclaw/logs/sanctum-bridge.log
force-flow ~/.openclaw/logs/force-flow.log
watchdog ~/.openclaw/logs/watchdog-rust.log
agent-trace ~/.sanctum/logs/agent-trace.log
ram-sentinel ~/.sanctum/logs/ram-sentinel.log
launchd-health ~/.sanctum/logs/launchd-health.log
signal ~/.sanctum/logs/signal-health.log
backup ~/.sanctum/logs/backup.log
self-test ~/.sanctum/logs/self-test.log
log-rotate ~/.sanctum/logs/log-rotate.log
Flag Behavior
--follow / --once, -f Stream (default) or take a one-shot snapshot
--lines, -n How many lines of history to show first (default 50)
--list Print every known service + its path, then exit

Anything not in the map is rejected with a pointer to --list — no fuzzy-match; know which log you want.


Read-only inventory, three tables: Family (per-person), Shared, and Unassigned (auto-discovered, not yet attributed). It reads the Screen Time module’s devices.yaml — the source of truth mapping MACs to people and categories.

Terminal window
sanctum devices

Lookup order: $SANCTUM_DEVICES_FILE (a fixture override; unset in production), then ~/.sanctum/screen-time/devices.yaml, then ~/Projects/sanctum-screen-time/devices.yaml; first existing wins. It does not mutate — assigning is sanctum screen-time assign (Family Pass Phase 2) or editing the YAML.


Read-only view of the curfew schedule — weekday/weekend cutoffs per child, plus shared-device hard curfews. No separate file; curfews live in the same devices.yaml that sanctum devices reads.

Terminal window
sanctum schedule

It shows; it does not edit. To extend a curfew once — a school event, a late movie — use the Force Flow override the command prints:

Terminal window
curl -X POST http://127.0.0.1:4077/screen/override \
-d '{"target":"NAME","minutes":30}'

Daily home-network health. One pane (Internet, WAN path, CDN/MSS guard, armor, hub) and a safe improve that only re-asserts the Firewalla MSS clamp — never flips WAN mode or Advanced DMZ.

Terminal window
sanctum net home
sanctum net home status --json
sanctum net home improve
sanctum net home doctor --apply

Walkthrough: Home Network. Deeper NAT/speed tools: check / optimize / speedtest below.


Read-only audit of your network topology. It works out whether you’re behind one NAT or two, names your ISP, finds your default gateway, and explains in one line what it concluded. It changes nothing — run it as often as you like.

Terminal window
sanctum net check

It prints three things: the NAT topology (single, double, or unknown), the ISP and gateway it detected, and the reasoning behind the verdict. That last line is the part to read — a double-NAT call is only as good as the evidence it cites.


The guided path from double-NAT to single-NAT — the configuration where your own router (a Firewalla, typically) holds the public IP instead of the ISP’s hub. It is opt-in and reversible: it snapshots a rollback baseline before you touch anything, warns you that the cutover briefly drops your internet, and walks an ISP-specific playbook step by step.

Terminal window
sanctum net optimize
sanctum net optimize --plan-only
sanctum net optimize --yes

It runs net check first. If you’re already single-NAT — or there’s no Firewalla to put in front — it says so and exits 0 without prompting. Otherwise it prints the plan for your detected ISP, captures the rollback snapshot, confirms you’re physically at the box (not remote — this drops the link), and then waits for you to run the steps before verifying the result.

Flag Behavior
--plan-only Print the ISP-specific plan and stop — no snapshot, no prompt, no verify loop. The dry-read
--yes / -y Skip the “are you at the box?” confirmation. For when you already know

After you’ve done the steps, it probes the result and renders one of three verdicts: VERIFIED (the cutover took), APIPA_ROLLBACK (the box fell back to a self-assigned 169.254.x.x address — the change failed, and it prints the rollback commands), or an inconclusive note when it can’t tell yet.


The honest throughput doctor. A multi-gig line routinely “tests slow” because the test is the bottleneck, not the line — a single TCP stream tops out near 2 Gbps, Wi-Fi caps you around 1-2, and the ISP hub’s built-in test runs on a weak CPU over one connection. This command runs a multi-stream test, reads the link speed of every hop it can see, and names the real ceiling instead of leaving you guessing.

Terminal window
sanctum net speedtest
sanctum net speedtest --streams 16
sanctum net speedtest --no-test
sanctum net speedtest --json

It walks the path — your NIC, whether you’re on Wi-Fi or wired, and the Firewalla’s WAN/LAN ports when it can reach them over SSH — finds the slowest known link, then runs a bounded parallel-stream download and interprets the gap. When a single stream stalls and parallel streams fly, it tells you the single number was the artifact. When you’re at the link ceiling, it says so and names the hop to fix.

Flag Behavior
--streams N Parallel download streams (default 8). Raise it on a very fast line or to escape a single-stream artifact
--no-test Ceiling audit only — read every hop’s link speed and interpret it, skip the live download entirely
--json Emit the full report as JSON (hops, bottleneck, verdict, advice) for the menu bar or a script

The interpreter encodes the field rules so the lie is visible:

Artifact What the doctor says
Single-stream cap A single connection stalls near 1-2 Gbps; the multi-stream figure is the real one — trust it
Wi-Fi ceiling Wi-Fi caps you at ~1-2 Gbps regardless of the line; go wired and re-test
Slowest port A 1G switch or a 2.5G NIC anywhere in the chain is your ceiling — no line upgrade moves it
NAT topology Single- vs double-NAT changes throughput by zero; do not chase NAT to go faster
ISP hub test The hub’s built-in test is single-stream on a weak CPU and under-reports; measure from your own machine
PPPoE CPU-bound on most routers, caps around ~3-3.5 Gbps; the band is named when the WAN uses it

Export an encrypted bundle of your Sanctum Keychain credentials — OpenRouter, Anthropic, Gemini, Firewalla-bridge, R2, B2. The single most important command in the CLI: sanctum uninstall revokes those entries and a dead disk takes them with it. The bundle re-keys a fresh Mac in seconds instead of by hand.

Terminal window
sanctum keys backup ~/Documents/sanctum-keys-2026-06-09.tar.gz.enc

It reads each sanctum/* Keychain entry into a mode-600 file, prompts for a passphrase (twice, minimum 12 characters — the CLI neither generates nor stores it), then tar.gzs and openssl enc -aes-256-cbc -pbkdf2 -salts the lot to the .enc path you gave. No copy anywhere, no cloud call. Restore with sanctum keys restore <path>.


Global options; everything else routes to the command.

Option Behavior
--version Print the CLI version and exit 0
--traceback Print a full traceback on an uncaught exception (otherwise you get the curt line)
-h, --help Print the usage banner and exit 0
Terminal window
sanctum --version # → sanctum 0.10.2
sanctum --help # → command roster

Code Meaning
0 Success (--help and --version included)
1 Command-level failure (a probe failed, a prereq is missing, a file wasn’t found)
2 Usage error (unknown command, missing required argument)

Command Purpose
sanctum status Host vital signs — one line with --oneline
sanctum doctor Are the LaunchAgents, providers, and backups healthy?
sanctum self-test Run the twelve canonical probes
sanctum update brew upgrade + self-test as the gate
sanctum uninstall Remove operational artifacts (preserve data by default)
sanctum uninstall --purge Also remove the ~/.sanctum/ data dirs
sanctum logs <service> Tail a known log — --list to see them all
sanctum devices Read-only haushold device inventory
sanctum schedule Read-only curfew view
sanctum net home Daily home-network health + safe CDN/MSS improve
sanctum net check Read-only NAT-topology + ISP audit
sanctum net optimize Guided, reversible double-NAT → single-NAT cutover
sanctum net speedtest Honest multi-stream throughput doctor — names the real ceiling
sanctum keys backup <path> Encrypt your Keychain credentials to a portable bundle
sanctum chat / code / vision Talk to the router-chosen / Claude / Gemini model
sanctum onboard One-shot first-run: recipe → cloud → first backup → canary