TypeScript API Reference

The TypeScript config module at command-center/lib/config.ts provides typed access to the Sanctum instance configuration. It reads from the same ~/.sanctum/instance.yaml file as the shell library and is used by the command center dashboard and any Node.js tooling.
Same YAML. Same config. Same haus. But now with type safety, because if your haus is going to be managed by code, that code should at least know the difference between a string and a number. The shell library makes no such promises.
Import
Section titled “Import”import { get, getConfig, isEnabled, expand, slug, name, vmSsh, whoami, isNode, myNodeType, nodeGet, nodeSsh, nodeSshTs, nodeVmSsh, getNodes, getNodesByType, isNodeOnline, isNodeServiceEnabled, nodeService, nodeHub, getSatellites,} from './lib/config.js';Config Access
Section titled “Config Access”Read any value from the instance config by dot-notation path. The optional
second argument is the fallback returned when the path is missing — so get
hands you a T, never an undefined you forgot to guard.
function get<T = string>(path: string, fallback?: T): T| Parameter | Type | Description |
|---|---|---|
path | string | Dot-delimited path into the config |
fallback | T | Value returned if the path is absent (default undefined) |
const port = get('services.dashboard.port', 3001);// 3333
const vmIp = get('network.vm_ip');// "10.0.0.10"
const tz = get('instance.timezone');// "America/New_York"getConfig()
Section titled “getConfig()”Return the entire parsed configuration object. The whole thing. Every detail your haus knows about itself, in one typed object.
function getConfig(): SanctumConfigconst config = getConfig();console.log(config.instance.name);// "Manoir Neo"isEnabled()
Section titled “isEnabled()”Check whether services.<name>.enabled is true. You pass the bare service
name — isEnabled prefixes the services. and suffixes the .enabled for
you. Pass the full path and it goes looking for services.services.x.enabled,
finds nothing, and politely returns false.
function isEnabled(service: string): booleanif (isEnabled('signal_proxy')) { console.log('Signal bridge proxy is active');}
if (isEnabled('voice_agent')) { // ...}expand()
Section titled “expand()”Expand a leading ~ to the configured Mac home directory (users.mac.home).
Just the tilde — no {{token}} interpolation, no environment substitution.
It is the smallest possible path helper, and it knows it. Anything that
doesn’t start with ~ comes back untouched.
function expand(path: string): stringconst result = expand('~/Projects/openclaw-skills');// "/Users/neo/Projects/openclaw-skills"Identity
Section titled “Identity”slug()
Section titled “slug()”Return the instance slug.
function slug(): stringslug();// "manoir-neo"name()
Section titled “name()”Return the human-readable instance name.
function name(): stringname();// "Manoir Neo"vmSsh()
Section titled “vmSsh()”Return the VM SSH target as user@ip, assembled from users.vm.username and
network.vm_ip. Not an SSH-config alias — the literal address you can hand to
ssh.
function vmSsh(): stringvmSsh();// "ubuntu@10.0.0.10"whoami()
Section titled “whoami()”Return the current node identity (read from ~/.sanctum/.node_id).
function whoami(): stringwhoami();// "manoir"isNode()
Section titled “isNode()”Check if the current machine matches a given node ID — a string compare against
whoami(). Note it takes a node ID (manoir), not a node type (hub); the
two are easy to confuse, and the type system won’t save you here.
function isNode(nodeId: string): booleanif (isNode('manoir')) { console.log('Running on the manoir hub');}myNodeType()
Section titled “myNodeType()”Return the node type of the current machine — reads nodes.<whoami>.type.
function myNodeType(): stringmyNodeType();// "hub"A plain string, not a sealed union. The convention is hub, satellite,
mobile, or sensor — the kinds of places your haus exists — but the function
returns whatever the YAML says. The type system doesn’t judge. It just relays.
Node Topology
Section titled “Node Topology”nodeGet()
Section titled “nodeGet()”Read a field for a specific node — sugar for get('nodes.<id>.<field>'), with
the same optional fallback.
function nodeGet<T = string>(nodeId: string, field: string, fallback?: T): T| Parameter | Type | Description |
|---|---|---|
nodeId | string | Node identifier (e.g., "manoir", "chalet") |
field | string | Dot-delimited path within that node’s config |
fallback | T | Value returned if the field is absent |
nodeGet('manoir', 'tailscale_ip');// "100.0.0.20"
nodeGet('chalet', 'type');// "satellite"
nodeGet('manoir', 'host');// "192.0.2.10"getNodes()
Section titled “getNodes()”Return the full nodes dict, keyed by node ID. For just the IDs, take the keys.
function getNodes(): Record<string, Record<string, unknown>>Object.keys(getNodes());// ["manoir", "chalet", "mbp", "ruview_front",// "ruview_basement", "ruview_garage", "ruview_living"]getNodesByType()
Section titled “getNodesByType()”Return nodes filtered by type, each as its full config object with the id
folded back in.
function getNodesByType(type: string): Array<{ id: string } & Record<string, unknown>>getNodesByType('hub');// [{ id: "manoir", type: "hub", display_name: "Manoir Neo", ... }]
getNodesByType('satellite').map((n) => n.id);// ["chalet"]getSatellites()
Section titled “getSatellites()”Convenience wrapper for getNodesByType('satellite') — all satellite nodes as
config objects.
function getSatellites(): Array<{ id: string } & Record<string, unknown>>getSatellites().map((n) => n.id);// ["chalet"]nodeHub()
Section titled “nodeHub()”Return the hub node ID that a given satellite syncs with — reads
nodes.<id>.sync.hub. It answers “who does this satellite report home to,”
not “which node is the hub.” Subtle difference, load-bearing in a two-haus
topology.
function nodeHub(nodeId: string): stringnodeHub('chalet');// "manoir"isNodeOnline()
Section titled “isNodeOnline()”Read the static nodes.<id>.online flag from config. Synchronous, no Promise,
no network — it reports what the YAML last declared, not what the wire is doing
right now.
function isNodeOnline(nodeId: string): booleanif (isNodeOnline('chalet')) { console.log('Chalet is marked online');}nodeSsh()
Section titled “nodeSsh()”Return the SSH connection string for a node over LAN.
function nodeSsh(nodeId: string): stringnodeSsh('manoir');// "neo@192.0.2.10"nodeSshTs()
Section titled “nodeSshTs()”Return the SSH connection string for a node over Tailscale.
function nodeSshTs(nodeId: string): stringnodeSshTs('chalet');// "neo@100.0.0.21"nodeVmSsh()
Section titled “nodeVmSsh()”Return the SSH connection string for the VM on a specific node.
function nodeVmSsh(nodeId: string): stringnodeVmSsh('manoir');// "ubuntu@10.0.0.10"Node Services
Section titled “Node Services”isNodeServiceEnabled()
Section titled “isNodeServiceEnabled()”Check if a service is enabled on a specific node.
function isNodeServiceEnabled(nodeId: string, service: string): booleanisNodeServiceEnabled('chalet', 'home_assistant');// true
isNodeServiceEnabled('chalet', 'vm');// falsenodeService()
Section titled “nodeService()”Get a service field for a node — sugar for
nodeGet('<id>', 'services.<svc>.<field>'), fallback param and all.
function nodeService<T = string>(nodeId: string, service: string, field: string, fallback?: T): TnodeService('chalet', 'home_assistant', 'port');// 8123Dashboard Integration
Section titled “Dashboard Integration”The command center dashboard serves the instance config (with secrets excluded) at the /api/config endpoint:
import { getConfig } from '../lib/config.js';
app.get('/api/config', (_req, res) => { const cfg = getConfig(); // Serve everything except secrets const { secrets: _s, ...safe } = cfg; res.json(safe);});vite.config.ts reads its dev-server port (and the proxy targets) from the
config module rather than hardcoding them — so the dashboard listens where
instance.yaml says, with a sane default if the key is missing:
import { get } from './lib/config.js';
const dashboardPort = get('services.dashboard.port', 3001);// ...server: { port: dashboardPort };