> ## Documentation Index
> Fetch the complete documentation index at: https://ahvn.top/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Scoped configuration with CM_HVNB.

<Note>
  *Once is fine. Twice is suspicious. Three times means you need to make your hyperparameters data.*
</Note>

Configuration is a layered dictionary backed by a retained config store. You read it like nested data, but HeavenBase resolves defaults, scope layers, version history, and interpolation for you.

<br />

## 1. Why Configuration Exists

Without a config manager, every wrapper that eventually calls a model, backend, prompt, cache, benchmark, or file helper has to accept and pass through the same knobs:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def enrich_user(
    user_id: str,
    model: str = "ds-flash",
    temperature: float = 0.0,
    seed: int = 42,
    timeout: int = 120,
    embedding_batch_size: int = 256,
):
    ...
```

That shape does not scale. A higher-level application quickly becomes a chain of functions that carry parameters they do not own. Changing one default means checking every wrapper. Adding one new backend or LLM option bloats signatures across unrelated code.

HeavenBase uses `CM_HVNB` to move those knobs into configuration data:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

model = CM_HVNB.get("heavenbase.llm.presets.chat.model")
timeout = CM_HVNB.get("heavenbase.llm.default_args.timeout", default=120)
```

Now application code can read the active defaults without turning every function into a pass-through config carrier. The function can still preserve important parameters that it needs to keep for other reasons, while the unimportant ones can be removed from the signature:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def enrich_user(user_id: str, model: str = None, embedding_batch_size: int = None):
    model = str(model or CM_HVNB.get("heavenbase.llm.presets.chat.model", default="ds-flash"))
    temperature = float(CM_HVNB.get("heavenbase.llm.default_args.temperature", default=0.0))
    seed = int(CM_HVNB.get("heavenbase.llm.default_args.seed", default=42))
    timeout = int(CM_HVNB.get("heavenbase.llm.default_args.timeout", default=120))
    embedding_batch_size = int(embedding_batch_size or CM_HVNB.get("heavenbase.llm.default_args.embedding_batch_size", default=256))
    ...
```

The legacy file-based shape also had a hard ceiling. A few local/global/default files work for one developer, but they become confusing when one package hosts multiple apps, environments, users, or experiments. HeavenBase keeps config layers in a database-backed store instead, so each scope can keep its own retained history and override only the values it owns.

<br />

## 2. Core Idea: Scoped Layers and App Overrides

In a nutshell, the HeavenBase configuration manager is using a database backend to store a scoped KV dictionary.

A scope is a named layer of overrides. Broad scopes hold shared defaults; narrower scopes override only what differs.

For example, `heavenbase.workspace.docs-demo` resolves through:

1. `heavenbase`
2. `heavenbase.workspace`
3. `heavenbase.workspace.docs-demo`

If the docs demo overrides only `heavenbase.query.near.default_top_k`, every other config value falls back to the broader scopes and finally to the package default template.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

scope = "heavenbase.workspace.docs-demo"
CM_HVNB.set("heavenbase.query.near.default_top_k", 25, scope=scope)

with CM_HVNB.scoped("workspace.docs-demo"):
    assert CM_HVNB.scope == scope
    top_k = CM_HVNB.get("heavenbase.query.near.default_top_k")
```

This is the application override pattern: set global infrastructure defaults once, then create child scopes for apps, environments, workspaces, tenants, or tests.

<Tip>
  Enter the scope before constructing objects that resolve config during `__init__`. If an `LLM`, workspace, backend, or helper snapshots config at construction time, changing the scope afterward will not rewrite the already-built object.
</Tip>

<Info>
  Scope is the only thing application code needs to carry. The actual model names, provider defaults, backend paths, serialization defaults, and prompt language can stay in config data instead of being threaded through every wrapper.
</Info>

<br />

## 3. Read Active Defaults

Start with `get(...)` when you need one value:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

top_k = CM_HVNB.get("heavenbase.query.near.default_top_k", default=50)
metric = CM_HVNB.get("heavenbase.query.near.default_metric", default="cosine")
```

Use `load()` when you want a mutable copy of the current merged config:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

config = CM_HVNB.load()
workspace_presets = config["heavenbase"]["workspace"]["presets"]
```

<Note>
  `load()` returns a copy. Mutating that dictionary does not write back to the config store.
</Note>

<br />

## 4. Use Scopes as Context

Use `scoped(...)` as a context manager when a block of code should read scoped values:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

with CM_HVNB.scoped("workspace.docs-demo"):
    top_k = CM_HVNB.get("heavenbase.query.near.default_top_k")
```

The same helper also works as a decorator:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

@CM_HVNB.scoped("workspace.docs-demo")
def read_metric() -> str:
    return CM_HVNB.get("heavenbase.query.near.default_metric")
```

Dynamic scopes can be provided by a callable when the active application context determines the scope name.

<br />

## 5. Reuse a Snapshot

For high-volume read paths, keep a snapshot and reuse it:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

snap = CM_HVNB.snapshot()
top_k = snap.get("heavenbase.query.near.default_top_k")
metric = snap.get("heavenbase.query.near.default_metric")
```

A snapshot is immutable. Config edits do not mutate snapshots you already hold. Ask for a fresh snapshot or call `CM_HVNB.refresh()` when a diagnostic path needs to bypass cached state immediately.

<br />

## 6. Edit a Scoped Layer

Config writes are persisted immediately. Use a scoped layer for demos and tests so you do not surprise the base configuration layer:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

scope = "heavenbase.workspace.docs-demo"

CM_HVNB.set("heavenbase.query.near.default_top_k", 25, scope=scope)
CM_HVNB.setdef("heavenbase.query.near.default_metric", "cosine", scope=scope)
CM_HVNB.unset("heavenbase.backends.vec", scope=scope)
```

List edits use path syntax:

* `items[0]` replaces an item.
* `items[]` appends.
* `items[2+]` inserts before index 2.

`unset(...)` writes a tombstone so a child scope can hide a value inherited from its parent scope. Dicts can use `__HB_OVERWRITE__` to replace a parent dict instead of recursively merging it.

<Warning>
  `remove(...)`, `compact(..., reset=True)`, and `setup(reset=True)` change retained config data. Use them only on scopes you intend to clean up.
</Warning>

<br />

## 7. Inspect Stored Layers

Use `layer(...)` when you need the raw layer stored in one scope before parent merge and interpolation:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

layer = CM_HVNB.layer(scope="heavenbase.workspace.docs-demo")
history = CM_HVNB.history(scope="heavenbase.workspace.docs-demo", limit=5)
known_scopes = CM_HVNB.scopes()
```

Each scope keeps retained versions. The default `heavenbase.config.versioning.keep_last_k` is `10`, so ordinary edits keep recent history without growing forever.

<br />

## 8. Use Resources and Package Paths

`resource(...)` resolves files under the package `resources/` directory when that package can be located. `load_default()` returns the in-memory default config template used to initialize scopes.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import CM_HVNB

default_yaml = CM_HVNB.resource("configs", "default.yaml")
config_db = CM_HVNB.pj("%/config.db", abs=True)
default_template = CM_HVNB.load_default()
```

`CM_HVNB.pj(...)` understands HeavenBase package aliases such as `%/` for package-local data and `&/` for package resources. For ordinary caller-provided paths, use `pj(...)` from the File System utilities instead. See [File System](/features/utilities/file-system) for more details.

<br />

## 9. Understand Interpolation

OmegaConf interpolation resolves when a snapshot is compiled:

* `${env:VAR}` is allowed by default.
* `${oc.env:VAR,default}` works through OmegaConf.
* `${cmd:...}` is disabled by default and requires an explicit policy override.

This is why provider defaults can read environment variables without making every call site handle environment parsing by hand.

<br />

## Further Exploration

<Tip>
  **Related resources:**

  * [Overview](/features/utilities/overview) - the rest of the Utilities Toolbox.
  * [File System](/features/utilities/file-system) - path and file helpers used around config artifacts.
  * [CLI Reference](/reference/cli/overview) - `hb config` commands over the same config manager.
</Tip>

<br />
