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.
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 findsymbol 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.
getcochangecontext 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 MEMTRACEDISABLECOREML=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.
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 MEMTRACEALLOWFOREIGNINSTALLWRITES=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. MEMTRACEIMPACTWALKBUDGETMS 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 MEMTRACEMEMDBDATADIR 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.
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.