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_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
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