Releases: qualixar/superlocalmemory
Release list
v4.1.3 — Your install, your tools, your memories
Fixed
- Installing the plugin could point your editor at a different, empty set of
memories. Its server configuration pinned a data directory of its own, so on
a machine already using SLM the editor read somewhere else entirely — measured
here, that directory held 28 KB while the real one held 611 MB and 5,370
memories. Nothing failed and nothing warned; it simply looked like everything
was gone. The plugin no longer says where your memories live. - Installing the plugin could take away tools you had turned on. Three of the
four editor builds forced a narrower tool set — 31 tools, without the eight for
coordinating between sessions. If you had deliberately enabled more, installing
something removed them. No build states an opinion about this any more. - Installing the plugin could give you a second copy of SuperLocalMemory. Two
launchers preferred a private environment of their own over the one you already
had frompip,pipxornpm. So a machine that had ever created one kept
using it — including after you upgraded properly — and two copies read the same
memories, with whichever started first deciding which one answered. Both now
use what you already have, in either install order, and fall back to their own
only on a machine with none. When a leftover copy is found beside a real
install, it is named, with both version numbers, instead of being used quietly. - The plugin would not start at all outside Claude Code. The path it built
came from a setting only Claude Code provides, so on Codex and Antigravity it
pointed nowhere and the server never came up — with no error explaining why. - Codex reported itself as Claude Code. The catalogue offered one build, the
Claude Code one, so Codex installed that and every memory written from Codex was
filed under the wrong tool. Codex now has its own entry and its own build,
with the Codex-shaped rules, hooks and launcher that were never being delivered.
Changed
- Antigravity is supported. It had no plugin at all. It now has the same
twelve skills, four sub-agents, command and hooks as every other editor.
v4.1.2 — The monitor that was watching nothing
Fixed
- A killed embedding worker was never brought back, and nothing said so. The
worker is stopped on an idle timeout roughly every hour, by design, and a
background monitor exists to revive it. That monitor decided whether anything
was wrong by looking at a probe search: results with no meaning-score meant a
broken embedder. But it explicitly did not count no results at all — and no
results is what a dead embedder produces, because the meaning channel returns
nothing and the probe phrase appears in nobody's memories. So the one symptom
that should have started a repair was read as proof that none was needed, and
because a clean verdict is silent, it left no trace. Observed on a machine that
sat for over an hour, across two restarts, with searching by meaning switched
off, no explanation in the log, and a manual restart the only cure. The monitor
now asks the embedder directly, which is a question a search cannot answer. - There was no way to tell a quiet monitor from a dead one. A check that
finds nothing wrong writes nothing, which is right — a monitor that narrates
every success is one whose warnings get skimmed past. But it left "is it even
running?" unanswerable except by waiting for something to break. The time of
the last check is now reported, so it can be looked at instead of inferred. - A failing repair would not say what it was failing. When a completed
upgrade step stops holding, the report named the step and not the condition —
and that step checks five separate things. Anyone who hit it had to come back
and ask which. It now says which. - One drifted row could make the whole store unreachable. Any failed upgrade
step made every request return "service unavailable". That is right when a
table is missing. It is wrong for the checks that guard data rather than
structure — ordinary use can undo those, a single background pass being
enough — and it left people restarting a daemon to fix something a restart
could not fix. Structural failures still refuse; a data check that drifted now
reports itself and keeps serving while it is repaired. Anything that does not
say which kind it is still refuses, so nothing became more permissive by
accident.
Changed
- The plugin now installs and lists everywhere it should. It is the main way
to get SLM, and it was only half-delivered:- Codex could not see it at all. Codex reads
.codex-plugin/plugin.jsonto
register a plugin and that file did not exist, so twelve skills, the hooks,
the launcher and the server config were all installed and none of it appeared
under Plugins. There was nothing to enable. - Codex was also missing two thirds of the product. It shipped skills and
neither the four sub-agents nor the slash command. Both come from the same
single source as the Claude Code copies now, so they cannot drift. - Antigravity had no plugin at all. It has one now, with the same skills,
agents, commands and hooks as every other surface. - VS Code was missing the slash command.
- Every release looked like no release. The marketplace entry carried no
version, so a client had nothing to compare and an installed plugin never
appeared out of date. This reverses a rule of our own making; the version is
now stated, and one script owns every place that states it.
- Codex could not see it at all. Codex reads
slm doctornow says whether your skills are as new as your install. The
skills, agents and commands are delivered by your editor, not bypip, so
upgrading the package leaves them untouched — and nothing had ever mentioned
that. This release changed 76 files across them. Doctor now reports the plugin
version beside the package version and names the command that updates it.
v4.1.1 — A store older than its own indexes
Fixed
- A store from an early version could not be opened at all, and there was no
way out of it. Starting up creates the indexes, one of which is on a column
that arrives with a migration scheduled to run after the engine is up. On a
store old enough to predate that column, the index could not be created, so
startup failed — and the migration that would have added the column could not
run, because it runs after a startup that never finished.slm db migratedid
not help either: it reports nothing failed and skips that class of migration by
design. Any store in that state was stuck on the version it was already on.
The column is now added before the index that needs it, so those stores open
and finish upgrading on their own. Measured on a real 637 MB store: it went
from refusing to start to a complete upgrade in 19 seconds, with all 7,707
memories, 2,590 records and 848,945 connections unchanged and the integrity
check clean.
v4.1.0 — Every door asks the same question
Fixed
-
Nothing was recording which memories a recall actually returned, so nothing
could learn from it. The step that notes "these memories were shown, for this
question, in this session" had no caller anywhere — a worker started with the
service and waited for events that were never sent. On a real store that left
every one of 162 recorded outcomes with no way to trace back to the recall that
produced it, every per-memory usefulness score sitting at its untouched
starting value, and the ranking model unchanged for eleven weeks. Recalls now
leave that record. It costs 1.6 microseconds and is written outside the reply,
so recall returns the same answers in the same time — measured across 30 warmed
queries, the difference was 3.5 ms in favour of the change, which is to say
none. It records only: whether what is learned may reorder your results remains
a separate setting that stays off unless you turn it on. -
Memories stored since the last graph analysis were ranked as unconnected.
Recall weighs a memory partly by where it sits in your knowledge graph. That
position was only recalculated when a consolidation happened to run or you
asked for it by hand, so on a real store 1,036 of 4,034 memories had no
position recorded — including every memory from the previous four days. They
were still found, then ranked as though nothing linked to them. The
calculation now runs on a schedule and again shortly after startup, it covers
every memory including ones with no links yet, and it no longer ranks memories
the store is not allowed to return, which had been diluting the scores of the
ones it can. -
One small calculation could push a handful of memories above everything
else. A separate routine gave every memory in a group the same score and
wrote it where the ranking reads. On a real store that score was more than ten
times the highest genuine one, so those memories took the largest ranking
bonus available for no reason beyond having shared a subject with a few
others. It has been removed; nothing depended on it. -
Turning on per-user access did not apply to agent connections. Company
mode is set from the dashboard, and the setting it writes was read by the web
interface but not by the connection your AI tools use — so with per-user access
on, two users configured, and one of them restricted to read-only, a write
arriving over the tool connection was accepted as the machine owner while the
same write through the dashboard was refused. Both now read the same setting,
and a tool connection that cannot identify who is calling is refused. Personal,
single-user use is unchanged and needs no login. -
The settings could claim a storage engine that was not there. A store
recorded the fast graph and vector engines as active with neither present on
disk and nothing in progress to explain it, so the dashboard reported one thing
while retrieval used another, on every restart. The claim is now checked
against what is actually on disk when the service starts, and dropped if there
is nothing behind it. Nothing is disabled: an engine that is installed is still
detected and used. -
A note about which schema versions had been applied was stored thousands of
times over. Seven versions were recorded as 3,496 rows on one store and
234,348 on another, because the six places that write it all assumed a
uniqueness rule the table did not have. The rule is now there, so those writes
do what they always intended, and the duplicates are collapsed to one row each
keeping the original date. -
A second workspace could take over a memory belonging to the first. Where
two workspaces on one store were handed the same identifier for a memory or a
fact — an import keyed on an external record id, feeding one source into two
workspaces, does exactly this — the later write could claim the first
workspace's entry outright: new owner, new content, and the notes attached to
it discarded, with nothing raised. Whether it was refused or went through in
silence depended on unrelated details of the entry, so neither outcome could
be relied on. A write that would move an entry from one workspace to another
is now refused, and says which workspace owns it. -
Restricting someone to read-only did not restrict every way in. Per-user
access was applied where a memory is written, and not where one is deleted or
corrected over the network, not on four of the compliance controls, and not on
bulk import — which established who was calling and then never asked whether
they were allowed to write. Three ways of reading stored memories back asked
nothing at all. Every entrance now asks the same question of the same setting. -
A workspace that could not answer "what is this person allowed to do?"
assumed the most permissive answer. If that lookup failed — a busy store, a
locked file — the caller was treated as able to write. A lookup that fails is
not a lookup that said yes; it is now refused outright and says so, and the
caller can retry. -
Deleting a memory left its connections behind. The connections were
expected to be removed along with it and nothing removed them, so recall kept
walking links to memories that no longer existed. Both kinds of connection are
now removed with the memory. Erasing a person had the same shape: their entry
was removed from the store and left in the copy that search reads, name and
all, which is not what an erasure request means. -
Housekeeping could remove connections it had no way to announce. If the
copy that search reads could not be told what had gone, the removal was
committed anyway and the two drifted apart silently. It is now undone and
retried instead.slm db regraphrebuilds that copy from the store if they
have already drifted. -
A request to be told what is held about you left out what had been learned
about how you work. Erasure removed it; the export did not include it. Both
now cover the same ground. -
Storing a memory waited on a model that was still loading. A write
computes the memory's vector on the spot so it can be found by asking a
question rather than only by quoting its own words, and gives that one second
before handing the job to the background worker. It started that wait even
when the model had not loaded, which it could never win — loading takes about
ten seconds. On a copy of a real store the first twelve writes after a fresh
start took a median of 1,055 ms and eleven stored no vector; they now take
34 ms. Writes against a loaded model are unchanged at about 75 ms. The service
now loads the model on startup, in the background, so the wait is not simply
moved onto whoever searches first. -
The dashboard reported "Healthy" whenever the service answered at all, and
the page never reloaded after an upgrade because the version it looked for was
never filled in — so an upgraded install kept showing the previous version's
page until someone cleared their cache by hand. Both fixed; the card now
reports what the service is actually doing, including how far the search copy
is behind. -
An unrecognised result was recorded as a mildly positive one. A client
reporting "ok" instead of one of the three accepted words had that counted as
partial success and fed to the ranking as though somebody had meant it. It is
now refused. An answer can also be reported on by name: recall returns an
identifier and a result quoting it is matched to that exact answer rather than
guessed at from overlap within a time window. -
A hosted model was reported as available before a key was set for it.
Switching to Mode C names a provider and leaves the key empty until you supply
one, and every surface said nothing was wrong while each model-backed feature
was about to fall back to assembling from your notes. It now says which step
is missing. -
Repeated failures in a background task looked the same as one hiccup. A
step failing every cycle for days reported exactly what a single transient
failure reported. It now says how long it has been failing. -
Upgrading a large store could appear to hang. Collapsing duplicated
schema-version records compared every record against every other of the same
version; on a store with 234,348 of them that had not finished after 25
minutes. It now takes 324 ms, and the whole upgrade of that store takes 40
seconds with every memory, fact and connection preserved. -
A refusal from the service was reported as a crash. Commands that were
correctly denied printed a stack trace instead of the reason, and one denial
told users to run a command that does not exist. -
slm connect claude-codetold you to run a command that does not exist.
It pointed atslm plugin install; there is noslm pluginsubcommand, so
the only instruction it gave ended in an error with nothing else offered. It
now names the two Claude Code commands that actually install the plugin, and
the setup wizard that runs both for you. Reported by @barrygfox (#123). -
The bridge install in the IDE guide named a package that is not on npm.
@modelcontextprotocol/client-clihas never existed, so the documented
install could not produce themcp-remotebinary that the config we write
points at. All three places now namemcp-remote, which does provide it.
Reported by @tonydzi (#122). -
Two settings did not survive a restart. The consistency threshold and the
per-channel retrieval weights were never written to the config file and never
read back, so tuning either one — by hand or by switching mode — lasted until
the next restart and then reverted to the default with nothing said. Both are
now saved and restored, a pair stays a pair through the file, and a section
someone has hand-edited into nonsense falls back to defaults instead of
stopping...
SuperLocalMemory 4.0.8 — Where you were actually looking
Added
- Summaries reach agents and the dashboard. 4.0.7 gave the summary layer a
command; an agent still had no way to ask for one, and neither did anyone
reading the dashboard. Adds theget_memory_summarytool and a Summaries
tab under Memories with Today, Yesterday, and a picker listing the projects
SuperLocalMemory has actually recorded activity in. Every result states how
many memories it was built from and how much it covered. - Bounded Loops has its own page, alongside the other integrations. It shows
whether Bounded Loops is installed, which agreement the two products
negotiated, and which finished runs have been imported — and states plainly
that imported evidence is read-only: SuperLocalMemory never learns from it, no
file paths leave your workspace, and the tamper-evidence it carries is not the
same thing as independent verification. - Mesh shows its history, not only who is connected this second. Sessions
leave the mesh when they end, so the page was empty between sessions even on a
machine with plenty of mesh activity.
Changed
- Recall Lab is the first thing you see under Memories, with example
questions to start from. Summaries sits next to it. The three browsing views
follow.
Fixed
- Memory stopped learning from use. Recall marks which memories it returned
so that later use can be credited back, but the mark never reached the
assistant, so nothing was ever credited. Every recall was scored as neither
good nor bad, which is why recall quality sat at its starting value and no
source ever showed a settled quality signal however much the memory was used. - The behavioural half of consolidation had never run. Nothing triggered it,
and when it did run, two of its four steps failed without reporting anything.
SuperLocalMemory now runs it on a schedule while idle — never while you are
storing or recalling — and at session end. - "This project" summaries could not work. The button sent no project, and
the answer was always an error. SuperLocalMemory installs once for your whole
machine, so a browser tab has no way to know which project you mean; it now
lists the ones it has seen. - Locally written summaries began with an apology. The local model was never
told what it was writing, so it replied as if in a chat. It now returns the
summary and nothing else. - A summary built from nothing claimed to cover everything. A project with
recorded activity but no saved facts is now reported as a partial view. - Multi-Agent Memory showed access tokens instead of agent names, and because
one agent uses many tokens over time, a single agent appeared as dozens. - Optimize invented a chart. The cache hit-rate graph drew a rising trend
generated from the current value rather than measured; no history is recorded,
so it is gone until there is something real to plot. "Tokens saved" was
labelled as a monthly figure with an upward arrow that nothing ever set — it is
a total since install, and now says so. The page also explains why its numbers
are zero while its switches are on. - One kind of memory pattern was never produced. The query that finds it
asked for columns that do not exist, so it failed on every run and was skipped
silently. - Code links never appeared for anyone. Two separate reasons. The pass that
creates them matched no facts at all on a real store — it looked for an empty
archive marker, while live facts carrylive, so every fact was excluded. And
the panel that displayed them was the search-results view, not the memory
drawer people actually open. Both fixed; on a real store this produces 7,470
links across 3,603 memories. - "Atomic facts" always read "No atomic facts recorded for this memory." The
drawer looked up child facts using the row's own id, but a row in that pane is
itself an atomic fact and its parent is a separate field. Records stored
directly, which have no parent, now say so rather than reporting missing data. - Summaries ignored your mode. The command never passed the configuration, so
every summary took the no-model path — a Mode B user got Mode A output. Ollama
now writes them when configured, falling back if it is unavailable. - Summary highlights were unreadable. Truncation counted characters but
ignored newlines, so one fact containing headings and blank lines rendered as
six lines and the list stopped being a list. - "Active entities" listed internal identifiers instead of names. It now
readsFixed (127), Gateway (124).
SuperLocalMemory 4.0.7 — Reachable
Everything here was already built. None of it could be used.
slm summary — a readable layer over your memories
slm summary day # what you recorded today (also: yesterday, or a date)
slm summary project # what was worked on, for a directory
slm summary session <id> # what one session covered
Requested in #113. The generators shipped in 4.0.6 with no command, tool or endpoint to call them — this is that missing surface.
Every summary states how much of the underlying data it could actually see, and --json lists the exact memories it was built from. Session data is sparse — roughly 4% of facts carry a session id — so a session summary reports that rather than presenting a fraction as the whole. No language model required, so these work in the fully offline mode.
Memories link to the code they mention
A memory that names a function, method or file is now connected to it in the code graph, with a short description of what it points at and a marker once that code has changed. Expanding a memory in the dashboard shows this; nothing appears if you have no code graph.
The bridge behind this had never run. Four things were missing at once: setup wrote a bridge_enabled flag no code read, the code-graph build discarded it, the code-graph settings had no loader at all, and the method the bridge was written against was an unimplemented placeholder. Enabling the code graph during setup left the flag on disk and the feature inert, with nothing to indicate it.
Linking runs during background maintenance, never when a memory is saved, and needs no language model — so it works in every mode including the offline one.
Fixed
Version numbers disagreed across the project. 4.0.6 shipped with the pip requirement pins, the npm lockfile, the editor plugin manifest, the citation metadata and the lockfile all still reading 4.0.5, and the agent rule footers reading 4.0.4. Installing from requirements.txt fetched the wrong release. One script now sets all fifteen, with a --check mode.
Stale-memory checks reported "nothing is stale" when the feature was off. They answer entirely from code links, so with linking disabled they returned an empty list — the most reassuring possible answer, from something that never ran. They now say so, and the remediation message names a setting that exists.
slm gdpr was missing from slm help, having shipped in 4.0.6. The drift guard that should have caught it read only one file.
Consolidation could create a database file named after a bad argument instead of refusing it.
Tests that had stopped testing anything
Three shipped features had no effective coverage, and the checks that were supposed to protect them had been passing or timing out for releases:
- The semantic index cap test performed 10,001 sequential writes and timed out in every full-suite run, including 4.0.6 — it never once verified the cap. Now three seconds.
- Ten event-time filter tests compared empty results, because their fixtures predated the 4.0.2 correction-admission check and every recall abstained.
- A prompt-hook stub took two arguments while the hook passes three, so it raised during argument binding and the path under test never ran.
- One Brain-pane test asserted properties of a UI file retired in 4.0.6.
- The latency gate reported machine load as a code regression; it now checks load before blaming the code.
pip install --upgrade superlocalmemoryFull changelog: https://github.com/qualixar/superlocalmemory/blob/main/CHANGELOG.md
Compare: v4.0.6...v4.0.7
SuperLocalMemory 4.0.6 — The Connected Brain
A dashboard that reads like a report rather than a metrics dump, and the knowledge graph fixed.
The Brain, rewritten for people who do not read telemetry
The Brain section leads with the number of questions your memory has answered instead of a raw event count. It names its ranking phase in words. It no longer presents a starting value as if it were a measured result, and source quality no longer lists internal identifiers. When nothing has been measured yet, it says so and explains what would change that.
The knowledge graph no longer opens blank
The graph could render nothing on first open — and again each time you came back to it — until you nudged the node slider. Two separate causes: the view framed its camera against a canvas that had no size yet, and re-entering the pane cleared the canvas without redrawing it. Default node count is now 50.
Below 1100px the details and chat panel stacks under the graph a full screen-height out of view. There is now a control to reach it, and a way back.
Fixes from reported issues
Saving dashboard settings no longer destroys your API key (#119, reported by @barrygfox). The write path distinguishes a field you left alone from one you deliberately cleared, and the endpoint keeps its scheme across a reload-and-save. The key is cleared when the destination provider actually changes, so a credential is never relayed to an endpoint it was not issued for.
Self-hosted rerankers on a private LAN work over plain HTTP (#112, reported by @unfall103-debug). retrieval.trust_plain_http_lan (default on) allows plain HTTP to numeric private addresses — the same posture already applied to loopback. Public IPs, carrier-grade NAT and bare hostnames still require HTTPS. Turn the flag off for hardened deployments.
WAL close-path hardening (#118, reported, diagnosed and fixed by @kenyonxu). Per-call connections disable checkpoint-on-close. On SQLite builds whose close-path checkpoint can block, closing a WAL connection could wait on reader marks pinned by another connection while holding SQLite's process-global lock, stalling every later connection in the process — and busy_timeout does not apply there. Reviewing that fix surfaced a second bug: wal_autocheckpoint is per-connection and is not stored in the database file, so the configured value had only ever applied to the short-lived startup connection while working connections silently ran on SQLite's default.
Recall survives a reranker that returns no scores — it falls back to its existing ranking instead of raising.
Presence says when it stopped being recorded. A gap in recording used to look identical to "no agents are active".
Code graph
build_code_graph had failed on every repository since late July: the resolver was written but never called, so unresolved edges reached the store and the whole build aborted on a foreign key. The resolver is wired into both the full and incremental paths, and a batch now inserts every node before any edge, so a result no longer depends on the order files happened to be processed.
Memory consolidation (#113, requested by @unfall103-debug)
Repeated facts about the same entity are merged during maintenance, and the originals are archived rather than deleted.
Session, daily and project summary generators also landed — but nothing calls them yet. There is no command, tool or endpoint, so that part is not usable in this release; the surface lands in 4.0.7. Tracked in #113.
Connected clients
Codex is listed with the configuration that proves it. Bounded Loops is detected when installed, with its version and the bridge it speaks.
Thanks to @kenyonxu, @barrygfox and @unfall103-debug — every reported fix in this release came from an issue with a reproduction attached.
pip install --upgrade superlocalmemoryFull changelog: https://github.com/qualixar/superlocalmemory/blob/main/CHANGELOG.md
Compare: v4.0.5...v4.0.6
SuperLocalMemory 4.0.5 — Reviewed time-aware corrections
Corrections you can review before they take effect.
Editing a memory is now a reviewed change, not an overwrite
A direct edit no longer replaces a fact. It creates a successor that waits for review:
- apply — the successor becomes current, the predecessor expires
- reject — current truth is untouched
- rollback — the predecessor's original temporal state is restored
The ledger is append-only and profile-scoped, so the history of what was corrected, when, and by whom survives. No correction stores raw fact text in the ledger itself. Available from the CLI, MCP, and authenticated HTTP, with compare-and-swap versions so two clients cannot silently overwrite one another.
Recall abstains instead of guessing
Current-truth checking now covers every path a candidate can arrive by — channel results, profile shortcuts, bridge and scene expansion, pins, and cache hits. When that check cannot be completed, recall abstains rather than returning a fact that may be stale.
The Brain reports its sources separately
BrainTruth v1 is shared by slm brain, MCP, HTTP, and the dashboard. Memory activity, feedback, receipt claims, external evidence, and correction quality are reported independently, and an unavailable source is marked unavailable instead of being shown as zero.
Safety
An ordinary forget on a correction-linked fact returns an explicit conflict rather than an opaque writer failure. Privacy deletion across both the fact store and the ledger remains the job of the dedicated erasure workflow.
pip install --upgrade superlocalmemoryFull changelog: https://github.com/qualixar/superlocalmemory/blob/main/CHANGELOG.md
Compare: v4.0.4...v4.0.5
SuperLocalMemory 4.0.4
What's Changed
Full Changelog: v4.0.3...v4.0.4
SuperLocalMemory v4.0.3
Full Changelog: v4.0.2...v4.0.3