Appearance
Config
IChatRuntimeConfig (src/runtime/resolve-chat-config.ts:18-91) is the typed configuration shape Chat resolves at startup. This page documents each section.
Top-level shape
ts
interface IChatRuntimeConfig {
mode: 'standalone-local' | 'standalone-connected' | 'daemon-hosted';
mount: string;
app: { ... };
transport: { ... };
bootstrap: { ... };
serviceRefs: { conversation, componentLibrary, identity?, preferences?, sessionState, mcp? };
state: { ... };
security: { ... };
theme: { ... };
timeouts: { promptMs, chatMessagesMs, streamIdleMs, serviceCallMs };
features: { ... };
telemetry?: { debug? };
}app
ts
{
appName: 'chat',
publicBase: './',
windowTitle: 'Matrix Chat',
showAddressTags: false,
readOnly: false,
enablePrintExport?: true,
enableMarkdownExport?: true,
enableJsonExport?: true,
}transport
ts
{
kind: 'in-memory' | 'nats' | 'browser-nats',
root: 'CHAT-LOCAL', // wire root
addressRoot: string | null, // authority root
daemonRoot: string | null, // legacy alias
natsUrl: string | null,
wsUrl: string | null,
credentialsRef: string | null,
connectionSharing: 'runtime',
debug: boolean,
}For standalone-local, kind is 'in-memory' with no URLs. For daemon-hosted, kind is typically 'browser-nats' and wsUrl is /nats-ws.
bootstrap
ts
{
source?: 'embedded' | 'host-http' | 'host-actor',
bootstrapUrl?: string | null,
authMeUrl?: string | null,
natsJwtUrl?: string | null,
required?: boolean,
}source: 'embedded' is for standalone-local. host-http and host-actor are for hosted modes.
serviceRefs
Each is an IChatServiceRef:
ts
interface IChatServiceRef {
required: boolean,
mode: 'local' | 'remote-actor' | 'http-adapter',
target: string, // mount path or URL
timeoutMs?: number,
}Default values (from config.defaults.json):
json
{
"conversation": { "required": true, "mode": "local", "target": "chat.conversation", "timeoutMs": 10000 },
"componentLibrary": { "required": true, "mode": "local", "target": "chat.component-library", "timeoutMs": 10000 },
"identity": { "required": false, "mode": "local", "target": "chat.identity", "timeoutMs": 3000 },
"preferences": { "required": false, "mode": "local", "target": "chat.preferences", "timeoutMs": 3000 },
"sessionState": { "required": true, "mode": "local", "target": "chat.session-state", "timeoutMs": 10000 },
"mcp": { "required": false, "mode": "local", "target": "chat.mcp", "timeoutMs": 5000 }
}In standalone-connected and daemon-hosted, the per-profile overrides switch mode from 'local' to 'remote-actor', so the binding picks the RemoteActor* adapter instead of the in-memory Local* service.
state
ts
{
provider: 'memory' | 'indexeddb' | 'local-record-store' | 'remote-session-service',
pageManifestKey: 'page_manifest',
canvasKey: 'canvas',
transcriptKey: 'transcript',
persistMessages: boolean,
persistInlineComponents: boolean,
}provider selects the state backend. In remote-actor modes, this is overridden to 'remote-session-service'.
security
ts
{
enableLocalCapabilityRealm: true,
enableTopicClaims: true,
spawnPolicy: 'sandboxed-ui-only',
defaultCapabilityTtlMs: 1_800_000, // 30 minutes
}Inline component spawning is gated by the local capability realm. spawnPolicy: 'sandboxed-ui-only' means components can render but cannot reach beyond their declared mount.
theme
ts
{
defaultPreset: 'dark',
persistScope: 'user', // 'user' | 'session' | 'local'
fallbackToLocalState: true,
}timeouts
ts
{
promptMs: 300_000, // 5 minutes — max time waiting for $activity frames
chatMessagesMs: 60_000, // request-reply timeout for chat.messages ops
streamIdleMs: 360_000, // max time between $activity frames
serviceCallMs: 10_000, // generic service call timeout
}features
ts
{
mcpStatus?: true,
inlineComponents?: true,
retargeting?: true,
exports?: ['md', 'json', 'pdf'],
}Per-mode profile overrides
Three profile files in chat/config/profiles/:
standalone.local.json— setsmode, in-memory transport, all serviceRefs tomode: 'local'.standalone.connected.json— setsmode, browser-nats transport (default), serviceRefs tomode: 'remote-actor'.daemon-hosted.json— setsmode, browser-nats transport with bootstrap fromhost-http, serviceRefs tomode: 'remote-actor'.
resolveChatConfig(overrides) deep-merges in this order: defaults → profile → overrides.
Resolution providers
matrix.json declares three config providers:
json
"providers": [
{ "kind": "env", "prefix": "MATRIX_CHAT_" },
{ "kind": "file", "env": "MATRIX_CHAT_CONFIG_FILE", "optional": true },
{ "kind": "service", "service": "system.config", "namespace": "@open-matrix/chat",
"env": "MATRIX_CHAT_CONFIG_SERVICE", "optional": true }
]resolveConfiguredChatConfig (in resolve-chat-config.ts:126) reads each provider in declared order and merges. So MATRIX_CHAT_* env vars override the file, which overrides the system.config service, which overrides the defaults.
Schema
config/config.schema.json documents the JSON Schema for the merged result. Used for validation when reading the file/service providers.
See also
Source:
projects/matrix-3/packages/chat/src/runtime/resolve-chat-config.ts:1-140,chat/config/config.defaults.json,chat/config/profiles/,chat/matrix.jsonconfigblock.