---
title: "Configuration"
description: "Realm-scoped config, generation CAS, and surface-consistent runtime settings."
icon: "sliders"
---

Configuration is realm-scoped. The active `realm_id` determines which config file is read and written.

## Realm-scoped config

Every realm has its own config file and runtime state:

- `config.toml` (user settings)
- `config_state.json` (generation counter for CAS)
- `realm_manifest.json` (pinned backend + metadata)

The canonical location is under the active realm state root. For CLI commands,
the default is project-local:

```text
<context-root>/.rkat/realms/<realm>/
```

For daemon/API surfaces that do not receive a `--state-root`, the default state
root is the platform data directory:

- macOS: `~/Library/Application Support/meerkat/realms/<realm>/`
- Linux: `~/.local/share/meerkat/realms/<realm>/`
- Windows: `%APPDATA%\meerkat\realms\<realm>\`

Use [realms](/concepts/realms) to choose whether state is shared or isolated.

## Effective precedence

For a given realm, effective persisted configuration is:

1. Built-in defaults
2. Realm `config.toml`
3. Per-request runtime parameters (for example model/system prompt/tool toggles on create/resume calls)

Environment variables still matter, but they are primarily part of **runtime credential resolution**, not a general config layer that mutates the loaded realm config. In practice:

- realm config remains the canonical persisted settings surface
- provider credentials can still come from `RKAT_*` or provider-native env vars at resolve time
- bindings and auth profiles decide how those credentials are used at runtime

## Config APIs and CAS

RPC, REST, and MCP all expose the same config envelope:

- `config`
- `generation`
- `realm_id`
- `instance_id`
- `backend`

Some surfaces also expose `resolved_paths` in diagnostic/admin contexts. Treat that field as optional rather than universal across all public config envelopes.

Writes support optimistic concurrency:

- `config/set` and `config/patch` accept optional `expected_generation`
- stale writes return generation conflict

This gives deterministic behavior when multiple clients or processes update config concurrently.

## Merge semantics

Meerkat uses two distinct update models:

1. Layered config loading (`defaults -> file -> runtime`) uses **field-wise merge**:
  - scalar/option values: last non-default wins
  - section values (for example `providers`, `store`, `comms`, `compaction`): replace whole section
  - hook entries: append/extend
2. Runtime patch APIs (`config/patch`, `PATCH /config`) use **RFC 7396 JSON merge-patch** semantics.

Use `config/set` when replacing the whole config intentionally, and `config/patch` for surgical updates.

## CLI behavior

CLI config commands operate on the selected realm:

```bash
rkat --realm team-alpha config get --format json
rkat --realm team-alpha config get --format json --with-generation
rkat --realm team-alpha config patch --json '{"agent":{"model":"gpt-5.5"}}' --expected-generation 4
```

Without `--realm`, CLI derives a stable workspace realm (`ws-...`) from the
current directory, or from `--context-root` when supplied.

## What about `~/.rkat/config.toml` and `.rkat/config.toml`?

Those files still exist for compatibility and developer ergonomics (`rkat init`, legacy flows, and some layered hook loading behavior), but realm config is the canonical runtime configuration for CLI/RPC/REST/MCP surfaces.

## Backend and storage settings

Session backend is pinned per realm in `realm_manifest.json` (`sqlite` or `jsonl`).
`--realm-backend` only matters on first creation of a realm.

## Compaction settings

Compaction runtime policy is configurable in realm config:

```toml
[compaction]
auto_compact_threshold = 100000
recent_turn_budget = 4
max_summary_tokens = 4096
min_turns_between_compactions = 3
```

When `session-compaction` is enabled, `AgentFactory` maps these values into the runtime `CompactionConfig`.

## See also

- [Realms](/concepts/realms)
- [Sessions](/concepts/sessions)
- [CLI configuration](/cli/configuration)
