Skip to content

Configuration

Magic Context reads magic-context.jsonc (or .json) from one shared CortexKit location across OpenCode, Pi, and OMP. Project config overrides user config, key by key. Prompt-surface routing is shared by all three harnesses; project config may select default and models, while guidance_override_path and tool_descriptions are stripped at the project trust boundary.

  • Project — <project>/.cortexkit/magic-context.jsonc
  • User-wide — ~/.config/cortexkit/magic-context.jsonc

Upgrading from an earlier version moves your existing config here automatically on first run (a .MOVED_READPLEASE breadcrumb is left at the old per-harness path).

Keys marked Live apply from the next historian or dreamer run (or dream-timer tick); a run already in progress keeps its original settings. Everything else requires a host restart. If a changed file is malformed, the last good configuration stays active and /ctx-status reports the error.

Add the schema line for editor validation and autocomplete:

{
"$schema": "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json"
}

Global on/off switches for the plugin and its agent-facing surface.

KeyTypeDefaultDescription
enabledbooleantrueEnable magic context (default: true)
allow_home_projectbooleanfalseAllow Magic Context sessions launched from the exact canonical home directory. A non-git home uses its deterministic dir: identity; a home repository uses its git: identity. USER-LEVEL ONLY: project config is ignored. The home identity is excluded from registry seed exports, never resolves descendants by containment, and cannot join a workspace.
languagestring—Output language for Magic Context’s generated content and guidance, as a 2-letter ISO 639-1 code (e.g. “tr”, “es”, “de”, “ja”, “pt”). When set, the historian, dreamer, and the agent-guidance block instruct the model to write its PROSE in this language while keeping all structural tokens (XML tags, the five memory category names, code identifiers, file paths) in English. USER-LEVEL ONLY (ignored in project config for security). Unset = today’s behavior (model mirrors the conversation; English scaffolding). Changing it triggers one cache re-materialization; existing compartments/memories keep their original language until naturally rewritten.
auto_updateboolean—Enable automatic npm self-update checks for the OpenCode plugin. Security: USER-only in config loader, so hostile project configs cannot suppress updates.
keep_subagentsbooleanfalseDebug: keep every settled Magic Context child session instead of deleting it after success: historian, all Dreamer tasks, smart-note evaluation and compilation, user-memory review, and memory migration. Kept Dreamer children can contain memory-pool text and user messages from other sessions of the same operator; their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect. On OpenCode 2, one hidden session holds many runs; it is kept once any of its runs settled, and only a Dreamer session none of whose runs settled is still deleted.
todowriteobject—Pi-only todowrite tool and overlay controls. Pi registers tools and widgets at extension boot, so changing this after /cd requires /reload or restart.
todowrite.enabledbooleanfalsePi only: off by default. Set todowrite.enabled=true to register Magic Context’s todowrite task-list tool and /todos command. OpenCode ships its own built-in todowrite; this setting has no effect there.
todowrite.overlaybooleantruePi only: show the persistent todo overlay above the editor while tasks are active.
muralobject—Experimental mural: a single deterministically-rendered image of project memories that did not fit the context budget. Cues are compressed per-memory by the compress-cues dreamer task.
mural.enabledbooleanfalse
mural.modelunknown—Deprecated: ignored. compress-cues now uses the dreamer model for each harness, like every other dreamer task; override it with dreamer.opencode.tasks.compress-cues.model (or the pi/omp equivalent). Remove this key; it no longer does anything.

Select the full or light built-in prompt preset. Model routes use the same progressive lookup walk as cache_ttl, with literal case-sensitive provider/model keys and the provider/* wildcard; guidance and tool-description overrides are user-level only.

KeyTypeDefaultDescription
prompt_surfaceobject—Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. OpenCode 1.x, Pi, and OMP register tool descriptions once per process (they follow the default preset). OpenCode 2 rewrites the five ctx_* descriptions per request from the draft model.
prompt_surface.default"full" | "light""full"Fallback prompt-surface preset (“full” or “light”).
prompt_surface.modelsmap<string, "full" | "light">—Literal per-model routing. Keys are bare model IDs, provider/model, or provider/*; matching is case-sensitive and preserves additional slashes in model IDs.
prompt_surface.guidance_override_pathstring—USER-LEVEL ONLY path to a complete primary guidance section. Relative paths resolve from the user config file.
prompt_surface.tool_descriptionsmap<string, string>—USER-LEVEL ONLY top-level description overrides keyed by ctx_* tool ID; parameter schemas and descriptions are unchanged.

When and how aggressively Magic Context manages the session’s context window. Per-model keys accept provider/model map form where noted.

KeyTypeDefaultDescription
cache_ttl Livestring | map<string, string>"5m"How long Magic Context assumes the provider’s cached prefix stays valid. This is MC’s own deferral gate — it does not change the provider’s actual cache lifetime. String (e.g. “5m”, “1h”, ”30s”) or per-model object ({ default: “5m”, “provider/model”: “1h”, “provider/*”: “never” }); keys resolve most-specific first (exact provider/model, bare model ID, shorter dash-prefixes, then the provider/* wildcard, then default). User and project settings, including an explicit “5m” or object default, apply on the next pass. Only built-in defaults are frozen per session, including across restarts: when unset, GPT-5.6 and later (including gpt-6*, through any provider prefix) use 30m, other models use 5m. /ctx-status shows the effective TTL and whether it comes from your config or a frozen built-in default. Editing the TTL does not itself rewrite prompt bytes; a lowered TTL rebuilds only after normal idle expiry. OpenAI documents at least 30 minutes since the latest write or reuse: https://developers.openai.com/api/docs/guides/prompt-caching (Cache lifetime and Summary of model differences). Set to “never” to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).
output_reservenumber (0–) | map<string, number (0–)>—User-only output-token reservation override. Number or per-model object ({ default: 16384, “provider/model”: 8192 }); 0 disables reservation. Takes precedence over every derived source: an explicit value here always wins against catalog output limits, provider window-geometry facts, and the 25%-of-context fallback (usable window = context window minus this reserve). When unset, Magic Context reserves the catalog output limit (capped at 25% of context) for shared-window providers and keeps proven separate-quota Google/Gemini windows unchanged.
execute_threshold_percentagenumber (20–90) | map<string, number (20–90)>65Context percentage that forces queued operations to execute. Number or per-model object ({ default: 65, “provider/model”: 45 }). Values above 90 are rejected because the runtime caps at 90% of the output-reserved safe window (MAX_EXECUTE_THRESHOLD). Default: DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE
execute_threshold_tokensobject—Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts default for all models or per-model keys. Values above 90% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000.
execute_threshold_tokens.defaultnumber (5000–2000000)—
protected_tokensinteger (4000–1000000)—Positive integer token floor to protect from automatic reclaim (min: 4_000, max: 1_000_000). When omitted, the derived default is clamp(round(0.05 × usableSoft), min(16_000, round(0.08 × usableSoft)), 64_000).
protected_tagsunknown—Deprecated: number of recent tags to protect. Ignored for behaviour; use protected_tokens instead.
clear_reasoning_ageunknown—Deprecated and ignored. Use keep_reasoning_tokens instead.
keep_reasoning_tokensinteger (0–1000000) | map<string, integer (0–1000000)>—Reasoning tokens to keep on rebuilding passes. Number or per-model object; exact, shorter model keys, provider/*, then default. Omitted: fixed 10,000. 0 removes all eligible historical reasoning; newest and exempt steps always stay.
history_budget_percentagenumber (0.05–0.5)0.15Fraction of usable context (context_limit × execute_threshold) reserved for the session history block (default: 0.15)

If cache_ttl is shorter than the provider’s real cache lifetime (for example, a locally hosted model whose prefix cache doesn’t expire), idle expiry rebuilds the prompt onto a cache that is still warm and pays for the rewrite for nothing. Set cache_ttl to match the provider, or to "never" for a cache that doesn’t expire.

Named user-owned model-selection overlays. A project may select a profile name but cannot define or alter profile contents.

KeyTypeDefaultDescription
profilestring—Select a named user-owned model profile. A valid project name overrides this user default; an empty string, null, or other non-string project value is ignored with a warning so the user selection still applies. Unknown names warn and use the base configuration.
profilesmap<string, object>—User-level named model profiles. A profile may contain only historian/dreamer model, fallback_models, OpenCode variant, and Pi/OMP thinking_level fields; task execution policy (including timeout_minutes) is excluded. Project configs may select a name but cannot define profiles.

The background agent that condenses old conversation into compact history.

KeyTypeDefaultDescription
historianobject—Historian metadata plus independent strict OpenCode, Pi, and OMP execution blocks. Retained metadata stays at historian; model, fallback_models, variant, and thinking_level belong only in historian.opencode, historian.pi, or historian.omp.
historian.temperaturenumber (0–2)—Sampling temperature (0-2)
historian.top_pnumber (0–1)—Nucleus sampling top_p (0-1)
historian.promptstring—Additional system prompt text
historian.toolsmap<string, boolean>—Tool enable/disable overrides
historian.disableboolean—Disable this agent
historian.descriptionstring—Agent description
historian.mode"subagent" | "primary" | "all"—Agent mode (subagent, primary, or all)
historian.colorstring—Hex color for the agent (e.g. ‘#a1b2c3’)
historian.maxStepsnumber—Maximum tool-call steps per invocation
historian.permissionobject—Per-tool permission overrides
historian.permission.edit"ask" | "allow" | "deny"—
historian.permission.bash"ask" | "allow" | "deny" | map<string, "ask" | "allow" | "deny">—
historian.permission.webfetch"ask" | "allow" | "deny"—
historian.permission.doom_loop"ask" | "allow" | "deny"—
historian.permission.external_directory"ask" | "allow" | "deny"—
historian.maxTokens Livenumber—Maximum output tokens
historian.expand_tools Livemap<string, string | boolean>—Readable historian tool expansions, keyed by exact host tool name. Templates override built-in defaults; false disables an expansion. Supports ${input.path}, ${output.path}, bare ${output}, array [N], [*].field, .each(”${field}”), .join(“separator”), .count and final .truncate(N). Missing fields are empty. Historian text and lists have no implicit caps; explicit .truncate(N) keeps complete sentences and marks omitted characters, or emits only the marker if no sentence fits. When the ctx_expand history-recovery tool is called in verbose mode, its tool-call previews retain their original built-in templates and limits (300 characters per placeholder, 10 list elements, 1000 characters per expansion). Valid in user and project config; never changes the wire or default ctx_expand transcript.
historian.opencodeobject—Strict OpenCode model-resolution block. It accepts no Pi vocabulary.
historian.opencode.model Livestring | object—Primary historian OpenCode model entry. When set, only this model and fallback_models are used; exhaustion reports failure, never the session model. When absent, OpenCode inherits the session model.
historian.opencode.fallback_models Livestring | object[]—Ordered historian fallback OpenCode entries. A configured primary never adds the session model after this list. Requires an array; legacy singleton values migrate to a one-element array.
historian.opencode.variant Livestring—OpenCode reasoning variant for the primary entry when it declares none. Fallback entries declare variants per-entry.
historian.piobject—Strict Pi model-resolution block. It accepts no OpenCode vocabulary.
historian.pi.model Livestring | object—Primary historian Pi model entry. When set, only this model and fallback_models are used; exhaustion reports failure, never the session model. When absent, Pi does not run the historian.
historian.pi.fallback_models Livestring | object[]—Ordered historian fallback Pi entries. The session model is never appended. Requires an array; legacy singleton values migrate to a one-element array.
historian.pi.thinking_level Live"off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max"—Pi thinking level for the primary entry when it declares none. Fallback entries declare thinking levels per-entry.
historian.ompobject—Strict OMP model-resolution block. It accepts no OpenCode vocabulary.
historian.omp.model Livestring | object—Primary historian OMP model entry. When set, only this model and fallback_models are used; exhaustion reports failure, never the session model. An absent OMP block inherits the Pi block; a selected block without a model does not run the historian.
historian.omp.fallback_models Livestring | object[]—Ordered historian fallback OMP entries. The session model is never appended.
historian.omp.thinking_level Live"off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | "inherit" | "auto"—OMP thinking level for the primary entry when it declares none. Fallback entries declare thinking levels per-entry.
historian.runner"broca" | "host"—Which side runs the historian completion in Rust transform mode: “host” queues it for this process to run on the configured historian model, “broca” routes it to the Broca module. When unset the harness decides: OpenCode 1 and OpenCode 2 use “host”, Claude Code (through the Thalamus gateway, which has no host to run a completion) uses “broca”. User-level config only — it decides whose provider account pays for the call.
historian.host_runnerobject—Controls for this process’s historian pull loop, which answers runs the Rust module queues for the host runner (historian.runner: "host", or unset on OpenCode 1 and OpenCode 2). User-level config only — it decides whether this machine’s provider account is spent on folds.
historian.host_runner.enabledboolean—Whether this process answers historian runs queued for a claimant (default true). Setting it to false stops the pull loop without changing historian.runner, so an operator can take one machine out of the lane and leave the queued runs for another claimant or for the runner setting to be changed deliberately.
historian.two_pass LivebooleanfalseRun a second editor pass over historian output to clean low-signal U: lines and cross-compartment duplicates. Adds ~1 extra API call and ~1.3x cost per historian run. Useful for models without extended thinking support. (default: false)
historian.disallowed_tools"\*" | "read" | "aft_outline" | "aft_zoom" | "aft_search"[][]Legacy compatibility setting. Historians, recomp and editor passes always run with zero tools and locked permissions; this list no longer changes their tool surface. (default: [])
historian_timeout_ms Livenumber (60000–)600000Timeout for each historian prompt call in both TypeScript and Rust transform modes, in milliseconds (default: 600000). A historian setting kept at the top level for compatibility; no effect while historian.disable is true or compaction.enabled is false.
commit_cluster_triggerobject—Commit-cluster trigger: fire historian when enough commit clusters accumulate in the unsummarized tail. A historian setting kept at the top level for compatibility; no effect while historian.disable is true or compaction.enabled is false.
commit_cluster_trigger.enabled LivebooleantrueEnable commit-cluster based historian triggering (default: true)
commit_cluster_trigger.min_clusters Livenumber (1–)3Minimum commit clusters required to trigger historian (min: 1, default: 3)

Durable project memory, semantic search, and recall features. OpenAI-compatible instruction-tuned embedding families receive their documented query instruction automatically because those models were trained to distinguish retrieval queries from passages; plain local encoders remain unchanged. Query instructions affect only live search vectors, not stored vectors, so changing embedding.query_instruction does not re-embed the corpus. A non-empty embedding.document_prefix does affect stored vectors and therefore changes the embedding identity.

KeyTypeDefaultDescription
memoryobject—Cross-session memory configuration. auto_search and git_commit_indexing sit here for history but work with memory.enabled false.
memory.enabledbooleantrueEnable cross-session project memory (default: true). Also gates the dreamer’s project-memory tasks: while false, map-memories, verify, verify-broad, curate, compress-cues, classify-memories, retrospective, promote-primers and refresh-primers neither run on schedule nor through /ctx-dream; maintain-docs, evaluate-smart-notes and review-user-memories still run. memory.auto_search and memory.git_commit_indexing do not depend on it. Does not affect history embedding or semantic ctx_search over session history; set embedding.provider to ‘off’ to stop all embedding.
memory.injection_budget_tokensnumber (500–20000)4000Token budget for memory injection on session start (min: 500, max: 20000, default: 4000)
memory.auto_promote LivebooleantrueAutomatically promote eligible session facts into memory (default: true). No effect while memory.enabled is false.
memory.retrieval_count_promotion_thresholdnumber (1–)3Currently has no effect: no code reads this value, and memories are not promoted to permanent by retrieval count. Kept so existing configs stay valid (min: 1, default: 3).
memory.auto_searchobject—Auto-search hint: transform-time ctx_search on each new user message; when the top hit clears the threshold, append a compact block of vague fragments to that user message. Does NOT inject full content. Graduated from experimental.auto_search; enabled by default (set enabled: false to opt out). Independent of memory.enabled despite its place under memory: with memory off it still searches past conversation and commits.
memory.auto_search.enabledbooleantrueAutomatically append a compact to eligible user messages when relevant memories, conversation, or commits are found. Graduated from experimental.auto_search; on by default (set false to opt out). Independent of memory.enabled despite its place under memory: with memory off it still searches past conversation and commits, only the memory source is skipped.
memory.auto_search.score_thresholdnumber (0.3–0.95)0.6Top hit score must exceed this threshold for the hint to fire (min: 0.3, max: 0.95, default: 0.60)
memory.auto_search.min_prompt_charsnumber (5–500)20Skip hint when user message is shorter than this (min: 5, max: 500, default: 20)
memory.git_commit_indexingobject—Index git commit messages from HEAD into ctx_search. Commits become a 4th searchable source alongside memories and session history. Graduated from experimental.git_commit_indexing; opt-in, default off (per-project embedding cost). Independent of memory.enabled despite its place under memory.
memory.git_commit_indexing.enabled LivebooleanfalseIndex HEAD git commits for ctx_search (git_commit source). Graduated from experimental.git_commit_indexing; opt-in, default off. Independent of memory.enabled despite its place under memory.
memory.git_commit_indexing.since_days Livenumber (7–3650)365Days of HEAD history to index (min: 7, max: 3650, default: 365)
memory.git_commit_indexing.max_commits Livenumber (100–20000)2000Max commits kept per project; oldest evicted (min: 100, max: 20000, default: 2000)
embeddingobject—Embedding provider configuration
embedding.provider"local" | "openai-compatible" | "off" | "synapse""local"Embedding provider. ‘local’ uses Xenova/all-MiniLM-L6-v2, ‘openai-compatible’ requires endpoint and model, ‘synapse’ uses the certified local Synapse lane with an explicit fallback provider, and ‘off’ disables embeddings. Session history is embedded for semantic ctx_search whenever the provider is not ‘off’, regardless of memory.enabled; memories are embedded only while memory.enabled is true.
embedding.fallback_provider"local" | "openai-compatible" | "off"—Fallback provider for the Synapse lane. Required when provider is ‘synapse’; local, openai-compatible, and off are valid.
embedding.modelstring—Embedding model name. Required for openai-compatible, ignored for local.
embedding.endpointstring—API endpoint URL. Required when provider is openai-compatible.
embedding.api_keystring—API key for remote embedding provider (optional)
embedding.input_typestring—Default input_type for stored/indexed (passage) embeddings in the request body. Required by some openai-compatible providers (e.g. NVIDIA NIM). Omitted from the request when unset.
embedding.query_input_typestring—Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM ‘query’). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type.
embedding.query_instructionstring | boolean—OpenAI-compatible query prefix override. A string is prepended verbatim to search queries; false disables the built-in model-family instruction. Qwen3-Embedding, gte-Qwen instruct, e5 instruct, and Nomic families have built-in recipes. Query-only changes do not re-embed stored content. User-level only; project values are ignored.
embedding.document_prefixstring—OpenAI-compatible stored-document prefix override, prepended verbatim. Defaults to the model-family recipe (empty for Qwen3/gte/e5 instruct; ‘search_document: ’ for Nomic). Changing it changes stored vectors and triggers re-embedding. User-level only; project values are ignored.
embedding.truncatestring—Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts ‘NONE’ | ‘START’ | ‘END’). Omitted from the request when unset.
embedding.max_input_tokensinteger (–9007199254740991)—Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.
embedding.local_runtime"auto" | "native" | "wasm""auto"Local provider only: ONNX runtime selection. ‘auto’ uses native under Node and uses WASM under Bun versions before 1.4.0, where Bun’s NAPI teardown race can panic on quit; native is restored automatically on Bun 1.4.0+. Inference runs in a dedicated worker after disabling POSIX telemetry in the native process environment. Compiled Bun hosts and hosts without a verified in-process opt-out use a subprocess instead. Windows native ONNX emits OS-controlled ETW diagnostics, not direct uploads. On Bun before 1.4.0, even explicit ‘native’ uses WASM because native worker teardown can crash the process. Set ‘wasm’ to avoid loading the native addon on newer hosts too.
embedding.local_dtype"auto" | "fp32" | "fp16" | "q8" | "int8" | "uint8" | "q4" | "bnb4" | "q4f16" | "q2" | "q2f16" | "q1" | "q1f16"—Local provider only: ONNX model dtype passed to the transformers.js feature-extraction pipeline. Accepts the @huggingface/transformers DataType strings (auto, fp32, fp16, q8, int8, uint8, q4, bnb4, q4f16, q2, q2f16, q1, q1f16). Omitted keeps today’s behavior (fp32). A non-default value changes the produced vectors and folds into the embedding model identity, so switching dtype re-embeds rather than mixing vector spaces. Useful for selecting a quantized variant (e.g. q8) of a larger multilingual model to cut memory and CPU cost; see issue #259.

Reranking reuses the existing prose-query gate, candidate preparation and stable score sorting for explicit ctx_search on OpenCode and Pi. Automatic per-turn search hints never call a reranker. With no block configured, local Synapse remains the default.

Hosted reranking sends retrieved text to a user-chosen service. Put this block in user config beside embedding (it is independent of the embedding provider):

"rerank": {
"provider": "remote",
"endpoint": "https://api.cohere.com/v2",
"model": "rerank-v3.5",
"api_key": "{env:RERANK_API_KEY}",
"timeout_ms": 1500,
"top_n": 20
}

The client posts to <endpoint>/rerank with {model, query, documents, top_n} and reads results: [{index, relevance_score}] (Cohere, Voyage, OpenRouter and Jina-compatible). Prefix the base URL with tei+ for Hugging Face TEI: {query, texts} in and [{index, score}] out. API keys are sent as Bearer tokens; user-level {env:NAME} and {file:path} expansion follows the embedding configuration rules.

Each document uses the existing location/title/body recipe, truncated at a UTF-8 character boundary to 1024 bytes. At most 20 documents are allowed per request; larger batches are refused, never split. top_n caps the fused candidate pool, and the wire request asks for all submitted scores. Scores must cover each document index exactly once and be finite; ties retain candidate order. Any failure preserves the original unreranked order, adds one short skip reason to the tool result, and never falls back to Synapse while remote is configured.

Project config may only set "rerank": {"provider": "off"}. Project routing, credentials and limits are stripped with a warning, and project {env:} / {file:} tokens never expand. Changes require a host restart. The dashboard currently requires its raw JSONC editor for this block.

KeyTypeDefaultDescription
rerankobject—Explicit ctx_search reranking only. Defaults to local Synapse. Hosted settings are user-level only; projects may only select off.
rerank.provider"synapse" | "remote" | "off""synapse"Explicit ctx_search reranker: local Synapse by default, remote for hosted scoring, or off. Projects may only select off.
rerank.endpointstring—User-level rerank API base URL; prefix with tei+ for Hugging Face TEI.
rerank.modelstring—Hosted reranker model name.
rerank.api_keystring—Bearer API key; supports {env:NAME} in user config, like embedding.api_key.
rerank.timeout_msinteger (-9007199254740991–9007199254740991)—Hosted request timeout in milliseconds, clamped to 50–15000; also cancelled by ctx_search’s abort signal.
rerank.top_ninteger (1–20)20Maximum fused candidates sent to the hosted reranker (1–20). Requests ask for a score for every submitted document; partial replies are rejected.

Off-hours maintenance through Dreamer.

KeyTypeDefaultDescription
dreamerobject—Dreamer metadata and scheduling plus independent strict OpenCode, Pi, and OMP execution blocks. schedule and promotion_threshold stay at dreamer.tasks; model, fallback_models, variant, thinking_level, and timeout_minutes belong only in the matching harness block. Each task follows the setting it serves: memory tasks need memory.enabled, evaluate-smart-notes needs smart_notes.enabled, review-user-memories needs its schedule, maintain-docs only a runnable dreamer.
dreamer.temperaturenumber (0–2)—Sampling temperature (0-2)
dreamer.top_pnumber (0–1)—Nucleus sampling top_p (0-1)
dreamer.promptstring—Additional system prompt text
dreamer.toolsmap<string, boolean>—Tool enable/disable overrides
dreamer.disable Liveboolean—Disable the dreamer: no scheduled or manual dream task runs. Also turns off smart notes (ctx_note drops surface_condition even with smart_notes.enabled true) and the historian’s collection of user observations for review-user-memories. dreamer.inject_docs still applies.
dreamer.descriptionstring—Agent description
dreamer.mode"subagent" | "primary" | "all"—Agent mode (subagent, primary, or all)
dreamer.colorstring—Hex color for the agent (e.g. ‘#a1b2c3’)
dreamer.maxStepsnumber—Maximum tool-call steps per invocation
dreamer.permissionobject—Per-tool permission overrides
dreamer.permission.edit"ask" | "allow" | "deny"—
dreamer.permission.bash"ask" | "allow" | "deny" | map<string, "ask" | "allow" | "deny">—
dreamer.permission.webfetch"ask" | "allow" | "deny"—
dreamer.permission.doom_loop"ask" | "allow" | "deny"—
dreamer.permission.external_directory"ask" | "allow" | "deny"—
dreamer.maxTokens Livenumber—Maximum output tokens
dreamer.runner"broca" | "host"—Which side runs the dreamer completions the Rust module routes (classify-memories) in Rust transform mode: “host” runs them on this process’s carrier, “broca” routes them to the Broca module. When unset, historian.runner applies, and when that is unset too the harness decides the same way it does for the historian. User-level config only.
dreamer.opencodeobject—Strict OpenCode dreamer model-resolution block. It accepts no Pi vocabulary.
dreamer.opencode.model Livestring | object—Primary OpenCode model entry.
dreamer.opencode.fallback_models Livestring | object[]—Ordered fallback OpenCode entries. New-shape configuration requires an array; legacy singleton values migrate to a one-element array.
dreamer.opencode.variant Livestring—OpenCode reasoning variant for the primary entry when it declares none. Fallback entries declare variants per-entry.
dreamer.opencode.tasks Livemap<string, object>—OpenCode task execution overrides. Each named task accepts only model, fallback_models, variant, and timeout_minutes.
dreamer.piobject—Strict Pi dreamer model-resolution block. It accepts no OpenCode vocabulary.
dreamer.pi.model Livestring | object—Primary Pi model entry.
dreamer.pi.fallback_models Livestring | object[]—Ordered fallback Pi entries. New-shape configuration requires an array; legacy singleton values migrate to a one-element array.
dreamer.pi.thinking_level Live"off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max"—Pi thinking level for the primary entry when it declares none. Fallback entries declare thinking levels per-entry.
dreamer.pi.tasks Livemap<string, object>—Pi task execution overrides. Each named task accepts only model, fallback_models, thinking_level, and timeout_minutes.
dreamer.ompobject—Strict OMP dreamer model-resolution block. It accepts no OpenCode vocabulary.
dreamer.omp.model Livestring | object—Primary OMP model entry.
dreamer.omp.fallback_models Livestring | object[]—Ordered fallback OMP entries.
dreamer.omp.thinking_level Live"off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | "inherit" | "auto"—OMP thinking level for the primary entry when it declares none. Fallback entries declare thinking levels per-entry.
dreamer.omp.tasks Livemap<string, object>—OMP task execution overrides. Each named task accepts only model, fallback_models, thinking_level, and timeout_minutes.
dreamer.tasksobject—Harness-independent task metadata. schedule, promotion_threshold, and other task metadata remain here; execution settings live under dreamer.opencode.tasks, dreamer.pi.tasks, or dreamer.omp.tasks.
dreamer.tasks.map-memories.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.map-memories.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.verify.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.verify.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.verify-broad.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.verify-broad.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.curate.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.curate.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.compress-cues.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.compress-cues.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.classify-memories.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.classify-memories.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.retrospective.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.retrospective.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.retrospective.recency_days Liveinteger (1–3650)30retrospective: collect source messages from only the most recent N days
dreamer.tasks.maintain-docs.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.maintain-docs.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.maintain-docs.max_tokensinteger (–9007199254740991)12000Maximum combined token count of proposed ARCHITECTURE.md and STRUCTURE.md
dreamer.tasks.evaluate-smart-notes.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.evaluate-smart-notes.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.review-user-memoriesobject—Promote recurring user observations into the block. A non-empty schedule also makes the historian collect user observations, but only while the dreamer is runnable (dreamer.disable not true); collection and review follow that one gate and do not depend on memory.enabled.
dreamer.tasks.review-user-memories.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.review-user-memories.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.review-user-memories.promotion_threshold Livenumber (2–20)3review-user-memories: min candidate observations before promotion is considered (default: 3)
dreamer.tasks.promote-primers.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.promote-primers.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.tasks.promote-primers.promotion_threshold Livenumber (2–20)2promote-primers: min recurring source days before promotion is considered (default: 2)
dreamer.tasks.refresh-primers.schedule Livestring""5-field cron schedule (e.g. “0 3 * * *”), or "" to disable this task.
dreamer.tasks.refresh-primers.token_budgetinteger (–9007199254740991)—Cumulative prompt-token investigation budget (input + cache read + cache write) for one tool-loop child. Defaults: 2,500,000 for map-memories and verify; 3,000,000 for verify-broad; other tool-loop tasks vary. Completed answers are retained even if their usage crosses the budget.
dreamer.inject_docsbooleantrueInject ARCHITECTURE.md and STRUCTURE.md into the m[0] <project-docs> block (default true). Not a dreamer setting despite its place under dreamer: it applies on every host, also with dreamer.disable true.

On Pi and Oh My Pi, historian and dreamer models, including fallback_models and per-task model overrides, must use provider names that host serves. opencode/* models are served only by OpenCode’s own provider, so Pi and Oh My Pi drop them at startup and log dropping Pi model not found: <model>. If every fallback is an opencode/* model, only the primary model is left. To see valid names, run omp models on Oh My Pi or pi --list-models on Pi. /ctx-status warns when a dreamer task or the historian has no usable model left.

Behavior tuning most installs never need to touch.

KeyTypeDefaultDescription
temporal_awarenessbooleantrueInject wall-clock gap markers () between user messages where > 5 min elapsed since the previous message, and add compact date ranges to compartment headings. Gives the agent a sense of session pacing and “how long ago” across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).
caveman_text_compressionobject—Age-tier caveman compression for long user/assistant text parts. Active for primary sessions when enabled; never for subagents. Oldest 20% of eligible tags (outside protected tail) go to ultra, next 20% to full, next 20% to lite, newest 40% untouched. Graduated from experimental.caveman_text_compression; opt-in, default off (lossy).
caveman_text_compression.enabledbooleanfalseApply deterministic caveman-style text compression to old conversation text. Active for primary sessions when enabled; never for subagents. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%).
caveman_text_compression.min_charsnumber (100–10000)500Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.
system_prompt_injectionobject—Controls whether and where Magic Context augments the system prompt. Lets users opt specific agents out of the Magic Context guidance and the surrounding project-docs / user-profile blocks. OpenCode’s internal hidden agents — title, summary, and compaction — are always skipped automatically.
system_prompt_injection.enabledbooleantrueWhen false, NO injection happens for ANY agent — global escape hatch. (default: true)
system_prompt_injection.skip_signaturesstring[]["<!-- magic-context: skip -->"]Substring opt-out list. If the agent’s system prompt contains any of these strings, skip ALL Magic Context injection for that call. Default "" is meant to be added inside a user’s custom agent prompt to opt that agent out.
sqliteobject—SQLite connection tuning for Magic Context’s own context.db. These are per-connection PRAGMAs applied at open; they do not change the schema or what is stored.
sqlite.cache_size_mbnumber (2–2048)64Page-cache size in MiB per connection (PRAGMA cache_size). Larger keeps more hot pages resident, cutting re-reads on repeated full-table scans. (min 2, max 2048, default 64)
sqlite.mmap_size_mbnumber (0–8192)0Memory-mapped I/O size in MiB (PRAGMA mmap_size). 0 disables mmap (SQLite default). Raising it can cut read overhead on large DBs at the cost of address space. (min 0, max 8192, default 0)
storageobject—Storage permission policy. The default keeps session content and memories owner-private. Disabling enforcement is for trusted shared-group storage managed externally; TypeScript mode follows that policy, but Rust transform mode always keeps its shared data directory owner-only because ck-mc’s store library enforces it.
storage.enforce_private_permissionsbooleantrueWhen true (default), Magic Context creates and re-tightens its TypeScript-mode storage directories to owner-only 0700 and storage files to owner-only 0600. Set false only for a deliberate trusted-group deployment whose operator manages those files externally; in TypeScript mode Magic Context then skips its own creation modes and recursive tightening. In Rust transform mode, ck-mc’s store library always keeps the shared data directory owner-only 0700, regardless of this setting. USER-LEVEL ONLY — ignored in project config for security. On Windows, POSIX chmod modes are already meaningless, so this setting is a no-op.
KeyTypeDefaultDescription
smart_notes.enabledbooleantrueEnable smart-note authoring and condition evaluation. Needs a runnable dreamer, which evaluates the conditions: with dreamer.disable true (or no dreamer block) ctx_note offers no surface_condition whatever this says. User-level only: tool definitions are process-wide. Changes require a host restart and rebuild each session’s cached prompt once. Pending notes remain stored and unchecked; already-ready notes still surface.
smart_notes.retina_handoffbooleanfalseWhen true, dreamer skips smart notes whose surface conditions compiled to retina provider configs at authoring time. Default false keeps both paths active until the retina consumer is deployed.
models.window_overlay_pathunknown—Deprecated: ignored. Fusiform no longer publishes window-overlay data, so this setting no longer changes model window geometry. Remove this key.
toast_duration_ms Livenumber (0–60000)5000TUI toast lifetime in milliseconds for Magic Context notifications. Set to 0 to disable Magic Context toasts entirely (min: 0, max: 60000, default: 5000)
subc.connection_filestring—Path to the owner-only subc connection file.
debug_rpcbooleanfalseDeveloper-only: enable authenticated loopback RPCs for memory counters and heap snapshots. Disabled by default. USER-LEVEL ONLY and requires a restart.
fail_closed_blockingbooleantrueWhen Magic Context cannot operate (schema fence mismatch, storage open/migration failure), block the primary-session prompt with a loud recovery error instead of silently degrading to native compaction. Default true. Set false only to restore the old degrade-silently behavior (not recommended). USER-LEVEL ONLY — ignored in project config for security. Requires a restart.
compaction.enabledbooleantrueWhen false, Magic Context stops managing the context window and keeps its knowledge layer: memory and docs/user-profile/key-files injection through additive m[0]/m[1], raw-message FTS indexing, dreamer, notes, ctx_search, ctx_expand, ctx_memory, and /ctx-embed remain available. MC’s historian/compartment preparation, tagging, markers, pruning, folding, drops, strips, splicing, synthetic context-management todos, temporal markers, nudges, and fail-closed blocking stop; ctx_expand remains a knowledge-surface tool. fail_closed_blocking is inert: a transform failure passes the input messages through without blocking or cancelling. This setting does not enable native compaction: OpenCode’s compaction.auto / compaction.prune or Pi’s equivalent owns the window, or nothing does. MC’s compaction.enabled in magic-context.jsonc is distinct from OpenCode’s compaction.auto / compaction.prune in opencode.jsonc; they are different files and different owners. On the first turn after disabling, a long session may trigger one native compaction cycle; MC removes only its own marker boundary, leaves native boundaries and stored compartments intact, and does no pre-trimming mitigation. Marker cleanup is lazy per session, so an unresumed session is cleaned when it is next resumed. If compaction is enabled again, run /ctx-wrapup when the historian is runnable to catch up. OpenCode peer verification against v1.18.4 confirms native compaction covers child sessions: subagents receive additive memory/docs injection and no MC reclaim in this mode, so keep subagent tasks small or leave compaction.enabled on for long subagent runs. This is boot-resolved and requires a process restart; project-tier compaction.enabled is stripped so a cloned repository cannot disable the user’s setting. The sidebar reports raw usage as Context: % · native compaction or Context: % · no active compaction and does not show an MC execute-threshold fill. /ctx-wrapup, /ctx-recomp, and /ctx-flush refuse without context-management side effects; /ctx-embed remains functional. Raw content hidden by a native boundary before Magic Context’s first pass is not retroactively indexed.
pi.subagent_extensionsstring[]—User-only allowlist of Pi extensions for Magic Context subagent children. When set, children use —no-extensions and load only these entries (plus Magic Context’s scoped child extension where applicable). Relative paths resolve from ~/.pi/agent, matching Pi’s settings.json package location. Unset preserves normal Pi extension discovery.
smart_dropsunknown—Deprecated: ignored. Content-aware supersession reclaim is always on, only on passes already rebuilding the cache. Remove this key; it no longer does anything.
protected_toolsmap<string, integer (0–9007199254740991)>{"todowrite":1,"ctx_reduce":3}Keep each tool’s newest N still-active results in every automatic drop lane (issue 621). User and project maps merge over defaults {todowrite: 1, ctx_reduce: 3}; 0 turns protection off. Names are case-insensitive and ignore leading mcp_. Holds even at 95% pressure, with no byte cap: large protected outputs can reach refusal sooner. Queued drops, from the agent or historian publication, are held until newer calls displace the result and a later cache-rebuilding pass applies them. The historian’s summary is unaffected; the raw result leaves at the next fold. Frozen strips are unaffected. Changes and rotation never originate a bust; dropped results are never restored.