Skip to main content
Realm inheritance shares configuration without sharing state. A realm can name one parent; resolution walks that linear chain and folds config root-first so the child wins.
This supports one global login, organization-wide MCP and hook policy, and workspace-specific model or limit overrides without copying config into every realm.

Resolve The Chain

A realm declares its parent in its owning config document:
Rules:
  • The chain is head-first and follows exactly one parent at each step.
  • A realm’s own document decides its own parent edge. Every ancestor is configured by its own document alone: a section another document states for it never stands in for it, and an ancestor whose own document is missing fails the chain (a missing parent) rather than composing as if it contributed nothing. Only the head realm takes a section another document states for it when its own document states none, and any composed document’s [realm.global] section configures global.
  • rkat realm delete and rkat realm prune keep a realm that another realm’s own document names as its parent, naming the child.
  • A terminal non-global realm appends global when a global config section is present.
  • An explicit parent of global is allowed even when no global section has been materialized; the absent document contributes nothing.
  • global is the root and cannot declare a parent.
  • Unrelated sibling realms are never searched.
  • The maximum chain depth is 16.
Traversal of explicit parent edges fails closed on a cycle, missing non-global parent, a parent of env_default, a parent on global, or excessive depth.
The current implicit-global append has a validation gap: it does not inspect global.parent or recheck depth after appending the tail. A chain of sixteen non-global nodes can therefore return seventeen nodes after that append. Keep global parentless and the entire chain within sixteen nodes; these remain configuration requirements, not relaxed limits. Do not rely on the implicit-tail path to enforce those two checks.
An absent head is legal for internal default-selection paths: it contributes no config and may still reach a configured global tail before environment fallback. A caller that explicitly names a configured realm or binding requires that head to exist and receives a typed error when it does not. The synthetic environment default is not a config realm. It cannot be a parent, cannot own durable config, and is selected only by the typed environment fallback path.

State Never Inherits

Every state domain remains keyed to the consuming head realm:
  • sessions and transcripts;
  • runtime liveness, operation-delivery state, provisional physical successors, and exact run-boundary receipts;
  • schedules, WorkGraph, and jobs;
  • blobs and artifacts;
  • mob state and derived projections.
A child never reads a parent’s sessions merely because it inherits the parent’s config. Storage providers open the child realm’s own stores.

Config Composes Root-First

The effective config fold starts from built-in defaults, then applies the resolved chain from root to head, then applies per-request overrides. There are no removal tombstones for inherited MCP servers, hooks, or skill sources. An empty child section does not delete a parent entry. config get, config set, and config patch operate on the raw head document. Runtime agent construction reads the composed effective config. This read/write split keeps inherited entries out of the child’s document, but a config get then config set round trip still flattens the child: config get returns the head document as a typed config with every default filled in, and config set is a full replace that writes each of those defaults as the child’s own override. The child then stops inheriting them, including capabilities the parent disabled. RFC 7396 config patch updates only the keys it names in the raw document (null removes a key so it inherits again); it is distinct from these realm-composition rules. Use it for partial edits.

Credentials Read Down, Write To The Owner

A child can use a binding defined by a parent or by global, but the resolved reference records the realm that defines it:
  • Reads inherit. Runtime resolution walks the chain and can select a matching ancestor binding.
  • HostAuthService and RPC/REST writes are strict-owner and explicitly addressed. A child-addressed credential write to an inherited binding is rejected and reports the owner so the caller can retarget; those services do not forward it automatically.
  • Managed leases use owner provenance. AuthMachine, TokenStore, and refresh coordination use the owning realm plus binding and optional profile by default. A configured credential_account instead uses the owning realm plus account, sharing the credential lifecycle across route bindings.
Current CLI logout exception: when the loaded config resolves child:<binding> to an inherited owner, rkat auth logout child:<binding> can clear that owner’s stored credential, including a shared account used by other routes. Explicitly address the true owner instead. A bare logout binding means global; --realm does not retarget logout. This exception does not change the strict-owner host/RPC/REST contract or the config read/write split.
Environment, inline-secret, and command sources still resolve their material at use time, but the configured binding itself retains owner provenance. Backend and auth profiles referenced by a binding are resolved inside the same owning realm section. A child cannot combine its auth profile with a parent binding or silently replace one half of an inherited pair.

The Global Realm

global is a reserved configured realm with a special document location:
Interactive OAuth/device rkat auth login provisions nonsecret binding configuration in this document and stores its credential separately through TokenStore under the global credential identity. Scripted API-key login only stores a token and requires matching managed-store config. Once a [realm.global] section exists, it becomes the implicit tail for workspace realms without another explicit terminal parent. The global realm is different from env_default:

Legacy Login Migration

Older Meerkat versions stored CLI logins under dev. The current run path has an idempotent no-clobber migration that copies an absent token/binding to global. New documentation and config should use global; dev is not a special fallback realm.

See Also