Skip to main content
memloom is a local-first memory engine for AI agents: one Postgres-native store on your machine, shared by every client. That means the CLI, MCP (Claude Desktop, Claude Code, Cursor, etc.), a browser viewer, and plain HTTP. This page gets you running. If you want to understand how the engine actually works, start with Features, then the concept pages: Architecture, Memory types & versioning, Conflicts, The graph, and Retrieval. For the command and tool surfaces, see the CLI Reference and the MCP Reference tabs.

Quickstart

Prefer to delegate? An AI agent can run this whole setup from one pasted prompt: see Agent setup. Requires Node 20 or later. Check with node -v.
If memloom is not found after installing, your Node is probably too old: npm skips a package whose engines it cannot satisfy, so nothing gets linked onto your PATH. Run node -v, upgrade to Node 20 or later, then install again.
init prints the path to config.env. To switch from offline mode to real embeddings, semantic dedup, and contradiction detection: set OPENROUTER_API_KEY there, then
The reembed step matters: offline and cloud vectors live in different spaces, and the daemon refuses to start on a store whose vectors do not match its config (see the note below).

Memory types

Every saved memory has a memoryType: the same taxonomy across every client, so a memory means the same thing whether the CLI, MCP, or a raw HTTP call wrote it. Pass it on save (defaults to fact): Recall results for ingested context chunks aren’t saved memories: they carry the sentinel type context, and their kind field is context rather than memory.

Context: bring your files

Files are chunked structure-aware, embedded, and fused into the same recall as memories. Markdown splits at headings; plain text and PDFs split along their outline: ALL-CAPS title lines and numbered points (2. DEFINITION. …). One point per chunk, so a chunk is exactly one definition, theorem, or exercise. Each chunk carries its breadcrumb and PDFs keep page numbers, so results from files always say where they came from: from lecture-notes.pdf › LIMITS OF FUNCTIONS > 2. DEFINITION (p. 1). PDF text is rebuilt from glyph geometry rather than stream order, so equation-heavy PDFs (Word/LaTeX math) come out in reading order, and 2-up print layouts (the same content twice, side by side) are de-duplicated. Symbols from unmapped fonts (∞, ∈, ≠) can’t be recovered from the text layer; that would need OCR, which is out of scope. Documents are mirrors: re-adding an unchanged file is a no-op, a changed file replaces its chunks. When memloom’s extraction pipeline improves, the pipeline version bumps and context add re-ingests files whose bytes didn’t change. memloom context list / memloom context remove <id> manage them. Context joins the graph too: memloom index extracts entities from chunks as well as memories, so documents appear in the viewer’s graph connected to your memories through the entities they share. Recall’s entity arm can surface document sections by entity as well as by wording. The graph shows one node per document (chunk-level mentions roll up into a weighted document → entity edge), so a 300-page PDF stays one node.

The daemon

memloom serve is the single owner of the store. Everything else is a client: Any CLI command auto-starts the daemon if it isn’t running. Stop it cleanly with memloom stop.
The Postgres wire pauses the API. PGLite is a single-connection database: while a DB client (Drizzle Studio, psql, an IDE database panel) is connected on port 54329, it holds an exclusive lock. Memory endpoints detect this and answer 503 “store is locked by a connected Postgres wire client” instead of hanging; the serve terminal also warns when a wire client connects. Disconnect the DB client to resume.

Configuration

~/.memloom/config.env, dotenv-style. Real environment variables win over the file.
Offline and cloud embeddings live in different vector spaces. If you switch modes, run memloom reembed (daemon stopped) to recompute every vector with the new provider; mixed embeddings make similarity meaningless, so the daemon refuses to start until the store matches the config.

Testing the API by hand

With the daemon running, curl any endpoint from your own machine:
The serve terminal logs every request twice: on arrival and with status + duration on completion. A locked store answers 503 within ~1.5s (see the warning above); a stalled provider call times out after 60s with the provider’s error in the response. Every endpoint is documented in the API Reference tab. The daemon only accepts browser requests from localhost origins by design, so test against it with curl or your own local tools rather than from a hosted page.