Repository navigation
user configuration
Steiner is configured with YAML files, a small set of environment variables, and command-line flags. This page is the reference for every config field, its type, default and constraints, plus file locations, precedence, environment variables, expansion syntax and project trust.
For provider and model recipes (aliases, profiles, selection), see Provider and model setup. Command-line flags are listed in CLI.
Sources are applied in this order; later sources win:
- Compiled defaults.
- Global config:
~/.config/steiner/config.yaml(under$HOME). - Project config:
<project>/.steiner/config.yaml, applied only once the project is trusted (see Project trust). - Environment variables.
- Command-line flags that override config:
--profile,--model,--verbose(setslogging.leveltodebug) and--unsafe(setssandbox.enabledtofalse).
Both files are optional and neither is created for you. --config <path> replaces the project config path (the global file is still read); unlike the default path, that file must exist. With no providers, models or profiles configured, starting a session fails with no model configured; inspection commands such as steiner config still work.
Maps merge by key across files (providers, model definitions, profiles, tools, MCP and LSP servers, limits.tool_timeouts, and the string maps inside them). Scalars and lists are replaced by the later file.
Unknown keys are rejected. Durations are Go duration strings such as 250ms, 30s, 5m or 1h. A leading ~/ is expanded to your home directory in these path fields: logging.file, logging.compaction_log_file, diagnostics.dir, lsp.cache_dir, paths.writable_paths, paths.blocked_paths, paths.exclude_paths, sandbox.host_mounts.<index>.path, tools.<name>.exec, project_context.extra_files and project_context.ignore_files.
steiner config prints the resolved configuration. It includes secrets in the output, so redact before sharing.
Only the variables below override configuration; there is no generic STEINER_ prefix mapping. Integer variables that do not parse make config loading fail. Steiner reads a few other variables outside config loading: STEINER_GITHUB_TOKEN for update checks (see Installation), STEINER_USAGE_TELEMETRY and STEINER_USAGE_TELEMETRY_RUN for usage telemetry (see Usage and cache statistics), the variable named by providers.<name>.api_key_env, and any variable referenced by ${VAR} expansion below.
| Variable | Effect |
|---|---|
STEINER_MODEL |
Active orchestrator model: a models.definitions alias or provider/model-id. An invalid value is silently ignored. --model wins over it; an invalid --model is also silently ignored. |
STEINER_SUB_AGENTS_MAX_PARALLEL |
Sets sub_agent.max_parallel. |
STEINER_TUI_FPS |
Sets tui.fps. |
STEINER_MAX_TURNS |
Sets limits.max_turns. |
STEINER_MAX_TOKENS |
Sets limits.max_tokens. |
STEINER_TOOL_OUTPUT_MAX_BYTES |
Sets limits.tool_output_max_bytes. |
STEINER_MAX_PARALLEL_TOOLS |
Sets limits.max_parallel_tools. |
STEINER_LOG_LEVEL |
Sets logging.level. |
STEINER_LOG_FILE |
Sets logging.file. |
STEINER_COMPACTION_LOG_FILE |
Sets logging.compaction_log_file. |
KAGI_API_KEY |
Fills search.kagi_api_key when it is empty. |
BRAVE_API_KEY |
Fills search.brave_api_key when it is empty. |
STEINER_TRUST_PROJECT_CONFIG |
1 or true trusts the current project's config for this run without prompting. Nothing is persisted. See Project trust. |
Scalar values in config files can reference environment variables. Keys and comments are never expanded.
| Form | Result |
|---|---|
${VAR} |
Value of VAR. Loading fails if VAR is unset. A set but empty VAR expands to an empty string. |
${VAR:-default} |
Value of VAR if set and non-empty, otherwise default (itself expanded). ${VAR:-} allows an empty value. |
$VAR |
Same as ${VAR}; has no default syntax. |
$$ |
A literal $. |
Backslash is not an escape character. An unquoted expansion is re-typed after substitution, so max_attempts: ${RETRIES:-5} and enabled: ${FLAG:-true} work; quoted values stay strings.
An undefined variable aborts loading at the first file that references one. The error lists every undefined variable in that file with its line, YAML path and name.
providers:
openai:
type: openai
base_url: ${OPENAI_BASE_URL:-https://api.openai.com/v1}
api_key: ${OPENAI_API_KEY}The first time Steiner runs in a directory it has not seen, it asks whether to trust that project before applying .steiner/config.yaml. The prompt appears whether or not the project has a config file. The trust key is the symlink-resolved absolute working directory, not a discovered git root, so a subdirectory of a trusted project prompts again.
When the project has a config, the dialog lists each leaf setting it overrides, compared against your global config (or the compiled defaults where the global file does not set it). Security-relevant fields are flagged with a leading !: sandbox, permissions, paths.writable_paths, paths.blocked_paths, paths.project_root_only, mcp.servers.<name>.transport, command, args, env, url, headers, approval and trust_annotations, lsp.servers.<name>.command, args and env, tools.<name>.exec and subcommand, and providers.<name>.base_url, headers, api_key and api_key_env. Existing values of api_key fields and anything under headers or env are shown as (set). Project values are shown unexpanded, so ${VAR} shows which variable would be used. If the project YAML fails to parse, the dialog shows the parse error instead of the diff.
Choices:
-
aAlways trust: recorded in~/.config/steiner/trusted_projects.json; later config changes do not prompt again. -
sThis session only: nothing is written. -
dDeny and exit: the default;EscandCtrl-Cchoose it. The process exits non-zero.
There is no revoke command: edit or delete trusted_projects.json. A corrupt or unrecognised-version file is deleted with a one-time notice; a read or permission error is fatal and leaves the file untouched.
The dialog needs an interactive terminal. With --exec or without a TTY, an untrusted project makes Steiner exit non-zero unless you pass --trust-project-config or set STEINER_TRUST_PROJECT_CONFIG=1 (or true). Both trust the project for that run only. steiner oneshot follows the same rule.
steiner config never prompts: it prints the resolved config including the project layer, prefixed with # project <root> is NOT trusted when the project is not in the trust store.
--unsafe and project trust are independent of each other.
| Path | Type | Default | Description |
|---|---|---|---|
providers |
map | empty | Model API connections. See providers block. |
models |
block | see section | Model definitions, discovery and profiles. See models block. |
limits |
block | see section | Turn, token, timeout and concurrency limits. See limits block. |
sandbox |
block | enabled | Bubblewrap sandbox. See sandbox block. |
permissions |
block | see section | Host capabilities granted to the sandbox. See permissions block. |
sub_agent |
block | enabled | Delegated child agents. See sub_agent block. |
advisor |
block | disabled | Stronger-model advisor. See advisor block. |
oneshot |
block | see section | Oneshot closeout. See oneshot block. |
desktop_notifications |
block | disabled | Desktop notifications. See desktop_notifications block. |
update_check |
block | enabled | Startup update check. See update_check block. |
tools |
map | empty | Custom subprocess tools. See tools block. |
project_context |
block | see section | Extra files added to the prompt. See project_context block. |
paths |
block | see section | Filesystem access limits. See paths block. |
logging |
block | see section | Session log files. See logging block. |
diagnostics |
block | disabled | Structured diagnostics capture. See diagnostics block. |
context_management |
block | see section | Context management baseline. See context_management block. |
search |
block | unset | Web search backend. See search block. |
mcp |
block | enabled | MCP servers. See mcp block. |
lsp |
block | disabled | Language servers. See lsp block. |
modes |
block | see section | Execution mode default. See modes block. |
tui |
block | see section | Interactive UI settings. See tui block. |
TUI appearance preferences (accent, sidebar, backgrounds) are not config keys; they live in ~/.config/steiner/prefs.yaml. See Interactive mode.
A map of named provider connections. The key is an arbitrary name that models.definitions.<alias>.provider and provider/model-id references use. Setup recipes are in Provider and model setup.
| Path | Type | Default | Description |
|---|---|---|---|
providers.<name>.type |
string | none | Required. One of openai_compat, ollama, lmstudio, openrouter, openai, anthropic, gemini, litellm, codex, opencode_go, opencode_zen, claude_subscription. See Provider types. |
providers.<name>.base_url |
string | per type | API endpoint. Required for openai_compat, ollama, lmstudio and litellm. |
providers.<name>.api_key |
string | none | API key. Prefer api_key_env or ${VAR} to keep secrets out of files. |
providers.<name>.api_key_env |
string | none | Name of an environment variable holding the API key, read at startup. api_key wins when both are set. |
providers.<name>.headers.<header> |
string | none | Extra HTTP header sent with every request to this provider. |
providers.<name>.timeout |
duration | unset | Timeout for each request attempt, covering headers, body and streaming. Unset means no overall request timeout, and a 30s response-header timeout applies instead. Setting a timeout bounds the whole request, including headers, and replaces the header timeout. Retries replay the request, so one call can take up to retry.max_attempts times timeout plus backoff. |
providers.<name>.compaction_fallback_after |
duration |
5m anthropic, 60m claude_subscription, 30m openai and codex, 0 otherwise |
Idle time after which compaction may use models.profiles.<profile>.compaction_fallback. 0 disables; negative is invalid. See Context management. |
providers.<name>.codex.min_request_interval |
duration | 0s |
codex only. Minimum gap between consecutive requests; 0 disables pacing. |
providers.<name>.codex.transport |
string | http |
codex only. http, or websocket (experimental; failures return an error with no HTTP fallback). |
| Type | base_url |
Credentials | Notes |
|---|---|---|---|
openai_compat |
required |
api_key or api_key_env optional |
Any OpenAI chat-completions compatible server. |
ollama |
required, e.g. http://localhost:11434/v1
|
optional | Ollama through its OpenAI-compatible API. |
lmstudio |
required, typically http://127.0.0.1:1234/v1
|
optional | LM Studio's local server. |
litellm |
required | optional | LiteLLM gateway. A 429 without Retry-After has its delay parsed from the body; budget-exhaustion 429s are not retried. |
openrouter |
default https://openrouter.ai/api/v1
|
required | OpenRouter gateway. |
openai |
default https://api.openai.com/v1
|
required | Native OpenAI API. |
anthropic |
default https://api.anthropic.com/v1
|
required | Native Anthropic API. Steiner appends /messages to base_url, so a custom base_url must include the /v1 suffix. |
opencode_go |
default https://opencode.ai/zen/go/v1
|
required | OpenCode Go gateway. Create the key in your OpenCode account. |
opencode_zen |
default https://opencode.ai/zen/v1
|
required | OpenCode Zen gateway. |
codex |
optional | ignored | OpenAI Codex subscription. Sign in with steiner login codex; authentication uses that OAuth login, not api_key. |
claude_subscription |
rejected | rejected | Runs your signed-in claude CLI. base_url, api_key, api_key_env, headers and timeout are rejected. See Claude subscription. |
gemini |
none | required | Accepted by validation but not supported at runtime; do not use. |
"Required" credentials mean one of api_key or api_key_env must be set, or validation fails.
Model definitions, discovery and named profiles. A profile assigns models to roles; a definition (alias) persists settings for one model. Every selection accepts a raw provider/model-id reference, so an alias is only needed to persist settings or give a model a short name. Selection order, aliases and profile usage are in Provider and model setup.
No profile is required. Every declared profile must set default_model, and profiles never inherit from each other. Without --profile, the profile named default is used; if there is none, role assignments are unselected and --model or STEINER_MODEL still sets the orchestrator model.
| Path | Type | Default | Description |
|---|---|---|---|
models.discovery_enabled |
bool | true |
Discover models from configured providers. false skips provider enumeration and network refresh; the chooser lists configured entries only. |
models.definitions.<alias>.provider |
string | none | Required. Name of a key in providers. |
models.definitions.<alias>.id |
string | none | Required. Model ID as the provider's API expects it. |
models.definitions.<alias>.params |
map[string]any | none | Request parameters sent in the request body, such as temperature, top_p, top_k. |
models.definitions.<alias>.extra_params |
map[string]any | none | Additional provider-specific body parameters. |
models.definitions.<alias>.prompt_suffix |
string | none | Text appended to the last user message of each request. |
models.definitions.<alias>.vision |
bool or null | null |
false strips image attachments from requests to this model with a warning. Unset assumes vision support. |
models.definitions.<alias>.retry.enabled |
bool | true |
Retry transient and rate-limit errors. Usage and quota limit errors are never retried. |
models.definitions.<alias>.retry.max_attempts |
int | 5 |
Total attempts including the first; at least 1. |
models.definitions.<alias>.retry.initial_backoff |
duration | 250ms |
Wait before the first retry; greater than zero. |
models.definitions.<alias>.retry.max_backoff |
duration | 5s |
Cap on exponential backoff; at least initial_backoff. |
models.definitions.<alias>.retry.retry_after_max |
duration | 60s |
Longest Retry-After wait honoured; at least initial_backoff. |
models.definitions.<alias>.prompts.system |
string | none | Replaces the default system prompt for this model. |
models.definitions.<alias>.prompts.system_suffix |
string | none | Appended after the default preamble. |
models.definitions.<alias>.prompts.compaction |
string | none | Replaces the compaction prompt for this model. |
models.definitions.<alias>.advanced.limits.context_window |
int | resolved from metadata | Context window in tokens. An explicit value wins over discovered metadata. If nothing resolves, 32768 is used. |
models.definitions.<alias>.advanced.limits.max_output_tokens |
int | resolved from metadata | Maximum tokens per response. If nothing resolves, 4096 is used. |
models.definitions.<alias>.advanced.limits.compaction_threshold_tokens |
int | 70% of the context window | Prompt-token count that triggers compaction; greater than zero and below the resolved context window. |
models.definitions.<alias>.advanced.reasoning_echo_back |
bool or null | resolved from metadata | Whether the model's reasoning content is echoed back in later requests. |
models.definitions.<alias>.advanced.transport |
string | auto |
auto, openai_compat or anthropic. auto follows models.dev metadata when available, otherwise the provider type. An explicit value overrides metadata. |
models.definitions.<alias>.advanced.reasoning.effort |
string | unset | Reasoning effort to request, as the provider names it (for example low, high). Unset sends no reasoning field. Must not be blank and must appear in supported_efforts when that is set. |
models.definitions.<alias>.advanced.reasoning.supported_efforts |
[]string | discovered | Efforts this model accepts, used to validate effort and fill the /model picker. No blank or duplicate values. Unset uses models.dev data. |
models.definitions.<alias>.advanced.codex.use_max_context_window |
bool | false |
codex providers only (rejected otherwise). Use the catalogue's max_context_window when positive, else its context_window. |
models.profiles.<profile>.default_model |
string | none | Required in every declared profile. A model reference, also the fallback for roles without their own assignment. |
models.profiles.<profile>.advisor |
string | unset | Model for advisor calls; falls back to default_model. |
models.profiles.<profile>.compaction_fallback |
string | unset | Model for compaction when the prompt cache is presumed cold. Needs a positive compaction_fallback_after on the main model's provider. Unset disables it; it does not fall back to default_model. |
models.profiles.<profile>.sub_agents.<type> |
string | unset | Model per agent type: explore, research, code, documentor, evaluate, sanity_check, review, vision. Empty or unset assignments use default_model, except vision, which requires an explicit assignment. |
models.profiles.<profile>.oneshot.<phase> |
string | unset | Model per oneshot phase: plan, implement, review. Unset phases use default_model. |
models.profiles.<profile>.workflow_handoff.<destination> |
string | unset | Model per handoff destination: implement, review, build. Unset destinations use default_model. |
The vision sub-agent type needs a vision-capable model; the vision tool is not registered unless sub_agents.vision is set. See Sub-agent delegation.
Runtime limits for turns, tokens, timeouts and tool concurrency. The caps apply to the parent run; tool_output_max_bytes, max_parallel_tools and the tool timeouts also apply to each sub-agent. See Tools for tool behaviour.
| Path | Type | Default | Description |
|---|---|---|---|
limits.max_turns |
int | 50 |
Maximum agent-loop turns before the run stops. 0 removes the limit; negative is invalid. |
limits.max_tokens |
int | 500000 |
Maximum output (completion) tokens generated across a run before it stops; at least 1. Input tokens are not counted. |
limits.model_call_timeout |
duration | 10m |
Longest a single provider call may take. 0 disables it. Tool work and sub-agent calls inside a turn are not covered. |
limits.tool_timeout_default |
duration | 30s |
Timeout for any tool without an entry in tool_timeouts; greater than zero. Also bounds MCP calls. |
limits.tool_timeouts.<tool> |
duration | see below | Per-tool timeout; greater than zero. Defaults: bash 600s, read 5s, grep 30s, ls 5s. For an MCP tool the key is its registered name mcp__<server>__<tool>, as shown by steiner tools. The bash entry caps the built-in Bash tool: whole seconds, at most 600s. |
limits.tool_output_max_bytes |
int | 65536 |
Output kept from one tool call; the rest is truncated. At least 1. |
limits.max_parallel_tools |
int | 4 |
Parallel-safe tool calls run concurrently in one turn, including built-in read-only tools, LSP tools and MCP tools with a read-only hint. At least 1; 1 is serial. Separate from sub_agent.max_parallel. |
Bubblewrap sandbox for bash and subprocess tools. What the sandbox isolates, how approvals interact with it and platform limits are in Sandboxing.
| Path | Type | Default | Description |
|---|---|---|---|
sandbox.enabled |
bool | true |
Enable the sandbox. --unsafe forces false. |
sandbox.warning_on_unsupported_platform |
bool | true |
Warn when the sandbox is unavailable or bypassed. |
sandbox.env_passthrough |
[]string | [] |
Extra host environment variable names passed to sandboxed processes. A trailing * matches a prefix (MYAPP_*). Entries must be non-empty, contain no =, and * may only be the last character. A bare * is rejected; use env_passthrough_all. |
sandbox.env_passthrough_all |
bool | false |
Pass the full host environment, credentials included, with no filtering. Always prints a warning while the sandbox is enabled, regardless of warning_on_unsupported_platform. |
sandbox.bind_host_cache |
bool | false |
Bind the real ~/.cache read-write instead of a sandbox-private cache directory. |
sandbox.host_mounts.<index>.path |
string | none | Host path to mount; ~/ expands. |
sandbox.host_mounts.<index>.mode |
string | read-only |
rw for writable access; anything else mounts read-only. |
Opt-in host capabilities for the sandbox. See Sandboxing.
| Path | Type | Default | Description |
|---|---|---|---|
permissions.docker |
bool | false |
true leaves the Docker socket reachable inside the sandbox. false masks it and unsets DOCKER_HOST. |
Delegated child agents. Behaviour, agent types and worktrees are in Sub-agent delegation. Per-type models are set in models.profiles.<profile>.sub_agents.
| Path | Type | Default | Description |
|---|---|---|---|
sub_agent.enabled |
bool | true |
false removes all delegation tools. The constraints below apply only when enabled. |
sub_agent.orchestration_level |
string | standard |
standard or low. low omits the delegation-steering sections of the system prompt. |
sub_agent.max_turns |
int | 120 |
Turn cap for each child run; at least 15. |
sub_agent.max_tokens |
int | 400000 |
Maximum output (completion) tokens per child run; at least 1. |
sub_agent.max_parallel |
int | 3 |
Session-wide cap on running children. Extra spawns queue; more than twice this many outstanding (running plus queued) fail. At least 1. |
sub_agent.max_follow_ups |
int | 5 |
Follow-up resumes allowed per child; at least 1. Each resume extends the child's turn budget. |
Optional advisor tool: a stronger model reviews the conversation and returns guidance. The model is chosen by models.profiles.<profile>.advisor. See Advisor.
| Path | Type | Default | Description |
|---|---|---|---|
advisor.enabled |
bool | false |
Enable the advisor tool. |
advisor.max_uses_per_run |
int | 3 |
Advisor calls allowed per session; at least 1 when enabled. |
advisor.max_uses_per_sub_agent |
int | 1 |
Advisor calls allowed per child agent; at least 1 when enabled. |
advisor.max_tokens |
int | unset | Output-token ceiling for advisor calls; greater than zero when set. |
advisor.timeout |
duration | 180s |
Timeout for each advisor request attempt. Overrides providers.<name>.timeout for advisor calls only; greater than zero when set. |
Closeout settings for autonomous steiner oneshot runs. Per-phase models are set in models.profiles.<profile>.oneshot. See Oneshot.
| Path | Type | Default | Description |
|---|---|---|---|
oneshot.auto_pr |
bool | false |
Let closeout push the branch and open a PR or MR after a passing review. |
Desktop notifications from the interactive TUI. They fire when a tool approval is required and when a workflow handoff is requested; there is no run-completion notification. See Desktop notifications.
| Path | Type | Default | Description |
|---|---|---|---|
desktop_notifications.enabled |
bool | false |
Enable notifications. |
desktop_notifications.duration |
int | 0 |
Display time in seconds. 0 leaves the notification until dismissed; negative is invalid. |
Background check for a newer Steiner release at startup. It runs in the interactive TUI only. See Installation.
| Path | Type | Default | Description |
|---|---|---|---|
update_check.enabled |
bool | true |
Enable the startup check. |
update_check.interval_hours |
int | 6 |
Minimum hours between checks; 0 checks on every startup; negative is invalid. |
Custom subprocess tools registered next to the built-ins. The map key is the tool name the model sees. Names reserved by built-ins (read, glob, grep, ls, bash, display_file, mutate, fetch_url, workflow_handoff) are rejected. The stdin/stdout contract a tool must follow is in Tools.
| Path | Type | Default | Description |
|---|---|---|---|
tools.<name>.exec |
string | none | Required. Executable to run; ~/ expands. |
tools.<name>.subcommand |
string | none | Passed to exec as its first argument. |
tools.<name>.description |
string | none | Description shown to the model. |
tools.<name>.parameters |
map[string]any | none | JSON Schema fragment for the tool's input. |
tools.<name>.timeout |
duration | none | Required; greater than zero. |
Extra files added to the system prompt, under a byte budget. See Context management.
| Path | Type | Default | Description |
|---|---|---|---|
project_context.max_bytes |
int | 8000 |
Byte budget for extra context files; files are truncated or skipped to fit. At least 1. |
project_context.max_tokens |
int | none | Deprecated alias of max_bytes (multiplied by 4); max_bytes wins when both are set. |
project_context.extra_files |
[]string | none | Files to include, relative to the project root. A path resolving outside the root is an error; missing files and directories are skipped. |
project_context.ignore_files |
[]string | none | Entries of extra_files to skip. An ignore entry matches a file by exact path, by base name, or as a trailing path suffix. Globs and directories do not match. |
Filesystem access limits for file tools, including each sub-agent's tools. Exclusion semantics are in Tools.
| Path | Type | Default | Description |
|---|---|---|---|
paths.project_root_only |
bool | true |
Restrict tools to paths inside the project root. |
paths.writable_paths |
[]string | [] |
When set, an allowlist that restricts mutation tools to these paths, including inside the project root. Outside the root it only adds to what project_root_only permits once that restriction is lifted by approval. May be inside or outside the project root; ~/ expands. |
paths.blocked_paths |
[]string | [] |
Paths always denied, even inside the project root; ~/ expands. |
paths.exclude_paths |
[]string | none | Paths excluded from searches and directory walks. Relative entries are anchored to the workspace root; ~/ expands. |
paths.exclude_patterns |
[]string | none | Globs excluded from searches and directory walks. |
Session log files. Treat log files as sensitive: they can contain prompts and tool output. The --log-file flag overrides logging.file and enables logging for the run.
| Path | Type | Default | Description |
|---|---|---|---|
logging.enabled |
bool | false |
Write the session log to logging.file. |
logging.level |
string | info |
trace, debug, info, warn or error. |
logging.file |
string | ~/.local/share/steiner/steiner.log |
Log path; required, ~/ expands. JSONL, appended across runs and rotated by size. |
logging.thinking_chunk |
bool | false |
Include reasoning chunks in the log. |
logging.assistant_chunk |
bool | false |
Include streamed assistant chunks, which duplicate the completed assistant message record. |
logging.compaction_log_file |
string | none | Separate log of compaction events; ~/ expands. |
Structured JSONL capture for measuring cache hit rates, provider calls, tool runs and TUI cost. Disabled by default and independent of logging: the directory is never derived from logging.file. Each record carries run_id, build_sha and dirty. Streams that write to disk are listed below; see Usage for cache statistics.
| Path | Type | Default | Description |
|---|---|---|---|
diagnostics.enabled |
bool | false |
Master switch. When false nothing is created. |
diagnostics.dir |
string |
$XDG_STATE_HOME/steiner/diagnostics, else ~/.local/state/steiner/diagnostics
|
Directory with one file per stream. Required when enabled; must not resolve inside the project root; ~/ expands. |
diagnostics.retention_days |
int | 30 |
Records older than this are dropped when the writer opens; greater than zero when enabled. |
diagnostics.streams.cache |
bool | false |
Prompt-cache observations (cache.jsonl). |
diagnostics.streams.provider |
bool | false |
One record per model call, whatever the outcome (provider.jsonl). |
diagnostics.streams.tool |
bool | false |
Tool execution and delegation traces (tool.jsonl). |
diagnostics.streams.tui |
bool | false |
Interactive TUI timings, counts and sizes, never content (tui.jsonl). |
diagnostics.streams.internal |
bool | false |
TUI developer error entries (internal.jsonl); sanitised and capped, but may still carry prompt or tool content. |
diagnostics.capture_bodies |
bool | false |
Capture full message, tool and block content instead of bounded fields. Expensive, and captures prompts. |
Baseline context management. Applies to the parent and to each sub-agent. See Context management.
| Path | Type | Default | Description |
|---|---|---|---|
context_management.read_annotations |
bool | true |
Annotate a read when an identical full read (same file_hash and range) is already in the carried conversation. false keeps full read results. |
Backend for the web_search tool. Setup is in Web search. The key fields can be filled from the unprefixed environment variables in Environment variables when empty.
| Path | Type | Default | Description |
|---|---|---|---|
search.backend |
string | unset |
searxng, kagi or brave. Selects which fields below are required. |
search.searxng_url |
string | none | SearXNG base URL. Required for searxng. |
search.kagi_api_key |
string | none | Kagi API key. Required for kagi. |
search.brave_api_key |
string | none | Brave Search API key. Required for brave. |
Model Context Protocol servers. MCP is on by default, but each server must be enabled individually. Approval behaviour and TUI surfaces are in MCP.
| Path | Type | Default | Description |
|---|---|---|---|
mcp.enabled |
bool | true |
Master switch for the MCP client. |
mcp.servers.<server>.enabled |
bool | false |
Start this server. The name must not contain __. |
mcp.servers.<server>.transport |
string | stdio |
stdio (subprocess) or http. |
mcp.servers.<server>.command |
string | none | Executable. Required for stdio; must be empty for http. |
mcp.servers.<server>.args |
[]string | none | Command arguments; must be empty for http. |
mcp.servers.<server>.env.<key> |
string | none | Extra environment variable for the server process; must be empty for http. |
mcp.servers.<server>.url |
string | none |
http or https endpoint. Required for http; must be empty for stdio. |
mcp.servers.<server>.headers.<header> |
string | none | Header sent with every request; must be empty for stdio. Names reserved by the MCP SDK (Content-Type, Accept, Mcp-Protocol-Version, Mcp-Session-Id, Last-Event-Id, Mcp-Method, Mcp-Name, and the Mcp-Param- prefix) are rejected. Use ${VAR} for bearer tokens. |
mcp.servers.<server>.approval |
string | ask |
ask, allow or deny. deny registers no tools. |
mcp.servers.<server>.trust_annotations |
bool | false |
Honour a tool's readOnlyHint annotation to skip approval. |
mcp.servers.<server>.connect_timeout |
duration | 15s |
Time allowed to connect. Unset or 0 uses 15s; negative is invalid. |
mcp.servers.<server>.allowed_tools |
[]string | none | Allowlist of the server's native tool names. Unset means no restriction; [] registers nothing. |
mcp.servers.<server>.blocked_tools |
[]string | none | Native tool names to drop, applied after allowed_tools. |
mcp.servers.<server>.sub_agents |
[]string | none | Agent types allowed to use this server's tools. Unset or [] grants none. Valid types: explore, research, code, documentor, evaluate, sanity_check, review, vision. |
Optional language servers for code intelligence tools. Disabled by default; servers are never installed by Steiner. Validation runs only when lsp.enabled is true. Server setup is in LSP.
| Path | Type | Default | Description |
|---|---|---|---|
lsp.enabled |
bool | false |
Enable LSP tools. |
lsp.idle_timeout |
duration | 5m |
Stop an idle server after this long; greater than zero. |
lsp.request_timeout |
duration | 10s |
Timeout for one request; greater than zero. |
lsp.ready_timeout |
duration | 30s |
Wait for a server to finish indexing before answering anyway; greater than zero. |
lsp.ready_grace_period |
duration | 2s |
Grace period for servers that never report progress; greater than zero. |
lsp.diagnostics_window |
duration | 2s |
Time to collect published diagnostics after opening a file; greater than zero. |
lsp.max_results |
int | 200 |
Maximum results per navigation query; greater than zero. |
lsp.cache_dir |
string | user cache directory | Base directory for server state; ~/ expands. |
lsp.servers.<name>.enabled |
bool | false |
Enable this server. The fields below are validated only for enabled servers. |
lsp.servers.<name>.command |
string | none | Required. Server executable. |
lsp.servers.<name>.args |
[]string | none | Command arguments. |
lsp.servers.<name>.env.<key> |
string | none | Extra environment variable for the server process. |
lsp.servers.<name>.file_extensions |
[]string | none | Required, non-empty, each starting with .. Two enabled servers cannot claim the same extension (case-insensitive). |
lsp.servers.<name>.root_markers |
[]string | none | Required, non-empty. Files or directories that identify a workspace root. |
lsp.servers.<name>.initialization_options |
map[string]any | none | Options passed to the server in the initialize handshake. |
Execution mode at startup. Mode behaviour and switching are in Execution modes.
| Path | Type | Default | Description |
|---|---|---|---|
modes.default |
string | build |
plan or build. plan limits project edits to .steiner/plans and .steiner/security. |
Interactive terminal UI settings; ignored outside the TUI. See Interactive mode.
| Path | Type | Default | Description |
|---|---|---|---|
tui.fps |
int | 60 |
Renderer frame rate, 1 to 120. Higher values reduce input latency at the cost of CPU. |
tui.quota_refresh_interval |
duration | 5m |
Age after which a finished run refetches subscription usage for accounts it used. 0 disables only this refresh; negative is invalid. See Usage. |
Minimal local setup with Ollama:
providers:
local:
type: ollama
base_url: http://localhost:11434/v1
models:
profiles:
default:
default_model: local/qwen2.5-coder:14bCloud provider (Anthropic):
providers:
cloud:
type: anthropic
base_url: https://api.anthropic.com/v1
api_key_env: ANTHROPIC_API_KEY
models:
profiles:
default:
default_model: cloud/claude-sonnet-4-5Get started
Using Steiner
- How to work with steiner
- Interactive mode
- CLI reference
- Skills
- Sub-agent delegation
- Oneshot
- Context management
- Advisor
- Security audit
Tools and integrations
Safety
Usage and cost
Reference
Internals and maintenance