Releases: cortexkit/magic-context
v0.23.0
v0.23.0 — Self-managing context, big-session speed, and the title fix
A minor release with three themes: the context-reduction system was rebuilt around quiet, cache-safe nudges (and subagents now manage their own context); the heaviest per-message work moved off the database hot path, removing multi-second stalls on large sessions; and the agent can now maintain its own project memories instead of only writing new ones. Includes two database migrations (applied automatically) and the fix for the missing-session-titles regression.
Highlights
The agent maintains its own memories now. ctx_memory grew update, archive (including batch archive in one call), and merge for the memories the agent already sees in its context — previously these were reserved for the background dreamer, so a wrong or outdated memory stayed wrong until the next maintenance run. Cross-project access stays locked down: an agent can only touch its own project's memories. Memory categories are now schema-enforced (the 5-category taxonomy), so invalid categories fail at validation instead of being silently rejected.
Context nudges are quieter and structurally simpler. The agent-facing context-reduction reminders (never shown in chat) used to be injected into the message stream and replayed byte-for-byte on every pass — which worked, but needed careful replay machinery to stay cache-stable. The redesign removes that machinery instead of maintaining it: a compact <system-reminder> appended to tool outputs when reclaimable context piles up (Channel 1) persists naturally in the session database with nothing to replay, and a single one-shot escalation near the threshold (Channel 2) is delivered mid-turn — between tool calls, while the pile is still growing — and only when a fresh measurement confirms it's still warranted, never on stale data. Channel 1 paces itself: the re-fire interval scales with the history budget, repeat reminders in the same severity band are suppressed, and the cycle resets once the pile actually shrinks — so a long turn sees a handful of escalating reminders instead of one per tool call. Subagents get the same self-management machinery now: they see §N§ tags and ctx_reduce, with a minimal guidance block, so long-running subagent sessions no longer balloon.
Emergency context recovery actually hits its target. At ≥85% pressure the tiered emergency drop (T3 misc → T2 edit/search → T1 navigation tools, newest 20% of each tier reserved) replaces the old need-blind age-based drops — and its reclaim target is now computed from the full live tail, fixing a systematic under-eviction the audits caught. The routine auto_drop_tool_age / drop_tool_structure config knobs are removed (doctor cleans them up); reduction is the agent's job via ctx_reduce, with the tiered drop as the safety net.
Big sessions got dramatically faster. Three structural fixes for sessions with tens of thousands of messages:
- The historian trigger no longer re-reads the session from the database on every streaming event (which froze the event loop ~3s per event on a 60k-message session). It now runs once per request, inside the transform, from the messages already in memory — zero database reads in steady state.
- Per-message token counts are computed once and cached on the tag row, then summed in SQL — the sidebar, the history boundary, and the nudge math all read the same durable counts (a 250ms-per-pass floor went to 2.4ms).
- The protected-tail boundary reads only the post-compaction tail, never the whole session.
History compaction can't deadlock on sparse sessions (#132). The protected tail — the recent slice the historian never summarizes — is now sized by tokens rather than "the last 5 user turns." Sessions with few user messages (long autonomous runs, AFK workflows) previously protected everything and could never compact; now they compact like any other session. And the inverse guard: the size-based trigger fires on actual summarizable content, so tool-heavy sessions at low pressure no longer spawn the historian to write fragmented mini-compartments — runs batch into properly-sized history chunks.
Session titles generate again in fresh directories (#129). OpenCode permanently skips title generation once a session contains more than one real user message — and Magic Context's startup notifications (config warnings, conflict warnings, announcements) could land in a brand-new session before its title was generated, suppressing it forever. This reproduced most often in non-git directories, where the new session is the only delivery target. Notifications now wait for the session to have a real title and retry on a later launch otherwise.
Improvements
- Tool descriptions rewritten for the agent. All five
ctx_*tools now explain what they're for and when to reach for them, with concrete examples (including what a<compartment>is and how to expand one). Pi previously carried drifted inline copies; both harnesses now share one source. ctx_noteread is paginated — newest 25 first with a "N older" continuation footer, instead of dumping hundreds of notes into context.ctx_memorytakes one unifiedidsarray — update one, archive many, merge several, all through the same parameter.- Notes are anchored to the conversation —
ctx_note readshows↳ @msg Nso the agent can expand the conversation that produced a note. ctx_searchgot literal-probe recall — exact symbol names, slash-commands, paths, and commit SHAs now match reliably alongside semantic search.
Fixes
Beyond the headline items, three blind audit rounds over this release's changes surfaced and fixed (among others):
- Channel-2 nudge could deliver on stale pressure data and permanently consume its one-per-session cap; delivery now revalidates the full trigger predicate and an unknown measurement never burns the cap.
- The cheap historian-trigger gate undercounted eligible history after tool drops, suppressing real compaction triggers in long sessions.
- Legacy tool tags (from sessions started before v0.23.0) never converged to the new token cache; they now backfill on first observation.
- A primary agent could merge another project's memories (now dreamer-only, like the rest of cross-project access).
- Token-count math: ordinal gaps from malformed rows no longer drop valid messages from boundary sums; a literal
<EOT>-like string in tool output no longer crashes tokenization. - Tool calls cleared by
ctx_reducecould be stripped one pass too early, busting the prompt cache on a defer pass (frozen-watermark replay fixes it). - Routine history compaction can no longer cross the newest user message — the active prompt always survives a background historian pass intact.
- The Channel-2 one-shot lease is crash-safe: a delivery interrupted mid-send (process kill, database contention) is recovered by a TTL-scoped heal instead of wedging the nudge off for the rest of the session.
- Two processes opening the shared database at the same moment could race during the WAL journal-mode switch; the busy timeout now installs first.
- One-shot notifications (upgrade reminder, context-limit alert) only mark themselves delivered after an actual send — a skipped or failed delivery retries on a later launch instead of being lost.
- Sidekick (the
/ctx-aughelper) is read-only on project memory now;ctx_memory archiverejects already-archived ids with a friendly error instead of silently re-archiving.
Config changes
- Removed:
auto_drop_tool_age,drop_tool_structure,nudge_interval_tokens,iteration_nudge_threshold(the features they tuned were replaced by the systems above). Stale keys in your config are ignored andnpx @cortexkit/magic-context@latest doctorremoves them. - Database migrations v31–v32 apply automatically on first start. As always with a schema bump: update both harnesses (OpenCode and Pi) around the same time if you use the shared database from both — an older binary fails closed (safely, with a notice) against a newer database.
Pi
Full parity for everything above: Channel 1/2 nudges (via tool_result mutation and agent_end follow-up), the tiered emergency drop, the protected-tail redesign, cached token counts, memory actions, and the shared tool descriptions.
Dashboard dashboard-v0.5.4
Dashboard v0.5.4
Companion release for plugin v0.23.0 — keeps the config editor in sync with the new context-reduction system.
Changes
- Config editor updated for v0.23.0. The removed context-reduction keys (
auto_drop_tool_age,drop_tool_structure,nudge_interval_tokens,iteration_nudge_threshold) are gone from the editor, so editing a config from the dashboard can no longer re-introduce keys the plugin removed. The schema parity guard now covers the new surface. - Dependency updates:
tarandopensslbumped in the Tauri backend (dependabot security updates).
Compatibility
Works with plugin v0.23.0 databases (schema v32). If you edit configs from the dashboard, update both around the same time.
v0.22.5
v0.22.5 — Security hardening, history-integrity, and Pi parity
A correctness-and-hardening patch from a deep audit sweep across the plugin, Pi, and the shared core. The headline is a set of fixes to the trust boundary around a repository you've cloned — a malicious repo's project config or project files could previously reach further than they should. There are also several genuine context-integrity fixes (including one that could silently drop history after a restart) and a round of OpenCode↔Pi parity corrections. No new features, no database migration — just fixes.
Security — hardening the malicious-repo boundary
A project-level config (.opencode/magic-context.jsonc, .pi/magic-context.jsonc) and project files are attacker-controlled the moment you open a cloned repo. These close gaps where that input reached too far:
- Project configs can no longer expand
{env:...}/{file:...}on Pi. OpenCode already blocked this (project configs must not read your environment variables or arbitrary files); Pi had the same guard missing. A cloned repo can no longer exfiltrate secrets through a project config on either harness. - Your embedding API key is no longer sent to an endpoint a project config redirected. If a project config points the embedding
endpointat a different server without supplying its own key, the user-level API key is no longer inherited along with it — so a repo can't redirect the endpoint to its own server and collect your key. A project that only repeats your own endpoint (e.g. to change the model) keeps working unchanged. - A repo can no longer reprogram the hidden agents. Project configs can no longer override the historian/dreamer/sidekick
prompt,system_prompt,permission, or tool set. This matters most for the dreamer, which runs autonomously in the background with shell access — a cloned repo must not be able to rewrite its instructions or widen its permissions. - Project-docs files are symlink-guarded and size-capped. The files rendered into your context as
<project-docs>are now rejected if they're symlinks (so a repo can't pointARCHITECTURE.mdat~/.ssh/...) and are bounded in size. - Embedding requests have an SSRF guard. Requests to cloud-metadata / link-local addresses (IPv4 and IPv6, including the AWS IPv6 metadata endpoint) are blocked, while localhost and LAN/self-hosted embedding servers (LM Studio, Ollama, etc.) keep working.
- Local RPC endpoints now require a per-process token (used by the TUI), compared in constant time, and the auto-update path validates the version string before touching
package.json.
What's Fixed
History integrity
- History could silently vanish after a restart. If the historian published a new compartment and you restarted right before the next turn consumed it, that slice could be trimmed from the live transcript while its summary hadn't yet folded into the cached baseline — so it appeared in neither. Fixed by persisting the baseline's coverage boundary and trimming cold passes to it (bringing OpenCode in line with how Pi already worked).
ctx_searchno longer surfaces your current prompt (#131). On a session with no compartments yet, search could return the live conversation tail (already in your context). It's now excluded.- Interrupted upgrades render correctly. Compartments left half-converted by an interrupted
/ctx-session-upgraderendered as empty blocks, dropping their content; they now fall back to their stored summary. - A single bad config value no longer wipes a whole section. Previously one invalid nested field (e.g. under
memory) reset the entire block to defaults, silently discarding your other valid settings in it. Recovery now repairs only the invalid field and keeps the rest. - Stale compaction markers are reconciled on Desktop and Pi. A startup consistency check that clears orphaned compaction-boundary state never fired on the Desktop/Pi runtime (a missing-row check that worked under OpenCode's SQLite returned the wrong result under Node's), so stale boundary state could linger; it's now cleared correctly on all runtimes.
Pressure & overflow
- Switching models mid-session no longer carries the old model's limit forward. A context limit detected from an overflow on a small-context model could leak into a switched-to large-context model's pressure math, over-shrinking history; it's now cleared on the switch.
- No more emergency-recovery loop with nothing to summarize. A session that hit an overflow but had no eligible older history could get stuck repeatedly aborting; it now disarms cleanly.
- Pi rejects bogus context-window values. A transient garbage window reading no longer collapses the history budget and over-archives; Pi sane-bounds it and falls back to the model's real window.
Pi parity & cache stability
- Pi no longer busts the prompt cache mid-turn on background publishes. A background historian/recomp finishing mid-turn could trigger a cache-busting rebuild while a multi-step turn was still in progress; Pi now defers it to a turn boundary, matching OpenCode.
memory.enabled: falseis fully respected on Pi. Pi could still inject project memories with the memory store disabled; it now injects none.- Pi dreamer reliability. The dreamer now uses the full model fallback chain on Pi, and is registered for projects you switch into mid-session (not just the one Pi launched in).
Other
- History-comparting failure notices are no longer alarming. A background history-summarization hiccup used to show a scary "check the historian model and try again" alert even when it was a one-off transient blip that the next turn fixed on its own. Now a single failure shows a calm "this was transient, Magic Context will retry automatically — nothing is lost" notice, and only persistent failures escalate to the actionable "your historian model needs attention" message (with the real error). Magic Context already silently retries every fallback model before saying anything.
ctx_reducetolerates the§N§tag markers the agent sees. Models frequently copy the transcript markers verbatim into a drop range (§302§-§380§) instead of the bare numbers, which used to error. Magic Context now strips the markers and drops the messages anyway. Thanks @Zireael for the suggestion.- Sharper agent guidance for
ctx_noteandctx_reduce. Notes are now clearly scoped to genuinely future concerns (not work coming up in a few turns, and not as insurance against a restart — Magic Context preserves context across restarts), which cuts spurious note-taking; and the agent is told to drop context silently instead of narrating it. - Per-project dream scheduling no longer cross-contaminates. One project's dream run could suppress another project's schedule and skew its docs-maintenance timing; scheduling is now strictly per-project.
- Embedding
input_type/truncateare now actually applied (e.g. for NVIDIA NIM) — they were accepted by config but dropped before the request.
Upgrade
npx @cortexkit/magic-context@latest doctor --forceNo database migration in this release. --force clears any cached older plugin install so the new version takes effect on next launch.
Dashboard dashboard-v0.5.3
Dashboard v0.5.3
A small patch release: clear stuck dream-queue entries, reference notes by id, and fixes to the per-model config rows and several project-scoped views.
What's New
-
Remove stale entries from the dream queue. Pending dream-queue cards now have a Remove button, so a run you started for a project that no longer has an active runner (e.g. queued from the dashboard, then the project went idle) can be cleared instead of sitting there forever.
-
Notes show their id. Session notes and smart notes now display their
#id, so you can reference a specific note unambiguously when discussing or acting on it.
What's Fixed
-
Per-model config sliders are draggable again. In the Config editor, per-model override sliders (e.g. Execute Threshold %) only moved one tick and then stopped — the row's DOM was being recreated on every input, which dropped the slider mid-drag. They now drag smoothly, and the slider fills the full row width instead of stopping short with a large empty gap before the value.
-
Per-model override rows line up. Longer model names no longer push a row's input, slider, value, and remove button out of alignment, and the Default row now lines up with the override rows below it.
-
Dream runs appear for all projects. The Dreamer panel resolved project filters by raw path, so projects keyed by a normalized identity (the common case) could show no dream runs even when runs existed. It now resolves the same identities the rest of the dashboard uses.
-
Correct session project identity. Session detail now resolves a session's Magic Context project identity from its worktree, matching the identity used by the project-scoped memory, notes, and key-file views — instead of OpenCode's internal project hash, which lives in a different space.
-
Pinning a memory no longer over-invalidates the cache. Bulk memory status changes only refresh a running session's cache for rows whose status actually changed; a no-op update (a memory already in the target status) no longer forces an unnecessary re-render.
v0.22.4
v0.22.4 — Cache stability: the history baseline now actually stays cached
The v2 history layout was designed so that summarizing your conversation never disturbs the large, stable part of the prompt the provider has already cached — that was the whole point of splitting history into a frozen baseline and a small volatile delta. This release fixes a wiring gap where it wasn't actually behaving that way: every time the historian published a new compartment, it rebuilt the baseline and busted the provider prompt cache, re-sending hundreds of thousands of tokens even mid-session when nothing else had changed. Now it works the way it was always meant to.
What's Fixed
-
Publishing a new compartment no longer rebuilds the cached history prefix. The history layout splits into a stable cumulative baseline (
m[0]) and a small volatile delta (m[1]), and the baseline is supposed to behave like a frozen prefix that survives routine work — precisely so the provider prompt cache keeps paying off across a long session. It wasn't: a wiring gap made publishing a new compartment count as a baseline-changing event, so every historian run — including ones that fired well below the execute threshold — folded the baseline and invalidated the cache from that point down through the rest of the conversation. New compartments now land in the volatile delta as intended, and the materialization decision is organized around a single, explicit bust taxonomy:- No change (defer passes, nothing new) → the whole
system + m[0] + m[1]prefix stays cached. - New compartment / memory / user-profile delta → only
m[1]re-renders; the baseline stays byte-identical and cached. - Genuine baseline change (model change, system-prompt change, tool-set change, idle past the cache TTL, or a structural history rewrite) → the baseline re-materializes — but only when the provider cache was already going to be invalidated anyway, so the rebuild is effectively free.
This also wires up two things the old layout never actually did: re-materializing the baseline when you come back to an idle session past its cache TTL, and detecting a tool-set change (the provider sends tools as a separate block ahead of the system prompt, so a tool change is invisible to the system-prompt hash on its own).
- No change (defer passes, nothing new) → the whole
-
Pi had the same gap, via a different mechanism — also fixed. On Pi the cache was being cleared on every history-refresh pass, which forced a full baseline rebuild every time — so Pi effectively never had a working stable-prefix path. Pi now keeps the cached baseline and surfaces new compartments in the delta block, matching OpenCode, with the visible-message trim boundary advancing in lockstep so nothing is duplicated.
-
Dreamer key-files and user-memory token usage now show up in the dashboard. The key-files selection step and the user-memory review step both spend real tokens on an LLM call, but neither was recording that spend — so the dashboard showed
—for those rows. Both now report their input/output tokens like every other dreamer task. (Particularly useful if you've turned onkeep_subagentsto study dreamer cost.)
What's New
keep_subagentsconfig flag (default off). When set totrue, Magic Context stops deleting its own background child sessions (historian, dreamer, sidekick, memory-migration) after they finish, so you can inspect exactly what they did. It's a debugging aid — leave it off for normal use, since these sessions otherwise accumulate.
Upgrade
npx @cortexkit/magic-context@latest doctor --forceThis release adds a database migration (schema v30) that runs automatically on first launch and clears the history cache once so the new baseline re-materializes cleanly. If OpenCode still loads a cached older plugin after upgrading, --force clears the cached install so the new version takes effect on next launch.
Dashboard dashboard-v0.5.2
Dashboard v0.5.2
A small patch release: edit user memories directly from the dashboard, and the Config editor catches up with the current plugin schema.
What's New
- Edit, expand, and delete user memories from the User Memories panel. Promoted memories and pending candidates now show their full content instead of a truncated one-line preview, and each memory has an inline editor (Save / Cancel) so you can fix wording without touching the database. Editing a memory refreshes a running session's profile, so the change takes effect on its next turn. The Delete button now asks for a second click to confirm before removing anything.
What's Fixed
-
The Config editor matches the current plugin schema again. The settings form had drifted from the plugin: it still wrote the retired
experimental.*keys for temporal awareness, auto-search, git-commit indexing, and caveman compression — which had graduated to top-level /memory.*in v0.22.0 — so toggling any of them in the dashboard quietly re-introduced the dead namespace and fought the plugin's own config migration. Those four now map to their real locations under a renamed History & Recall section, and a new Advanced section exposes settings that previously had no control at all:auto_update,keep_subagents,system_prompt_injection, and thesqlitecache/mmap tuning. -
Correct schema URL and setup command in generated configs. A freshly generated config pointed its
$schemaat the old pre-rename repository path and suggested an outdated setup command. Both now use the currentcortexkit/magic-contextrepository and the unifiednpx @cortexkit/magic-context setup.
v0.22.3
v0.22.3 — Tag-residue overflow fix, leaner internal agents, and log privacy
A focused patch: a community fix for runaway tag-marker corruption, Magic Context's own background agents no longer carry the user-facing context machinery, and dreamer logs stop printing absolute project paths.
What's Fixed
-
Runaway
§N§tag markers no longer corrupt chat history (#97). When the model mimicked Magic Context's§N§tag notation in its own output, the persistence-boundary cleanup stripped the bare§character but left the digits behind — so§40827§became40827, which then accumulated across turns (40827 40827 40827 …) and could eventually blow up the prompt into a context overflow. Persisted assistant text now removes whole§N§pairs (digits and all), and tag-only "ghost" messages left over after a tool drop are pruned instead of lingering as empty parts. Thanks to @Zireael for the fix. -
Dreamer logs no longer print absolute project paths. The dreamer, dream-timer, and git-commit log lines printed the full project directory (e.g.
dir=/Users/<you>/Work/<client-project>), which carried your username and project name — and those lines flow intodoctor --issuereports. They now log only the opaque project identity (git:<sha>/dir:<hash>), which still uniquely correlates a run for debugging without exposing anything sensitive.
What's Changed
- Magic Context's own background agents now bypass the Magic Context pipeline. The historian, dreamer, sidekick, and memory-migration sessions are short-lived helpers with their own fixed instructions — but they were still being handed the full
## Magic Contextguidance block and run through the message transform (tagging, heuristic drops) like a normal session. That was wasted tokens and a second, contradictory identity on top of their real one. These internal sessions are now fully exempted from both the system-prompt injection and the message transform. No effect on your own sessions or on regular subagents.
Upgrade
npx @cortexkit/magic-context@latest doctor --forceIf OpenCode still loads a cached older plugin after upgrading, --force clears the cached install so the new version takes effect on next launch.
v0.22.2
v0.22.2 — Accurate context limits, sharper ctx_search, and note anchors
A focused patch: correct per-account context-window detection, better symbol/command recall in ctx_search, traceable notes, and a fix for redundant commit-embedding work across multiple running instances.
What's New
-
ctx_searchnow reliably finds symbol, command, and path lookups. Searching for a literal token like/ctx-status,git_sweep_coordinator, orsearch.tsinside a natural-language question used to fail, because the query required every word to appear in the same message — so a message containing the exact symbol but not the surrounding words was never retrieved.ctx_searchnow extracts literal probes (slash-commands, identifiers, file paths, quoted phrases, commit SHAs, error codes) from the query and searches each one alongside the full query, ranking exact matches first. Plain natural-language queries are unchanged, and the automatic auto-search path is untouched. -
Notes remember where they were written.
ctx_notenow records the conversation position at write time and renders↳ @msg Nwhen you read notes back, with a hint toctx_expandaround that point. This makes it easy to jump back to the discussion that produced a note. Existing notes simply render without an anchor.
What's Fixed
-
Context window now reflects your actual provider limit. Magic Context could show a model's published context window (e.g. 922K for GPT-5.5) even when your account/plan resolved to a smaller cap (e.g. 400K with a Codex OAuth/Pro login) — which would let pressure and history-budget math run against a window the provider would reject. The limit is now taken directly from the harness's own resolved provider config (OpenCode's SDK, Pi's runtime) instead of a separately-read models.dev file, so account-specific caps are honored. This also eliminates a rare case where a momentary bad read reported a nonsensical limit (e.g. a few thousand tokens). (Pressure is measured against the model's max input size, so a 400K-context model shows ~272K — the real prompt cap that gates you.)
-
Redundant commit embedding across multiple instances. When several Magic Context instances run at once (e.g. OpenCode server, Desktop, Pi, background workers), each one independently re-embedded the same git-commit backlog, hammering the embedding provider with duplicate work. Commit indexing and backlog draining are now coordinated through a shared per-project lease, so only one instance works a given project's backlog at a time. (Affects users with
memory.git_commit_indexingenabled.) -
Commit-index over-eviction under concurrency. Two instances enforcing the commit cap at the same time could delete more than the intended number of oldest commits — and because indexing only fetches newer commits, the over-deleted ones never came back. Eviction is now computed from current state so it's safe under concurrent runs.
-
Large commit backlogs that never finished embedding. A repository indexed before embeddings were enabled could sit permanently at zero embedded commits, because the only path that drained a pure backlog wasn't running. That backlog now drains (coordinated, in bounded batches) until complete.
-
/ctx-recompwas mislabeled as "Upgrade" in the TUI. A plain recomp showed "Recomp / ✗ Upgrade failed" in the sidebar — a contradiction, because both the recomp and the session-upgrade flow shared one hardcoded "Upgrade" label. The progress now reads correctly per flow ("Recomp" vs "Upgrade"). A transient skip (the history comparter briefly holding the lock) now shows a neutral "skipped — retry shortly" instead of a red failure, and the recomp confirmation dialog reads clearly when a session has no compartments yet.
Housekeeping
- Removed several genuinely-unused internal symbols (verified zero references) and a few no-op lint suppressions.
Upgrade
npx @cortexkit/magic-context@latest doctor --forceIf OpenCode still loads a cached older plugin after upgrading, --force clears the cached install so the new version takes effect on next launch.
v0.22.1
v0.22.1 — Issue triage sweep: embeddings, context limits, Windows, config schema
A focused patch closing a batch of reported issues after v0.22.0.
What's New
-
NVIDIA NIM embedding support (#127). New optional
embedding.input_type("query"/"passage") andembedding.truncatefields for openai-compatible providers. They flow through the live request, the endpoint probe, and the dashboard's Test Connection.input_typeis part of the provider identity (it changes the vector space), so changing it triggers a re-embed. Omitted entirely when unset, so standard OpenAI-style endpoints are unaffected. -
magic-context.schema.jsonis now auto-generated from the Zod config schema (#109). The JSON Schema can no longer drift from the actual validated config — a CI guard fails the build if they diverge.
What's Fixed
-
Context usage reported as >1000% for ollama-cloud models (#117). Two real causes: (1) ollama invokes cloud models with a tag (
deepseek-v4-pro:cloud) while models.dev stores them tag-less, so the lookup missed and fell back to a 128k default; we now match exact-first, then retry with the tag stripped. (2) ollama's tiny defaultnum_ctxreported via the live API was overriding the correct large models.dev window; when both sources know a model we now take the larger limit. A genuinely smaller real limit still comes through the overflow-detection path. -
Native-module crash on process exit (#95). On Bun teardown, N-API finalizers could panic. Magic Context now does an orderly cleanup (RPC server, dream timer, auto-update controller) on OpenCode's
server.instance.disposedevent. -
Auto-update failing on Windows with a locked package directory (#103). The updater now tolerates
EBUSY/EPERMon the cache directory with a retry instead of aborting the update. -
"What's new" announcement showing on fresh and sandboxed installs (#99). The announcement state is seeded on first run, so the dialog only appears on an actual version change.
-
execute_thresholdabove 80% silently capped. The config loader now explains, via a validation message, that the runtime caps the effective execute threshold at 80% for cache-safety headroom (#111). -
Windows test-suite EBUSY teardown failures cleaned up so the suite runs green on Windows CI.
Housekeeping
- Bumped
@opencode-ai/pluginand@opencode-ai/sdkto^1.15.13. - Added a Feature Request issue template; documented the model cache and log paths plus sandbox guidance in the README Storage section (#100).
Upgrade
npx @cortexkit/magic-context@latest doctor --forceIf OpenCode still loads a cached older plugin after upgrading, --force clears the cached install so the new version takes effect on next launch.
v0.22.0
v0.22.0 — 🎊Historian v2🎊, a self-tuning history cache, and node:sqlite
This is the largest release since Magic Context launched. The history engine has been rebuilt from the ground up, the SQLite backend no longer needs a native module, two recall features are now on by default, and the Pi plugin reaches full behavioral parity with OpenCode.
Upgrading an existing session? Sessions compacted by the old historian keep working, but you'll be prompted once to upgrade them to the new format for better fidelity and cache stability. See Upgrading below.
Headline: Historian v2 and a self-tuning history cache > pure magic...
The old design summarized history into a single flat block and ran a separate LLM "compressor" pass to keep it small. That's gone. The new engine is deterministic, cheaper, and far more cache-friendly.
Tiered compartments. Every compartment the historian writes now carries four paraphrase tiers — from a verbose P1 (treated like "the last 12 hours," kept near-verbatim) down to a P4 anchor (just enough to recognize and re-find it). The historian also scores each compartment's importance as a decay rate: how long this needs to stay in high-fidelity memory.
Deterministic decay rendering — no more compressor LLM. Instead of paying a model to re-compress old history, a math function picks the right tier for each compartment on every render, from its age, its importance, and how much history budget you currently have. As a compartment ages or as budget tightens, it gracefully demotes P1 → P2 → P3 → P4, oldest-first. When your model's context window is large, history renders richer; when it's tight, it renders leaner — automatically, with zero LLM cost.
A two-slot history layout that keeps your cache warm. History now renders into two synthetic message slots:
- A stable baseline holding project docs, your user profile, and the decayed compartment history — treated like a frozen prefix that does not change on routine turns, so its prompt-cache bytes persist.
- A small volatile delta holding only what's new since the last baseline refresh — new compartments, new memories, and your pinned key files.
The practical effect: on a steady working day, the large stable prefix stays cached until TTL expires or system promopt changes, and only the small delta moves. Fewer surprise cache-misses, much lower cost on long sessions.
Memory edits no longer bust your cache. When the agent (or you) edits, archives, or merges a memory mid-session, that change now surfaces as a compact correction in the volatile delta instead of forcing the entire stable baseline to re-render. The agent sees the corrected state immediately; the expensive prefix stays put until the next natural refresh.
No more native SQLite module
The non-Bun runtimes (Pi on Node, OpenCode Desktop on Electron) used to depend on better-sqlite3 — a native module that needed a per-platform prebuild and, on Desktop, a runtime binary download with an ABI probe. That whole path is gone. Magic Context now uses the built-in node:sqlite on Node and Electron, and bun:sqlite under Bun.
No native module, no prebuild, no download, nothing to go wrong on install. If you ever hit better_sqlite3.node load failures or Electron ABI mismatches, those are eliminated.
Two recall features now on by default
Both were previously opt-in experiments and are now stable and on by default. Each can be turned off independently.
- Temporal awareness — the agent sees elapsed-time markers (e.g.
+2h 15m) between messages and dated compartments, so it understands when things happened. Opt out withtemporal_awareness: { enabled: false }. - Auto-search hints — each turn, a background
ctx_searchquietly whispers a compact "vague recall" when something relevant exists in your memories, past conversation, or git history. No full content is injected — just a nudge to look. Opt out withmemory: { auto_search: { enabled: false } }.
Experimental config graduated
The experimental.* namespace is retired. Settings moved to stable homes, and doctor migrates your existing config automatically (your opt-ins and opt-outs are preserved):
| Old | New | Default |
|---|---|---|
experimental.temporal_awareness |
temporal_awareness |
on |
experimental.auto_search |
memory.auto_search |
on |
experimental.git_commit_indexing |
memory.git_commit_indexing |
off |
experimental.caveman_text_compression |
caveman_text_compression |
off |
Collapsible sidebar
The TUI sidebar can now be collapsed (click the header). Collapsed, it keeps the context progress bar plus three compact summary lines — Historian state, Memories, and Status (compartment / queued-op / note counts) — for a glanceable view that takes minimal vertical space.
Pi reaches full parity with OpenCode
The Pi plugin went through an extensive parity sweep and now mirrors OpenCode's behavior across the board: the two-slot history layout, deterministic decay rendering, memory supersede-delta, the upgrade flow, detached (non-blocking) recomp/upgrade, model-fallback chains, and stable message-identity handling. A tracked PARITY.md now documents every intentional difference between the two harnesses so they don't drift.
Performance
- Transform hot path. A per-pass work-metrics computation was scanning the full assistant-message history on every turn; on large sessions that alone cost ~250ms per pass. It's now lazy and incremental — computed only when the sidebar asks for it. On a large session the post-transform phase dropped from ~240ms to a few milliseconds.
- Dashboard. Database and filesystem reads moved off the UI thread, the project dropdown is cached for instant History re-entry, and the session list no longer scans the full message table just to show a count. Navigating the dashboard is now snappy even on large databases.
- Tunable SQLite. New optional
sqlite.cache_size_mbandsqlite.mmap_size_mbknobs, plus a periodicPRAGMA optimize.
Dashboard
- Compartment view upgraded to the v2 model — per-tier (
P1–P4) inspection, importance, and episode-type badges. - New expandable Memory Changes drill-down on dreamer runs — see exactly which memories were written, archived, or merged.
- Token breakdown corrected to measure the actual injected bytes (Docs and User Profile are now their own categories).
Security and correctness hardening
This release folded in a large multi-round audit sweep across both harnesses and the dashboard. Highlights:
- Memory config bypass fixed — disabling the memory store no longer leaks memories into the prompt via a fallback path.
- Local RPC server now requires a per-process bearer token and drops wildcard CORS, so a stray local process can't drive the side-effecting endpoints.
- Resumed-session project resolution — note nudges and auto-search now resolve the session's project, not the launch directory, so
opencode -sfrom another repo behaves correctly. - More than 50 additional bugfixes across the plugin, Pi, and dashboard — migration collision handling, the upgrade flow, key-file selection, dashboard memory editing, and many more.
Upgrade
This release adds database migrations that apply automatically on first start. Your data is migrated in place.
# OpenCode
npx @cortexkit/magic-context@latest doctor
# Pi (requires Pi >= 0.74)
npx @cortexkit/magic-context@latest setup --harness piUpgrading old compartments. Sessions that were compacted by the previous historian remain fully usable, but their compartments are in the old flat format. When you open such a session you'll be prompted once to upgrade it — this reprocesses its history with the new historian into the tiered format (it can take a while on large sessions, and runs without blocking your work). You can also trigger it manually:
/ctx-session-upgrade
Upgrading is optional but recommended — un-upgraded sessions render in a degraded single-tier mode.