Skip to main content
Glama
README.md
# persistent-memory

**Give any AI agent a permanent memory.**

Most AI assistants forget everything the moment a conversation ends. This is the infrastructure that fixes that — a self-hostable memory layer any Claude (or other LLM) client can read from and write to, over the [Model Context Protocol](https://modelcontextprotocol.io). Your notes, decisions, and project state live in a Postgres + pgvector store, stay searchable by meaning (not just keywords), and mirror to plain Markdown files you own.

Built and used in production as the memory behind a personal knowledge vault. Extracted here as a clean, reusable starting point.

---

## What you get

| Piece | What it does |
|---|---|
| **MCP server** (`server/`) | A Cloudflare Worker exposing five tools — `search_vault`, `read_file`, `write_page`, `append_to_page`, `delete_page` — over MCP HTTP transport. Point any Claude client at it and the model gains long-term memory. |
| **Vector store** (`migrations/`) | Postgres schema for `pages` + `chunks` with `pgvector` (`halfvec`) embeddings and a `search_chunks` similarity RPC. Runs on any Postgres with the `vector` extension (Supabase, Neon, plain PG). |
| **Bulk embedder** (`src/embed.ts`) | Reads a folder of Markdown, chunks it (~500 tokens), embeds it, and upserts to the store. One command to load your whole knowledge base. |
| **File-sync mirror** (`src/sync.ts`) | Watches a local folder and keeps files ⇄ database in sync both ways, so you can edit in any editor and the memory stays current. |

## How it works

```
  Any LLM client ──MCP──▶  Worker (5 memory tools)  ──▶  Postgres + pgvector
        ▲                                                      │
        └───────────  semantic search results  ◀──────────────┘

  Your Markdown folder  ⇄  file-sync  ⇄  same database   (edit anywhere, stays in sync)
```

The database is the source of truth; the Markdown files are a backup mirror you can read, grep, and edit offline. Every write re-embeds only what changed, so ongoing cost is pennies.

## Quick start

1. **Provision a Postgres with pgvector** (Supabase is easiest — the `vector` extension is one click). Run the SQL in `migrations/` in order.
2. **Configure secrets** (never commit these):
   - `SUPABASE_URL` — set in `server/wrangler.toml` `[vars]` (replace `YOUR_SUPABASE_PROJECT_REF`)
   - `SUPABASE_SERVICE_ROLE_KEY`, `OPENAI_API_KEY`, `AUTH_TOKEN` — `wrangler secret put` each
3. **Bulk-load your notes:** `npm install && npm run embed`
4. **Deploy the memory server:** `cd server && npx wrangler deploy`
5. **Connect a client** — add the worker URL as an MCP connector. Auth is via URL path (`POST /mcp/<AUTH_TOKEN>`) because some clients don't send Bearer headers.

## Design notes

- **Embeddings:** OpenAI `text-embedding-3` by default; swap the provider in `src/embed.ts`.
- **Auth:** single shared `AUTH_TOKEN` in the URL path. For multi-tenant use, issue one token per agent and validate against a table.
- **Cost:** one-time bulk embed is a few dollars for a large vault; ongoing sync is pennies/day.

## How this pairs with Mothership long-session memory

These solve **different** amnesia problems:

| Problem | Layer | Where |
|---|---|---|
| “The chat forgot what we decided three hours ago when the window rolled over” | **Conversation continuity** — Persistent State ledger + verbatim tail + exact `recall` over the transcript archive | [Mothership](https://github.com/lennymadethat/mothership) (`docs/long-session-memory.md`) |
| “The model doesn’t know my projects, rules, or past work across *any* chat” | **Long-term knowledge** — searchable Markdown vault + embeddings | **This repo** |

Use both. Mothership keeps a *single long thread* coherent; persistent-memory keeps *your wiki* available to every agent. Neither should store secrets as pasted values — point at env files / secret stores.

See also [`docs/memory-layers.md`](docs/memory-layers.md).

## License

MIT — see [LICENSE](LICENSE). Use it, fork it, build your own memory on it.


---

<sub>Built by [lennymadethat](https://lennymadethat.com).</sub>