Settings
The settings window, and where settings are stored
Settings
Reference for the settings window of an OctoMY™ app: its columns, marks, levels, buttons and keys. The second half covers where settings are stored and the few node keys that you edit in a file.
For step-by-step guides, see Settings how-to guides.
The settings window
| Fact | Value |
|---|---|
| Opens with | Ctrl+, in every app. Also the platform's Preferences key where it differs: Ctrl+Shift+, on KDE, Cmd+, on macOS. Also the settings button of the app, for example the gear button in Construct's toolbar |
| Title | Settings — ‹app› |
| Windows per app | One. Opening it again raises the window that is open |
| Modal | No. The app stays usable while the window is open |
| Apply | Each change applies at once. There is no Apply and no Cancel |
| Remembers | Its size, its position, the split between the two sides, and the columns, for each app |
The window has a left side and a right side:
| Part | Holds |
|---|---|
| Filter field | The filter text, a clear button, and the ≡ menu with Changed only and Show advanced |
| Category column | The categories of the app. With filter text, only categories with a match, each with its number of matches |
| Title row | The name of the category shown, and Write to in an app with more than one level |
| Table | One row per setting, in folding sections |
| Detail strip | The label, the full description, the range, the unit and the id of the selected setting, and why it does not apply when it does not. A Help link when the setting names a help page and the app can show it. The link opens that page in the help browser |
| Restart banner | Restart ‹app› to apply: and the names of the settings that wait for a restart. Hidden when none waits |
| Footer | The buttons of Footer buttons |
Filter
| Rule | Value |
|---|---|
| Match | Every word of the filter text occurs in the label, the description, the id, the category names or the keywords of a setting |
| Case | Ignored |
| Pattern | A plain substring. Not a regular expression |
| When | As you type. There is no Enter |
| Matches | Highlighted in the label |
| Advanced settings | Found only while Show advanced is checked |
| Changed only | Keeps only settings whose value differs from the default |
Columns
Right-click a header to show or hide a column. Reset columns in that menu returns to the default set. Drag a header edge to resize a column.
| Column | Shown by default | Shows |
|---|---|---|
| Name | Always | The label of the setting, with its category stripe |
| Value | Yes | The value as seen from the level chosen in Write to, in the input of its kind |
| Default | Yes | The declared default |
| Reset and revert buttons | Yes | ↺ when the value differs from the default. The revert button when the chosen level sets the value |
| Source | When the app has more than one writable level | The level the value comes from, or Default |
| Effective | No | The value the app uses now, through every level |
| Range | No | The lowest and highest value, or the number of choices |
| Unit | No | The unit of a number |
| Description | No | The first sentence of the description |
| Id | No | The id of the setting, as OPAL tasks and settings files name it |
Inputs
| Kind | Input |
|---|---|
| Number | A drag field. Drag to change, click to type |
| Yes or no | A toggle that reads Enabled or Disabled |
| List | A drop-down list |
| Color | A swatch that opens the color picker. The settings file keeps the color as text: #rrggbb, or #aarrggbb for a color that is not opaque |
| Text, file, folder | A text field, with a browse button for a file or a folder |
| Text with suggestions | A text field with a drop-down list of known values. You can also type a value that is not in the list |
| Key sequence | A key recorder |
| Action | A button that does something at once, for example Regenerate all thumbnails |
| Status | Read-only text |
The mouse wheel scrolls the table. It changes a value only in the cell that is being edited.
Marks
| State | Mark | Second sign |
|---|---|---|
| Changed from default | Bold name, and a dot before it | The Default column. The ↺ button |
| Set at a lower level | The value dimmed | The Source column names the level |
| Set at the chosen level | The value at full strength, and the revert button | The Source column names the chosen level |
| Does not apply now | The whole row dimmed. It stays editable | The reason in the detail strip |
| Invalid stored value | A border in the danger color, and a warning icon | The reason in the detail strip |
| Needs a restart | The name in the warning color | The restart banner names it |
| Category | A colored stripe at the left of the name | The category name in the left column and in the section heading |
Levels
An app can keep a setting at more than one level, in priority order. A value at a higher level overrides the value at a lower level. An app with one level shows no Write to and no Source column.
| Element | Behavior |
|---|---|
| Write to | One segment per level you can write. A change, a reset, an import and an undo act at the chosen level |
| A value set at the chosen level | Full strength, with the revert button |
| A value not set at the chosen level | Dimmed. It comes from a lower level, which Source names |
| A setting the chosen level cannot hold | Shown read-only. Choose a level that holds it |
| Reset | Writes the declared default at the chosen level |
| Revert | Removes the value at the chosen level, so the lower level shows through |
The levels of Construct are New scenes, Scene and Camera: ‹name›. See Where Construct settings live.
Footer buttons
| Button | Does |
|---|---|
| Reset section | Resets every setting in the section of the selected row, or in the category shown. Asks first, with the number of settings |
| Reset all | Resets every setting of the app at the chosen level. Asks first, with the number of settings |
| Undo | Takes back the last step in the history of the chosen level |
| Redo | Takes back the last undo |
| Import… | Reads a settings file and writes its values at the chosen level, as one step |
| Export… | Writes the values set at the chosen level to a settings file |
A step is one edit, one drag, one reset, one Reset all or one import. A change made by an OPAL task of the config family is a step too. The file format is in Move settings between machines.
Keyboard
| Key | Where | Does |
|---|---|---|
| Ctrl+, | In the app | Opens the settings window. Shortcut id global.settings |
| Platform Preferences key | In the app | The same, where it differs from Ctrl+,. Shortcut id global.settings-platform |
| Any letter | In the window, outside an editor | Moves the focus to the filter field and types the letter |
| Ctrl+F | In the window | Moves the focus to the filter field |
| Down | In the filter field | Moves the focus to the first match |
| Esc | In the filter field | Clears the filter. With an empty filter, closes the window |
| Up, Down | In the table | Moves between rows |
| Enter | On a row | Opens the editor of the value |
| Space | On a toggle or an action | Switches the toggle, or calls the action |
| Undo, Redo keys | In the window | Undo and redo. Ctrl+Z, then Ctrl+Shift+Z on Linux and Ctrl+Y on Windows |
Where settings are stored
OctoMY™ keeps settings through a Settings class
over Qt's QSettings, in one of two modes:
| Mode | When | Storage |
|---|---|---|
| Platform default | A normal launch | The platform's native store: an INI file on Linux, the registry on Windows, a property list on macOS |
| File | A launch with --base-dir, for example a node that a constellation starts |
settings.ini in the personality directory |
The file mode keeps each personality apart: its settings live inside its own directory and go with it when the personality is nuked. For the folders that an app uses on each platform, see Where your data lives.
A personality directory holds these files:
| File | Holds |
|---|---|
settings.ini |
Settings |
keystore.json |
The key store |
addressbook.json |
The address book |
agent_config.json |
The configuration of an Agent |
logs/ |
Logs |
Node::nuke() removes every file in the directory except
personality_manifest.json.
In an INI file, a key group/name sits under [group] as name. A deeper key
keeps its rest with backslashes, so batch/remote/forwarded-types is stored as:
[batch]
remote\forwarded-types=construct/thumbnail_update
There is no other channel. OctoMY™ reads no environment variable for a setting: a value comes from the settings window, a settings file, the node configuration or a command-line option.
Node keys you edit in a file
Most settings are in the settings window, which shows the description of each one. The keys below are the exception: you set them in the settings file before the node starts, or another surface writes them.
| Key | Type | Default | Description |
|---|---|---|---|
batch/remote/forwarded-types |
string | "" | Job types this node sends to the executors of other nodes, and takes from them, as a comma list. Empty sends nothing away. Read at start |
fleet/config |
JSON | — | The provider, region, OS image, coordinator, executor image and SSH keys of the fleet. Written by Setup → Fleet settings on a HUB |
fleet/provider-token |
string | — | The API token of the provider, sealed to this node. Never readable as plain text |
fleet/record |
JSON | — | Every machine the fleet bought, its spend ledger and its spend limits |
See Fleet for the configuration the fleet keys hold.
Settings API
Code reads and writes settings through Settings (app/Settings.hpp).
#include "app/Settings.hpp"
// From a Node or an Activity
Settings *settings = node()->settings().data();
QString name = settings->getCustomSetting("network/name", "default");
settings->setCustomSetting("network/name", "MyRobot");
bool enabled = settings->getCustomSettingBool("discovery/enabled", true);
int port = settings->getCustomSettingInt("network/localPort", 8124);
double rate = settings->getCustomSettingDouble("sensor/updateRate", 50.0);
qint64 seen = settings->getCustomSettingLong("session/lastSeen", 0);
QByteArray state = settings->getCustomSettingByteArray("splitter/state");
QRect geometry = settings->getCustomSettingRect("window/geometry", QRect(100, 100, 800, 600));
if (settings->hasCustomSetting("pairing/skipped")) { /* ... */ }
settings->sync(); // Write now. Writes are normally batched
settings->resetConfiguration(); // Clear every setting
Most setters have a …Durable form that writes to disk at once, past the
batching. A file-based Settings takes the path of its INI file:
Settings platformDefault("group", "OctoMY Agent", "1.0");
Settings fileBased("group", "OctoMY Agent", "1.0", "/path/to/personality/settings.ini");
AppContext makes the file-based form when the app starts with --base-dir.
Node settings in the settings window
Hub, Agent and Remote show the settings of the node in one settings window. Open it in one of these ways:
- Push Settings in the setup menu of the node.
- Push Ctrl+,. Where the platform has its own Preferences key, that key also opens the window, for example Ctrl+Shift+, on KDE.
The window title is "Settings — Hub", "Settings — Agent" or "Settings — Remote". On Android the settings open as a page of the app, not as a window.
Each row is kept in the app::Settings of the node, under the key in the
tables below. The keys did not change when the window replaced the
Preferences page, so a node keeps its values. Each value is kept for each node:
two nodes on one machine keep their own values.
The OPAL tasks config.get, config.set and config.list reach the same
rows. Use the schema id in the first column of each table.
Node schema (node)
| Row | Key | Type | Default | Description |
|---|---|---|---|---|
appearance.bodyFontSize |
defaultBodyFontSize |
int, 6 to 36 pt | 10 | The point size of all body text. A change applies immediately |
prompts.openManager |
— | action | — | Opens the LLM prompt manager. Remote has no prompt manager, so the row is dim there |
banter.microphone |
banter/inputDeviceId |
choice | system default | The microphone for acoustic discovery and comms. The choices are the audio inputs of the machine |
banter.microphoneName |
banter/inputDevice |
text, read-only | empty | The name of the microphone. It changes with the microphone |
banter.speaker |
banter/outputDeviceId |
choice | system default | The speaker for acoustic discovery and comms |
banter.speakerName |
banter/outputDevice |
text, read-only | empty | The name of the speaker. It changes with the speaker |
banter.outputLevel |
banter/outputVolume |
number, 0 to 1 | 1 | The loudness of the acoustic transmission of this node. A change applies to the running comms immediately |
banter.discoveryCodec |
banter/discoveryCodec |
choice | OFDM |
The acoustic codec for discovery: OFDM, MCFSK, FSK, CSS or DPSK |
log.handshake |
logging/handshake |
choice | Off | Log verbosity: Off, Summary or Full |
log.scheduling |
logging/scheduling |
choice | Off | Log verbosity |
log.session |
logging/session |
choice | Off | Log verbosity |
log.discovery |
logging/discovery |
choice | Off | Log verbosity |
log.pairing |
logging/pairing |
choice | Off | Log verbosity |
log.data |
logging/data |
choice | Off | Log verbosity |
log.blob |
logging/blob |
choice | Off | Log verbosity |
The microphone, the speaker and the output level are also on the Banter screen of the comms channels. That screen writes the same rows, so a change on one shows on the other.
A log row applies immediately. When the node opens its main window, it applies the stored
levels. A category that the --log option raised for this run keeps the level
of the option.
Swarm schema (swarm, Hub only)
| Row | Key | Type | Default | Description |
|---|---|---|---|---|
swarm.enabled |
swarm/enabled |
bool | true | Take part in the swarm. A change attaches or detaches the swarm service immediately |
swarm.hostShards |
swarm/host-shards |
bool | true | Keep pieces of the data of other nodes on this node |
swarm.limit.contributionBudget |
swarm/limit/contribution-budget-gb |
int, 0 to 4096 GiB | 0 | The most disk space for other nodes. 0 is no limit |
swarm.limit.replicationFactor |
swarm/limit/replication-factor |
int, 1 to 16 | 3 | How many copies of new data the swarm keeps |
swarm.limit.bandwidthIn |
swarm/limit/bandwidth-in-mbps |
int, 0 to 1024 MiB/s | 0 | The most swarm traffic in. 0 is no limit |
swarm.limit.bandwidthOut |
swarm/limit/bandwidth-out-mbps |
int, 0 to 1024 MiB/s | 0 | The most swarm traffic out. 0 is no limit |
swarm.limit.maxStreamsPerPeer |
swarm/limit/max-streams-per-peer |
int, 0 to 128 | 0 | The most streams that one peer can open at the same time. 0 is no limit |
Trove schema (trove, Hub only)
The trove settings have their own window, "Settings — Trove". The Settings button of the projects wall and of a project board opens it. The trove schema has two levels:
- All projects (
app): the key below, in the settings of the node. - Project (
project): an override for one project, kept introve/projects.json. A row that a project does not set uses the value of all projects. The board of a project opens the window with "Write to" set to that project.
| Row | Key | Type | Default | Levels |
|---|---|---|---|---|
unattendedEnabled |
trove/unattendedEnabled |
bool | false | all projects, project |
idleTtlHours |
trove/idleTtlHours |
int, hours | 168 | all projects, project |
reaperCadenceMinutes |
trove/reaperCadenceMinutes |
int, minutes | 60 | all projects, project |
spawnStaggerSeconds |
trove/spawnStaggerSeconds |
int, 0 to 120 s | 5 | all projects only |
specPath |
trove/specPath |
text | content/doc/internal/specs/ |
all projects, project |
planPath |
trove/planPath |
text | content/doc/internal/plans/ |
all projects, project |
checkoutRoot |
trove/checkoutRoot |
folder | empty | all projects only. Needs a restart |
specAuditModel |
trove/specAuditModel |
text with suggestions | claude-haiku-4-5 |
all projects, project |
specAuditTransport |
trove/specAuditTransport |
choice | ClaudeSpawn |
all projects, project |
implModel |
trove/implModel |
text with suggestions | claude-opus-4-8 |
all projects, project |
implTransport |
trove/implTransport |
choice | ClaudeSpawn |
all projects, project |
RTS schema (rts, Hub only)
| Row | Key | Type | Default | Description |
|---|---|---|---|---|
rts.colors.fill |
rts/colors/fill |
color | the body color of the node's identicon | The fill of your units |
rts.colors.outline |
rts/colors/outline |
color | the limb color of the node's identicon | The outline of your units |
The RTS settings have their own window, "Settings — RTS". To open it, push Settings in the RTS menu, in the match lobby, or in the match panel of the game. Ctrl+, opens it too while the RTS menu, the match browser, the lobby or the game has the keyboard. Everywhere else in the Hub, Ctrl+, opens the settings of the Hub.
The two swatches of the match lobby write these rows. Factory reset in the lobby removes both keys, so the colors follow the identity of the node again.