We benchmarked our own memory library before writing the pitch for it.

Ask most memory systems "where does the user work" after a conversation where they've mentioned three different employers, and you'll get back whichever one happens to rank highest by cosine similarity, not necessarily the current one. Nothing in a plain vector-store-plus-top-K setup tracks that a fact went stale. It just retrieves the nearest neighbor and calls it an answer.

That's the actual hard part above vector search, and vector search itself stopped being a gap a while ago: sqlite-vec, LanceDB, and Chroma all do embeddable, in-process, mature, free vector indexing. What's missing is the layer that decides what's worth storing, notices when a new fact contradicts an old one, and gets the current answer back instead of just the nearest one. Purpose-built frameworks do that work (Mem0, Cognee, Zep, Letta), but every one of them wants a hosted account or a stack behind it: Mem0 self-hosted is Postgres plus a vector store plus optionally Neo4j, with no authentication on by default. That's a lot of infrastructure for a project that might have a handful of users.

The numbers

We built jottermem to close that gap without the infrastructure, and instead of just asserting it works, we measured it against a naive top-K baseline, same embedder on both sides, so the only variable is the memory-layer logic.

On a synthetic scenario built to isolate the staleness failure mode (three facts that each change over a short conversation), naive top-K got the current value right 0 out of 3 times. jottermem got 3 out of 3.

On LoCoMo, a published long-term-conversational-memory benchmark with 795 single-hop questions over a real 5,882-turn dataset, jottermem roughly doubled naive top-K's retrieval accuracy at every k we measured: 8.8% to 17.2% at k=1, up to 24.9% to 37.7% at k=10.

What it actually is

One SQLite file. No server, no account, no Docker.

from jottermem import Memory

mem = Memory("agent.db")

mem.remember("The user's favorite color is blue.")
mem.remember("The user works as a software engineer.")

for result in mem.recall("What color does the user like?", k=3):
    print(result.score, result.memory.text)

The default embedder and extractor are pure Python, so pip install jottermem pulls in zero third-party dependencies and still gives you working remember()/recall() immediately. Facts that change over time get a stable key instead of piling up as equally-confident contradictions:

mem.remember("Works at Acme Corp.", key="employer")
mem.remember("Works at Globex.", key="employer")

mem.list_memories()  # -> just "Works at Globex."

A near-duplicate fact gets deduped against what's already there, and once brute-force cosine scanning stops being fast enough, pip install jottermem[sqlite-vec] accelerates it transparently. Auto-detected, never required.

Who this is for

The people who run into this problem are usually building alone or on a small team: an indie hacker whose companion app needs to remember what a user said last week, without turning a side project into a Postgres-plus-vector-plus-Neo4j operation. A two-to-ten-person startup shipping a personalized feature, where memory quality matters but a stateful ops burden this early doesn't. A solo developer who wants to find out whether memory actually improves their product before committing to any infrastructure at all. An OSS agent-framework maintainer who wants a default memory backend to recommend that doesn't force their users into an account or a stack.

What they have in common is a size of problem, not a lack of ambition: real memory-quality needs, at a scale where a hosted platform or a Docker Compose file is a worse trade than the thing it's solving. If you're past that (multi-tenant, distributed, millions of users, a real entity graph), that's Mem0 Platform or Cognee's territory, and they're good at it. jottermem doesn't try to compete there; it's the right-sized tool for the far more common case that comes before it.

A portable memory folder, too

The engine above is built for a developer embedding memory into their own app. There's a separate, plainer layer on top for anyone who just wants Claude, ChatGPT, or another assistant to remember the same things about them across tools, without hosting anything or reading a line of code.

pip install "jottermem[mcp]"
jottermem-setup

The wizard asks whether your memory folder should live locally or inside your own Google Drive, creates it, and writes ready-to-use connection config for Claude Desktop and Claude Code. Every file it writes is plain markdown, one per topic, readable and editable in any text editor. There's also jottermem-app, a small local browser view for seeing, adding, editing, or deleting what's stored, with no setup beyond having jottermem installed.

One honest limitation. ChatGPT's custom connectors only accept a remote server reachable over HTTPS, not a local process, so this doesn't work with ChatGPT yet. That path needs a small hosted relay that talks to Google Drive on your behalf, and the code for it is written and tested in the repo, but it isn't deployed. Standing it up means registering a Google Cloud OAuth app and running a live service under that identity, and that's a bigger commitment than this project has earned yet. So for now: Claude and any other MCP-aware assistant, yes. ChatGPT, not yet.

Details and the full product plan are in jottermem-prd.md in the repo.

Try it

pip install jottermem

It's early: pre-alpha, but functional end-to-end. The benchmarks are in the repo, not just this post; run them yourself before taking our word for any of it.