README.md

August 26, 2026 · View on GitHub

keepmind

Persistent memory for Claude Code — Windows-first, node-only, cloud-free.

keepmind is a node-only, RAM-lean fork of thedotmack/claude-mem (Apache-2.0). See NOTICE for attribution.

License Version Node

Quick StartTwo Kinds of MemoryLasting EntriesSearchOperating ItConfigurationLicense

keepmind keeps two things across sessions: what happened, captured automatically and summarised; and what was decided, written by a person and stored word for word. Both are searched together, and a result says which kind it is and whether it still applies.


What's different from claude-mem

This fork strips the cloud/SaaS layer and the Bun/Chroma runtime dependencies so it runs as a self-contained node process on Windows:

  • node-only — the bun:sqlite dependency is shimmed to node:sqlite; the worker runs under Node ≥ 22.5. No Python, no uv, no Chroma service.
  • In-process vector search@huggingface/transformers (int8 multilingual-e5-small, 384-dim) + sqlite-vec. Hybrid RRF (vector + BM25), fully offline, and multilingual by design: memories written in English stay findable in the language you actually ask in.
  • Cloud layer removed — Postgres, BullMQ, Redis and better-auth are gone. Observation generation and the MCP tool surface stay intact.
  • Windows-hardened lifecycle — ephemeral worker port (eliminates the fixed-port orphaned-socket deadlock), session-bound refcount, atomic BOM-free settings.
  • Secret-safe — prompts and tool content are redacted on the way OUT to the model, not merely on the way in to storage; project-scoped by default.
  • A curated corpus — decisions and open items a person wrote, stored verbatim and never shown to a model. This is the part claude-mem has no counterpart for; see Lasting entries.

Data lives under ~/.keepmind/ (keepmind.db + vector-db/vectors.db).


Quick Start

Run the interactive installer — this is the one required step:

npx keepmind@latest install

The installer registers the plugin with Claude Code, installs the runtime (worker, Bun, native deps), lets you pick your AI provider/model, and starts the worker. If an existing claude-mem install is found, it offers to migrate your memories and remove it.

⚠️ The /plugin install marketplace flow alone is NOT enough. It only copies the plugin files — it does not install the runtime or configure a provider, so no memory is ever captured. Whether or not you added the marketplace, you must run npx keepmind@latest install to complete setup.

Then restart Claude Code. Memory injection begins on your second session in a project — the first seeds the store, subsequent sessions receive auto-injected context.

Check status any time with npx keepmind status, or diagnose setup with npx keepmind doctor.

Requirements: Node ≥ 22.5. Bun is required to install and to build, never to run; the installer fetches it if missing.


Two kinds of memory

Memory holds two kinds of text, and keepmind never presents them alike.

ObservationsLasting entries
Written bythe model, from your sessiona person
Contenta summary of what happenedthe exact wording, stored verbatim
Read asan account, possibly imprecisecurrent, until something supersedes it
Ever sent to a provideryes, to be compressednever — the write path reaches no model

That last row is a property of the code path rather than a promise: curated entries go straight to SQLite and enqueue nothing, and two tests fail the moment either write path reaches for anything else.


Lasting entries

A lasting entry is a decision (0138) or an open work item (V-0001). They can be imported from a file archive or written directly, and both routes take the same write path.

npx keepmind curated:add --title "Reviews run before the merge, not after"
npx keepmind curated:edit 0138 --status "abgelöst"
npx keepmind curated:supersede 0138 0064     # declare and apply a supersession
npx keepmind curated:show 0064 --all         # every revision, oldest first
npx keepmind curated:import                  # the configured source directories
npx keepmind curated:verify                  # did the file corpus arrive complete?

What holds them together:

  • Nothing is deleted. An edit writes a new revision and closes the previous one's window. Exactly one revision is current at a time — a floor as well as a ceiling.
  • A retired entry is not a missing one. Look one up after it was superseded and you get it back, marked retired, with the record that replaced it. A supersession chain you cannot follow to its far end is half built.
  • Relations read from both ends. An edge is declared once, by one record — but the direction a reader cannot know to ask for is the incoming one, so 0064 says "superseded by 0137" even though only 0137 wrote anything down.
  • The corpus keeps itself current. The worker imports at startup and on a debounced watch of the source directories. An import that did not make its rows searchable has failed and exits non-zero — "imported" has to mean "findable".
  • Machines without the corpus stay quiet. Records held with unreachable sources warn once and never fail; a machine with neither says nothing at all.

Two reports ask "how much has happened since this was written", and assert nothing beyond arithmetic:

npx keepmind curated:alter               # decisions, most-overtaken first
npx keepmind curated:alter --vorgaenge   # open items — each claims something is still unresolved

Before a question is put to a person, keepmind offers decisions that may already answer it, rendering each record's own statement rather than its header line.


One query, both kinds of text, and the result tells you what you are looking at.

  • Hybrid — offline semantic (sqlite-vec) fused with keyword (SQLite FTS5/BM25) via RRF.
  • Origin is labelled — a lasting entry is never spelled like a session summary, and sourceKind: 'curated' searches only the verbatim side.
  • Validity is marked — a hit that has been superseded says so, and an earlier wording of a current entry says that instead. Marked, never filtered.
  • Exact wording wins — a record containing your sentence in that order goes to the top. It is a promotion, not a third opinion in the ranking.
  • German spellings are reconciled — the query is embedded the way the corpus actually spells the word, evidenced by the index's own vocabulary. A spelling that does not occur is never invented.

MCP tools (search, timeline, get_observations, curated_*, save_checkpoint, …) and the /mem-search skill query all of this in natural language — "did we already solve this?", "how did we do X last time?".


Operating it

npx keepmind doctor      # runtime, provider, worker, memory, curated corpus — add --json
npx keepmind metrics     # observer cost per day: billed tokens, tokens/turn, gated share
npx keepmind maintain    # reclaim what the vector store does not need — and show the answers did not move
npx keepmind export <dir>   # the whole memory as readable JSONL + a hashed manifest
npx keepmind import <dir>   # restore on another machine and rebuild the semantic index

Two of these are deliberately hard to fool. maintain makes two claims — it got smaller and it still answers the same — and exits non-zero if a probe's results move. export/import verify the manifest, row counts and hashes before the transaction opens, preserve primary keys, and report what dangles rather than dropping it; vectors are never in the bundle, because they belong to the embedder that produced them.

A web viewer runs at http://localhost:<worker-port> (the port is shown at session start; ephemeral by design), with a live memory stream and the context-injection settings.


Configuration

Settings live in ~/.keepmind/settings.json (auto-created with defaults on first run): AI model, worker port/host, data directory, log level, curated sources, and context-injection behaviour.

Environment variables use the canonical KEEPMIND_* prefix; the pre-2.0 CLAUDE_MEM_* names are still honored as a fallback. Examples:

KEEPMIND_DATA_DIR         # override the data directory (default ~/.keepmind)
KEEPMIND_WORKER_PORT      # pin the worker port (default: ephemeral)
KEEPMIND_LOG_LEVEL        # INFO | WARN | ERROR | DEBUG
KEEPMIND_CHROMA_ENABLED   # 'false' → SQLite/BM25-only search (disables the vector store)
KEEPMIND_CURATED_PROJECT  # where an unattended curated import files its records

curatedSources names the directories the curated import reads, each with a kind (akten / vorgaenge) and optionally its own project.


Migrating from claude-mem

If you have an existing claude-mem install, adopt its database losslessly:

npx keepmind migrate            # auto-detects ~/.claude-mem/claude-mem.db
npx keepmind migrate --from <dir-or-file>   # explicit source
npx keepmind migrate --dry-run  # preview counts only

Adopt copies the source read-only (VACUUM INTO) and brings the schema up to date; Merge (--from into an existing store) inserts only missing rows. The source is never modified. An existing ~/.keepmind/claude-mem.db is renamed to keepmind.db automatically on first worker start.


Development

npm run build            # sync manifests, build hooks + viewer, gen plugin lockfile
npm run build-and-sync   # build, sync to the installed marketplace, restart the worker
npm run typecheck        # tsc --noEmit, both projects
npm test                 # the full suite

Source in src/, built plugin in plugin/, installed copy under ~/.claude/plugins/marketplaces/keepmind/. CLAUDE.md carries the invariants — each one paid for by a measured regression — and is the file to read before changing the observer, the curated path or search.


License

Apache-2.0. keepmind is a derivative work of thedotmack/claude-mem (Copyright Alex Newman), used under the Apache License 2.0. Fork copyright © 2026 Manuel Staggl. See LICENSE and NOTICE.