---
title: "Realms"
description: "Realm-first identity and storage model across CLI, RPC, REST, MCP, and SDK surfaces."
icon: "earth-americas"
---

Meerkat is realm-first. A `realm_id` is the only identity key for sharing or isolating state across surfaces.

For task-oriented CLI behavior, filesystem layout, and troubleshooting, see the
[realm guide](/guides/realms).

## Core rules

1. Same `realm_id` means shared sessions, config, and runtime metadata.
2. Different `realm_id` means strict isolation, even from the same folder.
3. Backend (`sqlite` or `jsonl`) is pinned once per realm via `realm_manifest.json`.
4. Realm IDs are user-chosen stable identifiers with syntax constraints. Reuse the same value to collaborate across surfaces.

Realm IDs must be 1-64 characters, start with an ASCII alphanumeric character, and may contain only ASCII alphanumerics, `_`, and `-`. They cannot contain whitespace or `:`, and UUID-like opaque values are rejected for explicit user-facing realm IDs.

## Surface defaults

| Surface | If `realm_id` is not provided |
|---------|-------------------------------|
| CLI (`rkat run/resume/sessions`) | Workspace-derived stable realm (`ws-...`) |
| RPC (`rkat-rpc`) | New opaque realm (`realm-...`) |
| REST (`rkat-rest`) | New opaque realm (`realm-...`) |
| MCP server (`rkat-mcp`) | New opaque realm (`realm-...`) |
| Python/TypeScript SDK | Whatever the spawned `rkat-rpc` process picks (new opaque realm unless `realm_id` is passed) |

This means CLI is workspace-friendly by default, while non-CLI surfaces are isolated by default.

The CLI workspace default uses the current directory as `context_root`, derives
identity from that path, and stores realm runtime state under
`<context-root>/.rkat/realms/` unless `--context-root` or `--state-root` is
provided.

## Explicit sharing

Use the same realm everywhere:

```bash
rkat --realm team-alpha run "Draft release plan"
rkat --realm team-alpha sessions list
rkat-rpc --realm team-alpha
rkat-rest --realm team-alpha
rkat-mcp --realm team-alpha
```

SDKs pass the same value when connecting:

```python
await client.connect(realm_id="team-alpha")
```

```ts
await client.connect({ realmId: "team-alpha" })
```

## Backend pinning

On first use, a realm writes a manifest with backend choice. Later opens must honor it.

| First open | Manifest pins |
|------------|----------------|
| `--realm-backend sqlite` | `sqlite` |
| `--realm-backend jsonl` | `jsonl` |
| No hint | `sqlite` when compiled, otherwise `jsonl` |

After pinning, all surfaces use the manifest backend for that realm.

## Default backend and same-realm sharing

When SQLite support is compiled in, new persistent realms default to `sqlite`.

- `sqlite` is the recommended backend for the normal Meerkat operating mode where multiple processes share one realm.
- `jsonl` remains explicitly selectable for inspectable file-based persistence.

Existing realms stay pinned to the backend recorded in their manifest. Changing the default does not migrate old realms.

## Config and CAS

Config is realm-scoped and generation-based.

- `config/get` returns the core envelope fields `config`, `generation`, `realm_id`, `instance_id`, and `backend`.
- Some surfaces may also include diagnostic fields such as `resolved_paths`, but those should be treated as optional.
- `config/set` and `config/patch` accept optional `expected_generation`.
- Stale writes fail deterministically with generation conflict.

`resolved_paths` should be treated as a diagnostic/admin field rather than a guaranteed universal field on every public config envelope.

## Why this solves multi-surface concurrency

1. 100 RPC servers from the same folder without `realm_id` do not collide.
2. 100 agents across RPC/REST/MCP/CLI with the same `realm_id` see the same state.
3. CLI workspace ergonomics remain simple without forcing filesystem identity onto non-CLI surfaces.

## See also

- [Sessions](/concepts/sessions)
- [Configuration](/concepts/configuration)
- [CLI commands](/cli/commands)
- [JSON-RPC](/api/rpc)
