Skip to main content

Global runtime scope flags

The top-level CLI parser exposes these realm scope and config flags:
  • --realm <id>
  • --isolated
  • --instance <id>
  • --realm-backend <sqlite|jsonl|memory> (creation hint only)
  • --state-root <path>
  • --context-root <path>
  • --user-config-root <path>
  • --default-model <model>
  • --confinement <trusted-host|workspace>, with --confinement-network <denied|unrestricted>, --confinement-read <path> and --confinement-write <path> (see OS process confinement)
The scope flags decide which realm config and state are used. --user-config-root overrides the user-level convention root. --default-model validates and persists the model in the scope-resolved config, then continues with the command or exits when no command was given. Storage maintenance verbs reject --isolated and --default-model because they dispatch before runtime-scope resolution. rkat mob host also rejects --isolated; a member host must use a stable workspace or explicit realm.

Default realm behavior

If you want CLI + RPC to share the same state, pass both the same explicit --realm and the same --state-root, resolving to the same physical store and provider. A matching server --context-root assists project-local candidate discovery; it does not select the CLI’s realm identity or guarantee the same root. Without --realm, RPC still creates an isolated realm. For CLI commands, the default invocation context is the current directory. The project-local state root is <project-root>/.rkat/realms, where the project root is the nearest ancestor containing a .rkat entry. If none exists, the context root is used. --context-root changes the ancestor-search starting point; --state-root bypasses discovery. Use --verbose on rkat run to print the active realm, context root, and physical realm root. See the realm guide for the full identity-vs-storage model.

Environment variables

For direct environment-backed provider auth, set at least one key pair below. Realm auth bindings and their configured credential stores can supply provider credentials instead, so these variables are not universally required. See providers for full key precedence (RKAT_* variants included).

Config files

The active realm document is the head of the runtime config chain. Under the default project-local state root it is <project-root>/.rkat/realms/<realm>/config.toml. Compatibility files still exist: These remain convention inputs for templates and compatibility workflows. CLI, RPC, REST, and MCP all resolve the same realm chain. Realm config supports explicit inheritance:
Resolution starts at the selected realm, follows each explicit parent, and appends the reserved global realm only when it is configured. Child values add to or override parent values. State never inherits: sessions, jobs, schedules, WorkGraph data, blobs, artifacts, and runtime rows remain owned by the selected realm. Credential reads inherit. HostAuthService and RPC/REST credential writes enforce strict ownership: a child-addressed inherited write is rejected with the owner identity. 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 credential account used by other routes. Explicitly address the true owner instead. A bare logout binding means global; --realm does not retarget it. This does not change the raw-head read/write split of config get / set / patch. Inherited MCP servers, hook entries, and skill sources have no removal tombstones, so an empty child collection does not delete inherited entries. Common tool gates:
These settings control tool availability. Realm selection chooses configuration and state, and provider credentials enable provider authentication; none installs native permission owners or selects OS confinement. Native governance requires explicit composition by a trusted embedding host. OS process confinement is the [confinement] section and the --confinement flags (below). See authorization integration for the current supported profiles and native governed embedding for Rust setup.
default_timeout and each per-tool timeout in [tools.tool_timeouts] accept humantime strings such as "30s", "2m" or "1h 2m". A per-tool timeout also accepts Serde’s duration table, shell = { secs = 120, nanos = 0 }, which is the form Meerkat writes when it saves a config, a config patch that sets a string included. Releases before 0.9.10 read only that table form: on them, a per-tool timeout string written by hand fails the config load. tools.mcp_servers is also accepted in runtime config, although the CLI’s user/project MCP convention files are managed separately as described below. Streaming retries have an inactivity watchdog: 300 seconds by default, or the model’s own window where it declares one (see retry and stream watchdog settings). Override it for every model with a humantime value above zero (keep it at 60 seconds or more), or disable only this watchdog explicitly:

OS process confinement

rkat confines the shell, command hooks and MCP stdio servers its agents launch as the composed [confinement] section states (see OS process confinement for the section, its modes and how documents compose). The workspace preset’s root is the project root: --context-root, else the nearest ancestor of the working directory containing .rkat, else the working directory.
The --confinement flags replace the section for one invocation, for every launch kind:
--confinement-network, --confinement-read and --confinement-write need --confinement workspace; relative paths resolve against the working directory. A launch the platform cannot confine as required is refused with typed feedback to the model and never runs unconfined. rkat prints its confinement report once on stderr: each launch kind’s requested and effective confinement and what keeps its own inputs from its confined processes (info: lines), and a warning: line for each launch kind this host cannot confine, a guarantee it does not claim, and each untrusted convention source. rkat refuses a command whose confined processes could change its realm state or user config document (see the host’s own inputs). On macOS the workspace preset protects <project>/.rkat, where the default realm state lives. On Linux it cannot, so start with --state-root <dir> outside the project:
A project mcp.toml or .rkat/config.toml that a confined process can write is not trusted: its MCP servers and hooks are refused, and rkat says so on stderr.

Custom model registry entries

Uncatalogued models served by a first-party API provider are declared once under [models.<id>], next to the per-provider default model strings. One definition feeds provider inference, compaction scaling, capability gates, and call timeouts:
provider parses into the closed provider vocabulary and fails closed on unknown names. Self-hosted models belong under [self_hosted.models] (below), not [models]. The same [models.<id>] table shape is accepted inside a mob definition (mob.toml) for mob-scoped models.

Self-hosted model config

Self-hosted models are defined directly in realm config:
stream_inactivity_timeout_secs sets this model’s stream-inactivity window, for example to cover a long prefill before the first token. It must be at least 60 seconds; config validation refuses a shorter window. Omit it to use the [retry] window. vision = true covers image input. With api_style = "chat_completions", image_tool_results must remain false; that result shape is available only through a validated responses endpoint. transport is currently openai_compatible only. api_style chooses the upstream API shape:
  • chat_completions is the safest default for Ollama, LM Studio, and vLLM in current Meerkat docs and examples
  • responses should be treated as an advanced/server-specific path you validate explicitly before depending on it
For Gemma 4, prefer chat_completions unless you have verified a server-specific responses workflow you want to use. supports_thinking and supports_reasoning describe the behavior you intend Meerkat to expose through that configured transport. Gemma 4 models themselves are reasoning-capable, but some servers expose those capabilities with provider-specific conventions. Server entries carry connection facts only — the legacy bearer_token / bearer_token_env server fields are rejected at config parse. Credentials and the connection itself are owned by a realm binding for provider = "self_hosted" (auth_method of none, api_key, or static_bearer); a self-hosted server with no realm binding fails closed at run time. See Self-hosting models for the realm binding shape.

Model fallback config

Model fallback is disabled by default. Enable an explicit non-empty backup chain to permit migration at a recoverable, pre-output LLM boundary:
There is no catalog chain. Writing enabled = true with no targets is rejected; enabled = false overrides an inherited enabled table. Writing an unknown fallback key (including the removed use_catalog_default_chain) is rejected. Config files written by rkat 0.8.36 and earlier still load. If one has enabled = true with no chain, or use_catalog_default_chain, that [model_fallback] setting is ignored: the realm inherits its parent’s explicit fallback policy, and fallback is off if there is none. rkat prints a warning on stderr naming the file, once per command, on commands that read the file: commands that load the config (such as rkat run), rkat config get, rkat config patch, rkat mob run/deploy and rkat auth login. rkat config set replaces the file without reading it, so it prints nothing. ~/.rkat/config.toml is reported when it is on the realm’s inheritance chain, and on commands that operate on it directly (rkat auth login, rkat config get --realm global, and the credential setup that rewrites it). The file is not rewritten until the next config write, which drops the legacy setting. To silence the warning, delete the [model_fallback] table, or add an explicit [[model_fallback.chain]]. rkat config patch merges onto the file as written, so adding a chain keeps enabled = true and turns fallback on:
See load vs write rules. Fallback targets include the auth binding identity. Use auth_binding on an explicit target to retry the same model/provider through a different configured credential. Cross-provider targets are skipped unless policy explicitly allows them. Defaults migrate only on capacity/provider unavailability after three failures, not transport or empty output. See the policy and resume contract. Fallback admission preserves the requested output reserve and, by default, required tools. Smaller targets that cannot fit the actual context are skipped even when the primary failure was capacity rather than context overflow. The agent receives a hidden system notice when a switch commits. Fallback is only attempted before user-visible stream output has been emitted. Structured-output extraction retries keep their schema and provider-native web search remains disabled after a fallback switch.

Session storage layout

CLI realm storage resolves by realm identity across the configured candidate roots. By default, a fresh workspace realm is created under the nearest ancestor containing .rkat, falling back to the context root:
Pass --state-root <path> to use a different parent directory. An explicit state root wins. Otherwise, an existing unique realm copy is reused across project-local and user-global candidates. If the same realm is materialized under multiple candidates, normal opens fail closed as typed split-brain. Use rkat storage doctor to inspect it and the fenced rkat storage migrate --apply --adopt-root <path> path to choose the copy to keep. Important files:
  • realm_manifest.json (backend pinning)
  • config.toml (realm config)
  • config_state.json (config generation CAS state)
  • sessions.sqlite3 (when backend is sqlite)
  • sessions_jsonl/ (when backend is jsonl)
  • runtime.sqlite3 (JSONL runtime companion)
  • jobs.sqlite3 (durable detached jobs)
  • workgraph.sqlite3 (WorkGraph state)
  • <projection_root>/.rkat/events/ (optional derived event audit/replay log)
  • <projection_root>/.rkat/sessions/<session_id>/ (rebuildable materialized session views)
  • blobs/ (realm blob objects)
  • artifacts/ (stable artifact records)
  • <store_path>/approvals.json (RPC approval-record sidecar when the persistence bundle exposes a store path)
  • <store_path>/approval_decisions.sqlite3 (durable decisions, created by the first hold)
  • <store_path>/approval_decisions.executor.lock and <store_path>/approval_decisions.executor.<kind>.lock (the decision executors’ OS locks, one per decision kind, created when an executor starts; they hold no data)
  • mobs/ (per-mob <mob_id>.db SQLite storage plus realm_profiles.db)
<store_path>/approvals.json is not an eighth RealmStorageProvider durability domain. The current storage doctor and storage migrate commands do not inventory or migrate this RPC-owned sidecar. They do cover approval_decisions.sqlite3 (schema domain approval-decisions), at the realm root and under sessions_jsonl/. For built-in SQLite and named memory realms, store_path is the realm root; for the JSONL backend, it is the sessions_jsonl/ directory. The optional event audit log and its .rkat/sessions/ materialized views belong to session/event projection, not additional RealmStorageProvider domains. Both are asynchronous derived state; the RuntimeStore/backend carrier remains authority. Per-session files may be regenerated when the audit log is healthy. --realm-backend is a creation hint. After first realm creation, backend selection is pinned by realm_manifest.json. This applies to both session storage and rkat mob command behavior in that realm. Manifest format 2 also records an optional external storage provider and explicit ephemeral_domains. Every storage provider must declare exactly one durability resolution for each of the seven domains: sessions, runtime, schedule, workgraph, jobs, blobs, and artifacts. A durable domain may not silently fall back to memory. When SQLite support is compiled in, new persistent realms default to sqlite.

MCP configuration

A session in a realm gets the MCP servers of three scopes: Project servers override user servers with the same name. A realm server and an mcp.toml server with the same name must be defined identically (they are then one server). A different definition is an error that names both scopes, so neither silently shadows the other. Realm servers are literal. mcp.toml expands ${VAR} in a server’s command, args, env values, URL and header values from the host environment; a realm server never does. A realm config is writable over the config APIs, so expanding it would let an API caller copy host environment variables into a request to a server of its choice. Writes refuse a realm server holding ${, and a realm config that already holds one fails when its MCP servers are resolved. Put env-derived values in an mcp.toml server. rkat run (and --resume) starts the servers of all three scopes, and rkat mcp login resolves them. The RPC and REST servers do not start configured servers in their sessions; hosts attach servers with mcp/add.

Exit codes

A command that fails with a typed error exits with the CLI code of that error’s public ErrorCode, the same code JSON-RPC reports for it (see the error code reference). A failure without a typed error, such as an argument, configuration, or lookup check made by the CLI itself, exits 1. A mob error with a typed console detail (codes 45-48 and 56) also prints one detail: line with that detail as JSON. Inspect the diagnostic or an available typed error payload rather than classifying a failure solely by its numeric code; not every CLI error has structured JSON, and code 2 is shared by usage errors and INVALID_PARAMS. Session persistence and compaction disabled conditions exit 1 like other internal errors.

See also