Canonical manifest and resolver for every user-tunable scalar config option.
This module is the single source of truth for the configuration surface: the
set of options, their types, typed defaults, env-var names, and config.toml
locations. The typed defaults for config-file-only options (notably the
[interpreter] section) live here as module constants, and Settings derives
its dataclass defaults from them — so a default is defined in exactly one place.
resolve_scalar is the shared resolution engine used both by the runtime
(Settings.from_environment) and by the config CLI command, so introspection
can never drift from what the app actually reads. Resolution precedence mirrors
the loaders: a DEEPAGENTS_CODE_-prefixed env var beats the canonical name,
env beats config.toml, and the typed default is the final fallback. A
malformed numeric/list/PTC value, an unrecognized boolean token, or a
wrong-typed TOML value is logged and falls back to the next layer rather than
raising, so a bad config never blocks startup.
Structured, user-defined config is not a flat scalar option and is parsed by
dedicated typed loaders elsewhere. The manifest references [threads].columns
and [warnings].suppress as STRUCTURED options for discovery; other tables
such as [models.providers.*] and [themes.*] are handled entirely by their
own loaders and the manifest does not enumerate them at all.
Import discipline: the module top level stays stdlib + _env_vars only (both
light) so it is safe to import from config.py at class-definition time without
pulling the heavy model_config/agent runtime onto the startup fast path.
Anything needing model_config (provider credentials, the config path, env-var
prefix resolution) is imported lazily inside functions.
_env_vars constants intentionally excluded from the option catalog.
Classify a raw env-var string as a truthy, falsy, or unrecognized token.
The single source of truth for which strings count as boolean on/off
values; is_env_truthy and the config resolver both build on it so they
agree on what "recognizably boolean" means.
Load ~/.deepagents/config.toml.
Resolve an option against the environment then config.toml.
Resolve the [interpreter] options into Settings constructor kwargs.
Only the interpreter group is resolved through the manifest. Credentials,
the shell allow-list, and the LangSmith project keep their dedicated
loaders in config.py (their empty-string-to-None and reload semantics
do not fit the generic resolver), so this stays scoped to the section whose
defaults this module owns.
Return every option, credentials-first then by domain group.
Cached: provider credentials are generated once from PROVIDER_API_KEY_ENV
on first call (which lazily imports model_config). The cache assumes that
registry is an immutable module constant; a test that monkeypatches it must
call get_config_options.cache_clear() (and _options_by_key.cache_clear()).
Return the manifest entry for key, or None when unknown.
Return every manifest key in definition order.
Return group names from options in first-seen order.
How an option's raw env/TOML value is coerced to a typed value.
All kinds flow through resolve_scalar. The scalar kinds (BOOL,
BOOL_PRESENCE, INT, FLOAT, STR) are coerced inline by
_coerce_env/_coerce_toml. SHELL_LIST_DELEGATE, SKILLS_DIRS_DELEGATE,
and PTC_DELEGATE defer to a bespoke parser (their semantics — colon-split
Path resolution, comma + recommended/all sentinels, the PTC allowlist —
do not compress into a generic coercion). THEME_DELEGATE is resolved
separately at the top of resolve_scalar and never reaches the inline
coercers. STRUCTURED marks user-defined tables that the scalar resolver
only passes through for display.
One user-tunable configuration option and where it can be set.