Skip to content

Shell API Reference

The function tree — every shell helper branching from a single source into the operations that keep the lights on

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.

Terminal window
source ~/.sanctum/lib/config.sh
source ~/.sanctum/lib/notify.sh

The second is optional unless you plan on raising your voice; the first is not.


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.

Terminal window
sanctum_get <key_path>
ParameterDescription
key_pathDot-delimited path into instance.yaml

Returns: The value as a string. Empty string if the key does not exist.

Terminal window
# Read a scalar value
port=$(sanctum_get services.voice_agent.port)
echo "$port" # 1138
# Read the instance slug
sanctum_get instance.slug # manoir-neo
# Read a nested value
sanctum_get network.vm_ip # 10.0.0.10
# A second argument is the default returned when the key is missing
sanctum_get services.firewalla.port 18094 # 18094 if unset

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.

Terminal window
sanctum_enabled <service_name>

Returns: Exit code 0 if services.<service_name>.enabled is true, non-zero otherwise.

Terminal window
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"
fi

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.

Terminal window
sanctum_expand <path>
Terminal window
sanctum_expand "~/Projects/foo" # /Users/neo/Projects/foo
sanctum_expand "~" # /Users/neo
sanctum_expand "/already/absolute" # /already/absolute (unchanged)

Return the configured Mac home (users.mac.home).

Terminal window
sanctum_home

Returns: The Mac home path — /Users/neo, not /Users/neo/.sanctum.

Terminal window
home=$(sanctum_home)
echo "$home" # /Users/neo

Return the instance slug.

Terminal window
sanctum_slug
Terminal window
sanctum_slug # manoir-neo

Return the human-readable instance name.

Terminal window
sanctum_name
Terminal window
sanctum_name # Manoir Neo

Return the VM IP address.

Terminal window
sanctum_vm_ip
Terminal window
sanctum_vm_ip # 10.0.0.10

Return the Mac bridge IP (the Mac-side IP on the host-only network).

Terminal window
sanctum_mac_ip
Terminal window
sanctum_mac_ip # 10.0.0.1

Return the user@ip SSH target for the VM — assembled from users.vm.username and network.vm_ip, not an alias.

Terminal window
sanctum_vm_ssh
Terminal window
sanctum_vm_ssh # ubuntu@10.0.0.10
ssh $(sanctum_vm_ssh) 'uptime'
# expands to: ssh ubuntu@10.0.0.10 'uptime'

Return the VM username.

Terminal window
sanctum_vm_user
Terminal window
sanctum_vm_user # ubuntu

Return the current node identity (read from ~/.sanctum/.node_id).

Terminal window
sanctum_whoami
Terminal window
sanctum_whoami # manoir

The existential question, answered in one function call.


Check if the current machine is a specific node.

Terminal window
sanctum_is_node <node_id>

Returns: Exit code 0 if the current node matches, non-zero otherwise.

Terminal window
if sanctum_is_node manoir; then
echo "Running on the hub"
fi

Return the node type of the current machine.

Terminal window
sanctum_my_type
Terminal window
sanctum_my_type # hub

The type comes from nodes.<me>.type — one of hub, satellite, mobile, or sensor.


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.

Return the type of a node.

Terminal window
sanctum_node_type <node_id>
Terminal window
sanctum_node_type manoir # hub
sanctum_node_type chalet # satellite

Return the LAN hostname or IP of a node.

Terminal window
sanctum_node_host <node_id>
Terminal window
sanctum_node_host manoir # 192.0.2.10
sanctum_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.


Return the Tailscale IP of a node.

Terminal window
sanctum_node_ts_ip <node_id>
Terminal window
sanctum_node_ts_ip manoir # 100.0.0.20
sanctum_node_ts_ip chalet # 100.0.0.21

Return the Tailscale device name of a node.

Terminal window
sanctum_node_ts_name <node_id>
Terminal window
sanctum_node_ts_name manoir # manoir

Return the SSH username for a node.

Terminal window
sanctum_node_user <node_id>
Terminal window
sanctum_node_user manoir # neo

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.

Terminal window
sanctum_node_online <node_id>

Returns: Exit code 0 if the cached online flag is true, non-zero otherwise.

Terminal window
if sanctum_node_online chalet; then
echo "Chalet is reachable"
fi

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.

Terminal window
sanctum_node_ssh <node_id>
Terminal window
sanctum_node_ssh manoir # neo@192.0.2.10
# Interactive shell
ssh $(sanctum_node_ssh manoir)
# Run a remote command
ssh $(sanctum_node_ssh manoir) 'uptime'

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.

Terminal window
sanctum_node_ssh_ts <node_id>
Terminal window
sanctum_node_ssh_ts chalet # neo@100.0.0.21
ssh $(sanctum_node_ssh_ts chalet) 'df -h'

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.

Terminal window
sanctum_node_vm_ssh <node_id>
Terminal window
sanctum_node_vm_ssh manoir # ubuntu@10.0.0.10
ssh $(sanctum_node_vm_ssh manoir) 'systemctl --user status openclaw-gateway'

Check if a specific service is enabled on a node.

Terminal window
sanctum_node_enabled <node_id> <service_name>

Returns: Exit code 0 if the service is enabled on that node.

Terminal window
if sanctum_node_enabled chalet home_assistant; then
echo "Chalet runs HA"
fi

As with sanctum_enabled, the service name is bare — the function builds the nodes.<id>.services.<name>.enabled path for you.


Get a service config value for a specific node.

Terminal window
sanctum_node_service <node_id> <service_name> <key>
Terminal window
sanctum_node_service chalet local_model port # 1234
sanctum_node_service chalet heartbeat interval # 300

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.”

Terminal window
sanctum_node_hub <node_id>
Terminal window
hub=$(sanctum_node_hub chalet)
echo "$hub" # manoir

Source ~/.sanctum/lib/notify.sh for notification support. When your haus has something to say, it should be able to say it.

Send a notification, routed by severity through a tiered set of channels (macOS Notification Center, the dashboard banner, Signal, the chitti samskara journal).

Terminal window
sanctum_notify <title> <message> [severity]
ParameterDescription
titleNotification title
messageNotification body
severityOptional: 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.

SeverityChannels
ambientchitti samskara journal only — never pages
infomacOS Notification Center
warnmacOS + dashboard banner
errormacOS + dashboard + Signal
criticalmacOS + dashboard + Signal (with the Sosumi alert sound)
Terminal window
source ~/.sanctum/lib/notify.sh
sanctum_notify "Backup Complete" "All files backed up successfully" # info
sanctum_notify "Disk Warning" "Boot volume is 90% full" critical # pages via Signal

#!/bin/bash
source ~/.sanctum/lib/config.sh
source ~/.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" error
fi

Twenty 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.