Rio
docs/preferences.mdRaw Markdown · GitHub ↗

Preferences

Every setting rio keeps, what it does, and which file on disk holds it.

Settings ▸ Preferences… gathers them in one window. The ones you change often are also on the View and Settings menus, as a second door to the same switch.

An extension's own settings are not here. An agent provider's API key, its server and its model belong to that extension. They are set in a window of its own, listed by name in the Extensions menu. What rio keeps about extensions is here, in Preferences ▸ Extensions: update checking, your repository list, and the signing keys you trust.

What is saved where

KindHoldsKept
PreferencesTheme, line wrap, wrapped-line indent, line numbers, dock side, which panes are shown, the editor font.prefs.json, on the machine running the window. Global: they load at every start, with or without a project.
WorkspaceThe files you had open in a project, and which tab was active.With the core, outside your source tree, keyed by project root. It resumes only when a project is open.

Neither ever holds your API key. That lives on its own, below.

Two settings belong to the core rather than to the window: how its https connections are checked, and whether it keeps recovery copies of your unsaved changes. Each has a file of its own on the core's host, and every window attached to that core shares it. Both are described below.

Changing a setting

The last value is the default, saved the moment you change it. There is no "make this the default" step and no "save settings" button.

From the window or the menus — the View menu (Wrap Lines, Indent Wrapped Lines, Line Numbers, Theme…, Dock Left/Right, the pane toggles), the Settings menu (Column Editing, Editing Mode, the agent's mode), and the shortcuts (Ctrl+Shift+W wrap, Ctrl+Shift+A agent pane, Ctrl+L line numbers). Each rewrites prefs.json at once.

By hand — edit prefs.json. It is plain JSON, parsed and never executed:

{"theme":"solarized-dark","wrap":"1","wrap_indent":"1","line_numbers":"1","column_edit":"0","editmode":"windows","layout":{ }}
KeyMeans
wrap"1" word-wrap on, "0" off
wrap_indent"1" aligns a wrapped line's continuation rows under its own indentation (visible only while wrap is on), "0" leaves them at the left margin
line_numbers"1"/"0" shows or hides the gutter
relative_line_numbers"1" numbers the gutter relative to the caret (vi-style), "0" counts from the top of the file
highlight_current_line"1" tints the line the caret sits on, "0" leaves it plain
column_edit"1" enables Notepad++-style column editing, "0" off
show_hidden"1" lists dot-files in the Files pane, "0" hides them, like ls
tab_layoutscroll — one row of tabs with ◂ ▸ arrows — or multi, wrapping them onto as many rows as they need
themea name from themes/, or default
font_familyan editor font overriding the theme's; empty means "use the theme's"
font_sizethe editor font size in points, 5–72; out-of-range values are ignored
editmodewindows, vi or emacs — the last two only work once installed as extensions
projectthe folder that was open at the last start, reopened at the next one (local cores only)
check_updates"1" looks for newer versions of your installed extensions shortly after start-up, "0" (the default) never touches the network unasked
allow_unverified_repos"1" uses a signed extension repository even where the core cannot check its signature, "0" (the default) refuses it — see below
agent_selection_menu"1" (the default) offers Change with Agent… in the editor's right-click menu while a provider other than Echo is selected, "0" never shows it — see the agent
layouta nested object holding the whole dock arrangement: which panes sit left, right or bottom, which are hidden, and their sizes

layout is awkward to write by hand. Toggle it from the View menu and let rio record it.

The file appears the first time you change a setting, or when you quit. You may create it by hand before the first start. Unknown or malformed keys are ignored, and a corrupt file is skipped rather than fatal.

Note. prefs.json is both your defaults and rio's saved state; there is no separate hand-authored settings file. Changing a setting for one session therefore changes your default too.

Editing modes beyond Windows

The core ships the Windows editing mode only. emacs and vi install as extensions:

  • add a repository that carries them with the Repositories… button in Extensions ▸ Browse…, then install from that window; or
  • drop the module by hand into ~/.config/rio/modes/. A mode extension installs there, so a hand-dropped file is exactly the same thing.

Once installed, the mode appears in Settings ▸ Editing Mode. If a saved editmode names a mode that is no longer installed, rio falls back to Windows.

Your repository list, by hand

The URLs you add with the Repositories… button are an apt-style sources file you can edit yourself: sources.list, one base URL per line, http:// or https://, with # comments and blank lines allowed. The dialog reads and writes that exact format, and a hand edit is picked up the next time the Extensions window scans.

As with a Debian source, https is an option rather than an obligation; plain http is just as supported. An https repository needs tcltls on the core's host — 1.8 or newer, or an older one with the switch under Network turned on (see INSTALL.md). One whose certificate does not verify can be reviewed and accepted. A repository of either scheme may be signed, which gives a plain-http one the integrity a certificate would otherwise provide.

On a first start rio pre-fills this file with the project's own repository, http://rio.skylm.org/extensions, so the Extensions window is not empty out of the box. Remove it in Repositories…, or delete the line, and it stays gone: the pre-fill only happens when the file does not yet exist. No file means no repositories.

What you have installed, and from where, is tracked separately in extensions.json. rio writes it; each entry records the source URL and version a kind/name came from, plus the fingerprint that signed it where the repository was signed. The scheme is not part of that identity, so moving a repository from http://host/rio to https://host/rio keeps the updates for everything you installed from it.

Checking for extension updates

Extension versions follow semver, so rio can tell you when a repository offers something newer than what you have. It compares on every scan and shows the answer on the row: [1.1.0 → 1.2.0]. Opening Extensions ▸ Browse… rescans, as does its ⟳ button.

ButtonDoes
UpdateReplaces that one extension.
Update AllTakes every pending update, after one confirmation listing them.

Nothing is ever installed on its own.

An update only comes from the repository that extension was installed from. There is no central index, so nobody owns a name: a same-named extension on another host is a different thing you may switch to by hand, not a newer version of yours. Where you know better, tick Also accept updates from other repositories on that extension in the Extensions window.

Preferences ▸ Extensions ▸ Check for extension updates at start-up (the check_updates key) makes rio look once, shortly after it starts, and tell you what it found. It is off by default. A version that does not follow semver, such as a date stamp, is shown but never compared.

Using a repository rio can't check

A repository can publish a signing key, and rio then checks every file it fetches from it against that repository's signature — see extensions. The checking is done by running ssh-keygen on the core's host, which needs OpenSSH 8.0 or newer there, and a core that knows about signatures at all. Where either is missing, a repository whose key you have confirmed is refused rather than used unchecked.

Preferences ▸ Extensions ▸ "Use repositories rio can't check" (the allow_unverified_repos key) lets those through. It is off by default. With it on, such a repository lists and installs marked unverified, never signed, and the install confirmation says so.

It excuses nothing else, and confirms no key for you: a signature that does not verify, a key that changed and a file whose hash does not match are all still refused. The switch lives with the window, in prefs.json, because it governs nothing but the Extensions window.

The signing keys rio trusts

Preferences ▸ Extensions ▸ Repository signing keys… lists every signing key you have confirmed: one row per repository, with the key's fingerprint, the date you confirmed it, and the URL without its scheme, since http:// and https:// are the same publisher. Where the core's host has no ssh-keygen there is no fingerprint to show, so the row names the key itself.

rio never adds a row on its own. A repository that signs with a key you have not confirmed is refused until you do, from its row in the Extensions window (see extensions).

Forget selected drops one, and that is a refusal rather than a tidy-up: the next scan of that repository asks you to confirm whatever key it publishes then, and nothing from it is listed or installed until you answer. To stop using a repository altogether, remove it in Repositories….

rio's own repository is listed (built in) as long as it is still in your sources. That is the one key rio ships with, and the one you were never asked about. Forget selected there withdraws it: the row stays, marked (built in, withdrawn), and rio asks about its own repository like any other until you confirm a key for it. Selecting either form of that row explains it in the line under the list. A window with no rows means you have confirmed no keys yet, and says so.

The list is the file repository-keys.conf, beside your sources.list. Deleting a section there is the same as forgetting a key here, and a section with no key line is a withdrawal.

Recovery files for unsaved changes

rio keeps a separate copy of every changed file, and never writes the file you are editing without a save. The editor describes what that means and how you get the changes back. This is where the setting lives.

Preferences ▸ Editor ▸ Keep recovery files for unsaved changes turns it on and off. It is on by default, and this is the only place to change it.

The setting belongs to the core, because the copies land on the core's disk. Every window attached to a core shares it, and over a remote core it is the server's. It is kept in autosave.conf in the core's config directory, in rio's usual key = value format, parsed and never executed:

autosave    = on
interval_ms = 30000
  • autosave — any plain way of writing no (off, 0, no, false, in any case) stops new copies. Anything else leaves it on: another value, a typo, a malformed file, no file at all.
  • interval_ms — how often a changed file is copied, in milliseconds. The default is 30000; below 1000 rio uses 1000. Nothing in the window sets this, and turning the setting off and on again leaves a hand-tuned interval alone.

autosave failing safe means on, which is the opposite of how tls.conf reads a value it does not understand: there the safe side is refusing a connection, here it is protecting work you have not saved.

Both keys are re-read before every copy, so a hand edit counts without restarting the core. The copies live under autosave/ in the core's data directory, listed below.

Network: how the core checks https

Preferences ▸ Network holds the settings for every https connection the core makes: to a hosted agent provider and to an https extension repository alike. They are stored on the core's host, and every window attached to that core shares them.

Allow https without host-name checks (tcltls older than 1.8) — off by default. A tcltls older than 1.8 checks that a certificate comes from a trusted authority but never that it was issued for the server: any valid certificate for any host would pass. On such a core the agent and https repositories refuse https until you tick this. Tick it only on a network you trust, where tcltls cannot be upgraded. It changes nothing on tcltls 1.8 or newer, and plain http:// is never affected. The line under it says which case you are in.

Accepted certificates… lists the certificates you accepted although they did not verify, with their host and port, and removes them. See extensions.

The switch is kept in tls.conf in the core's config directory, as unchecked_hostnames = allow. Only that line, exactly, allows: a missing file, any other value, a line inside a [section] and a malformed file all mean refuse. The file is read on every connection, so a hand edit counts without restarting the core.

Where everything lives

There is no single ~/.riorc. rio follows the XDG base-directory layout and keeps one file per concern, under two roots: config, your settings, safe to hand-edit and to keep in version control; and data, rio's own bookkeeping, machine-written.

Config — $XDG_CONFIG_HOME/rio/ (default ~/.config/rio/):

PathHoldsEdit by hand?
prefs.jsonwindow preferences — every key is listed aboveyes — plain JSON; layout best left to the View menu
keys.jsonkeyboard-shortcut overrides (defaults for everything you don't list)yes — see keyboard shortcuts
sources.listextension-repository URLs, one http:// or https:// base per lineyes (above)
repository-keys.confthe signing key you confirmed for each repository, one section eachyes — delete a section to forget that key
certificates.confcertificates you accepted although they did not verify, one section per host:port — on the core's hostyes — delete a section to take one back
themes/user theme files, read by the coredrop-in / installed
syntax/installed syntax highlighters (*.tcl)drop-in / installed
modes/installed editing modes — vi, emacs (*.tcl)drop-in / installed
agent/prompt.mdreplaces the shipped agent base prompt — an override, not a layeronly if you mean it
agent/plan.mdreplaces the shipped plan-mode prompt — an override, not a layeronly if you mean it
agent/system.mdyour system prompt: standing instructions added on top, for every project and provideryes — plain Markdown
agent/providers/<name>.mda per-provider prompt, applied only while that provider is liveyes — plain Markdown
agent/allow.listtrusted commands for all projects, one rule per lineyes — plain text
agent/providers/<name>.allow.listtrusted commands active only while that provider is liveyes — plain text
agent/providers/<name>.confwhat that provider remembers: the model and effort it was last set to, and whatever else it declares. For a provider that keeps profiles, only which profile is liveyes — key = value
agent/providers/<name>/<profile>.confone profile of such a provider: its own model, server, limits and key — see the agent. Per-profile files sit here too, such as the OpenAI-compatible provider's <profile>.extra.jsonyes — key = value
tls.confhow the core's https connections are checked — on the core's host (see above)yes — key = value
autosave.confwhether the core keeps recovery copies, and how often — on the core's host (see above)yes — key = value

Data — $XDG_DATA_HOME/rio/ (default ~/.local/share/rio/), written by rio:

PathHolds
sessions/per-project open files and active tab, keyed by project root
autosave/recovery copies of changed files, each under a mirror of its own path as #name# — see the editor
providers/installed agent providers — the extension kind that ships executable code, so it lives with the data rather than the hand-edited config
extensions.jsonwhat is installed, from which repository, at which version, and which key signed it
secrets/*.secretAPI keys, mode 0600 — never in prefs.json

Project-local, in a project's own tree:

PathHolds
.rio/agent.mdthe project prompt, layered on top of the system prompt
.rio/allow.listtrusted commands for this project only

Every one of these is optional: absent means "use the built-in default". Config files are plain text: JSON, Markdown, or one rule per line. They are parsed and never executed, and a malformed one is skipped with a note rather than being fatal.

The four agent/ prompt files and the three allow-lists have front doors in Preferences ▸ Agent (Agent Prompts… and Allowed commands…); editing them by hand and through the dialog are the same thing. The two overrides exist only if you ask for them: Agent Prompts… ▸ Make my own copy… writes rio's shipped text here as your file, and rio then reads yours. Delete it and rio's version comes back. See the agent.

Further reading