Shell API Reference

The Sanctum shell library provides a set of sanctum_* functions for reading instance configuration, querying node topology, and interacting with the Sanctum infrastructure from Bash scripts and LaunchAgent wrappers.
Under the hood, these functions read a JSON cache that a Python script generated from YAML. Bash shells out to a tiny inline python3 reader that walks JSON written by Python that parsed YAML you wrote by hand — Python at both ends, JSON in the middle, Bash holding it together with $(). The Rube Goldberg machine of config access. But it resolves any key in well under 50ms, it never breaks, and it’s been running in production for months. Sometimes the unglamorous solution is the correct one.
Two source lines at the top of any script and the entire sanctum_* namespace is yours. The first gives you the config reader; the second, a way to make the haus say something out loud.
source ~/.sanctum/lib/config.shsource ~/.sanctum/lib/notify.shThe second is optional unless you plan on raising your voice; the first is not.
Config Functions
Section titled “Config Functions”sanctum_get
Section titled “sanctum_get”Read any value from the instance config using a dot-notation path. The Swiss Army knife — the one function you’ll use more than all the others combined.
sanctum_get <key_path>| Parameter | Description |
|---|---|
key_path | Dot-delimited path into instance.yaml |
Returns: The value as a string. Empty string if the key does not exist.
# Read a scalar valueport=$(sanctum_get services.voice_agent.port)echo "$port" # 1138
# Read the instance slugsanctum_get instance.slug # manoir-neo
# Read a nested valuesanctum_get network.vm_ip # 10.0.0.10
# A second argument is the default returned when the key is missingsanctum_get services.firewalla.port 18094 # 18094 if unsetsanctum_enabled
Section titled “sanctum_enabled”Check whether a service is enabled. You pass a bare service name — the function prepends services. and appends .enabled, then checks the result. It returns an exit code, so it plays nicely with if statements — more than can be said for most things in Bash.
sanctum_enabled <service_name>Returns: Exit code 0 if services.<service_name>.enabled is true, non-zero otherwise.
if sanctum_enabled voice_agent; then echo "Voice agent is active"fi
if sanctum_enabled signal_proxy; then echo "Signal proxy is active"else echo "Signal proxy is disabled"fisanctum_expand
Section titled “sanctum_expand”Expand a leading ~ in a path to the configured Mac home (users.mac.home). That’s the whole job — no {{PLACEHOLDER}} engine, no template language. A path with no leading tilde comes back untouched.
sanctum_expand <path>sanctum_expand "~/Projects/foo" # /Users/neo/Projects/foosanctum_expand "~" # /Users/neosanctum_expand "/already/absolute" # /already/absolute (unchanged)sanctum_home
Section titled “sanctum_home”Return the configured Mac home (users.mac.home).
sanctum_homeReturns: The Mac home path — /Users/neo, not /Users/neo/.sanctum.
home=$(sanctum_home)echo "$home" # /Users/neosanctum_slug
Section titled “sanctum_slug”Return the instance slug.
sanctum_slugsanctum_slug # manoir-neosanctum_name
Section titled “sanctum_name”Return the human-readable instance name.
sanctum_namesanctum_name # Manoir NeoNetwork Functions
Section titled “Network Functions”sanctum_vm_ip
Section titled “sanctum_vm_ip”Return the VM IP address.
sanctum_vm_ipsanctum_vm_ip # 10.0.0.10sanctum_mac_ip
Section titled “sanctum_mac_ip”Return the Mac bridge IP (the Mac-side IP on the host-only network).
sanctum_mac_ipsanctum_mac_ip # 10.0.0.1sanctum_vm_ssh
Section titled “sanctum_vm_ssh”Return the user@ip SSH target for the VM — assembled from users.vm.username and network.vm_ip, not an alias.
sanctum_vm_sshsanctum_vm_ssh # ubuntu@10.0.0.10
ssh $(sanctum_vm_ssh) 'uptime'# expands to: ssh ubuntu@10.0.0.10 'uptime'sanctum_vm_user
Section titled “sanctum_vm_user”Return the VM username.
sanctum_vm_usersanctum_vm_user # ubuntuIdentity Functions
Section titled “Identity Functions”sanctum_whoami
Section titled “sanctum_whoami”Return the current node identity (read from ~/.sanctum/.node_id).
sanctum_whoamisanctum_whoami # manoirThe existential question, answered in one function call.
sanctum_is_node
Section titled “sanctum_is_node”Check if the current machine is a specific node.
sanctum_is_node <node_id>Returns: Exit code 0 if the current node matches, non-zero otherwise.
if sanctum_is_node manoir; then echo "Running on the hub"fisanctum_my_type
Section titled “sanctum_my_type”Return the node type of the current machine.
sanctum_my_typesanctum_my_type # hubThe type comes from nodes.<me>.type — one of hub, satellite, mobile, or sensor.
Node Topology Functions
Section titled “Node Topology Functions”These functions query the nodes section of the instance config. They accept a <node_id> argument — the real ones here are manoir (the hub) and chalet (a satellite at the cottage). Useful when your haus automation hobby has metastasized into a multi-site distributed system.
sanctum_node_type
Section titled “sanctum_node_type”Return the type of a node.
sanctum_node_type <node_id>sanctum_node_type manoir # hubsanctum_node_type chalet # satellitesanctum_node_host
Section titled “sanctum_node_host”Return the LAN hostname or IP of a node.
sanctum_node_host <node_id>sanctum_node_host manoir # 192.0.2.10sanctum_node_host chalet # (empty — the cottage has no LAN host)A node behind a different network has no host value — that’s the cue to use sanctum_node_ts_ip and the _ts SSH variant instead.
sanctum_node_ts_ip
Section titled “sanctum_node_ts_ip”Return the Tailscale IP of a node.
sanctum_node_ts_ip <node_id>sanctum_node_ts_ip manoir # 100.0.0.20sanctum_node_ts_ip chalet # 100.0.0.21sanctum_node_ts_name
Section titled “sanctum_node_ts_name”Return the Tailscale device name of a node.
sanctum_node_ts_name <node_id>sanctum_node_ts_name manoir # manoirsanctum_node_user
Section titled “sanctum_node_user”Return the SSH username for a node.
sanctum_node_user <node_id>sanctum_node_user manoir # neosanctum_node_online
Section titled “sanctum_node_online”Read the cached reachability flag for a node (nodes.<id>.online, defaulting to false). It does not ping anything — it reports the last value written by whatever heartbeat keeps the field fresh.
sanctum_node_online <node_id>Returns: Exit code 0 if the cached online flag is true, non-zero otherwise.
if sanctum_node_online chalet; then echo "Chalet is reachable"fisanctum_node_ssh
Section titled “sanctum_node_ssh”Resolve the LAN SSH target (ssh_user@host) for a node. It prints the target — it does not run ssh, so wrap it in an actual ssh call.
sanctum_node_ssh <node_id>sanctum_node_ssh manoir # neo@192.0.2.10
# Interactive shellssh $(sanctum_node_ssh manoir)
# Run a remote commandssh $(sanctum_node_ssh manoir) 'uptime'sanctum_node_ssh_ts
Section titled “sanctum_node_ssh_ts”Resolve the Tailscale SSH target (ssh_user@tailscale_ip) for a node — for off-LAN access, or for a node like the cottage that has no LAN host at all.
sanctum_node_ssh_ts <node_id>sanctum_node_ssh_ts chalet # neo@100.0.0.21ssh $(sanctum_node_ssh_ts chalet) 'df -h'sanctum_node_vm_ssh
Section titled “sanctum_node_vm_ssh”Resolve the SSH target for the VM running on a specific node (nodes.<id>.vm.ssh_user@nodes.<id>.vm.host), if that node has a VM.
sanctum_node_vm_ssh <node_id>sanctum_node_vm_ssh manoir # ubuntu@10.0.0.10ssh $(sanctum_node_vm_ssh manoir) 'systemctl --user status openclaw-gateway'sanctum_node_enabled
Section titled “sanctum_node_enabled”Check if a specific service is enabled on a node.
sanctum_node_enabled <node_id> <service_name>Returns: Exit code 0 if the service is enabled on that node.
if sanctum_node_enabled chalet home_assistant; then echo "Chalet runs HA"fiAs with sanctum_enabled, the service name is bare — the function builds the nodes.<id>.services.<name>.enabled path for you.
sanctum_node_service
Section titled “sanctum_node_service”Get a service config value for a specific node.
sanctum_node_service <node_id> <service_name> <key>sanctum_node_service chalet local_model port # 1234sanctum_node_service chalet heartbeat interval # 300sanctum_node_hub
Section titled “sanctum_node_hub”Return the node ID of the hub that a given satellite syncs with (nodes.<id>.sync.hub). It takes a node argument — there’s no no-arg form that magically finds “the hub.”
sanctum_node_hub <node_id>hub=$(sanctum_node_hub chalet)echo "$hub" # manoirNotification Functions
Section titled “Notification Functions”Source ~/.sanctum/lib/notify.sh for notification support. When your haus has something to say, it should be able to say it.
sanctum_notify
Section titled “sanctum_notify”Send a notification, routed by severity through a tiered set of channels (macOS Notification Center, the dashboard banner, Signal, the chitti samskara journal).
sanctum_notify <title> <message> [severity]| Parameter | Description |
|---|---|
title | Notification title |
message | Notification body |
severity | Optional: ambient, info (default), warn, error, critical |
Severity is not cosmetic — it decides which channels fire. Anything outside the five known values is silently normalized to info, so a typo like high lands in the quietest tier, not the loudest.
| Severity | Channels |
|---|---|
ambient | chitti samskara journal only — never pages |
info | macOS Notification Center |
warn | macOS + dashboard banner |
error | macOS + dashboard + Signal |
critical | macOS + dashboard + Signal (with the Sosumi alert sound) |
source ~/.sanctum/lib/notify.sh
sanctum_notify "Backup Complete" "All files backed up successfully" # infosanctum_notify "Disk Warning" "Boot volume is 90% full" critical # pages via SignalComplete Script Example
Section titled “Complete Script Example”#!/bin/bashsource ~/.sanctum/lib/config.shsource ~/.sanctum/lib/notify.sh
echo "Instance: $(sanctum_name) [$(sanctum_slug)]"echo "Node: $(sanctum_whoami) ($(sanctum_my_type))"echo "VM: $(sanctum_vm_user)@$(sanctum_vm_ip)"
if sanctum_enabled voice_agent; then port=$(sanctum_get services.voice_agent.port) echo "Voice agent running on port $port"fi
hub=$(sanctum_node_hub chalet)echo "Chalet syncs with: $hub ($(sanctum_node_host $hub))"
if sanctum_node_online chalet; then sanctum_notify "Chalet Status" "Chalet node is online"else sanctum_notify "Chalet Status" "Chalet node is offline" errorfiTwenty lines. Queries the config, checks the network, sends a notification. This is what the shell library is for — turning what would be 200 lines of raw python3 and ssh and osascript into something a human can read before coffee.