# How to Manage Configuration Using pydantic BaseSettings in DimOS

> Learn how to manage configuration in DimOS using pydantic BaseSettings. Centralize runtime settings from environment variables CLI flags and programmatic overrides into a single typed source of truth.

- Repository: [Dimensional/dimos](https://github.com/dimensionalOS/dimos)
- Tags: how-to-guide
- Published: 2026-03-15

---

**DimOS centralizes all runtime configuration in a singleton `GlobalConfig` class that inherits from `pydantic_settings.BaseSettings`, merging environment variables, dynamic CLI flags, and programmatic overrides into a single typed source of truth.**

DimOS (dimensionalOS/dimos) implements a robust configuration management pattern using pydantic BaseSettings. The recommended approach relies on a global singleton instance that lazy-loads values from `.env` files, automatically exposes every field as a CLI option, and supports runtime mutations without requiring application restarts.

## The GlobalConfig Singleton Pattern

All configuration resides in [`dimos/core/global_config.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/global_config.py) within the **`GlobalConfig`** class. This class subclasses **`pydantic_settings.BaseSettings`** and instantiates a singleton **`global_config = GlobalConfig()`** that is imported across the codebase.

Because `BaseSettings` parses environment variables lazily on first access, the singleton reflects the final merged configuration throughout the process tree. Modules receive consistent values whether they import `global_config` directly or accept it as a default parameter.

```python

# dimos/core/global_config.py

from pydantic_settings import BaseSettings, SettingsConfigDict

class GlobalConfig(BaseSettings):
    robot_ip: str = "localhost"
    simulation: bool = False
    
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

global_config = GlobalConfig()

```

## Configuration Sources and Precedence

DimOS merges configuration from three sources in the following priority order:

1. **Environment variables** loaded from a `.env` file via `SettingsConfigDict(env_file=".env")`
2. **CLI flags** generated dynamically from `GlobalConfig.model_fields`
3. **Programmatic overrides** via `global_config.update(...)`

### Environment Variables and .env Files

The `model_config` specifies `env_file=".env"` and `extra="ignore"`, allowing users to define defaults in a repository-root `.env` file without code changes. Variable names are case-insensitive and support standard pydantic type coercion.

```bash

# .env

ROBOT_IP=192.168.1.42
SIMULATION=true
VIEWER=rerun-web

```

### CLI Flags (Dynamic Typer Integration)

The CLI entry point in [`dimos/robot/cli/dimos.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/robot/cli/dimos.py) inspects `GlobalConfig.model_fields` to generate a Typer option for every configuration field. Adding a new field to `GlobalConfig` automatically exposes it as a `--kebab-case` flag without additional boilerplate.

### Programmatic Overrides

For runtime mutations, `GlobalConfig.update(**kwargs)` merges new values into the existing singleton instance. This allows the CLI or custom scripts to inject overrides after initialization.

## Declaring New Configuration Fields

Add typed fields to `GlobalConfig` to extend configuration. Each field requires a Python type annotation (`bool`, `int`, `float`, `Literal[...]`) to enable IDE autocompletion and static analysis.

```python

# dimos/core/global_config.py

from typing import Literal, TypeAlias

ViewerBackend: TypeAlias = Literal["rerun", "rerun-web", "rexconnect", "foxglove", "none"]

class GlobalConfig(BaseSettings):
    viewer: ViewerBackend = "rerun"
    navigation_timeout: int | None = None
    # Existing fields...

    
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

```

Any new field immediately becomes:
- An environment variable (e.g., `NAVIGATION_TIMEOUT=30`)
- A CLI flag (e.g., `--navigation-timeout 30`)

## Runtime Configuration Updates

Use the `update()` method to modify configuration after initialization. This pattern supports CLI flag injection and dynamic reconfiguration without recreating the singleton.

```python

# Custom script or CLI callback

from dimos.core.global_config import global_config

# Override specific values

global_config.update(viewer="foxglove", simulation=True)

print(global_config.viewer)      # → "foxglove"

print(global_config.simulation)  # → True

```

Modules should import `global_config` to access current values:

```python

# dimos/perception/perceive_loop_skill.py

from dimos.core.global_config import GlobalConfig, global_config

class PerceiveLoopSkill:
    def __init__(self, cfg: GlobalConfig = global_config):
        self._cfg = cfg
        
    def start(self):
        if self._cfg.simulation:
            self._setup_simulated_camera()

```

## CLI Integration

Running `dimos --help` reveals dynamically generated options mapping to every `GlobalConfig` field:

```bash
$ dimos --help
Options:
  --robot-ip TEXT                 Override robot_ip in GlobalConfig
  --simulation / --no-simulation  Override simulation in GlobalConfig
  --viewer TEXT                   Override viewer in GlobalConfig
  --navigation-timeout INTEGER    Override navigation_timeout in GlobalConfig

```

The dynamic callback in [`dimos/robot/cli/dimos.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/robot/cli/dimos.py) constructs these options by iterating over `GlobalConfig.model_fields`, ensuring new configuration fields are instantly available to users.

## Key Implementation Files

- **[`dimos/core/global_config.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/global_config.py)** — Central `GlobalConfig` definition and singleton instantiation
- **[`dimos/robot/cli/dimos.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/robot/cli/dimos.py)** — Dynamic Typer CLI option generation from `GlobalConfig.model_fields`
- **[`dimos/core/module_coordinator.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/module_coordinator.py)** — Example consumer importing the `global_config` singleton

## Summary

- **Use the singleton** `global_config` imported from `dimos.core.global_config` for consistent configuration access across modules.
- **Declare typed fields** on `GlobalConfig` to add new configuration options; pydantic handles validation and `.env` loading automatically.
- **Leverage `update()`** for runtime mutations without rebuilding the configuration object.
- **Rely on automatic CLI generation**—new fields appear as flags immediately without modifying [`dimos/robot/cli/dimos.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/robot/cli/dimos.py).
- **Set defaults in `.env`** using the `env_file` loading built into `SettingsConfigDict`.

## Frequently Asked Questions

### How does GlobalConfig handle environment variables?

`GlobalConfig` uses `SettingsConfigDict(env_file=".env", extra="ignore")` to load variables from a `.env` file at the repository root. Pydantic matches environment variable names to field names case-insensitively and coerces values to the declared Python types (e.g., parsing `"true"` as a boolean).

### Can I override configuration values at runtime?

Yes. Call `global_config.update(**kwargs)` to merge new values into the existing singleton instance. This method is used by the CLI to inject flag overrides after parsing arguments, and can be called from any module to change configuration dynamically.

### How do I add a new configuration option to DimOS?

Add a typed field to the `GlobalConfig` class in [`dimos/core/global_config.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/global_config.py). For example, `new_param: str = "default"`. The field immediately becomes available as an environment variable `NEW_PARAM`, a CLI flag `--new-param`, and a mutable attribute on the `global_config` singleton.

### Where is the CLI option generation handled?

The CLI dynamically builds options in [`dimos/robot/cli/dimos.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/robot/cli/dimos.py) by inspecting `GlobalConfig.model_fields`. The code creates a `Typer.Option` for each field, mapping configuration keys to command-line flags without requiring manual updates when fields are added or removed.