class

Smith::Config

Inherits Reference < Object

Resolved configuration, merged from (lowest to highest priority):

built-in defaults < global config < project config < env var < CLI flag

The CLI flag tier lives in Smith::CLI — it simply skips asking the Config when a flag was supplied. Everything below that is resolved here.

API keys are deliberately not read from the config file. They stay env-only so a plaintext config never becomes a place secrets get committed from.

Constants

BUILTIN_MODELS = {"openrouter" => "qwen/qwen3.8-max", "ollama" => "gemma4:latest", "anthropic" => "claude-sonnet-5", "openai" => "gpt-5.6-luna"}
CONFIG_FILE_NAME = "config.toml"
DEFAULT_APPROVAL_MODE = "prompt"
DEFAULT_BASH_TIMEOUT = 120
DEFAULT_CACHE = true
DEFAULT_CHECKPOINTS_ENABLED = true
DEFAULT_CONNECT_TIMEOUT = 10
DEFAULT_MAX_BACKGROUND_JOBS = 10
DEFAULT_MAX_CHECKPOINTS = 100
DEFAULT_MAX_CONTEXT_TOKENS = 120000
DEFAULT_MAX_OUTPUT_BYTES = 256 * 1024
DEFAULT_MCP_ENABLED = true
DEFAULT_MCP_TIMEOUT = 60
DEFAULT_MODE = "normal"
DEFAULT_MODEL = BUILTIN_MODELS[DEFAULT_PROVIDER]
DEFAULT_OLLAMA_HOST = "http://localhost:11434"
DEFAULT_PROVIDER = "openrouter"
DEFAULT_READ_TIMEOUT = 120
DEFAULT_REASONING_EFFORT = "none"
DEFAULT_RETENTION_DAYS = 30
DEFAULT_SEARCH_PROVIDER = "none"
DEFAULT_SEARXNG_HOST = "http://localhost:8888"
DEFAULT_SESSION_RETENTION_DAYS = 90
DEFAULT_STREAM = true
DEFAULT_THINKING = false
DEFAULT_THINKING_EFFORT = "medium"
DEFAULT_WEB_ALLOW_PRIVATE = false
DEFAULT_WEB_MAX_BYTES = 256 * 1024

Constructors

load(start_dir : String = Dir.current) : Config

Reads the global config, then the nearest project config, and merges them with the project file winning on conflicts.

Source
new(table : Hash(String, TOML::Any) = Hash(String, TOML::Any).new, sources : Array(String) = Array(String).new, global_hooks : TOML::Any | Nil = nil, project_hooks : TOML::Any | Nil = nil)
Source

Class methods

global_path
Source
project_path(start_dir : String = Dir.current) : String | Nil

Walks up from start_dir looking for .smith/config.toml, stopping at the git root — same boundary ProjectContext.discover uses, so running smith from a subdirectory still finds the project's config. Nearest wins.

Source

Instance methods

approval

Consumed by Tools::Approver via CLI#build_approver.

Source
bash

Consumed by Tools::Bash and Tools::BashJobs via CLI#build_agent.

Source
cache_for(provider_name : String) : Bool

Anthropic prompt caching. On by default; worth switching off only when the prompt is too short to reach the cache minimum.

Source
checkpoints

Consumed by Checkpoints::Store via CLI#build_agent.

Source
context

Consumed by issue #3 (history compaction).

Source
global_hooks

Everything except the project config's hooks. Used when the user has not trusted this project: their own global hooks still run.

Source
hooks

Global first, then project — the order hooks fire in.

Source
http

Consumed by issue #4 (HTTP timeouts).

Source
mcp

Consumed by MCP::Manager via CLI#mcp_manager. The timeout is per call: a server that hangs must not hang the agent with it.

Source
mentions

Budgets for @-mentions. allow_outside is off by default: a prompt coming from a skill file could otherwise pull in ~/.ssh/id_rsa.

Source
mode

Consumed by CLI#effective_mode, below the --plan flag.

Source
model_for(provider_name : String) : String
Source
ollama_host
Source
pricing

Rates keyed by "provider/model", overriding the built-in table. Vendors change prices; a table baked into a release cannot keep up.

Source
project_hooks_digest

Hooks run arbitrary commands with the user's rights, so a project config that defines them has to be trusted once. nil means the project config defines no hooks at all; the digest changes whenever they do.

Source
provider
Source
reasoning_effort

Was hardcoded in the OpenAI adapter.

Source
sandbox

Consumed by Sandbox.build via CLI#build_agent. Off unless asked for: confinement changes what a command can do, and a user who did not ask for that should not find out from a failing build.

Source
sessions

Consumed by CLI#setup_checkpoints, next to the checkpoint prune: a session older than this (last update) is dropped when a run starts. The newest session survives regardless (#82).

Source
sources

Config files that were actually read, lowest priority first. Useful for diagnostics ("why is smith using this model?").

Source
stream?
Source
subagents

Consumed by Subagents::Supervisor via CLI#build_agent. max_children = 0 switches subagents off entirely — the agent tool is then not registered.

Source
thinking?

Extended thinking is off by default: it costs tokens, and only Anthropic supports it in the form smith implements.

Source
thinking_budget

Only for Anthropic models older than 4.6, which take a token budget instead of an effort level. Unset on purpose: current models reject it.

Source
thinking_effort

How deep to think: low | medium | high | xhigh | max.

Source
web

Consumed by Tools::WebFetch and Tools::WebSearch via CLI#build_agent. API keys are not here — they stay in the environment, like every other key.

Source

Nested types