Every setting is a key in a config.toml (layers). Set one by hand or with orrery config set <dotted.key> <value>; orrery config explain <dotted.key> says where its value came from. A misspelt key in a checked table fails at load, naming the file, the line and the keys that exist.
Secrets are written "$VAR" (the file holds only the variable's name) or, in the user layer only, as the literal value.
#Top level
| Key | Meaning |
|---|
model | The model a turn runs, over the setup's own model. |
consent | once, always or never. See consent. |
driver · router | A loop driver and a delegation router an extension registered, by name. A name nothing registered fails at start. |
context | The context builder an extension registered, by name, in place of the harness's assembly (Context, compaction and memory). |
compactor | The compactor an extension registered, by name. Unset, compaction uses the summariser role. |
memory | The memory an extension registered, by name. Unset, no memory tools are offered. |
| Key | Meaning |
|---|
tools.selector | The selector an extension registered, which decides which tools are declared in the prompt and which only searchable (Which tools the model sees). Unset, every visible tool is declared. |
#[roles] and [agents.<name>]
| Key | Meaning |
|---|
roles.summariser | The agent that summarises history when a session compacts, by its [agents] name. |
agents.<name>.prompt | The agent's system prompt. For summariser and compactor it replaces the base prompt. |
agents.<name>.model | The model the agent runs on. |
agents.<name>.tools | The tools it may see. |
[agents.summariser]
prompt = "Summarise the conversation so the work can continue."
model = "claude-haiku-5-5"
[roles]
summariser = "summariser"
#[keys]
| Key | Meaning |
|---|
keys.<name> | Overrides a key an extension declares with [[provides.keys]] (Input, timers and questions). Esc, Ctrl+C, Ctrl+D, Enter and Tab are reserved. |
#[providers]
| Key | Meaning |
|---|
providers.default | The setup in use. |
providers.<name>.kind | The provider kind. Defaults to <name>. |
providers.<name>.baseUrl | The endpoint, when not the provider's own. |
providers.<name>.apiKey | The key, or "$VAR". |
providers.<name>.model | The model to use with it. |
providers.<name>.models | Extra model ids /model offers. |
providers.<name>.reasoning | off, low, medium or high. |
providers.<name>.oauthClientId | The OAuth client id, for a provider with a sign-in. |
providers.<name>.<setting> | Any setting the provider declares, such as Ollama's contextLength. |
#[profile.<name>] and [profiles]
| Key | Meaning |
|---|
profiles.default | The profile a session runs without --profile. |
profile.<name>.model | Its model. |
profile.<name>.extensions | Its extensions, MCP servers included as mcp.<name>. |
profile.<name>.skills | Its skills. |
profile.<name>.consent | Its consent mode. |
profile.<name>.env | Environment variables, as references. |
profile.<name>.permissions | Shorthands: read, write, net, spawn, creds = true / false. |
profile.<name>.budget | A [budget] table for this profile. |
#[permissions]
| Key | Meaning |
|---|
permissions.deny · ask · allow | Lists of rules, such as "write(./docs/**)". |
permissions.shell | allow, ask or deny for tool(builtin.bash). |
permissions.network | The same, for net(domain: *). |
permissions.commit · push · pr | The same, for tool(git.commit), tool(git.push), tool(git.pr). |
permissions.deny · ask · allow as "ui(<placement>)" | Where a surface may go: ui(pane.right), ui(band), or ui(*) for all. The placements are inline, footer, band, pane.left, pane.right, hidden; any other name fails at start. With no rule, a placement is allowed. Also written under [permissions."ext:<id>"]. |
#[budget]
Limits for one run of the main agent. Unset means no limit.
| Key | Meaning |
|---|
budget.maxTurns | Model passes. |
budget.maxUsd | Dollars. maxMicroUsd is the exact form. |
budget.maxTokens | Tokens. |
budget.wallClockMs | Wall clock. |
budget.toolTimeoutMs | One tool call's wall clock. 300000 (5 minutes) by default. |
#[limits]
Bounds on what extensions may do (decision 0077). Each has a default; a managed layer can only lower one. A value that is not a positive whole number fails at start and names its file and line.
| Key | Meaning |
|---|
limits.extensionRuns | Runs an extension starts with no person's input in between. 3 by default. |
limits.holdMs | How long an extension's hold may keep a run alive. 600000 (10 minutes) by default. |
limits.interceptorsPerPhase | Interceptors from processes on one phase. 8 by default. |
limits.interceptorMs.<phase> | One interceptor's answer, in milliseconds. tool.before 1000 · tool.after 2000 · context.build 2000 · memory.recall 2000 · provider.before 1000. |
limits.phaseMs.<phase> | All of a phase's interceptors together, in milliseconds. Three times interceptorMs.<phase> by default. |
limits.inFlight | Requests one extension has in flight. 16 by default. |
limits.modelCalls | Model calls one extension makes in a turn. 8 by default. |
limits.componentBytes | Serialized size of one component structure, in bytes. 65536 (64 KiB) by default. |
limits.dataBytes | Serialized size of one instance's data, in bytes. 262144 (256 KiB) by default. |
limits.dataUpdatesPerSec | Data updates one instance may apply per second. Extra updates are coalesced, not dropped. 10 by default. |
extensions.<id>.maxUsd | Dollars an extension may spend when no run pays for it. No limit unless set. maxUsd is in dollars, as in [budget]. |
An unknown key, or an unknown phase, fails at start and lists the valid ones.
Limits of componentBytes, dataBytes and dataUpdatesPerSec:
- A structure over
componentBytes is refused when it is declared or shown, and the refusal names the size and the key. Nothing is drawn from it.
- A data update that takes an instance over
dataBytes is refused. The last good data stays drawn.
- Updates over
dataUpdatesPerSec are coalesced: the last value wins at the next allowed moment. Nothing is dropped, but a fast-changing value is shown late, not in real time.
- Each of the three is a positive whole number.
0 fails at start, naming the file and line. 0 would mean no structure, no data or no updates ever, which is never what is meant.
- A managed layer can lower each value and cannot raise it. The user's value wins only below the managed one.
- The sizes are of the serialized JSON, so a few bytes of formatting count against the limit.
- There is no upper bound checked here. A very large
dataBytes is allowed, and every accepted update is written to the session log, so a large value grows the log faster.
#[retry]
| Key | Meaning |
|---|
retry.maxAttempts | Attempts on a rate limit or quota error. Default 3. |
#[prices]
A price for a model nothing prices, or an override, in micro-USD per million tokens:
[prices."gemini-3-flash-preview"]
inputPerMillion = 500000 # $0.50 / MTok
outputPerMillion = 3000000 # $3.00 / MTok
cachedPerMillion = 50000 # cache hits; otherwise billed as input
#[windows]
How many tokens a model holds: where the harness compacts, and what the footer's context percentage is measured against. An exact id or a prefix*, in any layer:
[windows."claude-haiku-5-5"]
tokens = 200000 # compact at 200K instead of the model's 1M
Without one, a model's window is the one the provider runs it at (Ollama's contextLength), else what the provider's model list reports (Anthropic's max_input_tokens), else what its extension declares, else the provider's one default. A model that comes in two sizes counts at the one Orrery's requests get: Claude Sonnet 4 and 4.5 reach 1M only behind a beta header Orrery does not send, so they count as 200K. A value that is not a positive whole number fails at load, naming the key. orrery config explain 'windows."<model>".tokens' says where a window came from.
#Agents and sub-agents
| Key | Meaning |
|---|
extensions.subagents.max_children | Sub-agents one spawn may start. Default 4. |
extensions.subagents.max_depth | How deep they nest. Default 2. |
extensions.subagents.maxTurns · maxUsd | A sub-agent's caps when nothing closer says. Default 16 turns, no cost cap. |
extensions.agents.dirs | More folders of agent files, beyond ~/.orrery/agents and .orrery/agents. |
tree.maxDepth · maxChildren · maxConcurrent · maxAgents | Core's ceiling on the agent tree. Can only lower the built-in one. |
agents.closeGrace | Seconds an extension's agents get to wind down on Esc. Default 5. |
agents.waitTimeout | Seconds an ask, a wait_for or a lock waits at most. |
#[extensions.<id>]
Declaring the table loads the extension; its keys are settings that extension reads. For example [extensions.theme] with default = "dark". The older top-level list, extensions = ["theme"], still works and says what to write instead.
| Key | Meaning |
|---|
extensions.<id>.model | The model an extension's { config: "model" } model call uses (Models and sessions). |
extensions.<id>.maxUsd | Dollars the extension may spend when no run pays. See Limits. |
extensions.<id>.resident | true keeps the extension's process running for the whole session; false lets it park after a quiet spell. Default: the manifest's resident (false unless it says otherwise). Must be true or false. |
Limits of resident:
- A resident extension keeps one process for the session. It costs memory even when idle (about 1 to 16 MB, by language).
- A parked extension's surfaces stop updating without saying so. Resident keeps them current.
- An extension that holds a subscription or a watch is never parked, resident or not.
#[mcp_servers.<name>]
| Key | Meaning |
|---|
mcp_servers.<name>.command | The program to start over stdio. Set this or url, not both. |
mcp_servers.<name>.args | Its arguments. |
mcp_servers.<name>.url | A remote server, over streamable HTTP (or SSE, detected). Set this or command, not both. |
mcp_servers.<name>.headers | Headers sent on every request to url. A "$VAR" value is read from the profile's env, then the process. |
mcp_servers.<name>.oauth | true signs in with OAuth (url only). Tokens are kept outside the file; sign in with orrery mcp login <name>. |
mcp_servers.<name>.deferred | true makes its tools searchable rather than declared in every prompt. Default false. |
#[mcp]
| Key | Meaning |
|---|
mcp.connector | The extension that connects MCP servers instead of the in-process default. |
#[skills.<name>]
| Key | Meaning |
|---|
skills.<name>.scope | Which agents may load it. Empty means all. |
skills.<name>.grant | What its scripts/ may do. Absent means they do not run. |
#[trust]
| Key | Meaning |
|---|
trust.auto | true trusts every workspace. Read from the managed, organisation and user layers only. |
trust.mode | always trusts every workspace; a managed never trusts none. |
#[registry]
Usually in the managed layer.
| Key | Meaning |
|---|
registry.index | The signed index bare names resolve against: a path or an https:// URL. Default: Orrery's public index. |
registry.key | The public key the index is signed with, as hex. |
registry.public | false (managed) forbids Orrery's public index. |
registry.unpinned | allow (default), warn or refuse for extensions not in the index. |
#[ui]
| Key | Meaning |
|---|
ui.default | The client to use, by id. |
ui.refuse_grants | Client grants no client may hold, such as ["consent"]. |
ui.placements."<id>".placement | Moves the surface with that id to a placement: inline, footer, band, pane.left, pane.right or hidden. Default: where the surface's owner put it. |
ui.<element>.show | false hides a Tier 1 element (for example ui.toast.show = false); true shows it. Default true. |
Limits of the chrome keys:
- A placement moves only a surface that exists. An id nothing has placed does nothing, and says nothing.
input, consent and trust cannot be shown, hidden or moved from config. The host draws them alone (decision 0087); a key naming one fails at start.
- Only Tier 1 elements take
show. Any other name fails at start and lists the ones that do.
- Every placed surface is labelled with its owner on screen. Config can move it, but cannot remove that label.
#[views."<event>"]
Where the surface an event produces goes. Each event kind has one binding; this table moves it (decision 0088 §7).
| Key | Meaning |
|---|
views."<event>".placement | inline, footer, band, pane.left, pane.right or hidden. The event kinds are run, agent, message, wait, lock, state, session, turn, tool and context. |
Limits of [views]:
- Only the placement can be set here. Which surface an event shows, and when, stays in the code that bound it.
- The event name is not checked at load. A misspelt name matches no event, so its binding keeps the default placement.
- A placement written here is still subject to
ui(<placement>) rules: a deny wins.
#[node] and [session]
For the node and the sessions it runs.
| Key | Meaning |
|---|
node.sessions | "container" runs each session in its own container. |
node.allowed_origins | Browser origins the node's HTTP listener accepts. |
node.idle_minutes | Then a container session hibernates. |
node.keep_workspace | Keep a session's clone after sessions.end. |
node.max_sessions · reserve_memory | Sessions running at once; memory kept for the host. |
node.retain_days | A hibernated session is removed after this long. |
session.worktree | false: a session on a repository works in it in place. Default true. |
session.memory · cpus · pids · disk · network · stall_minutes | A container session's limits. |
#[cloud] and [handoff]
| Key | Meaning |
|---|
cloud.tls_ca | One more certificate authority to trust for the relay and the control plane. User layer only. |
handoff.untracked | ask, include or skip for untracked files on a handoff. |