Skip to main content
Almost every setting has two names for one thing. There is a slash command you use in a session, and there is a variable name. They are the same setting because config.json is keyed on the variable names themselves, so /trajectory off and export SERI_TRAJECTORY_ENABLED=false write and read the same key. Use the command. The variable is for scripting a machine you are not sitting at.

Which wins

The environment, then ~/.seri/config.json, then the built-in default. A variable set to the empty string counts as unset and falls through to config.json rather than winning as a valid-looking blank.
A variable exported in your shell beats the slash command, including afterwards. Setting SERI_TRAJECTORY_ENABLED and then running /trajectory on writes config.json and changes nothing the next time you start, because the variable still wins. seri says so when you do it rather than letting the setting look changed when it is not. If a command appears to do nothing, check your environment first.
Every true/false setting is on unless the value is exactly false, except the two opt-in rails below that require the exact string true. A typo cannot silently disable a feature that uses the first rule, and it cannot silently arm either opt-in.

Provider credentials

A hosted login already pays for OpenRouter. /setup lists that coverage as a seri subscription row (plan name from the last /account-status fetch). OPENROUTER_API_KEY is your own key — present and unused while the seri plan is connected, used after you ignore the plan.

Model

A /model pick persists both keys once a turn has actually succeeded on it, so setting them by hand is the scripted equivalent of picking one. Temperature and seed are sent only on paths that accept them. A Grok or ChatGPT subscription omits both, because those hosts reject the fields. Anthropic and a metered OpenAI key omit seed. An unset value is recorded as unset rather than invented. Temperature and seed apply to the next turn. A pin is OpenRouter-only: it sets that upstream with no fallback, and it drops the session id OpenRouter uses for sticky prompt-cache routing. A pin change applies on the next run. A trajectory recording’s header lists the values that were in force, including whether a knob was unsupported on that path, plus hashes of the prompt files that were loaded. Changing one of those files changes its hash.

Subagent roles

<ROLE> is the uppercased role name: SERI_ROLE_EXPLORE_MODEL, SERI_ROLE_PLAN_PROVIDER. These supply a default for when a dispatch does not name a pair, which is how a script, and the archivist, get a model of their own. Set both or neither. They are one pin, not two settings. _MODEL on its own is inert, and a _PROVIDER that is not one of the six provider ids drops the pin rather than half-applying it. The role then falls back to the session model.

Checking code after a write

Both take effect on the next run rather than mid-session.

Memory

Trajectories

A retention value that is not a positive whole number falls back to 30 rather than failing. Retention covers recordings in seri.db as well as .jsonl files left by an older release. A session in the database ages out on its most recent record and a legacy file on its modification time. The session being recorded is never pruned.

Terminal background

Unset paints the paper ground, #141413, so the same build looks identical on every machine. That fill breaks terminal transparency and background blur, because seri is now filling every cell itself. terminal turns the fill off, and so does any other value that is not a six-digit hex color. A mistyped color leaves the background alone rather than failing, because this is read while the screen is still being built and a warning would have nowhere to print. The renderer is built once at launch, so a change applies on the next run. See Working in the session.

Profile

The flag wins over the variable. /profile new <name> creates a profile from inside a session but does not switch the running one.

Permissions and sandbox

SERI_ALLOW_UNSANDBOXED_COMMANDS follows the usual on-unless-false rule. The other two are opt-in: configBoolean is not used, because that helper is on unless the value is "false", so a typo would arm the exception. Path deny rules and autoModeOnBlock live in permissions.yaml, not here. See Permissions.

Install and update

SERI_VERSION pins which GitHub Release the install scripts and seri update fetch. Unset means the latest stable release. It is not stored in config.json and has no slash command. See Installation and Launching seri.

Settings with no variable

/mode and /max-turns last for the session and are never written to config.json. --dangerously-skip-permissions, --permission-prompts, and --max-turns are launch flags with no variable either. See Launching seri.

What this page leaves out

seri reads a handful of other SERI_* variables that point it at a different gateway, identity service or model-catalog endpoint, or that skip a check during testing. They are deployment and test escape hatches rather than settings, they have no stable contract, and setting one by accident is a worse outcome than not knowing it exists.