Stable

The default.
New features still ship here.

Stay on npm install -g memtrace for everyday use. Nightly is the same command with new features as they land, and it is not always stable.

A re-thought engine for every language, a code graph you can actually read, and sharper tools for your agents

New

  • Perl is indexed from the grammar rather than by pattern. A package statement changes the current lexical namespace, a qualified definition does not change the namespace of its body, and dynamic dispatch is reported as unresolved instead of guessed at.
  • Zig reads the module graph its build.zig declares. Zig binds a bare-name import per module, so @import("config") in two different executables names two different files; flattening those aliases into one repo-wide map sent the second module's import to the wrong file.
  • Zig enum variants are understood as receivers. Op.create.event_max() reads a variant as the receiver, and a variant is not a container — the receiver of its method is the enum that declares it. Nothing in the graph could previously say which names were variants.
  • Zig calls excluded by a comptime-known condition no longer produce edges. A branch guarded by a const bound to false cannot call what it contains, and an edge saying otherwise invites you to trace a path the compiler already removed.
  • SQL routine bodies contribute calls, taken from parsed expressions and never from text inside comments or string literals.
  • COBOL paragraphs and sections are both indexed as units control can be transferred to, which is what makes a COBOL program's flow followable.
  • Nextflow repositories are indexed across all three syntaxes they mix: DSL2 pipeline and component files, the declarative configuration files, and nf-test suites.
  • Dart indexing covers the declarations the language actually has — classes, mixins, extensions, extension types, enums, constructors, and function and method signatures — verified against the grammar's own node types.
  • R projects expose the surface that makes an R graph useful: package and namespace dependencies, and sourced files.
  • Vue component events are now a relationship you can follow. A template's @event="handler" is a subscription, not a call: the handler binds to the child component and the child records what it emits, so “who handles what this component emits” is answerable across files.
  • Swift attributes reach the graph. @objc, @available, @MainActor and @discardableResult were recorded nowhere, so “what is exposed to Objective-C” and “what is deprecated” had no answer.
  • TypeScript ambient and namespace declarations are extracted. Members of a declare class were never read, so a call inherited from an ambient base could not resolve, and a namespace body was treated as a block, so every value it declared was absent.
  • A callable's written signature facts reach the store and the read path. Each parameter's type and the return annotation are published in one canonical spelling — whitespace collapsed, a C++ plain name unqualified, a Rust borrow reduced to the type it borrows — with C++ member constness beside them, and get_symbol_context returns them on the symbol, on its callers, callees and siblings, and on the candidate list returned when a name matches several declarations — which is where overloads are actually compared. They were computed during indexing and discarded before, so nothing outside the indexer could see them. The candidate list also names annotations and marks contributed symbols, so an ambiguous match no longer reads as if every choice were parsed and unannotated.
  • Named tool registrations are anchored to the exact handler declaration that serves them, so a codebase that registers tools can be asked which handler answers which name.
  • Memtrace offers four ready-made workflows as MCP prompts: before_modifying, before_deleting, new_codebase and incident. Hosts that support prompts show them as slash commands, and each one expands into the full multi-tool routine with your symbol and repository filled in.
  • Every Memtrace MCP tool now declares whether it only reads, can remove data, or reaches the network. Hosts use these hints to decide what needs your approval, and Codex runs read-only Memtrace calls in parallel instead of one at a time.

Improved

  • Text search now runs inside MemDB. Before find_code could answer, it built a private search index on the machine asking, by reading every record of the repository back out of the store. Against a hosted or self-hosted MemDB that meant downloading the whole repository over the network first. MemDB now builds that index beside the data and answers the search itself, so nothing is downloaded. In our measurements on a repository of about 4,000 indexed records at 45 ms of network latency, the first find_code went from 32.8 seconds to 2.2 seconds, and repeat searches against a local store answer in about 60 ms. It makes no difference to ranking which side answers: the server and the local path share one scoring implementation, checked to produce bit-identical scores. Self-hosted MemDB servers gain this once they run this release; until then Memtrace keeps using the previous path, now with a time limit.
  • Every programming language Memtrace indexes is affected by this round. Twenty language frontends changed outright, and the shared work behind constructors, receivers, visibility and call resolution reaches the rest — ActionScript, Elixir, GDScript and Lua included. Configuration and infrastructure formats such as YAML, JSON, TOML and Kubernetes manifests are deliberately unchanged.
  • Go projects resolve their imports. A module whose path carries no dot or slash — module myapp, which covers most internal modules — resolved no package imports at all, so “what depends on this file” returned nothing for the whole project.
  • Java imports follow the package a file declares rather than the directory it sits in, so flat and non-standard layouts resolve. Wildcard imports such as import com.example.models.* reached nothing whatsoever and now resolve, and a module boundary marked by a pom.xml or build.gradle is respected rather than crossed.
  • Swift files in one module now connect when one genuinely uses the other. Same-module files see each other without an import, which we modelled as every file importing every other — that does not scale, and above a size threshold it silently produced nothing at all. A 400-file target went from no connections to roughly 2,400 meaningful ones.
  • Whether a declaration is exported is now decided the way each language expresses it, and that decision is the root set for dead-code analysis — a symbol nothing calls is only dead if it is also not part of the public API surface.
  • Rust namespace paths resolve through declared modules and imports, so a value that happens to share a module's spelling can no longer hide it.
  • Processes and impact walks get the benefit directly: cross-file imports now exist for Go, Java and Swift layouts that previously had none, so a process crossing a file boundary in those projects can be followed at all, and a blast radius no longer lists callers that never called.
  • The before_modifying prompt and the routing instructions check a symbol with one preflight_check call, which returns its dependents, the process flows it sits in, the files that change with it, its recent churn and a checklist of what to re-verify. They used to walk four separate lookups to gather the same answer.
  • find_central_symbols names the symbol kinds a repository actually has when a request ranks nothing or asks for a kind that does not exist, such as Interface or Protocol in a Rust repository. The next call can ask for traits directly instead of listing every symbol to find out.
  • find_symbol and find_code name the repositories to choose from when they need a repo_id, so a retry no longer has to list every indexed repository first. get_timeline called with a guessed scope_path that matches nothing now says to copy it from a find_symbol hit.
  • The All repositories graph shows each repository as its own island. Repositories that call or import each other sit side by side and blend along their shared border, unrelated ones sit apart, files with no relationships stay at the edge of their own repository, and each island keeps the shape it has when you open that repository on its own.

Changed

  • Java types carry their package, so com.a.User and com.b.User stop collapsing into a single symbol, and a type declared inside a method carries the name the JVM gives it. This changes symbol identity for packaged Java — reindex your workspace after upgrading to pick it up.
  • C# file-scoped namespaces (namespace Foo;, the modern default) now own the types written after them. Previously every type in such a file was unqualified, so two namespaces sharing a class name read as one type.
  • Constructors are one concept across fourteen languages, so “list this class's constructors” no longer answers differently depending on which language the class was written in. Python keeps __init__ as a method, because that is what the language makes it.
  • Members of a type are indexed as the kind they are. A property declared in a Kotlin, Dart or PHP class is now a field, as in Java and C#, where it used to be a variable, and a member of a Kotlin companion object belongs to its class. A Swift static let written after an attribute such as @available(*, deprecated) is a constant; it was read as a mutable field. A Java enum's constants are indexed, as constants owned by their enum. Java, Go, JavaScript and Ruby methods are methods rather than functions, so a search filtered to methods no longer leaves them out. Anonymous functions in Dart, Elixir and GDScript are named by where they are written, <anonymous>@line:column, with the function that holds them recorded as their owner. Kinds and names are part of a symbol's identity, so each repository is re-parsed once, automatically, on the first start after upgrading.
  • A class-qualified call resolves only where the type is declared locally and nothing shadows it, and a named upper bound is treated as a receiver contract rather than a concrete construction type.

Fixed

  • find_code against a hosted or self-hosted MemDB no longer waits indefinitely. Building its search index had no time limit, a request that gave up threw that partial work away so the next attempt started from nothing, and loading the query's embedding model could stall forever on a host with no route to the model download. Each is now bounded, and while an index is still being prepared find_code says so, answering not_ready with search_warming, instead of reporting no matches and suggesting a filesystem search.
  • Memtrace's own bookkeeping records, such as tool-call savings, session anchors and branch markers, are no longer indexed as searchable text, so they cannot appear among find_code results or skew its ranking.
  • The same query over the same data now returns results in the same order every time. The search index was built on several threads at once, so scores that were almost equal could swap places from one build of the index to the next.
  • A local store no longer loses saved changes after an unclean shutdown or a disk error. Four separate recovery faults could each discard changes that had already been saved, while the store still opened as if nothing was wrong: damage in data a checkpoint had already covered; a crash that cut a write off in its first few bytes, so the next save was written behind the fragment and lost on the restart after; a write that failed on a full disk; and an error while replaying changes at startup, which discarded the store's index of everything older. Recovery now keeps those changes. Where it cannot recover a store safely, the store now refuses to open with an error that names the problem, instead of opening without part of your data. A store that already lost changes this way is not repaired by upgrading: reindexing that repository rebuilds what was lost.
  • A memtrace start that cannot open the store no longer stops the Memtrace already serving that workspace. When a store belongs to a workspace file or a named workspace, a bare memtrace start from a folder above your projects is refused rather than allowed to widen it — but it stopped the running daemon on its way to refusing, so the workspace was left with nothing serving and no dashboard, under an error that ended “No data was changed”. The refusal now happens before anything is stopped, so the Memtrace you already had keeps serving and the message tells you which command to run. The added check is read-only — it takes no locks and writes nothing — and the authoritative check still runs where it always did.
  • The line Memtrace prints when a memtrace start replaces the daemon already serving a workspace no longer calls that daemon unhealthy. Three of the four reasons to replace one — --force, a change in workspace membership, and an unsafe store scope — say nothing about its health, and the actual reason is already printed on the line above.
  • An editor that launches Memtrace's MCP server while memtrace start is still coming up now waits for it. Start makes itself visible a few seconds before it records how to attach, and an editor arriving in that window exited with “no runtime record … refusing to attach”, leaving it without Memtrace tools until it was restarted.
  • An MCP session opened before any Memtrace store is running no longer hangs on each tool call. It used to wait about 25 seconds on a connection nothing would answer; until a store is up, calls now fail at once, and the session attaches as soon as a store appears.
  • Ruby assignments inside class_eval, instance_eval, instance_exec or Class.new are no longer attributed to the enclosing class's instance. Those blocks move self somewhere else entirely, so the resulting answers pointed at the wrong object.
  • A method defined in a TypeScript object literal binds this to that literal rather than to the class around it. We were reporting a member access the compiler rejects outright.
  • Java method references in a predicate slot, such as .filter(User::getName), no longer resolve to calls the compiler refuses. An unwritten or type-variable result now abstains instead of guessing.
  • A receiver typed with a bounded wildcard no longer resolves a call that cannot be written. ? super in Java and in in Kotlin genuinely can be called and still resolve.
  • PHP member calls on an untyped receiver are admitted only where the workspace holds exactly one method of that name with a matching arity and compatible arguments, and such a suggestion is never fed back into return-type propagation.
  • Rust attributes are recorded against the declaration they were written on, so two fmt methods on one type no longer trade #[inline] between them.
  • The graph now shows every relationship a repository's edge count includes. The count covered every kind, but the graph's edge list used an older, fixed list of kinds, so field reads and writes, interface implementations, definitions and component events were counted yet never drawn, and the graph tools that rank or cluster symbols left them out too. A JavaScript or Python function parameter is also no longer reported as reading a field of the same name elsewhere in the repository.
  • On Windows, Microsoft Defender began quarantining memcore-server.exe from the 1.2.8 nightly after a security intelligence update on September 24, which stopped Memtrace from opening its store. The store server is now built with the same compiler as every other Memtrace binary, and each Windows build is still scanned with current Defender definitions before it is published.
  • Four MCP tool descriptions no longer contradict their tools. get_changes_since stopped asking for inputs it rejects, so the calls an agent built from it now succeed; calculate_cyclomatic_complexity states the risk bands it actually reports and whether a score was measured or estimated; get_timeline names its required inputs and where to find them; and delete_repository no longer claims re-indexing restores what it deletes.
  • MCP clients now see Memtrace's documentation pages as resources. The list was always empty because Memtrace asked the docs site for a page that does not exist. Listing resources also no longer waits up to 20 seconds on a machine that cannot reach the docs site: it answers within 2 seconds and falls back to the copy it cached last time.
  • find_dependency_path refuses an edge_type it does not recognise and lists the valid ones, and find_central_symbols and find_bridge_symbols report kinds they did not recognise in kinds_ignored. Both used to answer a different question without saying so.
  • get_episode_replay in graph_summary mode says which section could not be computed and why, instead of returning an empty list that reads as "nothing central changed".
  • Passing a blank or placeholder repo_id is reported as an input error rather than a server fault.
  • Skills installed as the Claude Code plugin now find the parameter reference they point to, because the installer copies it into the plugin. Pi skills name each tool the way Pi registers it, in their descriptions as well as their instructions.
  • get_changes_since, get_evolution and episode replay count each change once. A full index could store its episode twice, so one commit read as two episodes with every total doubled, a commit recorded by both indexing and history replay was listed twice, and the markers an embedding pass and history replay leave behind were listed as changes.
  • Indexing a repository with history no longer leaves a second live copy of every symbol an earlier commit introduced and the latest commit did not touch. Reads showed one copy, but the duplicate doubled the raw graph, gave each symbol's timeline a phantom second version, and made deleted code look like it was still there.
  • get_codebase_briefing called without a repo_id briefs the only repository in the workspace. It used to report that nothing was indexed and advise re-indexing a repository that was already there; with several repositories indexed it now asks which one.
  • calculate_cyclomatic_complexity no longer refuses a unique function as ambiguous on a store that holds two rows for it, and it accepts the scope_path or the id other tools return, not only the bare name.
  • find_code with include_related=true now returns the callers, callees and type users of its top hits, the same relationships get_symbol_context lists, with each row marked outbound or inbound and its edge kind. Search also lifts the graph neighbours of strong matches into its ranking. Both used to come back empty, because the graph walk was filtered by a number the store does not index edges under.
  • The symbol panel in /ui no longer lists a caller or callee whose link exists only on another branch.
  • The code graph no longer collapses into one white mass pushed to one side, with a ring of loose nodes around it. On repositories with many execution flows, every flow step was laid out as its own link, which switched the layout to a mode that does no clustering. Each flow is now drawn with one link to its entry point, so related code groups into clusters again. Selecting a flow still highlights every step, and the edge count shows how many links are drawn beside the total.
  • Test functions no longer start execution flows. Every test that reached shared code added a near-copy of the same large flow, which buried the real flows and multiplied the graph size several times on large repositories. Run a reindex to shrink an existing index; otherwise each repository is corrected on its next saved edit.
  • On Windows, the Files panel, search results, symbol details and the all-repositories file tree show paths relative to each repository instead of putting every file under a single c: folder. Ignoring a file from the Files panel or from a graph node now works on Windows, and ignoring a file at the repository root ignores only that file, not every file with the same name in subfolders. A file's symbol list no longer includes symbols from a same-named file elsewhere in the repository.
  • The graph toolbar's zoom in, zoom out and fit-to-screen buttons work with the default renderer; they did nothing unless the compatibility renderer was selected. The graph also frames itself again once its layout settles, instead of staying framed on the wider starting layout.
  • Upgrading with npm 12 no longer leaves your coding agents on the previous version's skills, MCP configuration and Claude Code plugin. npm 12 blocks install scripts unless you allow them, so Memtrace now finishes setup on the first memtrace command after an install or upgrade: an existing setup is refreshed with a one-line notice, a new install asks first in a terminal, and elsewhere it prints how to run memtrace setup --yes. Your earlier --no-hooks and --project-only choices are kept, npm i -g memtrace --allow-scripts=memtrace runs setup during the install instead, and MEMTRACE_NO_AUTO_SETUP=1 turns the first-run step off.

The graph comes back, and your agents stop colliding

Fixed

  • Picking a point on the timeline shows the graph as it was at that moment again. Since 1.1.4 the dashboard had no way to build a historical picture: the change that stopped Memtrace from re-scanning the whole store on every dashboard load also removed the only code path that answered a time-travel request, so every point on the timeline came back as an empty graph marked “Graph view is materializing”. The chosen time is kept in the page address, so a reload brought the empty picture straight back, and the only way out was to switch to a single repository and back to all of them. Historical views are now built on request from the store — for one repository or for all of them — and are never written over the live graph's cache. The live graph is unchanged: it is still served from cache and a dashboard load still never triggers a store scan.
  • While a new picture is loading — after a timeline scrub, a branch switch or a repository switch — the graph already on screen stays put with the refresh indicator on, instead of being replaced by the “materializing” overlay until the next answer lands. A historical picture is a live walk of the store, so that gap is seconds, and it no longer blanks the view.
  • The graph no longer sits on “Graph view is materializing” after a reload. When the first answer for a view is still warming up or empty, the dashboard now keeps asking every couple of seconds until a drawable graph lands, then stops and goes back to push-driven updates. Before, it waited for a refresh signal that had already fired, so an empty first answer stayed empty until you switched repositories and back. A graph that is already on screen is never re-fetched on a timer, so the flicker fixed earlier does not come back.
  • Stale copies of edited functions no longer hang on the outer ring of the graph. When a function moves to a different line, Memtrace records the moved version as a new symbol and retires the old one; on some stores the old version's connections were retired but the symbol itself was written back as live, so it survived with no connections at all and the layout parked it on the ring reserved for unconnected nodes — on a nine-repository workspace that was about 1,200 ghost Rust functions, each with a connected twin of the same name in the same file. The graph now drops a symbol that has no connections when a connected symbol with the same name exists in the same file. Nothing else on that ring changes: files with no symbols (READMEs, empty init.py files) and symbols whose file has no entry of its own are real and stay. The ghosts leave the picture the next time a repository is indexed; run memtrace index to apply it to an existing store in one step.
  • An MCP session attached to a store that does not hold the repository you ask about now gets its answer from the running Memtrace that does hold it. Tools such as get_codebase_briefing, find_central_symbols, list_processes, find_code and find_symbol used to answer “0 symbols” or empty results from the wrong store while the Memtrace holding the repository sat idle; they now hand the same call to that runtime and return its answer, marked under _meta.answered_by so you can see who answered. When no running Memtrace holds the repository, or it cannot answer, the call is refused with a diagnostic naming this session's store, its members, where the repository lives and why it was not routed — never a silent empty. Only reads are routed; nothing is ever written to another store. A routed call counts once against your query quota, and a refused one not at all.
  • Running memtrace start or memtrace index in a terminal when a newer version is available no longer prints the update twice. The background version check printed its notice card — the versions, the release notes link, the upgrade command — and the interactive “Upgrade now?” offer printed the same card again right underneath it. The notice now yields to the offer. It still prints on its own for commands that never ask, and when the version check finishes too late for the prompt to have asked.
  • A store started from a workspace manifest or a named workspace now remembers who declared its member list, and a plain memtrace start run from the folder above it — or an MCP session Cursor or Claude spawned there while the daemon was down — can no longer widen that list to every repository it finds in the folder. Before, either would silently rewrite the store's scope to the whole folder, and the next memtrace start --workspace-file refused to open the store because its declared members no longer matched the manifest. A folder-walked start over an owned store is now refused up front with the manifest or workspace name and the command that may change the members; an MCP session opens the store's declared members as they are and never rewrites the scope of an existing store (it may still create the scope of a brand-new one). Every change to a store's member list now keeps the previous file beside it and appends one line to a journal naming the process, its arguments and working folder, so a surprise rewrite is answerable in seconds instead of hours.
  • On a machine running more than one Memtrace — a workspace on port 3030 and a second store that fell back to 3031 — a tool call routed to the other daemon now reaches it. The runtime registry advertised the port each daemon was configured with, not the one it actually bound after the fallback, so the call went to whichever daemon held the configured port and was refused there. The registry now records the bound port, and the router reads the port from the daemon's own published state first.
  • Session-ledger rows no longer fuse when two Memtrace sessions write at the same moment. A row was written as two pieces — the JSON, then its newline — so simultaneous sessions could interleave and produce a line holding two records, which the ledger readers then dropped. Each row is now written in one piece.
  • Cleaning up one project can no longer stop another one's Memtrace. memtrace stop and memtrace doctor --fix now require proof that whatever they are about to terminate belongs to the workspace being cleaned — the process must name that workspace's data directory itself, or be the daemon that workspace published, and still be the same process it was when it was inspected. Anything that cannot be identified is left running and the reason is printed instead of being silently skipped. Before, freeing a port terminated whichever process held it under a name match, and because a Memtrace whose port is busy moves to the next free one, that was routinely another project's healthy daemon.
  • A Memtrace session no longer waits on another session to read. A session that is not changing which repositories a workspace holds now takes no workspace lock at all. Before, the lock was held for the whole time a store was being opened, so an editor's session could sit for thirty seconds behind another one's startup and then fail outright with a lock timeout — on a large workspace that was every editor reload.
  • An editor-spawned Memtrace session can no longer change which repositories a workspace holds, under any flag — including when the editor's configuration passes a workspace file. It may set up a brand-new workspace and nothing more. Changing an existing one means editing the manifest and starting Memtrace with it, which is now the only path and is named in the refusal.
  • A tool call whose Memtrace goes away underneath it — a daemon that crashed, or one replaced by a newly started owner — now waits for the workspace's Memtrace to come back and answers, instead of failing after two quick retries. The wait is bounded at a minute, so a call never hangs waiting for something that is not coming. A store whose Memtrace you stopped on purpose is deliberately not waited for: that call fails straight away and says the owner exited.
  • The retrieval hook agents use now asks the Memtrace that owns the folder it ran in, rather than assuming the dashboard is on port 3030. On a machine running more than one project, port 3030 belongs to whichever project started first, so the hook could answer from a different project's graph with nothing in the answer to say so. When no Memtrace owns the folder, the hook now says so instead of guessing.

Improved

  • The GitHub badge in the top bar says what it counts. “5/6” now reads “GitHub 5/6 connected”, and its tooltip explains that it counts the repositories in this workspace that have a GitHub remote — not every repository — so a nine-repository workspace with six GitHub remotes no longer looks like a mistake.
  • The session ledger now records failed tool calls, not only answered ones, and every row names the runtime that answered: its store, owner process, endpoint, role (owner, attached, pending or standalone), working folder and workspace root, the repository you asked for and whether this store holds it. When a memtrace mcp session starts it prints one line with the same facts. After the demo incident it took an hour of log forensics to establish which store had answered a call; that is now one line in the ledger.
  • One project's heavy query no longer blocks everyone else's. Graph work that reads a whole repository still runs one at a time — that is a memory limit — but a call that cannot start within its budget now comes back as a retryable busy answer naming what is holding the lane and for how long, instead of queueing behind it indefinitely. Questions routed from another workspace get their own narrower lane, so a neighbour's work cannot crowd out the session in front of you.
  • Every running Memtrace is now reachable by the others. Each one opens a small loopback port and publishes it, so a question can be routed to a workspace whose Memtrace was started by an editor rather than from a terminal. Before, such a workspace had no reachable address and the question was refused even though the answer existed on the same machine.
  • The Memtrace skills no longer tell an agent to re-index when a repository looks missing. A repository that is indexed in a different workspace now produces a refusal naming where it lives, and the guidance an agent reads treats that as a routing answer rather than a coverage problem — following the old advice built a second copy of the repository in the wrong workspace.

Deleted code leaves the graph, and pulls no longer stall

Improved

  • The node inspector in /ui now shows the route registration for an API endpoint that was discovered from a route, instead of an empty Code tab, and says where a widened code snippet came from. When the Memtrace owner process is unreachable, the inspector's Code, Info and History tabs show the backend's message and the memtrace start recovery step with a Retry, instead of a spinner or a claim that the symbol has no history.
  • The update prompt says what the new version contains. When a newer build is available, Memtrace now links that version's release notes next to the version you are on and the one on offer — on the nightly channel that is the whole question you are being asked. Accepting shows which step the upgrade is on and how long it has been running, rather than a single line while the package manager's output scrolls past; if the upgrade fails, that output is printed in full before the remedy. Output that is captured rather than shown in a terminal — an agent's log, CI — keeps the plain form. Set MEMTRACE_PLAIN_OUTPUT=1 for plain text in a terminal too, or MEMTRACE_VERBOSE_UPGRADE=1 to watch the package manager's own output during an upgrade.

Fixed

  • Upgrading no longer leaves Memtrace running the previous version's program. A global install can keep a leftover copy of the native program from an earlier install alongside the current one, and when the package manager removed the newly installed copy during an upgrade, Memtrace fell back to that leftover and ran it — while memtrace --version, and the package itself, reported the new version. Anyone verifying a fresh build could be testing one that was weeks old, with the version check itself doing the lying. Memtrace now requires the native program to match the version of the package that installed it: the installer fetches the correct one instead of accepting whichever copy it finds first, and if a mismatch survives that, Memtrace refuses to start and prints both versions and the location of the leftover copy, so you can delete it and reinstall.
  • Deleting a file, or removing a function or type from one, while Memtrace is running now reliably removes it from the graph, whether you or your coding agent made the change. Some graph stores had accumulated more than one live copy of the same symbol (indexing a repository that has several local branches did this about half the time), and a deletion retired only one copy, so search, the graph page, and your agent kept being handed code that no longer existed anywhere in your checkout. Every copy is now retired when its file is deleted or its definition removed, including copies that were already in your store, with no reindex required.
  • Established projects now run the startup repair that removes leftover duplicate copies of a symbol. Memtrace has a repair pass that closes extra live copies of the same symbol left behind by older versions — the copies that make a deleted function keep turning up in search and for your agent — but on projects whose graph had grown large enough for Memtrace to skip its full startup scan, this repair was skipped along with it. Those are precisely the projects that accumulate the copies, having been indexed for weeks, so the stores most in need of repair were the only ones never receiving it, and upgrading did nothing for them. The repair now runs on large projects too. It stays bounded — it declines a repository too large to scan cleanly rather than slowing start — and it is a cheap no-op on a healthy store. Turning startup indexing off still turns it off.
  • Re-indexing a project no longer leaves a second live copy of every unchanged symbol. When Memtrace re-indexed a repository, it timestamped the current code from the moment HEAD last moved to the checked-out commit (a checkout or branch switch), while its git-history pass timestamped the same code from the commit's own time. Whenever those two moments fell in different seconds — routine after any branch switch, and the norm on a long-lived project — the two passes disagreed by a second and the store kept both, so one symbol became two live rows. Reads still showed one (the newest wins), but the raw graph doubled, and a store re-indexed for weeks accumulated a heavy layer of these twins that made deletions look like they had not taken. Both passes now read the commit's own time, so they agree and only one row is written. Existing duplicate rows are closed by the startup repair with nothing for you to do.
  • Memtrace no longer stops reconciling after a git pull on an established project. Once a project graph grew past the point where Memtrace skips its full startup scan, the first change after a pull could leave the watcher retrying the same step every few seconds indefinitely: the pull was never applied, newly pulled files never appeared in search or for your agent, and the only cure was a manual reindex. Startup left a marker saying a graph publication still had to be confirmed, and the step that would have confirmed it was the very step being held back. Memtrace now tells an in-progress publication apart from a leftover marker, so the pull is applied normally. Verified on a 1,600-file pull: applied without stalling, with the API responsive throughout.
  • Files deleted by a pull are now removed from the graph on large projects. Their functions and types used to stay behind and keep being returned by search and to your coding agent, so an agent could be told about code that no longer existed anywhere in your checkout, and follow it. Memtrace looks up a deleted file's existing entries to retire them, but it was searching under a different spelling of the file path than the one it stores, so it found nothing and retired nothing. On smaller projects this never showed, because they load their index differently and never reach that lookup. Verified on a 1,600-file pull, where the clean-up now runs instead of being skipped entirely. A side benefit: entries superseded by a large pull are now retired rather than accumulating, so stores stop growing with copies of code that has already changed.
  • Memtrace no longer skips its startup catch-up on large projects. When an existing graph store is big, Memtrace skips the full startup scan so that start stays fast — that is deliberate — but it was also skipping the much cheaper catch-up that applies whatever changed since the last run, so that step never ran at all on those projects. It now runs, and its cost tracks what actually changed rather than how big the store is. First-time indexing of brand-new repositories is still deferred on large stores, and the catch-up runs in the background, so start is no slower than before.
  • A pull or branch switch that deletes files now removes them from the graph. Memtrace read the incoming change correctly but forwarded only the added and modified paths, so deleted files lingered in search results and on the graph page until the next full index — symbols that no longer existed anywhere in your checkout were still offered to your agent.
  • When Memtrace cannot measure the size of an existing store in time, it now treats it as a large store and still runs the catch-up, instead of treating it the same as a store you had explicitly told Memtrace to leave alone.
  • A function handed to another function by reference now counts as a caller. Passing a function as an argument — run_in_threadpool(parse_transactions_csv, body), rows.map(formatRow), Thread(target=run_job) — was invisible to the graph, because only the function being called directly was read from each call. A symbol used that way reported zero callers and showed only its importing file under "Called by", so dead-code and blast-radius answers were wrong in the direction that costs you: they said nothing reached a symbol that something did. These now resolve to the function that passes the reference, labelled "passed as an argument" so you can tell an indirect call from a direct one. Sibling files in a Go package are still an exception, because Go names them with no import to resolve against. Existing indexes pick this up when a file is re-indexed or edited; memtrace index --clear applies it to a repository in one step.
  • The Called by and References lists explain how each relationship was found in words rather than internal codes — "imported here, never called" instead of unused-import-specifier.
  • ⌘V / Ctrl+V works in the dashboard's search and filter fields when it is open inside an embedded browser. Preview panes in coding tools consume the paste shortcut themselves and never pass it to the page, so the field stayed empty while typing worked normally. The dashboard now reads the clipboard itself when the paste never arrives, and leaves the ordinary path alone everywhere it already works.

Decision recall finds your decisions again

Fixed

  • Decision recall returns your recorded decisions again on Windows. Recall asks decision memory for decisions belonging to the workspace you are in, and the answer is matched against the workspace each decision was captured under — but the two were being written in different spellings of the same path, so nothing ever matched. Every query answered "no decisions recorded" while the Cortex tab showed a full store, which is a misleading answer for an agent checking prior decisions before it edits. Both sides now spell a workspace the same way, and decisions captured by earlier versions are still found.
  • A failure in the Memtrace rail hook no longer blocks your coding agent. When the hook could not run — unreadable input, or arguments a newer configuration used that the installed version did not recognise — it exited in a way the editor reads as "denied", and the editor then refused every tool call for the rest of the conversation, including the ones needed to diagnose it. Reloading the editor did not clear it. The hook now allows the tool call and explains itself instead.
  • Members of an organization with an active subscription get the Insights panel. Insights unlocked only through referrals, so people whose organization had already bought seats were told to go and refer others first. Approving an organization now grants every member access, with nothing to set per person.

Saving a file stops re-indexing the whole file

Fixed

  • Saving a file no longer re-indexes it from scratch. Editors that save atomically — VS Code, IntelliJ, and vim in its default configuration — write a temporary file and rename it over the original, which the file watcher reports as a deletion followed by a creation. Memtrace treated that as a real deletion, discarded everything it knew about the file, and then re-created every symbol and relationship in it. On a 6,000-key YAML, inserting one line re-created 6,063 symbols and tombstoned 12,119 relationships in about three seconds; it now updates 1 symbol and 2 relationships in about 0.7 seconds, and writes roughly a tenth as much to the store. This affected every file type, not only configuration files.
  • A configuration key's identity is now its dotted path rather than its line number, so inserting or removing a line above other keys no longer changes their identity. Config files were the most affected because they emit roughly one symbol per line, where source code emits about one per twenty.
  • Items in a YAML list now carry their position in the key path, so the steps of a CI job read as jobs.build.steps[0].uses and jobs.build.steps[1].run. Previously every step in a list produced the same path and the same display name, which made them indistinguishable in search and the graph view.
  • Organization invitations can be accepted when the invited address and the account differ only by a plus tag — an invite sent to name@example.com now works for someone who signs in as name+tag@example.com, because both spellings reach the same mailbox.
  • The organization invite page now says why an invitation cannot be used instead of giving one message for every cause: whether it was sent to a different address, has expired, or was cancelled. Its sign-in button signs you out first, so it no longer returns you to the same error while you are still signed in as the wrong account, and opening an invite link for an organization you already joined takes you into that workspace rather than reporting a failure.
  • Cortex no longer reports a connection problem when decision memory is merely busy. A request that had to wait — because the service was still starting, or because it was working through a slow first classification — was reported as though the service were missing. Busy and absent are now told apart, and only a genuinely absent service is described as one.
  • Opening Cortex starts decision memory on demand when it is entitled and not already serving, instead of showing a connection error until something else happened to start it first.
  • Cortex now shows only the repositories this workspace is watching or has indexed. Governance previously listed repositories belonging to other workspaces on the same machine, which made it look as though Memtrace were tracking work you had never opened here.
  • Stopping Memtrace now keeps decision memory stopped. The on-demand start honours the saved opt-out and entitlement, so a workspace you have closed — or a session you have opted out of — no longer brings the service back.
  • Governance documents such as ADRs kept in a watched repository are classified through decision memory rather than being skipped, so they appear in Cortex for the repositories you are actually working in.
  • On Windows, a workspace is recognised as the same workspace however its path is spelled, so Cortex no longer treats one project as two. Records left behind by a session that has since exited are cleared instead of keeping a workspace listed as active.
  • On Windows, governance classification no longer fails with “The pipe is being closed” as soon as a repository has more than one governance document. A request larger than the local pipe's buffer was refused whole and the connection never recovered, so two ADRs — or one long one — could not be classified while decision memory was running and idle; one short ADR fitted and worked, which is why the fault looked like a connection problem rather than a size one. Requests are now sent in pieces the pipe always accepts.

New

  • New features reach the nightly channel first: npm install -g memtrace@nightly. Nightly is not always stable. The default install receives stable releases, and memtrace install keeps the current channel.

Changed

  • Configuration keys are identified by their key path rather than their position in the file from this release on. Existing indexes keep working and need no action: the entries for a file are brought up to date the first time that file is re-indexed or edited. If you would rather clear a store in one step, run memtrace index --clear on that repository.

Improved

  • When Cortex genuinely cannot start, the message now says what to do about it — check memtrace status, and run memtrace cortex debug for a redacted report — instead of repeating an internal error string.

External MemDB clients attach to the running daemon

Fixed

  • In external MemDB mode, memtrace mcp and memtrace status attach to a running memtrace start daemon for the same workspace right away. Daemon liveness is now judged by the daemon's own heartbeat instead of a short probe of the remote database endpoint, which previously waited 12 seconds and then reported a healthy, idle daemon as not responding.
  • MemDB endpoints without an explicit port, such as an Azure Container Apps address, resolve with the standard port for their scheme instead of being treated as unreachable.

Improved

  • When an external-mode daemon really has stopped responding, the startup error reports the age of its last heartbeat so the stale owner is easier to recognise.

Windows CUDA works across fresh launches and npm upgrades

Fixed

  • Windows tools that launch the native Memtrace executable directly now find the installed user-local CUDA runtime. Warmup, GPU status, CUDA verification and the engine use the same runtime as CUDA setup.
  • A healthy CUDA installation is reused after npm replaces or moves the Memtrace package, without requiring another runtime download. Custom ONNX runtime overrides, CPU fallback and no-AVX2 packages remain supported.

Improved

  • GPU diagnostics identify MEMTRACE_SKIP_EMBED or MEMTRACE_NO_EMBED when either setting disables CUDA verification, including verification performed by CUDA setup. Unset the reported variable before retrying.

Quieter background work, clearer resource usage and complete release history

New

  • New features reach the nightly channel first: npm install -g memtrace@nightly. Nightly is not always stable. The default install receives stable releases, and memtrace install keeps the current channel.

Fixed

  • Synthetic search warmup finishes after startup instead of repeating while the workspace is idle. Normal search and model warmup remain available.
  • Cursor transcript capture uses indexed lookups instead of scanning unrelated records in large local conversation databases. Regression checks preserve the captured records and literal conversation identifiers.
  • File notifications from Memtrace storage are filtered before they enter the watcher queue, reducing background work caused by the database writing its own files.
  • Insights loads and refreshes panels on demand, so opening the dashboard no longer starts expensive work for every hidden panel.
  • Database property queries filter matching records before decoding their properties, reducing repeated work on large stores.
  • Windows-shaped import paths resolve consistently across platforms. Explicitly imported callees remain distinct from same-named declarations in neighbouring files.

Improved

  • Resource accounting includes the database and decision-memory processes owned by Memtrace, making background CPU and memory usage easier to diagnose.
  • Windows packages must pass Microsoft Defender scans before publication. Release checks cover both standard and no-AVX2 packages; a rejected executable blocks publication.
  • The public website and installed UI retain the complete archived Stable and Nightly release history. Original publication dates and actual nightly versions are preserved, older notes remain readable during a failed refresh, and new release archives update independently of Discord announcements.
  • Release notes retain environment-variable underscores and accept older Markdown layouts, so published instructions and historical notes remain readable.

Changed

  • These changes do not establish a universal idle-CPU target or a guaranteed first-index time. Large populated macOS workspaces and long first-index runs still require a measured retest on the affected setup.

Native desktop receipts, faster GPU embedding, and graphs that follow your checkout

New

  • New features reach the nightly channel first: npm install -g memtrace@nightly. Nightly is not always stable. The default install receives stable releases, and memtrace install keeps the current channel.
  • Native desktop receipts on Windows, macOS and Linux summarize useful code lookups, symbol matches, connections and impact results. Receipts combine concurrent agent sessions, highlight concrete returned results and show referenced file counts. Context comparisons are labeled estimates; they do not claim money saved, engineer time saved or bugs prevented.
  • Receipts are enabled by default in interactive desktop sessions and stay quiet in CI, SSH and headless environments. The first receipt follows at least five useful lookups and two minutes; continued activity produces receipts about every 30 minutes, with idle and graceful-exit recaps. A shared delivery budget prevents duplicate or empty receipts and limits frequency.
  • memtrace notifications status, on, off and interval control desktop receipts. View the latest receipt with memtrace notifications show, inspect example data with preview, or test OS delivery with test. Preference changes reach running sessions within 30 seconds, and saved mute settings persist.
  • macOS receipts use a bundled native Memtrace app with its own icon, View receipt and Mute receipts actions. Windows receipts include branded details and actions; Linux uses the desktop notification service. Receipts respect operating-system permissions and focus settings. The local receipt view needs no dashboard or downloaded fonts.
  • Windows and Linux x64 can install the complete CUDA runtime from the terminal when an NVIDIA GPU is available. Install and startup offer consent before downloading missing dependencies; memtrace gpu install-cuda --yes supports unattended setup. Downloads are versioned and checksum-verified, need no Python or CUDA toolkit, and require a working NVIDIA driver.
  • memtrace gpu verify-cuda runs real GPU inference with CPU fallback disabled and checks its output. Setup uses this check before reporting success, and GPU diagnostics retain the selected device and runtime failure reason.

Improved

  • CUDA embedding uses the full-precision code model on supported NVIDIA hardware. Warm embedding throughput on an RTX 5070 improved 22.3 times on Windows and 24.1 times on Linux under WSL2, with minimum CPU/GPU vector cosine similarity above 0.99999986. These measurements cover embedding after warmup, not total repository indexing time.
  • macOS embedding allows CoreML to use the GPU as well as the Neural Engine and CPU. Bounded model inputs let CoreML accept work previously excluded by dynamic shapes, and incomplete batches return only the requested vectors. Physical M5 Pro checks confirmed GPU execution, vector accuracy and full-repository indexing. The Apple Silicon path has no M5-only restriction; older chips and macOS releases still need physical validation.
  • Indexing reuses bounded parse, syntax-tree and query caches, builds line offsets lazily, and avoids repeated syntax-tree traversal and service-root discovery. Changes to parser code invalidate cached results, and unchanged derived-label inputs skip redundant computation.
  • Matched structural indexing benchmarks, including database writes and excluding embedding inference, reduced wall time by 9–13% on Windows and 5–8% on Linux under WSL2. CPU time including database writes fell 29–33% on Windows and 51–55% in WSL2. Structural preparation alone improved 2.6–3.7 times on cold runs and 5.0–5.3 times on warm runs, with 74–89% less CPU time across the two platforms. Cached and uncached output was checked across 22 languages. These workload-specific results do not establish temperature or energy savings.

Fixed

  • Linux x64 nightly and stable packages now compile CUDA support. Managed runtime activation reaches child processes, upgrades can replace the incomplete older bundled runtime, and an outdated GPU architecture list no longer rejects a newer runtime that can execute inference successfully.
  • The opt-in CPU governor now enforces zero-budget pauses, charges concurrent CPU samples once, restores the correct allowance when interactive work ends, and keeps safety pauses in force during interactive boosts. A disabled governor no longer scales batches or parks work. Eight-worker measurements held requested two- and four-core budgets within about 1.1% on Windows and WSL2; enabling the governor still requires MEMTRACE_CPU_GOVERNOR=on.
  • The macOS CPU governor now reads real AC/battery state, battery percentage and session idle time, so its existing battery and idle policies respond to the Mac. Governance remains opt-in and can increase background completion time.
  • Mac memory gating now follows the kernel pressure state. Compressed-memory estimates no longer cause false critical-memory pauses; actual warning and critical pressure still reach the existing safety policies.
  • Agent hooks now follow the Memtrace daemon lifetime. Cached hooks return silently after shutdown or a crash, and registrations are removed when no running daemon needs them. Saved off settings survive inherited agent settings and installation updates.
  • On macOS, hooks recognize alternate paths to the same workspace, including temporary-directory aliases. Nested workspaces select their own daemon, while similarly named sibling directories stay separate.
  • Exact identifier searches try indexed symbol lookup before semantic fallback and check the returned name, repository, path and source line. Normal supported hooks route directly to the running daemon.
  • Agent installation preserves custom MCP settings and unrelated hooks. Claude has a user-level registration fallback, and the bundled VS Code registration supplies the active workspace directory.
  • Windows history replay uses consistent file identities, so moving a declaration between lines no longer leaves every old version live. A versioned repair pass revisits affected history on upgrade, preserves explicit replay limits, and records completion so subsequent starts do not repeat the repair. Startup logs distinguish checking HEAD and repairing history from a fresh index.
  • Branches inherit shared graph records and store their own changes, including removals and restorations, without copying or deleting parent records. Full indexing and incremental label updates preserve those removals, so deleted symbols, relationships and derived labels do not reappear through inheritance. Replacement metadata is acknowledged before older records are retired, making partial-write retries safe.
  • The watcher follows the actual checked-out branch, including linked worktrees, detached HEAD and Git metadata outside the working directory. It arms the relevant metadata watches before reporting readiness, rejects duplicate watches of the same canonical path, and recovers missed branch notifications with a lightweight poll.
  • Switching branches reconciles the destination before publishing its identity to the UI. Work from the outgoing branch cannot publish into the new checkout, failed reconciliation retries with backoff, and files unchanged from the default branch reuse inherited records. When the default branch advances, only files whose Git content differs are invalidated for reconciliation.
  • Repeated checkouts compact redundant repository and branch summary records while preserving lineage metadata. A known main or master lineage no longer includes the other branch as an unrelated fallback. Windows can now read resident memory correctly when deciding whether to reconstruct a cached graph.
  • Graph views, symbol lookup, hybrid-search results and repository statistics consistently resolve the selected branch, prefer its overrides, and hide inherited removals and unrelated branches. Statistics include inherited records even when a branch also has a substantial delta; previously incorrect counts can change.
  • A graph already on screen stays usable when a refresh times out. A compact delayed-refresh notice offers retry instead of covering the graph with a blocking error; an initial load failure still shows an error. Existing inflated history requires the repair pass before its graph counts shrink.
  • Database-writing regression tests use isolated stores, and an integration-test fallback can no longer inherit a configured external database endpoint.

Hosted stores index at full speed again

New

  • New features land on Nightly first: npm install -g memtrace@nightly is the same memtrace command, and it is not always stable. They still ship on the default install. memtrace install stays on the channel you already have.

Fixed

  • A graph cache that outlives its store no longer stalls a start. When the store behind a workspace is reset or written by another release, the cache files under .memdb/graph-cache can no longer be proven complete; 1.1.10 re-read them on every refresh, kept the repositories queued, and waited out remote scan deadlines between repositories, up to 21 minutes each. A cache that fails the proof is now evicted at the first rejection and rebuilt from the store.
  • The per-repository insight card printed during memtrace start is limited to 30 seconds; when the graph is busy the card is skipped and the next repository starts at once.
  • Startup embedding no longer vanishes when cross-repo linking is still settling. A repository whose embedding had to wait is listed as deferred in the memtrace start summary and embedded automatically once the graph settles, instead of being counted as embedded.
  • A repository whose graph was rebuilt during memtrace start (a fresh index, or the self-heal regeneration) is always embedded in that same start, even when the restart shortcut would otherwise skip the full pass. Such a repository could previously finish the start with no vectors at all.
  • A repository that an earlier start left without vectors is embedded at the next memtrace start. The restart shortcut that skips embedding when HEAD is already indexed now also requires the embedding-complete marker for that HEAD.
  • Indexing against a hosted MemDB is dramatically faster. Memtrace read records from the store four at a time, a width picked for a database on the same machine where a read costs CPU. On a hosted database a read costs a network round trip instead, so that width capped the client at about 125 records a second and a workspace that used to index in minutes could run for hours with both machines almost idle. Memtrace now measures the round trip to its store and reads as wide as that justifies, and sizes the connection for a remote database. A local database keeps exactly the width it had. MEMTRACE_STORE_READ_CONCURRENCY pins it if you need to.
  • memtrace no longer reports the database connection as lost when it was not. A single failed request marked the connection down before anything had checked it, so a recovered hiccup logged a "connection lost" warning that the next line contradicted. The connection is reported lost only once a repair attempt has actually failed, and the reason it failed is logged with it.

A second Ctrl-C no longer strands the sidecars; a Cortex owner stops only its own store's daemon

New

  • New features land on Nightly first: npm install -g memtrace@nightly is the same memtrace command, and it is not always stable. They still ship on the default install. memtrace install stays on the channel you already have.

Fixed

  • A second Ctrl-C during shutdown used to leave the database sidecar and the Cortex daemon running until the next memtrace stop, start, or doctor --fix: the second press exits the owner immediately, before its shutdown reaches the sidecars, and macOS ties no child to its parent. The owner now hands every sidecar it recorded a termination signal on that immediate exit, from the signal handler itself, so one press or two both end with nothing left behind; whatever ignores the signal is still closed from the ledger by the next stop.
  • A Memtrace owner or MCP session that had just claimed its Cortex store used to stop every Cortex daemon on the machine before starting its own, including daemons serving other stores (a second MEMCORTEX_STORE_DIR on the same machine, for instance), whose owners then restarted them. It now stops only daemons whose command line names its own store, and leaves alone any process whose command line it cannot read.

The 1.1.9 CPU governor is opt-in

New

  • New features land on Nightly first: npm install -g memtrace@nightly is the same memtrace command, and it is not always stable. They still ship on the default install. memtrace install stays on the channel you already have.

Changed

  • The CPU governor introduced in 1.1.9 is now opt-in (MEMTRACE_CPU_GOVERNOR=on). On by default it budgeted background work to half the performance cores and a quarter on battery, moved indexing and embedding threads to efficiency cores, and parked work its watchdog judged idle; on a busy laptop that read as memtrace start and memtrace index doing nothing. 1.1.10 schedules exactly as 1.1.8 did. The restart fixes that made 1.1.9 cheap to leave running (a checkpoint and vector-index recovery proportional to what changed, no re-embedding on restart) do not depend on the governor and stay on.
  • The database sidecar runs at normal scheduling priority again. 1.1.9 started it one notch below normal (MEMTRACE_SIDECAR_PRIORITY=low brings that back), which made every query wait behind whatever else a loaded machine was running.

Fixed

  • Sidecars are always closed by memtrace stop and by Ctrl-C, on every platform. On macOS the Cortex daemon (memcortex-daemon) kept running and burning CPU after memtrace stop and after Ctrl-C: the stop command matched sidecars to a workspace by a --data-dir argument that the Cortex daemon does not use, and macOS ties no child to its parent the way Windows job objects and Linux parent-death signals do. Every owner now records each sidecar it spawns in a ledger next to its pid file, and memtrace stop, the owner's own shutdown and signal paths, the next owner's start, and memtrace doctor --fix close whatever that ledger names, with a hard kill after three seconds; a recycled pid is never touched.
  • The 1.1.9 check for symbols that already have a vector is now limited to 5 seconds per repository (MEMTRACE_EMBED_PRESENCE_SCAN_SECS; 0 disables it); past that the pass embeds from cache as before, and its duration is logged. MEMTRACE_FORCE_EMBED=1 re-embeds everything.
  • Windows: a workspace owner started from an elevated terminal, or any process the current user may not open, is no longer treated as dead. Attaching sessions tried to take over its store and reported the store as locked.

Memtrace governs its own CPU

New

  • Memtrace now governs its own CPU. Background work — daemon rebuilds, the file watcher, embedding, cross-repo convergence — draws from one CPU budget (half the performance cores by default) that yields to your own builds and editors, runs at a quarter rate on battery and pauses below 15%, and lifts to full speed once you have been away from the keyboard for five minutes. An interactive memtrace index keeps every performance core but still backs off under heat, on battery, or under critical memory pressure. MEMTRACE_CPU_GOVERNOR=off restores the previous scheduling; MEMTRACE_CPU_BUDGET_CORES sets the allowance and MEMTRACE_BACKGROUND_ON_BATTERY=off|full changes the battery policy.
  • An idle-burn watchdog ends the class of overheating where Memtrace burned CPU for hours on a machine where nothing changed. When the daemon and its database sidecar spend CPU for ten minutes without parsing, embedding, converging, or serving anything, every background loop is parked and the budget drops to a trickle until real work arrives — a saved file or an index request lifts it immediately. memtrace status, /api/health, and the mem_diag tool now show where every CPU-second went (parse, embed, convergence, watcher, serving), the current budget and why it was chosen, and any parked loops.
  • New features land on Nightly first: npm install -g memtrace@nightly is the same memtrace command, and it is not always stable. They still ship on the default install. memtrace install stays on the channel you already have.
  • A real int8 build of the default code model is available as an opt-in (MEMTRACE_EMBED_QUANT=q8): a 162 MB first-run download instead of 641 MB and the same recall on natural-language queries against the vector index alone. In a paired benchmark of name-style find_code queries the int8 graph combined with the new length-sorted batching lost 4 points of top-10 accuracy (the quantised graph calibrates per batch, so documents batched together drift away from queries embedded alone), while the int8 graph on its own lost half a point at 45 % less embedding CPU. So every host keeps the full-precision graph by default, batching is switched off automatically under q8, and existing caches stay valid; switching to q8 re-embeds once. (The auto tier's previous "int8" label had always loaded the full-precision graph; the label is unchanged.)
  • Code the machine has already embedded is never embedded again: a second worktree, a clone under another name, a fork, or a vendored copy of the same symbols reuses the vectors from a machine-wide cache keyed by symbol content (MEMTRACE_EMBED_CACHE_GLOBAL_CAP_MB, default 512 MB). MEMTRACE_EMBED_CACHE=off disables caching for benchmarks.

Improved

  • Bulk indexing threads, the embedding worker, and the database sidecar now run below normal priority — on Windows 11 with EcoQoS, which moves them onto efficiency cores — so Memtrace stays out of the way of whatever you are doing. MEMTRACE_SIDECAR_PRIORITY=normal keeps the sidecar at the default priority.
  • Embedding, reranking, and SPLADE inference threads no longer spin-wait between operators, which burned one core per thread whenever the model pool was idle; MEMTRACE_ORT_SPIN=1 restores spinning. The SPLADE session also no longer takes one thread per core.
  • Hybrid Intel and AMD processors are now recognised on Windows and Linux. An 8P+12E Core Ultra previously counted as 20 performance cores, so both the interactive and the background thread pools sized themselves to every core on the chip.
  • Embedding batches are sorted by length and cut by a token budget, so short symbols no longer pay for the longest symbol in their batch (every batch used to be padded to its longest text). The vectors are identical to the unsorted ones (per-document cosine 1.00000 in our check) at 28 to 35 % less embedding CPU per symbol in our measurements; memtrace status and /api/health report the share of inference spent on real tokens. MEMTRACE_EMBED_BUCKETING=off restores the old batching.
  • The vector index writes far less to disk: adding a symbol no longer rewrites the full record (vector included) of every neighbour it links to, only their neighbour lists, and the 1-bit codec (MEMTRACE_HNSW_CODEC=rabitq) now scores candidates by popcount instead of decoding each one back to floats. The first start after this upgrade rebuilds the vector index once from the stored vectors.
  • A new embed-text recipe is available for operators who want the last bit of indexing CPU: MEMTRACE_EMBED_RECIPE=headtail:900,400 embeds the head and the tail of long symbol bodies instead of the first 1500 characters — in our measurements the same recall at 13 % less embedding CPU. It changes the cache namespace, so switching re-embeds once; the default recipe is unchanged.
  • memtrace gpu status reports the NPU: whether one is present, whether the OpenVINO runtime and provider are installed, and what is still missing before MEMTRACE_ENABLE_OPENVINO=1 can use it. MEMTRACE_OPENVINO_DEVICE selects the device (default AUTO:NPU,CPU) and the provider now takes precedence over DirectML when enabled.
  • On Windows, a failed ONNX Runtime load now names the usual cause — the Microsoft Visual C++ 2015-2022 runtime is missing — with the download, instead of pointing at PATH.
  • memtrace doctor on Windows now checks for the Microsoft Visual C++ 2015-2022 runtime that Memtrace's embedding runtime needs and prints the download link when it is missing, so a fresh machine learns this before the first memtrace start fails to load ONNX Runtime.
  • list_watched_paths, embed_diag and mem_diag now say which process answered (_meta.scope: the daemon, or an MCP session's own stdio process, with the daemon's pid), so an empty watch list or idle embed state seen from an editor session is no longer mistaken for the daemon doing nothing.
  • MCP tool results say when the graph is still being written. While indexing or cross-repo linking is running, every result carries _meta.graph_converging: true with the pass state, so an agent can tell a partial impact or caller answer from a settled one and retry instead of trusting it. Thanks to Magalz for the report.

Fixed

  • A working-tree change whose exact delta could not be computed re-parsed the repository every five seconds forever, and every attempt re-armed cross-repo linking. The retry now backs off from five seconds to five minutes and resets as soon as a delta applies.
  • The observe-mode measurement drain no longer runs real searches every 20 seconds against an empty spool; it backs off and parks after five empty passes, resuming on its own when entries appear.
  • A vector index holding a single symbol was never written to disk until a second symbol arrived, and compacting a 1-bit index silently rebuilt it as full floats.
  • Semantic search kept working on large stores: once a local store passed 512 MB, background maintenance of the vector index was switched off to save CPU, so every symbol saved after that was findable by name but not by meaning. The vector index now keeps updating on stores of any size; only the structural index rebuild is skipped on large stores, and memtrace start says so.
  • On Windows the file watcher reported itself armed but never recorded a change: the watched folder was stored in one path spelling and change events arrived in another, so every save was silently dropped. Saves and pulls now reach the index, dropped events are counted, and a batch that lands during a merge or rebase is deferred until git is done instead of being thrown away.
  • memtrace govern and the dashboard's Governance panel no longer fail with "cortex.sock I/O failed: The pipe is being closed" on repositories with many rules or ADRs (Windows). Classification is now sent in bounded batches instead of one request carrying every document's text.
  • memtrace govern docs/architecture now finds ADRs under numbered or underscored directories such as 09_architecture_decisions; previously the sweep reported 0 governance docs for them.
  • The installer registers the Memtrace MCP server where Claude Code actually reads it (~/.claude.json) when the claude CLI is unavailable, and memtrace doctor checks that file; before, skills appeared in a session while every Memtrace tool was missing and doctor still reported the registration healthy.
  • memtrace start picks the next free port when 3030 turned out busy between the check and the bind instead of aborting.
  • memtrace govern and the Governance panel no longer say "MemCortex is not running" when MemCortex is running but did not accept a connection in time (starting up or busy); the message now says what happened and suggests retrying.
  • Restarting Memtrace on a large store no longer burns CPU for an hour with nothing to do. After an unclean stop (a crash, a kill, a machine restart) the database used to flush every mapped page of the whole store up to three times and rewrite its entire record index, and when the vector-index log had grown past 512 MB it replayed that whole log in the background on every start, forever, because nothing ever shrank it. The checkpoint now costs only what changed since the last one, and the vector-index log is rotated down to one record per live symbol after such a recovery and whenever it outgrows the live index, so the next start recovers it in seconds. Measured on a copied store restarted after a kill: checkpoint 0.12 s, vector index recovered from the rotated log with no background rebuild. Existing stores get the rotation on their first start after the upgrade.
  • Restarting Memtrace no longer re-embeds every repository. Three minutes after each start, a background clean-up of duplicate record versions marked every repository's symbols as changed even when it had nothing to close, which invalidated the embedding completion record (or withheld it while embedding was still running), so the next start re-ran the whole embedding pass — on large stores, sustained CPU after every restart. The clean-up now scans first and records a change only when it actually closes something.
  • memtrace mcp answers initialize as soon as it is attached to the workspace store, before it hydrates repositories, starts Cortex, or validates the licence session; those now run in the background and the first tool call waits for them (up to a minute). On a busy or very large workspace the server used to sit silently after MemDB ready until every MCP client timed out. While it starts, stderr now names the phase it is in (still starting (10s): validating the licence session), and a start that cannot reach the session within two minutes exits with that phase instead of lingering — so periodic probes no longer accumulate as hung processes. MEMTRACE_MCP_STARTUP_TIMEOUT_SECS raises the limit. Thanks to BadMrPotatoHead for the report.
  • A startup embedding pass no longer re-embeds symbols that already have a vector. When a restart found the embedding completion record missing, the daemon re-embedded the entire repository from cache and rewrote every vector in the store — hours of sustained CPU on a large workspace, on every start, and it never converged when the pass was interrupted. The pass now skips symbols whose vector already exists, records those as complete, and so finishes in proportion to what is actually missing. memtrace index now reports the symbols that already had vectors in its summary, and MEMTRACE_FORCE_EMBED=1 re-embeds everything, for a model change or a suspect store. Thanks to BadMrPotatoHead for the report.
  • On Windows, memtrace doctor --fix, memtrace reset, and memtrace stop now recognise that a workspace owner has exited. The liveness check behind all three always answered "alive", so a killed owner's daemon.pid and daemon-state.json were never swept, doctor reported "heartbeat is alive but health is not responding", and reset refused to proceed until the files were moved by hand. A pid is now checked against its real exit state, including the case where a parent shell still holds a handle to the dead process. Thanks to Magalz for the report.
  • Related symbols in get_symbol_context (contains, community_siblings, callers) now carry annotations and annotation_args like the primary symbol; the related-symbol projection had dropped both fields, which rendered them as null for symbols whose direct payload had them. Thanks to Magalz for the report.
  • get_repository_stats.nodes_by_kind now includes every kind the indexer stamps — Constant, Field, Variable, TypeAlias, SQL, Terraform, and CI kinds among them — instead of a fixed subset, so the rollup reconciles with what find_symbol returns. Thanks to Magalz for the report.
  • Attaching memtrace mcp to a long-running owner no longer fails after the machine's clock is adjusted. The owner's runtime record was verified by its wall-clock start time, which shifts under WSL2 after a clock step and made every later attach refuse a healthy daemon ("has no runtime record for store"). On Linux the record now carries the kernel's clock-tick start time and boot id and is verified by those; other platforms keep the start-time check. Thanks to Magalz for the report.
  • Agent guidance from the Memtrace MCP server now reaches the agent intact. The routing instructions had grown past the size limit coding agents apply to a server's instructions, so the tail was silently cut off — including the note telling agents to pass an explicit repo_id in an ambiguous multi-repo workspace, which is exactly where scoping mistakes happen.
  • Memtrace's MCP tools are now offered to the agent from the first turn. Coding agents defer tool definitions until something asks for them, so Memtrace's tools arrived as bare names while the built-in search tools arrived complete — biasing the agent toward grep before it could see what Memtrace offered. Run memtrace install to pick this up.
  • Operator surfaces now answer for the daemon that actually does the work. An MCP child spawned without workspace context (an IDE launching at the filesystem root) used to answer list_jobs, list_watched_paths, mem_diag, and embed_diag from its own empty process — zero watches while the daemon held 44, an 18 MB memory report while the engine held gigabytes — with no hint anything was wrong. These surfaces now find the workspace daemon through the same runtime discovery repository listing uses and answer from it, naming the answering process in _meta.answered_by; jobs and watches merge both processes' entries, a daemon job id can be polled from the child, and when no daemon is reachable the payload says so (_meta.daemon_unreachable with the exact reason and remedy — including "restart the daemon" when it predates these routes) instead of presenting silent empty lists as the truth.

Convergence knows when to stop

New

  • The built-in CPU profiler now works on Linux and macOS as well as Windows: set MEMCORE_SELF_PROFILE=1 and the database engine samples its own hot functions and writes named stack reports into its normal log — no admin rights or external tools on any platform, and reports carry function names rather than raw addresses.
  • New features land on Nightly first: npm install -g memtrace@nightly is the same memtrace command, and it is not always stable. They still ship on the default install. memtrace install stays on the channel you already have.

Fixed

  • Preserving a repository's last-published graph is now a settled, certified-clean outcome of convergence instead of a reported failure. Treating it as an error left the repository permanently dirty and queued, and both halves of convergence looped on that state — the link pass re-armed itself off the non-empty queue, and every dashboard poll and boot probe re-queued the still-dirty publication.
  • Background link passes that leave repositories queued but make no progress now stop re-arming themselves under one capped policy. Index completions, watcher saves, and dashboard polls still schedule passes normally, so no single unsettleable repository state can pin a background loop again.
  • Indexing no longer crashes on non-ASCII source. Statement windows in the Rust transport detector sliced at fixed byte offsets that can land inside a multi-byte character, killing ingestion on any codebase with Danish, German, French, or Czech comments or identifiers ("byte index N is not a char boundary"). All four windowing sites now align to character boundaries, pinned by a property test that feeds the detector arbitrary unicode.
  • The telemetry opt-out now means zero non-licence traffic. Previously the licence heartbeat carried graph statistics and record counts regardless of the opt-out, so an opted-out user's usage still appeared server-side. With MEMTRACE_TELEMETRY=off — or the industry DO_NOT_TRACK convention, now honoured equally — the heartbeat still validates your session and carries contract-billing meter counts, but graph statistics, repository rows, and record counts never leave the machine, and the launcher's npm version check goes quiet too. TELEMETRY.md now documents exactly what flows in every mode, verifiable with a network sniffer.
  • One global VS Code MCP entry now serves every project: the installer writes "cwd": "${workspaceFolder}", so each window anchors the server on its own project instead of the editor's ambient directory — previously all projects could silently share one wrong, empty user-level store. memtrace mcp --help also finally documents the --workspace flags it has always accepted.
  • Windows lock-contention classification is now guarded at the source level: every file-lock site routes through one shared platform rule, so a raw os error 33 (the Windows spelling of "lock is busy") can never again be treated as a fatal error by a site that missed the mapping.
  • .memtraceignore now governs live working-tree ingestion, not just memtrace index. Saving an ignored file used to re-ingest it into the graph as a working-tree episode — the ignore file appeared to work until the file was next touched. The watcher batch now filters through the exact matcher the CLI uses (user patterns over the built-in noise baseline, !path re-includes intact), edits to .memtraceignore take effect on the very next save, and benchmark-fixture saves stop generating episodes the CLI scan would never have indexed.
  • Decision-memory queries no longer fail against a momentarily busy Cortex sidecar. The sidecar serves local IPC one request at a time, so a recall queued behind a long ingest could burn its whole deadline and be reported unavailable — enterprise sessions measured roughly one failure in four calls. Read-only decision queries now retry once with a fresh window, a transport failure reports how many attempts were made and stays unmistakably distinct from a genuine “no matching memories” answer, and recall answers name the workspace scope they were filtered by — so a zero-match answer against a store the dashboard shows full of decisions is diagnosable as a scope mismatch rather than reading as “no decisions recorded”. MEMCORTEX_DECISION_TIMEOUT_MS raises the deadline for very large stores.
  • memtrace doctor no longer flags three healthy states as problems needing --fix: a locked workspace PID file is the live owner's own singleton advertisement, not a stale file (and --fix no longer offers to delete it out from under the running daemon); the UI port being held by the very owner doctor just called healthy is not a port conflict; and Claude Code skills installed through the plugin marketplace are now found in the plugin cache instead of being reported as “0 skills” on a fully working setup.
  • Manually curated symbol links (link_symbols) now survive a repository clear-and-rebuild. A full reindex previously wiped them along with the parser's own output; the rebuild now snapshots them first and restores them afterwards, re-attached to the re-parsed symbols through their deterministic identities.

Relinking settles instead of retrying forever

Changed

  • Setting MEMTRACE_MEMDB_ENDPOINT (or MEMTRACE_MEMDB_ENDPOINTS) now always means "connect to that server" — external mode — including loopback addresses such as an SSH tunnel or kubectl port-forward to a hosted MemDB. Previously a loopback value silently selected local mode, ignored the address, and started a local engine, so writes meant for the appliance landed in a local store. Only the literal default endpoint still selects local mode; set MEMTRACE_MEMDB_MODE=local explicitly if you relied on the old inference.

Fixed

  • Cross-repository relinking no longer loops forever on a repository whose live graph is empty while a good last-published graph is on disk: keeping that graph is now a settled outcome rather than a retried failure, so convergence completes, the dashboard stops reporting an endless warm-up, and startup embedding stops waiting behind it. Stores already stuck this way settle on their own after upgrading, no reindex needed. Background link passes that repeatedly make no progress now back off and eventually stop re-arming themselves, so no single repository state can pin that loop again.
  • Live file-watch updates against an https:// hosted MemDB no longer fail while every other query path reports the server healthy: the watcher's incremental persists now dial through the same TLS-capable connection as the rest of Memtrace instead of a cleartext-only path that could never reach a TLS endpoint.
  • A refreshed seat token can no longer replace a working credential with one the server rejects. Session start used to blindly store the freshly minted seat token for the active endpoint; on a deployment that does not authorize that seat yet (the organization's pinned endpoint does not cover it, or the seat was revoked), this overwrote the credential memtrace connect had installed and every following session failed. The refreshed token is now verified against the live server first, and an unauthorized one is reported — with the endpoint-pinning fix to apply — while the existing credential stays in place.
  • An authentication rejection from a hosted MemDB is now reported as exactly that, instead of "could not reach the external MemDB" with DNS-and-firewall guidance for a server that answered. The error now says the server is reachable but rejected the bearer, and lists the credential-side fixes: pin the endpoint in the dashboard so member seats are accepted, or reconnect with your connection file.
  • memtrace start no longer aborts a completed boot with a bare "No such file or directory (os error 2)". Concurrent publishers of the daemon's owner-state file shared one temp filename, so one could lose a rename race — a benign, self-healing condition the write layer already classified as ignorable, but the startup path treated as fatal. Each write now uses a unique temp name, a lost publish is logged and re-published by the heartbeat within seconds, and the heartbeat republishes the resolved UI port rather than the boot-time one.
  • A warming flag can no longer outlive the condition it reports. The boot readiness probe ran exactly once; when an editor's MCP child booted before memtrace start, every response carried warming: true and empty_state_reason: "warming" forever — including fully populated results, which taught agents to abandon a healthy graph for grep. The flag now re-probes on observation and in the background once an owner appears, and a non-empty result is always labelled as real data (not_empty) no matter what the flag says.
  • Repository discovery no longer sweeps OS profile trees. Launched from a home directory, the scan used to walk the entire user profile — registering package caches, Temp scratch directories, and editor backup folders as zero-node repositories, slowly. AppData, Library, and Application Data are now skipped, the walk is depth-bounded, and multi-repo discovery rooted at the home directory itself is refused with a clear message.
  • When the MemCortex local endpoint is reserved by a leftover handle that no longer answers, Memtrace no longer launches a daemon doomed to print an ownership error on every supervisor tick. It skips the futile spawn, explains once what actually holds the endpoint and how to free it — including the case a plain taskkill cannot fix, where a process that inherited the handle outlived the daemon — and takes over automatically the moment the endpoint frees.
  • The one-time post-upgrade index refresh now verifies itself: each refreshed repository is re-checked, and if its schema markers did not persist — the condition that made a demo estate silently re-parse and re-embed on every start — the boot log names the repository and the exact stored versions instead of looping quietly.

Sessions clean up after themselves, and reset never deletes your history

New

  • Clearing or resetting a store no longer deletes anything: everything it held moves to a sibling history archive next to the store, ready to restore by moving it back. The new memtrace history command lists archived generations, and only the explicit memtrace history purge --store <path> --delete-forever can permanently remove them.
  • memtrace stop now also collects engine processes left behind in other workspaces when the store's own records prove their owning session is gone, so a forgotten window can no longer leave a database engine running for days.
  • New features land on Nightly first: npm install -g memtrace@nightly is the same memtrace command, and it is not always stable. They still ship on the default install. memtrace install stays on the channel you already have.
  • A built-in CPU profiler: set MEMCORE_SELF_PROFILE=1 and the engine samples its own hot functions and writes named stack reports into its normal log — no admin rights or external tools needed on any machine.
  • memtrace ui serves the dashboard on its own against an engine that is already running. It does not index, watch, or take workspace ownership, so the dashboard and the engine can be restarted independently and a status page can outlive the editor session that used to keep it alive.
  • memtrace claude install writes a Memtrace routing directive into a project's own CLAUDE.md, so Claude Code reaches for Memtrace before text search in that repository. It survives context compaction, can be committed so a team shares one rule, and memtrace claude uninstall removes it leaving the rest of the file byte-identical.
  • Directories that are not git repositories can now be indexed as a point-in-time snapshot, with --allow-non-git or MEMTRACE_ALLOW_NON_GIT. Symbols, relationships, impact and search all work; history-derived answers are unavailable by construction and now say so rather than returning an empty result that looks like nothing ever changed.
  • cleanup_stale_records gained a check_stale_spans scope that reaches symbols left behind in files that still exist — the case the missing-file scope cannot see, which previously needed deleting the whole repository.
  • --index-ignored (or MEMTRACE_INDEX_IGNORED) indexes the files a repository's ignore rules would normally hide. Every ignore source is turned off together, parent directories included, so an ancestor cannot keep filtering a tree you asked to see in full. Off by default: a repository's ignore rules are written for building the product, and honouring them is what almost everyone wants.
  • Fields and constants are now first-class symbols with read and write edges, extracted across 18 language families and classified by each language's own write-once form — so get_impact finally answers who reads a feature flag, config constant, or magic number, with no getter workaround. Compound assignments record both a read and a write. Thanks to Magalz for the field report behind this batch.
  • link_symbols records cross-repository relationships at symbol granularity — queue producer/consumer pairs, gRPC seams, shared schemas the HTTP linker cannot infer — and get_impact walks them in both directions. An ambiguous name is refused with the candidates listed, never guessed.
  • ingest_graph_fragment lets your own tools contribute nodes and edges for structure Memtrace cannot parse — generated stubs, in-house DSLs, build-graph output — with a provenance tag stamped on every contributed record and surfaced in queries, and rerunning generators rewrite their rows instead of duplicating them.
  • find_code_review_issues flags a value consumed inconsistently across call sites — the classic money, timestamp, and ID bug no single-file rule can see — listing every consuming site, and staying quiet when narrowing is unanimous and deliberate.
  • Annotation names and their arguments are captured and queryable: find_symbol can filter by annotation and get_symbol_context surfaces them, across Java and Kotlin annotations and Python and TypeScript decorators.
  • Named milestone anchors bind a name to an instant, and get_evolution can diff the graph between two named states — release-to-release change reports without hunting timestamps. Re-creating a name moves the anchor, because a re-cut release is the common case.
  • An opt-in query-level audit log (MEMTRACE_QUERY_AUDIT=1) records one line per tool call — who, what, when, outcome — exported with export_query_audit. Tool arguments are deliberately not recorded, so the audit trail can never become a second copy of your source under weaker access control.

Fixed

  • Closing an agent session no longer leaves its database engine running in the background — every exit path now shuts the engine down with the session.
  • Background agent sessions no longer advertise a dashboard port they never opened, which made memtrace start mistake a healthy session for a broken one and restart it, briefly taking every connected agent down with it.
  • Memory no longer spikes by hundreds of megabytes per code search in each connected agent: searches now reuse the running workspace engine for query embedding, the reranking model unloads when idle, and freed memory returns to the system promptly.
  • Recovering a store with damaged records no longer floods the engine log with megabytes of repeated warnings per minute; repairs are summarized instead.
  • Stopping Memtrace in one workspace can no longer discard the runtime record of a different workspace whose session is still running.
  • History and timeline questions no longer scan and decode the entire store: all-time and as-of queries are answered from the property index, so a daemon left running with no clients measures around one percent of a core instead of holding two or more cores forever.
  • Deleted or superseded code now stays deleted after a restart. Soft-deletes used to live only in memory, so every boot brought removed vectors back as live and searchable and the compactor re-reclaimed them each time; deletes are now durably logged and replayed on boot, with no store migration needed.
  • If the property index cannot record a write, the store now marks that index incomplete and answers from the full data until it heals, instead of silently missing rows.
  • A single slow engine call can no longer hold a client request open indefinitely: per-call deadlines fail fast with a clear error instead.
  • On NVIDIA cards, embeddings no longer route through DirectML when the runtime documents a better provider for that hardware — and when CPU is measurably faster, Memtrace says so plainly instead of pretending the GPU helps.
  • Windows no longer loops demoting and rebuilding the insights cache: file replacement follows one atomic rule everywhere, and Windows now matches macOS across path handling, locks, and Cortex startup.
  • Startup embedding and cross-repository relinking can no longer deadlock each other during boot.
  • Starting the dashboard next to a headless agent session takes over the store cleanly instead of leaving both processes wedged.
  • Stale overlay copies of a symbol no longer outrank the current version in search results, and a modified symbol now closes its superseded predecessor rows so watched repositories stop accumulating duplicates.
  • Cleanup no longer flags virtual paths as missing files, and branch-scoped statistics explain a near-empty scan instead of looking broken.
  • Starting no longer aborts with a multi-gigabyte allocation failure when a recovery checkpoint points into the middle of a record instead of at a record boundary. A damaged checkpoint now costs a slower start rather than a database that can never be opened again, and the recovery path can no longer shorten a log to a position it has not verified.
  • Repository enumeration is bounded and no longer stalls a whole agent session. If it outruns its deadline it reports what to do instead of leaving the client to give up in silence, and tools that need a repository will now read the store's own membership record when enumeration cannot answer — so a slow discovery call no longer blocks everything behind it.
  • A relationship query that finds no connections now says whether that is a conclusive answer. A count of zero used to read as proof that a symbol was unused even when the lookup itself had not resolved, which is the worst possible wording ahead of a deletion.
  • A background pass that processed nothing is no longer reported as a failure. An empty work-set cannot have failed, and calling it one led users toward wiping a store whose data was intact and only needed its index repaired.
  • The graph view only suggests running an index when the store is confirmed empty. While indexing is in progress, or while counts are briefly unavailable, it now says so instead of advising a second indexer against a store the first one is still writing.
  • The upgrade hint names sudo when, and only when, the install location actually needs it, so an upgrade on a system-owned install no longer fails with a permissions error after you have already confirmed it.
  • memtrace status confirms the dashboard is really listening before printing its address, and says so plainly when the port is recorded but nothing answers on it.
  • MCP sessions no longer leave behind lease files owned by processes that have exited, and a session that is stopped abruptly is cleaned up by the next start rather than accumulating. The Cortex socket is removed when the daemon that owned it stops.
  • doctor --fix now names the sessions it could not stop, which application owns each one, and the exact command to stop them — rather than reporting that it found processes and then leaving them running.
  • A workstation that sleeps overnight no longer fills the log with one identical heartbeat warning per cycle. The first failure is reported, the rest stay quiet, and a single line says when the network came back and how long it was gone.
  • The documentation assistant no longer tells Windows and Linux readers to press a key their keyboard does not have; the search shortcut now shows the modifier for the reader's platform.
  • The documentation assistant follows a streaming answer the way a terminal does: it stays pinned while you are at the bottom, releases as soon as you scroll up to read, and re-attaches when you scroll back down.
  • --allow-non-git passed inside an actual git repository no longer disappears without a word. The flag only opens the gate for a directory with no version control, so it now says it does not apply, names the repository it resolved, and points at --index-ignored when indexing ignored files is what you were after.
  • Files whose extension matches no supported language are now counted and reported by the scan instead of vanishing from every statistic. A tree Memtrace has no parser for used to be indistinguishable from an empty one.
  • Running out of file watches on the host no longer costs you the whole daemon. Exhausting the operating system's watch capacity used to abort startup outright — no dashboard, no agent connection, no way to reach an index that was already complete. Memtrace now starts without live watching, names the limit it hit and the exact command to raise it, and keeps serving search, graph and impact. Watcher failures it cannot explain still stop startup, because those are not something a host setting fixes.
  • memtrace install no longer depends on npm being resolvable from the shell it happens to run in — it now finds the npm that ships beside Node itself. And when the upgrade genuinely cannot run, it says what went wrong in one line instead of crashing with a stack trace that buried the reason.
  • Upgrades no longer complete silently WITHOUT their finishing step on newer npm versions whose script policy blocks install scripts by default: the installer now grants itself permission to run its own completion step, so the platform binary and the consented configuration always arrive together with the package.
  • Installs and upgrades now succeed even from a shell where Node itself is not on PATH: the installer carries its own Node location into every step it runs. It also stops a running Memtrace before replacing its files, so a live daemon can no longer make a Windows upgrade half-land on locked binaries.
  • find_duplicate_code no longer reports a symbol as a duplicate of itself. Copies the index holds more than once — branch snapshots, working-tree saves, path-spelling variants — are collapsed before pairing, so each real duplicate appears exactly once and cites the correct original. Thanks to Trekkie for the report.
  • find_duplicate_code now honors its branch parameter: results are scoped to the requested branch, or to the repository's current branch when omitted, and asking for a branch with no indexed code is a clear error instead of a silent unscoped scan. Thanks to Trekkie for the report.
  • The dashboard's exact-duplication figure now counts real duplicated function bodies instead of raw scan rows, which could overstate duplication roughly twenty to one. Thanks to Trekkie for the report.
  • cleanup_stale_records now treats file_path_pattern as a strict boundary: combined with any staleness scope, nothing outside the pattern can be selected for deletion, a pattern that matches nothing deletes nothing, and the sampled paths always satisfy the pattern. Previously the scopes combined as a union, so a cleanup scoped to one file could silently select records across the whole repository; scrubs that intentionally span scopes now take one call per scope. Thanks to Trekkie for the report.
  • get_repository_stats can no longer present a healthy graph as empty: when an exact branch match finds almost nothing, statistics are recomputed with the same branch-ancestry visibility every other graph tool uses, and any remaining divergence is explained in the response with the store's real live counts and the likely cause — so zero edges never silently looks like a failed index. Thanks to Trekkie for the report.
  • get_repository_stats without a branch now reports the repository's primary indexed branch — the one list_indexed_repositories shows — instead of whatever branch the local checkout happened to be on, and the tool reference now defines every node count and when indexing_incomplete is set. Thanks to Trekkie for the report.
  • When the database backend dies or stops answering mid-session, the heavy graph tools — get_cochange_context, get_evolution, get_symbol_context — now fail within seconds with the clear endpoint-unreachable error, even for calls already queued behind another heavy query, instead of blocking for up to thirty minutes. Thanks to Trekkie for the report.
  • Cancelling or abandoning a tool call now stops its server-side work, so an abandoned heavy query no longer keeps burning CPU or starving the queries behind it. Thanks to Trekkie for the report.
  • memtrace index no longer stalls for five minutes and exits with an error when embeddings are enabled: the wait for cross-repository graph convergence now happens only after the index has published its results, so indexing and background relinking can no longer lock each other out.
  • index_directory now attaches to a repository's index job already in flight instead of starting a second run, which could race the first and leave the older job's record stalled forever.

Improved

  • The agent-tooling hook that routes code searches now asks the running workspace service directly instead of launching a new program for every terminal command, removing dozens of short-lived processes per minute during active coding sessions.
  • Symbol evolution views make one pass over the history window instead of one query per episode, so long histories load quickly.
  • Cross-repository topology lookups seek directly to the rows they need instead of walking unrelated ones.
  • Background maintenance now reports each tick's cost in the log, so a busy daemon can say what it was doing.
  • The documentation now covers clone detection and repository statistics: what find_duplicate_code pairs and how its branch scoping works, what the dashboard's duplication figure counts, every get_repository_stats node count and when indexing_incomplete is set, and how cleanup scopes combine. Thanks to Trekkie for flagging the gaps.
  • A branch-scoped symbol miss now names the branches that do carry the symbol, instead of returning the same empty answer as a symbol that does not exist.

Cross-repository calls stay connected from service map to graph

New

  • Python subprocess calls and commands embedded in Nextflow script and shell processes can now connect to matching command-line programs in another repository when the executable is statically identifiable.
  • R projects now retain structured evidence for base and Tidyverse pipelines, tidy-evaluation operators, data masks, tidy-select helpers, and formula lambdas instead of flattening those expressions into unrelated symbols.

Improved

  • Cross-repository service discovery now recognizes more C# and C++ HTTP clients plus gRPC, WebSocket, and common message-queue framework calls.
  • Django model relations, string URL views, class-based views, decorators, dynamic module imports, and common framework string references now leave inspectable graph evidence when their targets can be resolved.
  • Inferred relationships expose their confidence and reason in the graph inspector, so a framework or cross-repository link can be checked instead of accepted as an unexplained line.

Fixed

  • Opening a cross-repository call from the service map now keeps that relationship in the main graph and makes the connection visible instead of selecting an apparently isolated node. Agent impact and blast-radius queries follow the same call through its remote endpoint and handler, and identify the affected repositories explicitly.
  • Code previews now apply syntax highlighting to R and use one supported-language mapping for every language Memtrace indexes.
  • Python handlers and framework entrypoints no longer look dead merely because the framework reaches them through a decorator or a resolved string reference.
  • Malformed Kotlin input can no longer leave an extra-symbol query consuming a full core and gigabytes of memory indefinitely.
  • The first memtrace index or memtrace start used to keep embeddings and parsing on a full-speed CPU pool even after the indexer itself stepped down to a background slice of cores. Those jobs now share that same cap, so a first run on a passively cooled laptop stays usable. Pass --max-cores N if you want a smaller slice.
  • Parsed symbols are written as soon as resolve finishes, so find_symbol and the graph in /ui can start answering while modules are still being detected.
  • On Windows, indexer threads run at below-normal priority so the desktop stays in front while a first index is running.

Start Memtrace and sit still — idle CPU stays down

New

  • New features land on Nightly first: npm install -g memtrace@nightly is the same memtrace command, and it is not always stable. They still ship on the default install. memtrace install stays on the channel you already have.

Fixed

  • After memtrace start on a database you already indexed, Memtrace no longer rebuilds search indexes just to open it. Leave it running with no agent and no index job and the machine stays quiet.
  • On a large already-indexed store, start no longer counts every node per repository and no longer rebuilds search indexes in the background while you sit still. That was the leftover CPU after Skip.
  • Closing Claude Code or another editor's memtrace mcp no longer leaves memcore-server listening on 127.0.0.1:50051. On Linux the sidecar dies with the parent, including a hard kill. The next spawn reaps a leftover for this store, and WSL can see that port with ss when lsof is missing.
  • memtrace mcp can join a running memtrace start even when the npm wrapper started several seconds before the real binary. That timestamp mismatch used to look like an unverifiable runtime and closed the MCP connection.
  • get_cochange_context no longer times out on repositories whose working-tree history is a dense in-tree build. It skips those wide save episodes, uses the files already on each episode, and does not scan the graph once per episode. A 30-second client deadline is enough again; other tools on the same daemon are not starved by abandoned co-change calls.
  • Checking out a feature branch keeps the original main graph and applies only that branch's delta. It does not copy the whole graph. Changed nodes are restamped on the feature; checking main back out returns the original.
  • Cortex no longer rereads every decision document on a timer while nothing changed. Saving an ADR or an agent-rule file is what wakes capture.
  • Cortex Governance no longer reports the daemon as down when a request fails. If Cortex is running, the page says so, including when the editor has more than one folder open.
  • Insights tabs that already have something to show now paint it instead of spinning while another tab rebuilds. Reconnecting the dashboard no longer forces every tab to start over.
  • The All repositories graph no longer sits empty for tens of seconds just because graph work is happening somewhere else. If that view was already built, it paints immediately.
  • The All repositories graph also paints the repository graphs that are already ready while another repository is still rebuilding.
  • Asking an editor what Memtrace has indexed no longer comes back empty when that editor started Memtrace from your home folder. It joins the one running memtrace start and lists those repositories.
  • You do not have to sit in the workspace folder. After memtrace start, an editor opened on one repository in that folder joins the same runtime and lists every repository.
  • A leftover editor helper that never connected, including one whose folder we cannot see, is closed when start comes up so the next agent call can attach.
  • Starting with a different workspace than the one already in .memdb no longer moves that database aside and rebuilds from empty. Memtrace keeps the existing graphs, adds newly listed repositories, and refuses when the requested set would drop or replace members. Pass --clear only if you mean to discard the store.
  • Indexing a workspace no longer leaves later repositories empty because another graph pass briefly held the store. Those indexes wait for the lock instead of failing.
  • A new repository in the workspace is indexed when you run memtrace start or when the editor's memtrace mcp owns the store. A terminal start asks first (default yes). Large stores still skip re-walking repositories that already have a graph.
  • After memtrace start, Memtrace does not re-read the whole database to fill dashboard graph pictures. A file save patches the picture you already have. Indexing a repository writes that picture from the graph just built. Indexed repositories with no changes stay idle.
  • Cortex Governance now lists the docs for the repository you have selected, even when the editor window has more than one folder open.
  • The memtrace start banner now shows the real logo spiral and a title-case Memtrace wordmark, not a block MEMTRACE stencil.
  • Nightly memtrace start no longer repeats Memtrace on the version line.
  • The in-app Nightly What's new list is this soak's notes, not an older handwritten snapshot.
  • Scrolling to zoom the GPU graph no longer fights the browser. The wheel zooms instead of scrolling the page.
  • Any editor that runs memtrace mcp — Cursor, Claude, Codex, VS Code, Zed, and the rest — joins memtrace start whether the editor or Memtrace came up first. A live helper stays alive and attaches; start does not kill it to force a respawn, because Claude Code does not respawn a dead stdio server. Only a leftover helper from an older build that never registered is closed.
  • Nightly Discord notes now list only what this soak changed. They no longer repeat the whole pending release every time a new nightly ships.

Improved

  • The service map draws the function that makes an HTTP or gRPC call, with the method and the file it lives in. gRPC is a different color from HTTP.
  • A new API route shows up on the API tab once the graph has the endpoint. A route nobody calls will not grow a topology arrow, because there is no caller to draw.

Changed

  • On Apple Silicon, embedding uses the Neural Engine by default. Set MEMTRACE_DISABLE_COREML=1 if you want CPU only.

An editor session connects instead of pegging the CPU

Fixed

  • Opening Memtrace from Cursor or Claude no longer grabs every fast core on the machine. Each chat used to start a full-speed copy of the indexer, so a few open sessions drove idle CPU into the nineties and then the editor gave up waiting for tools. Those sessions now stay small. If yours is already stuck, reload the Memtrace MCP server after upgrading.
  • A second editor session can join a Memtrace that is still starting, instead of dying with a closed connection and launching yet another copy. The first session used to keep its address unpublished until the database finished opening, which is slow, and every retry piled on.
  • A session that joined an already-running Memtrace no longer starts its own file watcher or background Cortex process. That second copy was competing for the same store, which is part of why idle CPU climbed and tools flapped.

Claude gets workflow shortcuts wherever Memtrace is installed

New

  • Claude Code now has four manual shortcuts into Memtrace's canonical workflows: onboard, preflight, recall, and impact. Each shortcut hands its arguments to the matching skill instead of carrying a second copy of the workflow that can drift out of date. They ship through both the Claude marketplace and the npm fallback installer, so the available commands no longer depend on whether Claude could clone the marketplace. Native Rail remains the one enforcement path; this release does not install a second shell hook.

Community credit

  • Huge thanks to @Regis on Discord (Regis-RCR on GitHub) for proposing the workflow-shortcut layer and sharing the gap analysis that led to this release.

A watched repository is actually watched, and a running index says where it is

Fixed

  • A repository watched by an editor session is now genuinely watched. Asking to watch a folder reported success and listed the path, but when Memtrace was serving an editor directly - rather than through a separate background service - no file save ever reached the graph. Saving a file produced nothing for as long as you waited, while asking for a re-index picked the same change up in seconds. Saves now reach the graph within seconds again in that mode.
  • A running index reports the stage it is actually in. Progress was sent to the dashboard but not to the record that tools and assistants poll, so a large index looked frozen on the very first step from start to finish while the work proceeded normally underneath. Anything waiting for that record to move now sees it move.
  • Clearing a repository while re-indexing it now says that its commit history has to be rebuilt. The clear removes that history along with everything else, but the result reported nothing outstanding, so the gap was invisible until a history query came back empty. Clearing is still not a safe refresh - remove the repository and index it again instead - and this at least stops the result from hiding it.
  • A stalled internal lock can no longer block every write for as long as Memtrace keeps running. One lock could wait forever with no error and no way to see what it was waiting for; if that happened, re-indexing and cleanup stayed blocked and deleted code kept appearing in search until the process was restarted. It now gives up after a bounded wait and reports what it could not take.
  • Connecting an editor session to an already-running Memtrace no longer refuses in one specific case where the running instance was healthy and had published everything correctly. This does not cover every report of that refusal - if yours persists, the message now names exactly what it looked for.

Search spans the workspace, and the graph updates at the cost of the change

New

  • Searching without naming a repository now searches every repository in your workspace. Previously a search needed to know which repository held the answer before it could give you one, so the most natural question - asking without knowing where the code lives - either refused outright or quietly searched a single repository and reported nothing. Results from every repository are now merged into one ranked list.
  • Typing a name you already know puts that symbol first. An exact identifier match used to arrive somewhere inside a list of merely similar-looking code, because scores coming from different repositories were combined without recognising an exact match for what it is.
  • The repository list tells you whether the graph is current with your saves, not just when the last full index ran. Those are different questions, and only the second one used to be answered.
  • Cleanup now repairs duplicate entries left behind when two installations disagreed about a symbol's identity. Those duplicates could not previously be removed by any means, and a save now also heals a file whose history the watcher had lost track of.
  • Two installations pointed at the same database now say so, and the second one no longer writes to it. Reading stays open to both; indexing, watching and replaying history are refused with both installations named, because two builds that disagree about identity are where duplicate entries came from in the first place. Set MEMTRACE_ALLOW_FOREIGN_INSTALL_WRITES=1 to allow it deliberately.

Changed

  • Saving a file now updates the graph by the size of your change rather than the size of your repository. Every save used to rebuild the whole graph, so keeping the view current got slower as a project grew instead of staying proportional to what you edited. Open dashboards receive just the difference and apply it in place.

Fixed

  • A search running while the graph is still being built now returns the last good answer, marked as possibly out of date, instead of nothing at all. An empty result was indistinguishable from the code not existing.
  • A dashboard showing an empty canvas over a populated database now says the view is still being built rather than reporting the repository as unindexed, which read as data loss.
  • Leaving a dashboard open can no longer postpone the graph being published indefinitely. Each refresh used to restart the waiting period the publisher depends on.
  • Reading the graph no longer waits on graph work that the answer does not depend on.
  • Clearing a repository now also clears its embeddings from the search index, and deleting an entry takes its embeddings with it, so a search can no longer return content that has already been removed.

Improved

  • Working out what a change affects no longer slows down as a repository grows, and a search that times out leaves its groundwork in place so the next identical search is fast instead of paying the same cost again forever.

The daemon stops working when there is nothing to do, and stop finishes the job

Fixed

  • Running Memtrace in one project no longer stops the database serving another. Starting anything — a session, an index, an editor's background server — swept up every storage server on the machine whose launching process had exited, on the reasoning that such a server belongs to nobody. That reasoning is wrong on macOS and Linux: a daemon started in the normal way outlives its launcher and is adopted by the system, which is what a healthy one looks like for the rest of its life. So each new invocation killed the storage server of every other project's running session, and the session it belonged to lost its database until something restarted it. Found by running two projects side by side on one machine. A server is now only collected when the scope is unambiguous — stopping the project it belongs to, or reclaiming a port that is genuinely needed — and never as a side effect of starting something. No indexed data was at risk; the affected sessions lost their connection, not their graph.
  • A store that has been indexed more than once no longer sends the daemon into a permanent rewrite. Attaching a vector to a symbol records a new copy each time, while the search graph keeps one entry per symbol — so a repository indexed twice holds two stored vectors per symbol and was read as having lost half of them. The response to apparent loss was to write every vector again, which added another copy per symbol and made the next reading worse, so the conclusion confirmed itself on every pass. In the field this ran at roughly three cores of continuous writing with no reads for hours on end, with the store growing the whole time. Apparent loss of that kind is now repaired by refilling the graph from the vectors already stored, which writes nothing; only genuine damage found while recovering triggers a rewrite.
  • Re-indexing a repository no longer leaves a second live copy of every vector behind. Attaching a vector to a symbol recorded a new copy and nothing ever removed the one it replaced, so a repository indexed twice held two live copies per symbol — measured on this release as 960 stored vectors against 480 symbols. That surplus is what the check above was reading as loss. A symbol's vector is now replaced rather than added to, and the new copy is written before the old one is dropped, so an interruption leaves a redundant copy the next pass clears rather than risking the only copy of a vector. The record log is append-only, so this does not shrink a store on disk; it stops the live count from multiplying, which is what drove the repeated re-indexing that grew one reported store to 3.6 GB. Copies written by an earlier version are left in place and are harmless.
  • Saving a file in a repository with a large number of ignored paths no longer stalls the watcher. Before deciding what changed, the watcher asks git which paths are ignored, and it sent the whole list before reading any of the answer. Past roughly sixty-four kilobytes of paths both sides were waiting for the other, so the check never returned and file watching stopped for that repository until the daemon was restarted. The two directions are now handled independently, with a timeout, and a batch of six thousand paths completes in well under a second.
  • Stopping now also reaps helpers that are not themselves Memtrace programs. This was named as a known limitation in 1.0.8: a stuck helper the daemon had spawned — a git process, for example — kept both itself and the daemon alive, and both had to be killed by hand. Stop now walks the owner's entire process tree, deepest first, and escalates until it is gone. It also finds that owner by inspecting running processes rather than by reading a file the dead process took with it, so an ownerless daemon is no longer invisible to it. Sessions belonging to other editors and agents are still left alone.
  • Blast radius on a symbol with very high fan-out now returns instead of running past any deadline. This was the other known limitation in 1.0.8: the walk read one symbol's edges to completion even once the answer was already capped. It now works to a time budget and returns what it found, marked incomplete, rather than not returning. MEMTRACE_IMPACT_WALK_BUDGET_MS raises or lowers the budget from its fifteen-second default.
  • The decision-memory handoff file no longer grows without bound. Captured sessions are appended to it and the background service records how far it has read, but nothing ever reclaimed the part already read — reported in the field at 2.53 GB with the service continuously working through it. The consumed portion is now dropped at startup, at the one moment no service is reading the file, and the unread remainder is preserved exactly.
  • Two Memtrace installations driving one store now say so. A globally installed copy and one built from source can be pointed at the same database, and the newer of the two writing under the older's assumptions is difficult to spot from the outside. Startup now records which installation claimed the store and warns when a different one attaches. An installation it cannot identify is never reported as a conflict.

Every session opens the same graph, and stop leaves nothing behind

Fixed

  • A shared workspace graph is now opened by every session inside it, not only by one started at the workspace folder itself. Marking a folder as a workspace is meant to give the repositories inside it one shared index, but a session started with no flags ignored that marking unless its working directory was the workspace folder. Started from a repository inside the workspace it opened a private database instead, so searches answered from a store holding a few unrelated repositories with your own repository simply absent, and one such store appeared per running editor or agent session.
  • Sessions started inside a git worktree no longer get their own private, near-empty graph. A linked worktree looked like a separate repository to the check that decides which database to open, so a session started inside one created and bound a worktree-local database. Nothing reported an error, and indexing wrote a full graph into the stray copy. Worktrees now open the graph of the repository they belong to.
  • A store that is being skipped is now named at startup. The two fixes above change which graph an existing session opens, and from the outside that looks identical to the problem they fix: the index appearing to vanish. Startup now lists the database it opened alongside any it stepped over, and states plainly that nothing was deleted. Leftover copies stay on disk untouched, and MEMTRACE_MEMDB_DATA_DIR pins a specific one.
  • Stopping Memtrace no longer leaves part of it running. It reported success while the supervising process kept consuming a core and a background service held nearly two gigabytes, both of which had to be killed by hand. The stop signal was sent once and never escalated, services were located through a file the dead process had taken with it, and a session that ended took nothing with it. Stopping now escalates until the process is actually gone and collects whatever is left ownerless, while sessions belonging to other editors and agents are still left alone.
  • Only one decision-memory service runs per machine again. Each session reaped every other session's service before starting its own, so two agents working in different repositories killed each other's and the supervisors restarted them in a loop, with several running at once against a store meant to have a single owner. Ownership is now decided once per machine, and a session that does not own it waits to take over rather than competing.
  • Blast radius answers in about a second instead of timing out. Impact, callers and references walked the graph one symbol at a time, and each step asked a question the database answers by reading every record it holds, so a two-hop query on a real repository never returned. They now ask once per step for the whole frontier, through the index.
  • The dashboard no longer starves the database it is reporting on. Health counted repositories in a way that reads and decodes every record in the store, and the dashboard polls health continuously, so every poll piled another full scan on the ones still running. The database saturated every core with no forward progress, and the abandoned requests tore down the connection that the indexer was using to write a repository's relationships. Health now computes at most one answer at a time and serves the last good one rather than starting more work.
  • A repository whose relationship write failed no longer reports every symbol as safe to change. Its symbols still resolved, so blast radius came back as no impact and low risk, which is indistinguishable from a genuine answer. An incomplete graph now reports unknown risk and marks the result incomplete.
  • An index that writes symbols but no relationships now says so. It reported completion with a symbol count and no relationships, which reads as success, and a repository in that state cannot answer a single impact, caller or reference question. Completion now carries an explicit warning naming what is missing and what to do about it.
  • Indexing reports progress through the database write. The bar stopped at 85 percent for the whole write stage, the longest one on a large repository, with no output at all, which was twice mistaken for a hang.

Changed

  • Blast radius may now run alongside background index maintenance. It previously waited for exclusive access, which is why a single background repair could make every impact question hang no matter which symbol was asked about. It now waits briefly and then proceeds, which is safe because the same release made that walk read a capped number of symbols in fixed-size pages.
  • Stopping always terminates. Memtrace stop used to report failure and leave the process family running if the supervising process did not answer in time. It now escalates to a forced stop after a grace period, so anything scripted around the old failure exit should be re-checked.

Cold starts stay inside their workspace and large graphs use less memory

New

  • A portable workspace manifest can now name repositories that live in different folders. Run Memtrace with an explicit workspace file when several repositories belong together; relative paths travel with the manifest, while duplicate and unsupported entries are rejected before anything starts.

Changed

  • Running memtrace start without a workspace now means a true cold start of exactly the repository or folder where it was invoked. Parent-folder markers, editor workspace files and another running Memtrace process no longer enlarge that scope implicitly.

Fixed

  • Repositories left in an older shared database no longer become members of the active workspace's main graph, repository list, watches or live insight scans. Workspace membership comes from the repositories discovered for this start, not from every repository record that happens to exist on disk.
  • Opening the dashboard on a very large graph no longer launches several full-graph analyses at the same time. Expensive graph and insight materializations now share one gate, while repository statistics load record payloads in bounded pages, substantially reducing peak physical memory.
  • Concurrent workspaces no longer adopt the same sidecar port or overwrite one another's runtime ownership. Start, stop, clear and reset operations are scoped to the selected store, confirm the owner and retain the store lock throughout cleanup.
  • A legacy or mismatched local database is no longer opened and trusted. Start and index move its payload into a recoverable sibling quarantine by same-filesystem rename, then rebuild a clean database for the exact workspace; standalone MCP and replay fail closed until that cold rebuild can be performed.
  • Health, Quality and Architecture stay current while agents or editors change the graph. Every successful or partial mutation invalidates the affected repository, stale values remain visibly marked while one serialized recomputation runs, and a durable five-second check catches changes written by another process.
  • Clear and reset refuse filesystem roots, home directories, project roots, symlink redirections and unrecognizable data directories. On Unix the recursive clear is pinned to the validated directory handle; platforms without that guarantee now refuse the operation instead of risking the wrong directory.

Test coverage measures maintained code, not frozen copies

Fixed

  • The Test tab now excludes immutable evidence copies from its coverage denominator. Frozen bot snapshots, materialized opponent zoos and saved policy candidates stay indexed and searchable, but they no longer count as separate code that needs a duplicate test suite. A repository whose maintained source was well covered could previously report roughly three percent simply because it kept thousands of those copies.

Insight panels tell the truth about every language

Fixed

  • Dead code is measured correctly in Java, C#, Go and every other supported language. Whether a function is part of a project's public surface was only ever worked out for Rust and JavaScript; everywhere else nothing counted as public, so anything not reachable from a web route was reported as dead. On a fully tested codebase that was a third of all functions. Visibility is now modelled per language, including Go's capitalisation rule, Kotlin and Swift defaults, leading-underscore conventions in Python, Dart and GDScript, Ruby's private sections, Elixir's private definitions, and static linkage in C and C++.
  • Improvements to how code is read now reach projects that were indexed by an older build. Re-indexing skipped any symbol whose source text had not changed, and the comparison carried nothing about how that text had been interpreted — so a smarter reading of the same file could never take effect. Upgrading now refreshes exactly the records the change affects, without re-computing embeddings.
  • The dependency and coupling view works for projects that import by package or namespace rather than by file path. Java, C#, Kotlin, Go, Python, Ruby, PHP, Swift, Dart, Elixir, Lua and C++ imports now resolve to the files they name, so a panel that reported no resolved imports at all now measures real architecture.
  • Cross-repository connections appear without restarting. The picture the interface reads was rebuilt before those connections were worked out, and the rebuild was skipped whenever a re-index produced no brand-new links — which is the normal case for a repository that was already connected. Indexing now settles first and the picture is always rebuilt afterwards.
  • Panels no longer show numbers from a graph that has moved on. Freshness was inferred from a derived file rather than announced when the graph changed, so on any branch other than the main one the panels could freeze indefinitely. Separately, repositories with no such file all shared a single cache key and could show each other's results.
  • Duplicate findings are actually duplicates. Comparison ignored names and text values, so two functions with the same shape were reported as copies of each other — a web controller matched a small network client, and two clients that differed only in the address they call were treated as identical. Findings on one service went from thirty-six to none, with genuinely unreachable code unaffected.
  • The dead-code grade takes its own confidence into account. Findings the analysis itself marked as uncertain still drove the score to the worst possible grade. Uncertainty means reflection or dynamic behaviour could not be ruled out; that now limits how far the score can fall, while findings that are certain still count in full.
  • An empty hotspot list explains itself instead of showing nothing. The view now reports how many functions were examined, how many changed recently, and how they compare with the threshold, so a quiet codebase is distinguishable from a broken one.
  • A single-project .NET service now produces architecture insight. Components were derived only from project files, so the ordinary shape of a .NET service had exactly one component and nothing to compare.
  • A repository containing several services now appears in the service map. Everything was grouped by repository, so services living together were treated as one box and every call between them was hidden as internal traffic.
  • The service map no longer scatters across an empty canvas. Services that call each other in both directions — the normal case — were laid out as if the loop had to be followed, spreading five services across twenty-four columns and pushing the diagram off screen with no way to bring it back. The view now fits itself on load, on resize, and whenever the selection changes.

Changed

  • There is now one high-performance graph renderer instead of two. Choosing Auto quietly selected an older renderer, so the three options in the menu produced three different-looking graphs. Auto and the high-performance option are now the same renderer, with the compatibility renderer as the automatic fallback.
  • Calls that cross a repository boundary stand out in the graph. They were drawn in the colour of whatever they came from and faded with distance — and those calls are long by nature, so the rarest and most valuable connections were the hardest to see. They are now drawn in red at a constant thickness.
  • Windows only, and worth knowing before you upgrade: the one-time re-index rebuilds the semantic search index in memory, and on Windows it is not always written to disk before Memtrace exits. Search is correct for that session; on the NEXT start the semantic half can go quiet and results fall back to keyword matching. Run an explicit re-index to restore it. The condition is now reported in the log instead of being silent, and a fix is coming in the next release. macOS and Linux are unaffected.

API handler linkage stops counting database tables as routes

Fixed

  • A busy sidecar is no longer mistaken for a missing one on small requests. The time allowed for an answer grew with the number of documents, but the wait to be served does not — it depends on how busy the sidecar is. A request covering only a few documents was therefore given the least time exactly when the sidecar was most loaded, and the view reported the sidecar as not running while it was simply working.
  • Decision records load again, and fast. The sweep that finds a project's governance documents was walking into the throwaway copies of the repository that coding agents create for themselves, and treating every markdown file inside them as a governance document. On this project that turned a handful of real documents into nearly two thousand, and sixteen megabytes was sent to the decision sidecar every time the view opened — so it timed out and showed nothing. Those agent copies are now skipped.
  • The API handler linkage score no longer counts database tables as web routes. Every table in a database migration was being treated as a code-registered HTTP route, and since a table cannot have a request handler, each one counted against the score. On this project that was 86 of the 93 routes reported as unlinked, reporting the worst possible grade for a codebase whose actual route linkage is good. The score now covers only things that can genuinely have a handler, and anything new has to be explicitly included rather than counted by default.

Decision memory answers again on real repositories

Fixed

  • Decision records and governance load on real repositories. Classifying a repository's governance documents sends their contents to the decision sidecar in one message, and anything past about two megabytes was cut off mid-transfer and the connection dropped. The dashboard then reported the sidecar as not running, while it was in fact healthy and answering everything else. On one workspace the request was seventeen megabytes, so the view never had a chance to load. Transfers are now limited by going quiet rather than by total size, so a large request is read to the end.
  • GPU diagnostics name the library that is actually missing. When the CUDA provider fails to load, Windows reports exactly which dependency it could not find. That answer was being ignored in favour of our own guess, so a machine with cuDNN already installed was told to install cuDNN — when the real gap was a CUDA Toolkit library. The message now quotes the module the loader named and points at the package that ships it.

Correct numbers: vendored code no longer counts as yours, and self-hosted workspaces index again

New

  • A dedicated Test tab. Coverage used to be a single reachability percentage tucked inside Quality — the least informative thing the graph knows about a suite, because reachability is generous by design. The tab now splits that number into the three groups it hides: code a test calls directly and therefore actually asserts on, code reached only through a chain that would break without any test going red, and code nothing touches. It adds coverage per language, the test frameworks in use, untested public surface ranked first, and where the gaps cluster.
  • A governance lookup that takes a file path. Asking what rules constrain a piece of code previously required an internal identifier that nothing ever handed you, which made the feature unreachable in practice. Pass a repository and a file path — what every search result already gives you.

Fixed

  • Self-hosted workspaces connected to a hosted database now index. Sign-in, seat enrolment and the connection check all reported success while indexing quietly wrote nothing, because the part of the product that builds the graph could not open a secure connection at all. Everything that reports health could. A local database hid the problem completely, so it only ever appeared on real deployments.
  • Vendored dependencies are no longer graded as your own code. Libraries checked into a vendor folder were being read, parsed and scored as first-party source — on one project that was almost two gigabytes of someone else's database engine, supplying 17% of the detected API surface. It inflated the totals every quality score divides by, added foreign code with no local caller to the dead-code count, and shipped duplicate copies of the same contract, which made the linker discard real connections as ambiguous. Scores that looked like a verdict on your code were partly a verdict on your dependencies.
  • A workspace repairs itself when the rules about what to index change. Upgrading to a version that excludes something new used to leave every existing workspace holding the old records until someone rebuilt the index by hand. Those records are now dropped the next time the graph is read.
  • Trace density no longer reads zero on a graph full of connections, and neither do the readings derived from it.
  • Hovering a node shows its name, kind and file path again. The card had gone missing on the default renderer.
  • Clicking a community focuses it in the graph instead of appearing to do nothing.
  • An indexing job reports that it finished. A run that completed successfully could sit at ninety-nine percent forever, which is indistinguishable from being stuck — and was reported as being stuck, twice, when the work had actually finished.
  • Clearing stale records completes on a large repository. It used to get slower the better your search pattern matched, so a pattern that matched a whole folder never returned at all.
  • Replaying an episode accepts the shortened identifier the interface displays. The only identifier you could see was one the lookup rejected, so a perfectly healthy episode reported itself as missing.
  • A repository identifier is checked before use. A client that sent an empty value could create a phantom repository holding twenty thousand entries that could only be removed by deleting the whole thing.
  • An episode that was not fully written is no longer counted as saved, so a partial write is visible instead of silently reported as success.
  • The decision-memory sidecar explains itself instead of failing with an unhelpful system error, and stops retrying a start that cannot succeed.
  • Identifiers returned by decision memory survive a round trip through JavaScript. They were large enough to lose precision silently, and the rounded value looked valid — so follow-up questions answered honestly about a decision that was never actually found.
  • A run whose indexing failed no longer ends by reporting a complete, successful bootstrap.
  • A failed connection to the database explains why it failed instead of reporting only that it did.
  • Publishing a release no longer fails when the hosting provider takes a moment to catch up with itself.
  • Decision records show up again in a workspace that holds more than one repository. Governance would only answer for whichever repository happened to sit at the root of your workspace; asking about any other one beside it was refused outright, so the Governance view came back empty for most people who keep several projects in one folder. Requests are now accepted for any repository inside the workspace, and still refused for anything outside it.
  • A busy decision sidecar is no longer reported as a missing one. Every governance request had to finish within the same fraction of a second allowed for noticing that the sidecar is not running — but answering one means opening and classifying every governance document in the repository, which takes longer than that on any real project. The result was an error saying the sidecar was not running while it was in fact working. Detecting an absent sidecar is still immediate; the work it was asked to do now gets time proportional to the size of the job.
  • GPU diagnostics now name every missing CUDA prerequisite. Running CUDA needs two separate pieces: the execution provider Memtrace ships, and NVIDIA's cuDNN 9. When both were absent the warning mentioned only cuDNN, so people installed it, saw no change, and concluded the GPU support was broken — the piece Memtrace can install for you was never mentioned. The warning now lists everything that is missing, with the right remedy for each, and no longer suggests a 400 MB download that would not have helped.

A new Memtrace: redesigned throughout, a graph engine 27x faster, and dependencies you could not see before

New

  • A completely redesigned application. Every workspace surface — the graph, Insights, the inspector, Cortex, Fleet, notifications, settings — has been rebuilt rather than restyled, and the old interface has been removed. The new workspace ships with 841 tests across 83 files, against 693 for the interface it replaces.
  • A new graph engine, roughly 27x faster. Layout runs as a Barnes-Hut force kernel on the GPU instead of the CPU: measured on a live 136,048-node, 328,522-link workspace, a simulation step went from 295 ms to 11.3 ms, the graph settles in about 3.4 seconds, and once settled frames cost 0.1 ms. Positions never leave the GPU between compute and drawing.
  • The graph is legible at that size, not just fast. Edge lengths went from a 269x spread to 7.9x, so long-range links no longer swamp everything near them; there is no boundary wall, because the space is unbounded and nothing is pinned against an edge; and the layout is re-fit on every update so the graph cannot drift out of view.
  • Related code is clustered before the simulation starts. Communities are detected and used to seed the layout, so the graph resolves into readable lobes — this force model settles two groups only a little apart, a difference invisible among a hundred thousand points, so structure has to be placed rather than discovered.
  • A light mode for the graph, built as a second rendering path rather than an inverted palette, and using the same colours as the rest of the product.
  • A redesigned service topology. A repository is a container and every participating caller and receiver is listed inside it, with each connection landing on the exact function it reaches. Repository-level arrows can only tell you two services talk; with twenty functions in a box, the question left is which of them is doing the talking. Labels are sized from measured text, so they cannot overflow their boxes.
  • Dependencies that are not HTTP now appear in the topology, across eighteen languages: gRPC, message queues (Kafka, RabbitMQ, JMS, SQS, Google Pub/Sub, NATS, MassTransit, NServiceBus, Azure Service Bus), WebSocket, Socket.IO, SignalR, STOMP and GraphQL. A service whose only link to its neighbours was a gRPC channel or a queue topic previously appeared to have none.
  • Java and C# are first-class in cross-repository topology. Both previously contributed HTTP routes only — between them not a single gRPC service, queue topic, hub or GraphQL endpoint was visible. Their API surfaces are also detected now: Spring and JAX-RS including the jakarta namespace, ASP.NET attribute routing and Minimal API.
  • Kubernetes manifests are part of the graph. Every object is indexed with its kind and namespace — including custom resources from any operator, because they share the same contract — and a workload's configured service URLs are read as outbound dependencies, so a deployment states who it talks to.
  • SQL schemas are navigable. Tables, columns, views and indexes are searchable symbols, with foreign keys shown on the column and each column scoped to its table. A repository that writes a table and one that reads it are linked.
  • OpenAPI specifications contribute their endpoints, so a service that publishes a contract is connected to the clients that call it.
  • R and Nextflow projects are indexed.
  • Deep code search over full source. Whole files are indexed with lexical search, and results are returned as windows centred on the query rather than whole-file dumps.
  • Test coverage in Insights, derived from the call graph. It shows which code no test reaches, in every language at once, with nothing to run. It measures reachability rather than executed lines and says so — the actionable half is the list of code with no test path at all.
  • A governance review room in Cortex: Memtrace finds the documents that govern how code is written — architecture decision records, agent rule files, contributing guides — and a human confirms, excludes or scope-approves each one.
  • Release notes inside the product, so you can see what changed without leaving the workspace.
  • Startup and job progress are visible in the activity centre, and graph self-repair appears as its own state rather than looking like a routine re-index.

Improved

  • Insights reports an evidence-bounded quality profile instead of a flattering weighted average. The headline is limited by the weakest measured dimension, each dimension states its confidence and what it was calculated from, and missing evidence is reported as missing rather than scored as a pass — an unmeasured dimension no longer invents a failing grade either.
  • Dead code is scored by reachability from real entry points, with confidence bands, so a symbol reached only dynamically is not reported as confidently as one nothing references. Test modules and configuration formats are excluded.
  • Coupling is measured from component topology rather than directory nesting, and distinguishes missing evidence from a clean result.
  • Complexity rankings say which metric put an item first, and no longer look nearly perfect by scoring only part of the codebase.
  • The graph payload is 43% smaller — measured on a real seventeen-repository workspace, 40.5 MB down to 23.1 MB — and decodes far faster, which is what a reload actually waits on rather than the download.
  • Pages stop refetching data nothing is watching: the episode timeline revalidates instead of re-downloading megabytes, unrelated changes no longer invalidate its cache, and a single repository no longer double-fetches on every load.
  • Code search is faster and steadier — query time no longer grows with the size of the candidate pool, repeated queries skip redundant work, and results are better matched for questions phrased as observed behaviour rather than as symbol names.
  • Memtrace will not exhaust your machine. A footprint watchdog is armed in every long-running entry point after an incident where a session reached 63 GB with no guard firing, because the limit was read but never enforced anywhere.
  • Large repositories catch up in bounded chunks, with individual file failures quarantined rather than stalling the pass, and full git-history replay streams commit by commit instead of holding all of it in memory.
  • Episode detail is complete: deleted files appear, and multi-batch catch-up episodes list every file they applied.

Fixed

  • Selecting a very large file no longer freezes the graph.
  • The code panel in the inspector scrolls with the mouse wheel.
  • The graph refresh indicator stops instead of spinning forever.
  • Large updates no longer defeat the file watcher.
  • Blessed Folder Groups keep every member repository live.
  • A repository being refreshed no longer empties while it rebuilds, and cross-repository topology refreshes leave it intact.
  • Insights no longer reports perfect health while its analysis is still building, keeps dead-code, coupling and API results through a database restart, and reflects newly indexed code instead of holding a stale picture.
  • Cross-repository connections that were closed are restored when the dependency returns, instead of staying invisible.
  • A file no longer splits into a second, empty copy of itself, and existing splits are repaired at startup.
  • Renaming a file while Memtrace is watching no longer leaves the old name behind.
  • Concurrent indexing can no longer permanently disable embeddings, and concurrent saves no longer leave two live versions of one symbol.
  • Shared local databases no longer erase each other's snapshots, stored lookups survive dependency upgrades and restarts, and a read issued just after the server returns no longer hangs.
  • A graph view is never served from a snapshot built under a stale branch, and a good snapshot is never overwritten by an empty one.
  • Decision recall fails fast rather than hanging when Cortex is unresponsive, stays available on Windows and macOS, and supervision no longer stops a healthy daemon.
  • MCP indexing runs in the background instead of blocking the session, and a standalone MCP session can own its own database.
  • Clean symlinks no longer mark a repository as changed.
  • Hosted projects keep their identity across reseeds.
  • Source files stay searchable by ordinary text tools after indexing.
  • Public pages render correctly on first load for search engines and link previews.
  • Accepting a governance batch from the command line now persists it.
  • Telemetry documentation matches the events actually sent, with all eleven types and their properties listed.

Search, graph, and Windows GPU fixes

Fixed

  • CUDA embedding stays stable on NVIDIA Turing GPUs.
  • Search can infer the repository when the scope is unambiguous.
  • Search now distinguishes a warming index from a genuine no-results response.
  • Rust trait dispatch remains connected in the code graph.

Safer Cortex recovery

New

  • New reset and diagnostic commands recover local Cortex state without deleting durable decisions.

Cortex stays responsive across desktop platforms

Fixed

  • Decision recall no longer becomes unresponsive on Windows or macOS.

Cleaner upgrades and steadier live updates

Fixed

  • Installed background services stop cleanly during upgrades.
  • Windows indexing keeps branch identities intact.
  • Dashboard updates reconnect to the correct local address.

Embedding startup adapts to the machine

Improved

  • Memtrace now chooses a safer embedding startup path based on the available hardware.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Graph and Fleet tools over REST

New

  • Graph analysis and Fleet coordination can now be called through the REST interface.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Model downloads recover from temporary failures

Fixed

  • Embedding model downloads now retry transient network errors.

Embedding retries use smaller batches

Fixed

  • Machines under memory pressure can retry embedding work with a smaller allocation.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Watcher failures are reported clearly

Fixed

  • Memtrace now reports when the operating system rejects a file-watch request instead of pretending it succeeded.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Removed folders stop being watched

Fixed

  • Deleted repository folders are removed from the file watcher during startup and while Memtrace is running.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Temporal Insights

New

  • Insights can now show how churn, coupling, and code quality change over time.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Cortex recall works on Windows again

Fixed

  • Decision recall no longer disappears on native Windows installs.

Ansible project support

New

  • Playbooks, inventories, roles, and task relationships can now be indexed.

PHP project support

New

  • PHP symbols and common framework routes can now be indexed.

Fresh starts recover cleanly

Fixed

  • Starting with --clear can initialize a missing data store instead of failing early.

GDScript support

New

  • Godot projects can now be indexed with their classes, methods, signals, and inheritance.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Deeper ActionScript, Dart, and Elixir indexing

New

  • Classes, functions, imports, and language-specific symbols now appear in the graph.

Dart and Elixir support

New

  • Dart and Elixir projects can now be indexed and searched.

Service maps stay complete as projects evolve

Fixed

  • Service dependency maps no longer appear empty after a project has been indexed and updated many times.
  • Multiple definitions of the same service in one repository are now treated as one destination, so valid cross-repository calls still connect.

Safer recovery after restarting Memtrace

Fixed

  • Restarting Memtrace no longer risks rebuilding a healthy repository while startup recovery is still running.
  • A repository is checked twice before automatic repair starts, which prevents temporary startup states from being mistaken for missing graph data.

Missing graphs repair themselves

New

  • Repositories whose current graph data is genuinely missing can rebuild themselves after an update without deleting their saved history.
  • Graph repair now appears as its own activity in the top bar, separate from normal indexing.

Fixed

  • Repositories that still exist on disk no longer disappear from the combined workspace view when saved metadata is incomplete.
  • File names stay repository-relative when older metadata is missing a repository location.

Governance classification works again

Fixed

  • Governance review can classify and confirm documents without returning a malformed response.

Combined graphs no longer wait on empty repositories

Fixed

  • The All repositories view reaches ready state using the repositories that actually contain graph data.

Governance review

New

  • Teams can review the documents and standing rules that guide how agents change a repository.
  • Cortex guidance is surfaced when an agent prepares to edit affected code.

Cortex starts cleanly across platforms

Improved

  • Decision memory now starts by default and avoids duplicate background processes after restarts.

CUDA acceleration for Windows

New

  • Windows machines with NVIDIA GPUs can download the matching CUDA provider during installation.

Cleaner shutdowns

Fixed

  • Stopping Memtrace now closes its background services instead of leaving detached processes behind.

Cortex decision memory

New

  • Memtrace can now capture and recall the decisions behind code changes.
  • The dashboard includes a Cortex view for decisions and their history.

Ignored files stay filtered after restart

Fixed

  • Reloading an existing index no longer brings ignored files back into the graph.

Ignored files leave the graph immediately

Fixed

  • Files newly covered by ignore rules are removed without waiting for a full rebuild.

Timeline history survives repository aliases

Fixed

  • Timeline snapshots remain available when the same repository appears under an alternate name.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Kotlin symbols are indexed correctly

Fixed

  • Classes, methods, enums, objects, and top-level functions now appear in shipped builds.

Index optimization finishes when it should

Fixed

  • The Optimize memory dialog no longer freezes at zero or reports a false timeout.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

One slow embedding batch no longer stops the repository

Fixed

  • Embedding retries continue after an isolated timeout instead of leaving the whole repository at zero.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

The graph settles instead of drifting forever

Fixed

  • Large graph layouts now stop simulating after they settle and fit themselves into view.

Lower memory use for large histories

Improved

  • Long-running Memtrace sessions keep less cold history in memory while preserving it on disk.

Large graph operations complete reliably

Fixed

  • Large graph updates no longer fail when a request exceeds the default transfer size.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Linux ARM64 builds

New

  • ARM64 Linux machines can now install a prebuilt Memtrace package.

Inspector tabs and light mode are easier to read

Fixed

  • Info and History tabs no longer blank the explorer when timestamps use different formats.
  • Code highlighting and usage meters now follow the active theme.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Readable terminal output is back

Fixed

  • The Memtrace banner and terminal status symbols render correctly again.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Rapid search no longer stalls the dashboard

Fixed

  • Concurrent searches now share one index build instead of starting duplicate work.

Search stays fast on large repositories

Fixed

  • Dashboard search now uses the same ranked index as code search instead of scanning thousands of records.

Agents can match the codebase’s real style

New

  • The new style fingerprint reports the naming and control-flow patterns already used in each language.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Timeline support and light mode

New

  • The embedded engine can now answer timeline and time-travel queries.
  • The dashboard includes a complete light theme with clearer graph contrast.

Large workspaces stay responsive

Fixed

  • The repository list no longer stalls when one repository is slow to respond.

Lower memory use during long sessions

Improved

  • Indexing and concurrent search use less memory, with steadier peaks across repeated runs.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

One workspace, one Memtrace store

New

  • Multi-repository workspaces can now share a stable workspace root across nested Git repositories.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Safer indexing on Windows

Fixed

  • Windows indexes are fully flushed before the command exits, preventing damaged data on the next start.

Faster replay without duplicate graph data

Fixed

  • Repeated starts no longer inflate node and edge counts.
  • History replay now processes only new commits after the first run.

Graph activity becomes visible

New

  • The dashboard now highlights graph nodes as agents investigate them.
  • A pre-commit impact check can warn when staged changes affect callers.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

A quieter installer

Improved

  • The installer no longer asks to install unrelated third-party software.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Maintenance release

Changed

  • Maintenance release. No customer-facing changes were announced for this version.

Ship with memory

Your next release deserves this paper trail.

Memtrace remembers what changed, why, and what it broke — for your agents and for you.