(pkg-config)=
# `rath.config`
Persistent local configuration for LLM providers, embedding/VLM provider selection, MCP servers, memory stores, and backend presets. v1.3.0 separates routing config from credentials and centralizes environment-variable declarations.
## Source
| Module | Source |
| --- | --- |
| `rath.config.paths` | `src/rath/config/paths.py` |
| `rath.config.schema` | `src/rath/config/schema.py` |
| `rath.config.secrets` | `src/rath/config/secrets.py` |
| `rath.config.credentials` | `src/rath/config/credentials.py` |
| `rath.config.env` | `src/rath/config/env.py` |
| `rath.config.store` | `src/rath/config/store.py` |
## Public contract
OpenRath resolves config in this order:
```{figure} ../_static/config-resolution-stack.png
:alt: OpenRath configuration resolution stack
Config resolution starts with explicit `Provider` fields, then environment
variables, and finally the resolved `.openrath/config.json` store.
```
| Location | When used |
| --- | --- |
| `$OPENRATH_HOME/config.json` | Explicit override. |
| `./.openrath/config.json` | Project-local marker directory exists. |
| `~/.openrath/config.json` | Default user config. |
The routing file is JSON. Unknown fields round-trip through the Pydantic models so newer OpenRath or third-party tools can add sections without losing data. API keys live in a sibling `credentials.json` after save.
`config.json`:
```json
{
"version": 1,
"llm": {
"default_provider": "openai-main",
"providers": {
"openai-main": {
"provider_kind": "openai",
"model": "gpt-5.5",
"base_url": "https://api.openai.com/v1"
},
"claude": {
"provider_kind": "anthropic",
"model": "claude-sonnet-4-5"
},
"gemini": {
"provider_kind": "litellm",
"model": "gemini/gemini-2.0-flash"
}
}
},
"mcp": {
"default_enabled": ["filesystem"],
"servers": {
"filesystem": {
"command": ["python", "-m", "mcp_server_filesystem"],
"env": {}
}
}
},
"memory": {
"default_provider": "local-main",
"providers": {
"local-main": {
"backend_kind": "local",
"path": ".openrath/memory",
"embedding_provider": "openai-main",
"chat_provider": "openai-main"
}
}
},
"backend": {
"default_provider": "sandbox-main",
"providers": {
"sandbox-main": {
"backend_kind": "opensandbox",
"domain": "127.0.0.1:8080",
"options": {}
}
}
}
}
```
`credentials.json` (mode `0600` on POSIX):
```json
{
"version": 1,
"llm": {
"providers": {
"openai-main": "sk-...",
"claude": "sk-ant-..."
}
},
"backend": {
"providers": {
"sandbox-main": "sandbox-key"
}
}
}
```
Legacy inline `api_key` values still load and take precedence over the sidecar.
The next `save()` migrates them. When another non-empty credential causes the
sidecar to be rewritten, keys set to `None` are omitted. If the resulting
credentials payload is empty, v1.3.0 does not remove or rewrite an existing
sidecar; remove that file or entry explicitly when revoking the last key.
```{admonition} OpenSandbox config boundary
:class: warning
In v1.3.0, backend `domain` participates in availability/config resolution but
is not injected into the SDK connection created by the backend, and backend
`api_key` has no runtime consumer. Configure actual connections with
`OPEN_SANDBOX_DOMAIN` and `OPEN_SANDBOX_API_KEY` (or the SDK's
`~/.sandbox.toml`).
```
### Store helpers
| API | Behavior |
| --- | --- |
| `ConfigStore.load()` | Loads the resolved default path or seeds an empty config. |
| `store.save()` | Splits secrets, atomically replaces each written file independently, sets user-only permissions on POSIX, writes `.gitignore` guards, and refreshes the root manifest. This is not a two-file transaction. |
| `store.get_llm_provider(name)` | Returns a named provider, or `llm.default_provider` when `name=None`. |
| `store.find_provider_by_kind(kind)` | Finds the default matching provider, then the first matching provider. |
| `store.get_memory_provider(name)` | Returns a named local memory provider, or `memory.default_provider` when `name=None`. |
| `store.get_backend_provider(name)` | Returns a named backend provider, or `backend.default_provider` when `name=None`. |
| `store.get_mcp_server(name)` | Returns one MCP server entry. |
| `store.enabled_mcp_servers()` | Resolves every name in `mcp.default_enabled`. |
### Consumers
| Consumer | Config behavior |
| --- | --- |
| `Provider.from_config(name=None, **overrides)` | Builds a `Provider` from `llm.providers`; explicit overrides win. |
| `EmbeddingProvider.from_config(name=None, **overrides)` | Uses `llm.embedding_provider` first, then chat default credentials with a safe embedding model. |
| `VLMProvider.from_config(name=None, **overrides)` | Uses `llm.vlm_provider` or an explicit name; no chat fallback is assumed. |
| `MemoryStoreSpec.from_config(name=None, **overrides)` | Builds local memory store options from `memory.providers`. |
| `RathOpenAIChatClient` | Falls back to the first `provider_kind="openai"` config entry after Provider kwargs and environment variables. |
| `RathAnthropicChatClient` | Falls back to the first `provider_kind="anthropic"` config entry after Provider kwargs and environment variables. |
| `RathLiteLLMChatClient` | Does not scan OpenRath config directly; use `Provider.from_config(...)` before client dispatch. Requires `openrath[litellm]`. |
| `mcp_tools_from_config(name=None)` | Builds MCP tool wrappers from one configured stdio server. |
### Environment registry
`rath.config.env` is the central registry for provider and OpenSandbox
environment variables. (`OPENRATH_HOME` remains path configuration.) It
preserves the existing precedence:
**explicit field → environment → config**.
| API | Behavior |
| --- | --- |
| `get_env_spec(name)` | Returns one declared `EnvSpec` or raises on a typo. |
| `env_value(name)` | Returns a stripped value/default or `None`. |
| `env_flag(name)` | Interprets `1`, `true`, `yes`, or `on`. |
| `resolve_env(name, *explicit)` | Returns the first explicit non-empty value, then the environment tier. |
| `all_env_specs()` | Returns sorted declarations. |
| `env_reference_rows()` / `env_reference_markdown()` | Produces stable documentation data without secret values. |
## Autodoc
```{eval-rst}
.. autofunction:: rath.config.resolve_config_dir
.. autofunction:: rath.config.resolve_config_path
.. autofunction:: rath.config.is_project_local
.. autoclass:: rath.config.RathConfig
:members:
.. autoclass:: rath.config.LLMConfig
:members:
.. autoclass:: rath.config.LLMProviderConfig
:members:
.. autoclass:: rath.config.MCPConfig
:members:
.. autoclass:: rath.config.MCPServerConfig
:members:
.. autoclass:: rath.config.MemoryConfig
:members:
.. autoclass:: rath.config.MemoryProviderConfig
:members:
.. raw:: html
.. autoclass:: rath.config.schema.BackendConfig
:members:
.. raw:: html
.. autoclass:: rath.config.schema.BackendProviderConfig
:members:
.. autoclass:: rath.config.env.EnvSpec
:members:
.. autofunction:: rath.config.env.get_env_spec
.. autofunction:: rath.config.env.env_value
.. autofunction:: rath.config.env.env_flag
.. autofunction:: rath.config.env.resolve_env
.. autofunction:: rath.config.env.env_reference_markdown
.. autoclass:: rath.config.ConfigStore
.. autoexception:: rath.config.ConfigError
```
[← API Reference](index.md)