Mnemosyne 4.0.0b1 is published. It went to PyPI on 24 August, it is flagged as a pre-release, and it is opt-in: a plain install still resolves 3.15.1 and will keep doing that until 4.0.0 is final. Nobody gets moved onto this by accident.
pip install --pre "mnemosyne-memory[embeddings]"
The double quotes are not decoration. zsh globs the brackets and refuses the command outright, and zsh is the default shell on macOS. Single quotes fix that but break cmd.exe, which hands them to pip as part of the requirement string. Double quotes are the one form that survives zsh, bash, PowerShell and cmd alike.
The embeddings extra is not optional either, and that is deliberate. The headline risk in this release lives in embedding dimension resolution. A tester who installs without embeddings never reaches the code I most need exercised.
Why 4.0 and not 3.16
Because I numbered it wrong the first time, and a wrong version number is free to fix before a tag exists and expensive afterwards.
Back in July a change landed that makes an unrecognised embedding model fail loudly at startup instead of silently assuming 384 dimensions. I wrote about it at length in What's Landed Since 3.15.1 and I am not going to repeat the whole story here. The short version: a vector table is dimensioned once, at creation, so a silent guess got baked permanently into fresh databases and corrupted vector search for anyone running a model outside the built-in table.
That is a breaking change, and it was staged as 3.16.0. A MINOR is not what SemVer prescribes for a startup that used to work and now raises. Nothing had been tagged yet, so the correction cost nothing except saying it out loud: the unreleased line became 4.0.0. Our own release policy then requires a migration guide and at least one beta before any MAJOR ships, which is precisely why you are reading about a beta rather than a release.
You are affected only if both of these are true: you point
MNEMOSYNE_EMBEDDING_API_URL
at a custom embedding endpoint, and the model behind it is not in the
built-in table and you have not set
MNEMOSYNE_EMBEDDING_DIM.
Default model, any listed model, an explicit dimension already set, or
embeddings disabled entirely: none of those are touched. The full guide is
docs/migration-4.0.md
in the repository, and it opens with that same "am I affected" checklist so
you can stop reading in the first paragraph if the answer is no.
Multimodal is in the box, and it is switched off
Two weeks ago I wrote a post about teaching Mnemosyne to see that opened by telling you it was not live and not close, and that there was no version you could install to get it. That has changed faster than I expected. The stack is in 4.0.0b1.
remember_media(ref)
takes a reference to a piece of media, registers it, describes it through a
configured provider, and writes the description back as an ordinary memory
that hybrid recall already understands. Nothing about text recall changes.
The whole thing is additive: two sidecar tables created on first open, no
ALTER TABLE, no migration step, no new package dependency.
-
It is off unless you turn it on.
modality_enableddefaults to false and every endpoint and model key defaults to empty. An installation that does not opt in behaves exactly as it did before. -
The seam is named after the protocol,
not a vendor. The configuration keys say
MODALITY, and they point at any OpenAI-compatible endpoint. A second backend can be added later without inheriting the first one's name. -
Ingest tells you how far it got.
The call returns one of
ok,partial,unavailableorrefused, because the path degrades in stages and a caller needs to know which one it landed on.unavailableis a success: the asset is registered and can be described later, once a provider exists.
One trap I will save you an hour on.
On a fresh 4.0 install, setting
MNEMOSYNE_MODALITY_ENABLED=1
in your environment does nothing at all. The key is now seeded into the
generated config file, and a value present in that file wins over the
environment variable. The instruction that actually works is:
mnemosyne config set modality_enabled true
I know this because it cost me a full afternoon of CI failures that looked like broken code and were not.
What else is in the box
4.0 has been accumulating for a while, and the breaking change is the only part of it that asks anything of you. The rest is the ordinary work of the last few months. A few pieces worth knowing about:
-
Native MCP Streamable HTTP.
mnemosyne mcp --transport streamable-httpserves the modern MCP transport on one endpoint that handles GET, POST and DELETE, so clients post JSON-RPC straight to it with no separate messages route to proxy. Loopback binds need no token; anything else requires bearer auth and an explicit allowed-hosts list, because a non-loopback bind is exposing a local database to the network and should have to say so. - Canonical facts can be retired over MCP. A client can now remove a canonical slot from active recall while keeping it as history, instead of having no way to say "that used to be true."
-
The model cache has a home you
choose. The local GGUF was pinned to a fixed path under your home
directory, and the only escape from a small partition was a symlink.
MNEMOSYNE_MODEL_CACHE_DIRmoves it. An explicitly set path is authoritative: if it cannot be written, the download fails loudly rather than quietly reinstating the location you moved away from. -
Version reporting that does not boot the
world. Both CLIs answer
--versionwithout initializing any data, which matters when the thing you are debugging is why initialization fails. -
The wheel stopped shipping things that
were never yours. Installing used to place a top-level
examplespackage into your site-packages, where it could shadow anyone else's. The regression test now asserts the entire top-level surface rather than the specific directories that leaked, so the next one cannot slip through unnoticed. - Exports admit what they left out. A portable export now carries a completeness manifest, and import reports what the artifact actually contains instead of implying a lossless restore.
- Windows got real attention. Native virtualenv discovery, and a genuinely actionable message when Windows refuses symlink creation, instead of a raw error code and silence about how to proceed.
Very little of that list is mine alone. The breaking change at the centre of this release came from a community contributor, sharpened considerably in review, and the streamable transport landed alongside an issue and an implementation from someone who just wanted it to exist. Since Denis joined as second maintainer the review bar has been higher than I could hold on my own, and this release is visibly better for it.
What I am actually asking for
Not stars, and not downloads. Download counts on a pre-release tell me nothing except that pip works.
The evidence I need is narrow and specific: a real upgrade from 3.15.1, on a database you already care about, ideally on a non-default embedding dimension. That is the exact path the breaking change puts at risk, and it is the one path I cannot fully exercise alone, because my own databases were built by the person who wrote the guard.
Two or three of those, reported either way, are worth more than a thousand quiet installs. If it upgraded cleanly, say so. If the startup error caught you and the migration guide got you out of it without asking anyone, that is the single most useful report I can receive, because it tests the documentation and the guard at the same time. If it caught you and the guide did not help, that is a documentation bug and I want it filed.
Everything goes in one place: the 4.0 beta tracker .
Back up the database first, the way you would with any pre-release. The upgrade path is designed to be uneventful, but "designed to be" is the claim this beta exists to test.
The beta has an end date
The way a beta fails is not by going badly. It fails by never ending: a tag exists, it feels like progress, and nobody is ever asked to install it, so the thing sits in pre-release limbo for months while everyone waits for someone else to test it.
So this one has both a floor and a ceiling. The earliest I will consider promoting to 4.0.0 final is 7 September, because nothing before that is evidence of anything. The latest I will leave it undecided is 5 October. If that date arrives with no external upgrade reports, I will say that out loud rather than promote on silence, and then either ship it while stating plainly that the migration was never exercised by anyone but me, or re-announce once and reset the clock. Waiting quietly is not on the list.
Two corrections from the same fortnight
This website was publishing benchmark numbers that were not ours. The BEAM section carried three scores as Mnemosyne results. Only the first was. The other two belong to Hindsight, and Hindsight leads that benchmark as published, including at the scale where the one genuine number of ours sits. The mistake came out of a correction pass: an older run had covered three scales, three slots existed in the markup, the newer run only re-covered one, and the empty slots got filled from the wrong column of the baseline table. It looked researched, which is exactly why it survived as long as it did. It is fixed. Every number on the page is now attributed to whoever measured it, the only score presented as a Mnemosyne result is the one Mnemosyne actually produced, and any copy claiming we lead is gone.
And for about a day, CI stopped being able to verify anything. A test drives an authenticated event stream by hand, and it never sent the opening request message that the ASGI specification requires. That is our bug, and it had been there the whole time. It stayed invisible because the dependency answered without waiting for that message. A new release of that dependency started reading the request body to enforce a size limit, so the handler correctly blocked, the test wedged, and the job ran to its six-hour ceiling reporting nothing at all. Production was never affected, and I checked that over a real socket on both versions before saying so. The fix is written and landing as I post this: it delivers the message the specification asks for rather than pinning the dependency backwards, because pinning would have turned the build green while leaving our own contract violation in place.
Both of those are the same category of thing, and it is the category I find most worth writing about: a check that was reporting success while checking nothing.
Go break it
4.0 is the first major since the project became something other people depend on, and the whole difference between a good major and a bad one is whether the breaking change was found by the people who wrote it or by the people running it in production. Install the beta, upgrade something real, and tell me what happened.
