# Giving Claude Code a Memory That Survives Sessions (MCP + Hybrid Recall)

> Every new Claude Code session starts from zero. Zekra is an open-source memory service that any agent reaches over MCP: retain what matters, recall it next session, with citations. Setup takes five minutes.

*2026-10-21T07:01:59Z*

Claude Code memory doesn't survive the session: every new session I start knows nothing about the last one. Which branch we deploy from, why we picked Postgres over SQLite for this project, the flag that breaks the build on Windows: I either paste it into `CLAUDE.md`, or I explain it again.

`CLAUDE.md` is fine for rules. It is not fine for the hundreds of small facts a project collects in a month, and it doesn't travel: Codex, Cursor and Gemini each want their own file, and none of them can update it safely while you work.

So I built **Zekra**: a memory service that any agent reaches over **MCP**. The agent retains what it learns, and the next session (in the same tool or a different one) recalls it, with a citation to where it came from. I've used it every day for months. My own assistant, my product repos and my coding sessions all share it.

This post shows how to set it up in about five minutes, what actually happens when an agent remembers something, and where it is still rough. If you'd rather watch first, here is the [47-second demo](https://youtu.be/juky4ieH018).

## Five minutes to Claude Code memory that lasts

**1. Create an account and a brain.** Sign up at [app.zekra.dev](https://app.zekra.dev/register), open **Brains** and click **New brain**. Call it after your project, e.g. `my-project`. A brain is a namespace: one per project or team keeps memories from leaking between them.

**2. Get a token.** Open the brain, then **Sessions** → **Launch a session**. Leave write off if you only want the agent to read. Copy the `cbt_…` token. Treat it like a password.

**3. Install the CLI and connect your agent.**

```sh
curl -fsSL https://app.zekra.dev/install.sh | sh
zekra auth login --token cbt_...
zekra mcp:install claude-code --brain my-project
```

Swap `claude-code` for `claude-desktop`, `cursor`, `codex` or `gemini`. The installer merges a `zekra` entry into the client's MCP config and leaves your other servers alone. Restart the client.

**4. Try it.** Tell the agent:

> Remember that staging is Postgres 16 and deploys go out from the `release` branch.

It calls `memory_retain`. Open a **new** session and ask:

> Which branch do we deploy from?

It calls `memory_recall` and answers from the stored memory. You can check from the shell too:

```sh
zekra recall my-project "deploy branch"
```

## What happens when an agent remembers

Storing text is the easy part. The two hard parts are not filling memory with duplicates, and finding the right memory later.

**On write, Zekra decides instead of appending.** Each new memory goes through a write-decision step: **ADD** it, **UPDATE** an existing memory, **INVALIDATE** one it contradicts, or **NOOP** because it's already known. If you told the agent in June that staging is Postgres 15 and in October that it's 16, recall returns 16, and the old fact is still in history if you ask for it. Nothing is hard-deleted: `memory_forget` soft-invalidates. More on that in [stale memories: invalidate, supersede, decay](/en/blog/stale-memories-ai-agents-invalidate-supersede-decay).

**On read, it uses more than one signal.** Vector search is good when the wording changes; it's bad at exact things like an issue key, a package name or a flag. Zekra runs both:

- dense vectors (multilingual embeddings) for meaning,
- BM25 for exact terms,
- fused with reciprocal rank fusion, nudged by salience, reranked,
- then expanded one hop through the **entity graph**, so a memory about a repo can pull in the package it depends on.

Every result comes back with its source and time, so the agent (and you) can tell a fresh fact from an old note.

## More than a key-value store

A few things I ended up needing once more than one agent used it:

- **Brains and grants.** Each agent identity gets grants on specific brains, enforced on the server, not in the prompt. A session token only sees its own brain.
- **Data sources.** Connectors pull in markdown, a crawled site, a GitHub repo, a SQL query or a webhook, and push them through the same write pipeline. Your docs become recallable without anyone retaining them by hand.
- **Chat with a brain.** A tool-calling agent that uses the brain's own recall, search and graph as tools, and answers with citations plus a trace of what it looked up.
- **Knowledge gaps.** When recall comes back empty for something that should be known, it's logged, so you can see what your agents keep asking that nobody has written down.

## Under the hood

Zekra is a Go service built on [ToGO](https://to-go.dev). Storage is Postgres with pgvector, VectorChord and BM25, Redis as an L1 cache and an object store as the cold tier. Embeddings and reranking run on Text Embeddings Inference (Qwen3-Embedding-0.6B and bge-reranker-v2-m3), so Arabic and English memories are recalled from the same index. The MCP server is a thin adapter over the REST API, and there's a REST API and a TypeScript client if you'd rather call it directly.

## An honest note from running it

In September search on production went dark. Two bugs together: the hybrid query and its vector-only fallback shared one Postgres transaction, so when the hybrid failed the fallback failed with it, and the BM25 layer had never actually been provisioned in production. Recall had quietly been running on vectors alone. Both are fixed: each attempt now runs in its own read-only transaction, and BM25 was backfilled. The lesson for anyone building agent memory: **test that your fallback degrades instead of dying**, and check that every retrieval signal you think you have is really there.

## What it won't do (yet)

- **It doesn't make the agent remember on its own.** The agent has to call `retain` and `recall`. A line in `CLAUDE.md` ("recall before answering about this project; retain decisions") helps a lot. The capture hook can retain automatically from Claude Code.
- **Don't put secrets in memory.** Zekra has a separate secrets vault for that; memories are meant to be read back into prompts.
- **Memory is context, not authority.** If the live database says one thing and a memory says another, the database wins. Tell your agent that.
- **It's young.** The hosted service is run by one person (me). If you need it inside your own network, [self-hosting is documented](/en/blog/self-hosted-ai-agent-memory-server), but it needs Postgres with the vector and BM25 extensions plus an embeddings server.

New to the idea? Read [what an MCP memory server is](/en/blog/what-is-an-mcp-memory-server). Weighing options? See [Zekra compared with mem0, Zep, Letta, Basic Memory and OpenMemory](/en/blog/ai-agent-memory-compared-mem0-zep-letta-basic-memory).

## Try it

Zekra is open source under AGPL-3.0. Start with the [quickstart](/en/docs/quickstart), read the [MCP tool reference](/en/docs/mcp), or look at the code on [GitHub](https://github.com/fadymondy/zekra). If something breaks, open an issue. I read them.

- **Watch:** [Zekra in 47 seconds](https://youtu.be/juky4ieH018)
- **Ask:** [Zekra Discord](https://discord.gg/99JBJd6FsR)
- **Support the launch:** [Zekra on Product Hunt](https://www.producthunt.com/posts/zekra)
- **Start free:** [app.zekra.dev](https://app.zekra.dev/register)

---

Source: https://zekra.dev/en/blog/claude-code-memory-across-sessions-mcp
