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

# Realms

> The identity, isolation, storage, and durability boundary shared across Meerkat surfaces.

A realm is Meerkat's state boundary. Sessions, config, auth bindings, runtime
state, schedules, WorkGraph, jobs, blobs, artifacts, and mob state are all
scoped by a `realm_id`.

Sharing requires both the same logical realm and the same physical storage
provider/root. Supplying the same ID with two deliberately different explicit
state roots selects two different stores.

For task-oriented commands and troubleshooting, see the
[realm guide](/guides/realms).

## Identity Rules

Explicit user-facing realm IDs:

* are 1-64 characters;
* start with an ASCII alphanumeric character;
* contain only ASCII alphanumerics, `_`, and `-`;
* cannot contain whitespace or `:`; and
* cannot use a UUID-like opaque value.

Use a stable descriptive ID such as `team-alpha`, `prod`, or `audit_2026`.
Meerkat-generated workspace and isolated IDs use separate typed construction
paths.

## Surface Defaults

| Surface                         | No explicit realm                                                                                                                              |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| CLI run/resume/session commands | Stable `ws-...` ID derived from the canonicalized current directory or `--context-root`, with raw-path fallback only if canonicalization fails |
| `rkat-rpc`                      | Fresh opaque `realm-...` ID                                                                                                                    |
| `rkat-rest`                     | Fresh opaque `realm-...` ID                                                                                                                    |
| `rkat-mcp`                      | Fresh opaque `realm-...` ID                                                                                                                    |
| Python/TypeScript SDK           | The realm selected by the connected/spawned `rkat-rpc`; fresh unless the client passes one                                                     |

The CLI is workspace-friendly by default. Server processes are isolated by
default so unrelated launches do not collide.

## Context Root And Project Root

Meerkat keeps two path facts distinct:

* **Invocation context** is the supplied current directory or `--context-root`.
  Its canonicalized path determines the workspace-derived realm ID (raw path
  only if canonicalization fails), while the supplied path remains the
  no-walk-up boundary for MCP config/trust discovery.
* **Project root** is found by walking upward from the invocation context to the
  nearest existing `.rkat` entry. Its `.rkat/realms` directory is the
  project-local realm-storage candidate. Outside any existing project, the
  exact invocation context is used for a fresh local candidate.

Running from a nested directory can therefore derive a different default
`ws-...` realm while storing that realm under the ancestor project's
`.rkat/realms`. Use an explicit `--realm` or a common `--context-root` when
the nested command should share the parent's logical realm.

## Realm-ID-First Root Resolution

Meerkat resolves identity first, then looks for that realm under candidate
roots:

1. `--state-root` selects one explicit root and disables candidate probing.
2. Otherwise, the resolver probes the project-local candidate and user-global
   platform data root for the resolved realm ID.
3. If the realm exists under exactly one candidate, Meerkat opens it where it
   already lives.
4. If it exists under both, startup refuses with a typed split-brain error
   rather than choosing silently.
5. If it exists nowhere, the surface creates it under its default root: local
   for CLI and user-global for servers.

Server surfaces include the project-local candidate only when started with an
explicit context root.

First creation reserves the realm across the candidate set that invocation
actually resolved before writing the manifest. Processes using the same
multi-root candidate set cannot mint twins, but a bare server that probes only
the user-global root does not coordinate with a CLI probing a project-local
root. Use a common `--state-root` or matching server `--context-root` when
cross-surface first-start convergence matters.

Use these operator commands when layout is unclear:

```bash theme={null}
rkat realm current
rkat realm show <realm>
rkat realm list
rkat storage doctor
rkat storage migrate
```

`rkat storage migrate` is a report-only dry run unless `--apply` is
supplied. Adopting one root archives the other registered copy; it does not
merge divergent state automatically.

## Explicit Sharing

```bash theme={null}
rkat --state-root /srv/meerkat/realms --realm team-alpha run "Draft release plan"
rkat --state-root /srv/meerkat/realms --realm team-alpha session list
rkat-rpc --state-root /srv/meerkat/realms --realm team-alpha
rkat-rest --state-root /srv/meerkat/realms --realm team-alpha
rkat-mcp --state-root /srv/meerkat/realms --realm team-alpha
```

SDK clients pass the same value when connecting:

```python theme={null}
await client.connect(realm_id="team-alpha", state_root="/srv/meerkat/realms")
```

```typescript theme={null}
await client.connect({ realmId: "team-alpha", stateRoot: "/srv/meerkat/realms" })
```

When separate hosts do not share a filesystem, use the same external
`RealmStorageProvider` rather than assuming equal realm IDs make local disks
shared.

## Backend And Provider Pinning

The first open writes `realm_manifest.json`. It pins the built-in backend or
external storage provider, so later surfaces cannot reinterpret the realm:

| First-open choice        | Pinned value                                       |
| ------------------------ | -------------------------------------------------- |
| `--realm-backend sqlite` | `sqlite`                                           |
| `--realm-backend jsonl`  | `jsonl`                                            |
| `--realm-backend memory` | `memory`                                           |
| No hint                  | `sqlite` when compiled, otherwise `jsonl`          |
| External provider        | `external:<provider-name>` plus the provider field |

`sqlite` is the normal durable same-realm multi-process profile. `jsonl`
keeps inspectable session files and a durable `runtime.sqlite3` companion for
runtime authority. `memory` is explicitly ephemeral and process-local.

Manifest format 2 can also record operator-declared ephemeral domains. A storage provider
must declare exactly one durability result for each required domain:
`sessions`, `runtime`, `schedule`, `workgraph`, `jobs`, `blobs`, and
`artifacts`. A durable domain resolving to undeclared non-persistent storage
refuses startup unless the manifest explicitly declares that domain ephemeral.
A provider can instead return the typed `DeclaredEphemeral` resolution itself,
as the JSONL backend does for its disabled schedule store; that typed provider
declaration does not require a duplicate manifest entry.

Readers reject a manifest format newer than they support and reject a provider
or backend mismatch. Existing realms remain pinned when defaults change.

## Config And State

The realm's own config document is `<state-root>/<realm>/config.toml`, except
for the reserved `global` realm, whose config is home-rooted at
`~/.rkat/config.toml`.

Config can inherit from parent realms, but state never does. A child can inherit
models, bindings, MCP servers, hooks, skills, and limits while keeping its
sessions and every durable state domain local.

## See Also

* [Realm guide](/guides/realms)
* [Realm inheritance](/concepts/realm-inheritance)
* [Storage operations](/guides/storage-operations)
* [Configuration](/concepts/configuration)
* [Sessions](/concepts/sessions)
