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)
--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:
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.
--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:
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_completionsis the safest default for Ollama, LM Studio, and vLLM in current Meerkat docs and examplesresponsesshould be treated as an advanced/server-specific path you validate explicitly before depending on it
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: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:
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:
--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.lockand<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>.dbSQLite storage plusrealm_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 publicErrorCode, 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.
