# config

URL: /milo-cli/api/milo/config/
Section: milo
Description: Configuration system with deep merge, environment overlays, and origin tracking.

---

> For a complete page index, fetch /milo-cli/llms.txt.

Open LLM text
(/milo-cli/api/milo/config/index.txt)

Share with AI

Ask Claude
(https://claude.ai/new?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fmilo-cli%2Fapi%2Fmilo%2Fconfig%2Findex.txt)

Ask ChatGPT
(https://chatgpt.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fmilo-cli%2Fapi%2Fmilo%2Fconfig%2Findex.txt)

Ask Gemini
(https://gemini.google.com/app?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fmilo-cli%2Fapi%2Fmilo%2Fconfig%2Findex.txt)

Ask Copilot
(https://copilot.microsoft.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fmilo-cli%2Fapi%2Fmilo%2Fconfig%2Findex.txt)

Module

#
`config`

Configuration system with deep merge, environment overlays, and origin tracking.

2Classes10Functions

## Classes

`ConfigSpec`

5

▼

Declarative configuration schema.

Describes where config comes from and how it merges::

cli.c…

Declarative configuration schema.

Describes where config comes from and how it merges::

```
cli.config_spec = ConfigSpec(
    sources=("bengal.toml", "config/*.yaml"),
    env_prefix="BENGAL_",
    profiles={"writer": {"build.drafts": True}},
    overlays={"production": "config/production.yaml"},
)
```

#### Attributes

Name
Type
Description

`sources`

`tuple[str, ...]`

—

`env_prefix`

`str`

—

`defaults`

`dict[str, Any]`

—

`profiles`

`dict[str, dict[str, Any]]`

—

`overlays`

`dict[str, str]`

—

`Config`

12

▼

Immutable, merged configuration with origin tracking.

Usage::

config = Config.load(spec, root…

Immutable, merged configuration with origin tracking.

Usage::

```
config = Config.load(spec, root=Path("."), profile="dev", overlay="production")
url = config.get("site.url", "http://localhost")
print(config.origin_of("site.url"))  # "file:config/site.yaml"
```

#### Methods

`load`

4

`Config`

▼

Load, merge, and freeze config from all sources.

Merge precedence (lowest to h…

classmethod

`def load(cls, spec: ConfigSpec, *, root: Path | None = None, profile: str = '', overlay: str = '') -> Config`

Load, merge, and freeze config from all sources.

Merge precedence (lowest to highest):

- spec.defaults

- File sources (in order)

- Environment variables

- Profile overrides

- Overlay file

##### Parameters

Name
Type
Description

`spec`
`—`

`root`
`—`

Default:`None`

`profile`
`—`

Default:`''`

`overlay`
`—`

Default:`''`

##### Returns

`Config`

`from_dict`

2

`Config`

▼

Create a Config from a plain dictionary.

classmethod

`def from_dict(cls, data: dict[str, Any], origin: str = 'dict') -> Config`

##### Parameters

Name
Type
Description

`data`
`—`

`origin`
`—`

Default:`'dict'`

##### Returns

`Config`

`get`

2

`Any`

▼

Dot-notation access: ``config.get("site.url")``.

`def get(self, key: str, default: Any = None) -> Any`

##### Parameters

Name
Type
Description

`key`
`—`

`default`
`—`

Default:`None`

##### Returns

`Any`

`origin_of`

1

`str`

▼

Return the source that contributed a key's value.

`def origin_of(self, key: str) -> str`

##### Parameters

Name
Type
Description

`key`
`—`

##### Returns

`str`

`as_dict`

0

`dict[str, Any]`

▼

Return a deep copy of the merged config.

`def as_dict(self) -> dict[str, Any]`

##### Returns

`dict[str, Any]`

`to_state`

0

`dict[str, Any]`

▼

Convert to a Store-compatible state dict.

`def to_state(self) -> dict[str, Any]`

##### Returns

`dict[str, Any]`

`validate`

2

`list[str]`

▼

Validate config values against the spec's defaults for type consistency.

Retur…

`def validate(self, spec: ConfigSpec, *, raise_on_error: bool = False) -> list[str]`

Validate config values against the spec's defaults for type consistency.

Returns a list of error messages. An empty list means validation passed.
Type expectations are inferred from the default values in`spec.defaults`.

When raise_on_error is True, raises`ConfigError`if any
validation errors are found instead of returning the list.

##### Parameters

Name
Type
Description

`spec`
`—`

`raise_on_error`
`—`

Default:`False`

##### Returns

`list[str]`

`init`

3

`Path`

▼

Generate a starter config file from a ConfigSpec.

Writes spec.defaults to the …

staticmethod

`def init(spec: ConfigSpec, *, root: Path | None = None, fmt: str = 'toml') -> Path`

Generate a starter config file from a ConfigSpec.

Writes spec.defaults to the first source pattern's filename.
Returns the path of the created file.

##### Parameters

Name
Type
Description

`spec`
`—`

`root`
`—`

Default:`None`

`fmt`
`—`

Default:`'toml'`

##### Returns

`Path`

Internal Methods
4

▼

`__init__`

2

▼

`def __init__(self, data: dict[str, Any], origins: dict[str, str]) -> None`

##### Parameters

Name
Type
Description

`data`
`—`

`origins`
`—`

`_validate_types`

4

▼

Recursively check that actual values match the types of defaults.

staticmethod

`def _validate_types(defaults: dict[str, Any], actual: dict[str, Any], errors: list[str], prefix: str) -> None`

##### Parameters

Name
Type
Description

`defaults`
`—`

`actual`
`—`

`errors`
`—`

`prefix`
`—`

`__contains__`

1

`bool`

▼

`def __contains__(self, key: str) -> bool`

##### Parameters

Name
Type
Description

`key`
`—`

##### Returns

`bool`

`__repr__`

0

`str`

▼

`def __repr__(self) -> str`

##### Returns

`str`

## Functions

`_load_file`

1

`dict[str, Any]`

▼

Load a TOML or YAML file.

`def _load_file(filepath: str) -> dict[str, Any]`

##### Parameters

Name
Type
Description

`filepath`
`str`

##### Returns

`dict[str, Any]`

`_load_env_vars`

1

`dict[str, Any]`

▼

Load environment variables with a given prefix into nested dict.

BENGAL_SITE_U…

`def _load_env_vars(prefix: str) -> dict[str, Any]`

Load environment variables with a given prefix into nested dict.

BENGAL_SITE_URL -> {"site": {"url": "value"}}

##### Parameters

Name
Type
Description

`prefix`
`str`

##### Returns

`dict[str, Any]`

`_deep_merge`

5

`None`

▼

Deep merge source into target, tracking origins for leaf values.

`def _deep_merge(target: dict[str, Any], source: dict[str, Any], origins: dict[str, str], origin: str, prefix: str = '') -> None`

##### Parameters

Name
Type
Description

`target`
`dict[str, Any]`

`source`
`dict[str, Any]`

`origins`
`dict[str, str]`

`origin`
`str`

`prefix`
`str`

Default:`''`

`_track_origins`

4

`None`

▼

Recursively track origins for all keys in a dict.

`def _track_origins(data: dict[str, Any], origins: dict[str, str], origin: str, prefix: str) -> None`

##### Parameters

Name
Type
Description

`data`
`dict[str, Any]`

`origins`
`dict[str, str]`

`origin`
`str`

`prefix`
`str`

`_expand_dotted`

1

`dict[str, Any]`

▼

Expand dotted keys into nested dicts.

{"build.output": "_site"} -> {"build": {…

`def _expand_dotted(flat: dict[str, Any]) -> dict[str, Any]`

Expand dotted keys into nested dicts.

{"build.output": "_site"} -> {"build": {"output": "_site"}}

##### Parameters

Name
Type
Description

`flat`
`dict[str, Any]`

##### Returns

`dict[str, Any]`

`_write_toml`

2

`None`

▼

Write a dict as TOML (stdlib-only, simple values).

`def _write_toml(filepath: Path, data: dict[str, Any]) -> None`

##### Parameters

Name
Type
Description

`filepath`
`Path`

`data`
`dict[str, Any]`

`_write_toml_section`

3

`None`

▼

Recursively write TOML sections.

`def _write_toml_section(data: dict[str, Any], lines: list[str], prefix: str) -> None`

##### Parameters

Name
Type
Description

`data`
`dict[str, Any]`

`lines`
`list[str]`

`prefix`
`str`

`_toml_value`

1

`str`

▼

Format a Python value as TOML.

`def _toml_value(value: Any) -> str`

##### Parameters

Name
Type
Description

`value`
`Any`

##### Returns

`str`

`_write_yaml`

2

`None`

▼

Write a dict as YAML.

`def _write_yaml(filepath: Path, data: dict[str, Any]) -> None`

##### Parameters

Name
Type
Description

`filepath`
`Path`

`data`
`dict[str, Any]`

`_write_yaml_simple`

3

`None`

▼

Simple YAML writer for basic types.

`def _write_yaml_simple(data: dict[str, Any], lines: list[str], indent: int) -> None`

##### Parameters

Name
Type
Description

`data`
`dict[str, Any]`

`lines`
`list[str]`

`indent`
`int`
