Every WattSwarm node reads a startup_config.json file from its state directory when it starts. This file controls the node’s network mode, which peers it contacts on first boot, which gateway URLs it advertises, and which executor runtime handles tasks by default. Changes to this file take effect the next time the node starts — or immediately when you save them through the kernel console UI.
Where the file lives
The default state directory is .wattswarm/ in the current working directory. Inside Docker Compose the default container path is /var/lib/wattswarm/, backed by the named volume wattswarm_state_data.
<state-dir>/startup_config.json # startup configuration
<state-dir>/node_state.json # records node UP / DOWN status
<state-dir>/node_seed.hex # Ed25519 private key seed
You can override the state directory with --state-dir <path> on any wattswarm CLI command, or with the WATTSWARM_STATE_DIR environment variable in Docker Compose.
How to edit it
You have two options:
- Kernel console UI — open
http://127.0.0.1:7788/ and go to the Startup panel. Changes are validated and written to startup_config.json immediately.
- Direct JSON edit — open
<state-dir>/startup_config.json in any text editor and save. The node reads the file on next startup; it does not hot-reload.
Key fields
| Field | Type | Description |
|---|
network_mode | string | Node operating mode: "local", "lan", or "wan". Controls how the node bootstraps its network context on startup. |
bootstrap_contacts | string[] | Iroh contact strings for WAN or LAN mode, in <iroh-node-id>@<host:port> format. Cleared automatically in local mode. |
gateway_urls | string[] | Optional gateway HTTP URLs used for network sync. Trailing slashes are stripped on save. |
core_agent | object | Configuration for the default executor runtime. Contains mode, provider, base_url, model, and api_key sub-fields. |
The core_agent.base_url field is the URL registered as the core-agent executor in the local PostgreSQL executor_registry_local table whenever you save from the startup UI. Setting it to your runtime’s HTTP address (e.g. http://127.0.0.1:8787) is equivalent to running wattswarm executors add core-agent <url>.
Example: local mode
A minimal single-machine configuration. No P2P or bootstrap contacts are needed.
{
"network_mode": "local",
"bootstrap_contacts": [],
"gateway_urls": [],
"core_agent": {
"mode": "local_url",
"provider": "openai-compatible",
"base_url": "http://127.0.0.1:8787",
"model": "",
"api_key": ""
}
}
Example: WAN / network mode
A joining node that connects to an existing shared network. The bootstrap_contacts value comes from running wattswarm node export-contact on the genesis node.
{
"network_mode": "wan",
"bootstrap_contacts": [
"abc123nodeId@203.0.113.10:4001"
],
"gateway_urls": [
"https://gateway.example.com"
],
"core_agent": {
"mode": "remote_url",
"provider": "openai-compatible",
"base_url": "https://runtime.example.com",
"model": "",
"api_key": ""
}
}
Other state-directory files
node_state.json records whether the node is currently UP or DOWN. The wattswarm node up and wattswarm node down commands write to this file. You do not need to edit it manually.
node_seed.hex contains the Ed25519 private key seed that determines the node’s permanent identity (node_id and public key). The kernel derives the node’s node_id from this seed on every startup.
Never copy node_seed.hex from one node to another. Each node must have a unique seed. If two nodes start with the same seed, the registry bootstrap raises a clear conflict error because node_registry.node_id and node_registry.public_key must be unique across the network. Generate a fresh state directory for every new node.
How startup UI saves differ from full bootstrap sync
When you save fields in the Startup panel, the kernel writes network_mode, bootstrap_contacts, gateway_urls, and core_agent directly to startup_config.json. It does not write network topology or signed network parameters into PostgreSQL at save time. The full NetworkBootstrapBundle — including network_id, genesis_node_id, params_hash, and the genesis signature — is imported into PostgreSQL only during node startup, when the kernel fetches and verifies the bundle from a configured bootstrap peer. You cannot bypass that verification step through the UI.