
# MemPalace
Local-first AI memory. Verbatim storage, pluggable backend, 96.6% R@5 raw on LongMemEval — zero API calls.
[![][version-shield]][release-link]
[![][python-shield]][python-link]
[![][license-shield]][license-link]
[![][discord-shield]][discord-link]
> [!CAUTION]
> **Beware of impostor sites.** MemPalace has no other official websites. The **only** official sources are this **[GitHub repository](https://github.com/MemPalace/mempalace)**, the **[PyPI package](https://pypi.org/project/mempalace/)**, and the docs at **[mempalaceofficial.com](https://mempalaceofficial.com)**. Any other domain (including `.tech`, `.net`, or other `.com` variants) is an impostor and may distribute malware. Details and timeline: [docs/HISTORY.md](docs/HISTORY.md).
> [!IMPORTANT]
> **Claude Code sessions expire in 30 days without auto-save hooks wired.** [Read this →](https://github.com/MemPalace/mempalace/discussions/1388)
>
> Need the shortest recovery/setup path? Use the [Claude Code retention setup checklist](https://mempalaceofficial.com/guide/claude-code-retention.html).
---
## What it is
MemPalace stores your conversation history as verbatim text and retrieves
it with semantic search. It does not summarize, extract, or paraphrase.
The index is structured — people and projects become *wings*, topics
become *rooms*, and original content lives in *drawers* — so searches
can be scoped rather than run against a flat corpus.
The retrieval layer is pluggable. The current default is ChromaDB; the
interface is defined in [`mempalace/backends/base.py`](mempalace/backends/base.py)
and alternative backends can be dropped in without touching the rest of
the system.
Nothing leaves your machine unless you opt in.
Architecture, concepts, and mining flows:
[mempalaceofficial.com/concepts/the-palace](https://mempalaceofficial.com/concepts/the-palace.html).
---
## Install
MemPalace ships a CLI, so install it in an isolated environment to avoid
PEP 668 errors on Debian/Ubuntu/Homebrew Pythons and to keep mempalace's
deps (`chromadb`, `numpy`, `grpcio`, …) from conflicting with anything
else in your global site-packages.
We recommend [`uv`](https://docs.astral.sh/uv/) — `uv tool install` puts
the `mempalace` CLI in an isolated environment on your PATH:
```bash
uv tool install mempalace
mempalace init ~/projects/myapp
```
[`pipx`](https://pipx.pypa.io/) works the same way if you prefer it:
`pipx install mempalace`.
Prefer plain `pip` only inside an activated virtualenv where you
explicitly want `import mempalace` available:
```bash
python -m venv .venv && source .venv/bin/activate
pip install mempalace
```
### Docker
A container image is also available for running the MCP server or the CLI
without a local Python toolchain. Multi-arch (amd64 + arm64), so it runs
natively on Apple Silicon:
```bash
docker pull ghcr.io/mempalace/mempalace:latest
```
Everything persists under `/data` — palace, config, and the cached embedding
model — so mount a volume there and reuse it across runs:
```bash
# MCP server over stdio — note the `-i` flag (JSON-RPC needs stdin)
docker run -i --rm -v mempalace-data:/data ghcr.io/mempalace/mempalace
# Run any CLI command instead. The container only sees what you mount, so
# mount the directory you want to mine — read-only is enough, mining never
# writes to the source.
docker run --rm -v mempalace-data:/data -v /path/to/project:/work:ro \
ghcr.io/mempalace/mempalace mine /work
docker run --rm -v mempalace-data:/data ghcr.io/mempalace/mempalace search "why GraphQL"
```
The first command that needs embeddings downloads the model into `/data`
(~80 MB for the default `minilm`, ~300 MB for `embeddinggemma`). It is a
one-off as long as the volume persists, but it does mean the first call is
slow and needs network — worth knowing before assuming a hung container.
Wire it into an MCP client (e.g. Claude Code) as a stdio server. Mount
anything you want the server to be able to mine — it cannot reach your
transcripts otherwise:
```json
{
"mcpServers": {
"mempalace": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "mempalace-data:/data",
"-v", "/absolute/path/to/.claude/projects:/transcripts:ro",
"ghcr.io/mempalace/mempalace"
]
}
}
}
```
Use a real absolute path there — `~` and `$HOME` are not expanded by every
MCP client. Paths are container paths from then on: mine `/transcripts`, not
`~/.claude/projects`.
**Mount permissions on Linux.** The image runs as uid 1000 and bind mounts
keep their host ownership, so a mounted directory has to be readable by that
uid — an ordinary `0755` checkout is fine, a `0700` directory is not, and the
failure surfaces as `PermissionError: [Errno 13]` rather than anything about
Docker. Docker Desktop maps uids on macOS and Windows, so this only bites on
Linux. Do **not** work around it with `--user`: `/data` is owned by uid 1000
inside the image, so another uid cannot write the palace at all.
`docker compose run --rm mcp` works too (see `docker-compose.yml`), and
`deploy/docker-compose.server.yml` stands up the team server. To build the
image yourself instead of pulling — required for the GPU variant, which is not
published:
```bash
docker build -t mempalace . # CPU
docker build --build-arg EXTRAS="extract,spellcheck" -t mempalace .
docker build -f Dockerfile.gpu -t mempalace:gpu . # CUDA; run with --gpus all
```
The GPU image is x86_64-only: `onnxruntime-gpu` publishes no aarch64 Linux
wheels, so that last build fails on an ARM host (including Apple Silicon) with
a dependency-resolution error rather than an obvious one.
Note that a build from a clone uses whatever branch you checked out; `develop`
is the default branch, so pull the published image if you want the released
version.
## Storage backends
ChromaDB is the default and needs no configuration. MemPalace also ships a
pluggable backend contract, exercised across deliberately different substrates
so the contract is never accidentally shaped around one vendor. Every
non-default backend is opt-in.
| Backend | Mode | Install | Namespaces | Lexical | Configure with |
| ------- | ---- | ------- | :--------: | :-----: | -------------- |
| `chroma` _(default)_ | Local (embedded) | bundled | – | ✓ | – |
| `sqlite_exact` | Local (exact) | bundled | – | ✓ | – |
| `milvus` | Local (Lite) · Server opt-in | `mempalace[milvus]` | ✓ | ✓ | `MEMPALACE_MILVUS_URI` |
| `qdrant` | Server (REST) | bundled | ✓ | ✓ | `MEMPALACE_QDRANT_URL` |
| `pgvector` | Server (Postgres) | `mempalace[pgvector]` | ✓ | ✓ | `MEMPALACE_PGVECTOR_DSN` |
Select with `--backend