Configuration File Guide

Explains Saba-chan's data folder, the config.json settings file, instance folders, and token files based on what the code actually does.

Configuration File Guide

Saba-chan's settings and state live under the data folder %APPDATA%\saba-chan (= C:\Users\<your-name>\AppData\Roaming\saba-chan). This document summarizes how the actual code uses the files inside it, and distinguishes between files you can safely edit by hand and files you should not touch.

The daemon (saba-core) does all the work; the GUI and CLI only call the daemon's local HTTP API. That's why it's safest to change settings from the GUI or CLI: the daemon checks the format when it saves them.


1. Folder Structure

%APPDATA%\saba-chan\
├── config.json                ← All user settings (by namespace)
├── config.json.bak            ← Last good copy (for automatic recovery)
├── .ipc_token                 ← Daemon ↔ GUI/CLI auth token (regenerated every time the daemon starts)
├── .node_token                ← Discord (cloud relay) connection token. Saved by the daemon at pairing
├── instances\                 ← Server instances
│   ├── order.json             ← List order
│   └── <id>\
│       ├── instance.json      ← Instance info
│       ├── settings.json      ← Per-module game setting values
│       ├── logs\              ← Server console logs
│       ├── backups\           ← Backups
│       └── server\            ← Default install location (game server files)
├── modules\                   ← Installed game modules
├── extensions\                ← Installed extensions
├── logs\                      ← GUI logs (saba-chan-<timestamp>.log)
├── audit.log                  ← Record of server start/stop/commands (secrets masked)
├── updates\                   ← Update staging area
└── installed-manifest.json    ← Installed component versions
  • The portable Python runtime (python-standalone\, python-env\) is created in the install folder if it is writable, otherwise in this data folder.
  • There are also files the daemon manages on its own (daemon.lock, scan-verdicts.json, sandbox-temp\, etc.). Don't touch them.
  • You can override the data root itself with the SABA_DATA_DIR environment variable, but it is generally not recommended.

2. config.json — The File That Holds Every Setting

User settings go into one file, config.json, grouped by namespace (top-level key).

NamespaceContentsWhere it's changed
guiGUI behavior, theme, language, daemon portGUI settings
relayDiscord integration (prefix, aliases, per-guild settings)GUI Discord page
updatesUpdate check interval, auto-downloadGUI settings
bootLast chosen boot mode (GUI / CLI / daemon only)Boot selector
extensionsEnabled extension list enabled, per-extension settings settingsGUI settings → Extensions
chatbotAI chatbot settingsGUI Discord page
sandboxConsent to run unverified components without isolationThe launch-blocked prompt, Settings → Advanced
cli, etc.Each client's own settingsThat client

Saving and automatic recovery

  • Saves are atomic (write to a temp file, then replace), and the last good copy right before the replacement is kept as config.json.bak.
  • If config.json is corrupted and can't be read, the daemon moves it aside as config.json.corrupt-<timestamp> and restores from .bak.
  • Unknown keys put into gui or relay are dropped when saving.

Migration of old settings files

Older versions stored settings in separate files (settings.json, bot-config.json, cli-settings.json, update-config.json, boot-config.json, extensions_state.json, extensionConfig.json). The current version moves them into config.json only once. The originals are left as they are, with a .migrated copy next to each. Once that copy exists the file is not migrated again, so editing an old file has no effect on the current settings.


3. gui — Shared GUI / Daemon Settings

When the daemon boots, if no SABA_IPC_PORT environment variable is set, it reads gui.ipcPort; if that's also missing, it falls back to the default 57474. The other keys are mostly read by the GUI.

KeyTypeDefaultDescription
ipcPortnumber57474Daemon HTTP API port (always opened on 127.0.0.1 only)
autoRefreshbooleantrueAutomatic GUI status refresh
refreshIntervalnumber (ms)2000GUI status polling interval. Lowering it too far raises CPU usage
consoleBufferSizenumber2000Number of lines the GUI console keeps
portConflictCheckbooleantrueCheck for port conflicts before starting a server
languagestringinferred from OSLanguage (ko, en, ja, de, es, fr, pt-BR, ru, zh-CN, zh-TW). Also used for module and Discord replies
themestringnone (GUI uses auto)"dark" / "light" / "auto"

There are also appearance keys such as colors, font scale, and window size; whatever you change in the GUI settings is saved as-is.


4. relay — Discord Integration

The Discord bot runs only on the cloud relay, so there is no bot process or bot token on your PC. This namespace stores the prefix, aliases, and per-guild settings you edit in the GUI; after pairing, the daemon syncs them to the relay through its heartbeat.

KeyTypeDefaultDescription
prefixstring"!saba"Chat command prefix. A space must follow the prefix for the message to count as a command
moduleAliasesobject{}Module aliases. Example: { "minecraft": "mc, 마크" }
commandAliasesobject{}Command aliases
instanceAliasesobject{}Instance ID → list of aliases. Used to pick one when you run several servers of the same game
nodeSettingsobject{}Per-guild settings (allowed instances, command permissions, Discord language and music settings, etc.)
cloudobjectrelayUrl, hostId. Filled in at pairing

Permission and Discord settings inside nodeSettings change only through their dedicated screens (APIs); saving the whole bot config does not overwrite them. The old musicEnabled, musicChannelId, and token keys are no longer used.

Command Syntax

!saba <server name or alias> <command> [arguments…]
  • !saba minecraft start
  • !saba mc stop (alias)
  • !saba palworld status
  • !saba list — server list, !saba help — help

Every server has the default commands start, stop, and status; other commands are defined by the module. Extra features such as music are provided by the bot on the relay-server side.


5. instances\ — Server Instances

Each server you create in the GUI is stored as its own instances\<id>\ folder. <id> is a UUID.

  • instance.json — Name, module, executable/working folder, port, REST connection info, scheduled tasks, extension data (extension_data), etc.
  • settings.json — Game setting values the module declares (e.g., max players, difficulty).
  • order.json — Order of the GUI list.
// instances\<id>\instance.json (excerpt)
{
  "id": "3f6c…",
  "name": "My Minecraft Server",
  "module_name": "minecraft",
  "working_dir": null,
  "port": 25565,
  "extension_data": {}
}
  • RCON is not used. Game commands are sent to the server console (stdin), and Palworld uses its REST API. Leftover RCON keys in old files are removed when they are loaded.
  • extension_data is reserved storage for extensions. For example, for modules installed through SteamCMD, the install method and app info go here.
  • When you save server settings (GUI server settings, PATCH /api/instance/:id), keys that are neither common instance fields nor settings the module declares are rejected with an unknown_setting error.
  • Deleting an instance deletes the whole instances\<id>\ folder, including the game server files in the default install location (server\) and backups\.

Only hand-edit these files while the daemon is not running. Editing them while it runs diverges from the daemon's in-memory state, and the next save overwrites your edit.


6. Token Files (.ipc_token / .node_token)

FileFormatWhen createdUsed by
.ipc_tokenUUID v4 (single line)Regenerated every time the daemon startsGUI / CLI / modules and extensions (local API calls)
.node_tokensbn_<hostId>.<secret>Saved by the daemon when Discord pairing completesThe daemon's relay connection

IPC token

The daemon API listens only on 127.0.0.1, and every request except /health needs the X-Saba-Token header.

GET /api/servers HTTP/1.1
Host: 127.0.0.1:57474
X-Saba-Token: <contents of the .ipc_token file>
  • The token changes whenever the daemon restarts. The GUI and CLI re-read the token file when authentication fails, so you don't need to do anything.
  • The token file location can be changed with SABA_TOKEN_PATH.

Node token

.node_token is the secret that connects this PC to the Discord bot (cloud relay). The daemon sends it to the relay over HTTPS to authenticate. Never show it to anyone; if you suspect it leaked, pair again from the GUI. Re-pairing invalidates the old token.


7. Extension and Isolation Settings (extensions / sandbox)

  • extensions.enabled — List of enabled extension IDs.
  • extensions.settings — Per-extension setting values { "<id>": { "<key>": value } }. Changed through the daemon API PUT /api/extensions/:id/config.
  • sandbox.unisolated — Consent to run, without isolation, a component whose isolated environment couldn't be prepared. It is stored as a fingerprint of the component's files and is asked again if any file changes. You can withdraw it under Settings → Advanced → "Run without isolation" in the GUI, or with saba-chan-cli sandbox revoke <component>.

8. Key Environment Variables

VariableTargetDescription
SABA_IPC_PORTDaemon / CLIOverrides gui.ipcPort
SABA_DATA_DIRDaemonRe-points the data root itself (advanced)
SABA_TOKEN_PATHDaemonIPC token file path
SABA_MODULES_PATH / SABA_EXTENSIONS_DIR / SABA_INSTANCES_PATHDaemonRe-point the module, extension, and instance folders
RUST_LOGDaemonLog filter (default info)
SABA_IPC_URLModule/extension subprocessesDaemon API address. Injected by the daemon into child processes
SABA_LANGModule/extension subprocessesCurrent language (gui.language)
PYTHONPATHModule/extension subprocessesModule and extension paths combined and injected
SABA_ENABLED_EXTENSIONSModule/extension subprocessesList of active extension IDs (,-separated)
PYTHONIOENCODINGModule/extension subprocessesAlways utf-8
PYTHONUNBUFFEREDModule/extension subprocesses1 — flush stdout immediately

If you suspect you've broken something, stop the daemon first, then delete the file in question and launch again; most files are regenerated with defaults. Deleting config.json resets every setting, including your Discord integration settings, so try restoring config.json.bak first. Don't delete the instances\ folder: your server list and any game files installed in the default location go with it.