What changes once it is connected
The agent stops living inside a single chat. Decisions, lessons and preferences survive
/clear, survive the week-end, and β most importantly β survive the
jump to your next project.
Memory across sessions
Clear the chat, come back tomorrow β the agent recalls what was decided and why, from a database, not from scrollback.
Experience transfer
Start a new project and the server answers "where have I seen this before?" β similar past projects arrive with their lessons, so old mistakes are not repeated.
Search by meaning
A multilingual embedding model (e5) runs in-process. A question in Russian finds a lesson written in English. No keywords, no exact phrasing.
Self-cleaning
Near-duplicates are refused, short-lived events expire, stale records get nominated for review. Durable knowledge is never deleted without your confirmation.
Knowledge graph
Directed, typed links between projects β uses, depends_on, implementsβ¦ Symmetric "related" is never stored: vector similarity derives it on the fly.
Yours, locally
One SQLite file in your home directory by default. No accounts, no cloud, no telemetry. When you outgrow one machine β the same server speaks PostgreSQL.
Quick start
Install
Needs the .NET 10 SDK. This puts the snail-mcp-memory command on your PATH (~/.dotnet/tools β the .NET installer takes care of it):
dotnet tool install --global Snail.MCP.Memory --prerelease
Alternative, no install: the SDK ships the dnx runner β dnx Snail.MCP.Memory --yes --prerelease fetches the package from NuGet on first use, caches it and runs it.
Connect it to your client
For Claude Code, one command; other clients are a few lines of JSON β see Clients.
claude mcp add mem0 --scope user -- snail-mcp-memory
Use it
In your next session, just say:
The agent registers the project, and if memory already knows similar work, the reply carries a briefing: which past projects look alike and which of their lessons apply here. From then on the agent saves decisions as you work and recalls them when they matter.
~/.snail-mcp-memory/models/. Until it arrives β or on machines where it
never can β everything still works, with text search instead of semantic search.
Connecting to a client
The server speaks stdio: every client config boils down to "run snail-mcp-memory" (or dnx Snail.MCP.Memory --yes --prerelease to skip installation). The examples register it as mem0 β the slash commands in the repo pre-approve tools under that name. Zero configuration required β settings only change the defaults.
Claude Code β .mcp.json
{
"mcpServers": {
"mem0": {
"command": "snail-mcp-memory"
}
}
}
Running through dnx instead: "command": "dnx", "args": ["Snail.MCP.Memory", "--yes", "--prerelease"].
Claude Desktop
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Β·
Windows: %APPDATA%\Claude\claude_desktop_config.json β same JSON as above.
If the command is not found, use the full path /Users/<you>/.dotnet/tools/snail-mcp-memory.
VS Code β .vscode/mcp.json
{
"servers": {
"mem0": {
"type": "stdio",
"command": "snail-mcp-memory"
}
}
}
Configuration
Every setting is an optional environment variable. This example lists all of them with their defaults β copy it and keep only the lines you change:
{
"mcpServers": {
"mem0": {
"command": "snail-mcp-memory",
"env": {
"SNAIL_MCP_MEMORY_PROVIDER": "Sqlite",
"SNAIL_MCP_MEMORY_DIRECTORY": "~/.snail-mcp-memory",
"SNAIL_MCP_MEMORY_CONNECTION_STRING": "",
"SNAIL_MCP_MEMORY_WORKSPACE": "",
"SNAIL_MCP_MEMORY_EMBEDDING_ENABLED": "true",
"SNAIL_MCP_MEMORY_EMBEDDING_MODEL_PATH": "~/.snail-mcp-memory/models/model.onnx",
"SNAIL_MCP_MEMORY_EMBEDDING_TOKENIZER_PATH": "~/.snail-mcp-memory/models/sentencepiece.bpe.model",
"SNAIL_MCP_MEMORY_EMBEDDING_MODEL_URL": "https://huggingface.co/Xenova/multilingual-e5-small/resolve/main/onnx/model_quantized.onnx",
"SNAIL_MCP_MEMORY_EMBEDDING_TOKENIZER_URL": "https://huggingface.co/intfloat/multilingual-e5-small/resolve/main/sentencepiece.bpe.model",
"SNAIL_MCP_MEMORY_EMBEDDING_DIMENSIONS": "384",
"SNAIL_MCP_MEMORY_DUPLICATE_THRESHOLD": "0.95",
"SNAIL_MCP_MEMORY_SIMILARITY_FLOOR": "0.75",
"SNAIL_MCP_MEMORY_IDLE_TIMEOUT_MINUTES": "60"
}
}
}
}
The same keys β bare names, without the prefix β can live in a JSON file instead:
~/.snail-mcp-memory.json (also read: the path in
SNAIL_MCP_MEMORY_CONFIG, ./.snail-mcp-memory.json,
./snail-mcp-memory.json, ~/.config/snail-mcp-memory/config.json).
Environment variables win over the file.
| Setting | Default | Meaning |
|---|---|---|
PROVIDER | Sqlite | Sqlite β single local file with sqlite-vec; Postgres β server database with pgvector |
DIRECTORY | ~/.snail-mcp-memory | where the database and the models live; understands a leading ~ |
CONNECTION_STRING | β | SQLite: a file path or Data Source=β¦ (default {Directory}/memory.db). PostgreSQL: the full connection string, required |
WORKSPACE | (empty) | partition of a shared database: writes are tagged with it, reads see only it; empty β the whole base |
EMBEDDING_ENABLED | true | false turns semantic search off; recall falls back to text matching |
EMBEDDING_MODEL_PATH | {Directory}/models/β¦ | where the ONNX model lives; downloaded on first use |
EMBEDDING_TOKENIZER_PATH | {Directory}/models/β¦ | where the SentencePiece tokenizer lives; downloaded on first use |
EMBEDDING_MODEL_URL / β¦_TOKENIZER_URL | e5-small | download sources for a missing model (default: multilingual-e5-small, int8) |
EMBEDDING_DIMENSIONS | 384 | vector length of the configured model β change only together with the model |
DUPLICATE_THRESHOLD | 0.95 | similarity above which remember refuses a near-duplicate and offers supersession |
SIMILARITY_FLOOR | 0.75 | similarity below which a search hit is dropped; raise to ~0.8 if recall feels noisy |
IDLE_TIMEOUT_MINUTES | 60 | minutes without a tool call before an orphaned server process shuts itself down |
PostgreSQL
For a shared or backed-up memory, point the server at PostgreSQL with the pgvector extension (the pgvector/pgvector Docker images ship it). Nothing else changes β same tools, same behavior:
"SNAIL_MCP_MEMORY_PROVIDER": "Postgres", "SNAIL_MCP_MEMORY_CONNECTION_STRING": "Host=db.example.com;Database=memory;Username=snail;Password=β¦"
What the agent can do with it
You normally never call these yourself β the agent does, guided by instructions the server ships inside the protocol itself. Knowing them helps you phrase requests.
Every record carries a kind; the vocabulary is open, the core carries semantics:
| Tool | What it does |
|---|---|
init_project_memory | registers a project and returns the experience briefing; description finds similar past projects, seedFrom preloads named donors |
remember | stores one typed record; refuses a near-duplicate (supersede with replaceId, keep both with force) |
recall | semantic search; empty project β the whole memory (that is how experience crosses projects), empty query β an overview of the newest records |
forget | deletes records by id, several ids comma-separated |
review_memory | nominates stale records for deletion; the deletion itself stays a confirmed forget |
list_projects | the projects that have memory, optionally narrowed by a name prefix |
rename_project | renames a project everywhere: registry, records, edges |
link_projects | a directed, typed edge: uses, depends_on, design_of, part_of, implements, documents |
unlink_projects | removes the edges of a project pair |
get_graph | the edges around a project, depth 1β5, without loading records |
Integration: copy two things from the repo
The protocol carries the tool descriptions β enough for basic use. The full integration is two files you copy yourself from the git repository into your agent's setup; nothing is installed automatically:
1. Slash commands. .claude/commands/ holds
mem0-init, mem0-recall,
mem0-remember, mem0-link,
mem0-graph, mem0-list β manual one-shot
shortcuts with the mem0 tools pre-approved, so they run without
permission prompts:
cp .claude/commands/mem0-*.md ~/.claude/commands/
Registered the server under another name? Adjust the mcp__mem0__
prefix inside the files.
2. Memory rules. server-instructions.md at the repo
root is the full instruction set β the kind vocabulary, when to save unprompted, when to search
before proposing, how to self-heal wrong records. Paste its content into your agent's instruction
file β ~/.claude/CLAUDE.md for Claude Code, or the system prompt of a
custom agent. The agent works without it, but with it the memory maintains itself.
Good to know
| π Language | record content is stored in the language of your conversation; the model is multilingual, so search works across languages |
| βοΈ Offline | after the one-time model download the server needs no network at all |
| β³ Lifecycle | event records expire after 90 days; durable kinds are only deleted by an explicit, confirmed forget |
| π§― Housekeeping | an orphaned server process shuts itself down after an hour of silence (IDLE_TIMEOUT_MINUTES) |
| ποΈ Your data | one SQLite file at ~/.snail-mcp-memory/memory.db, inspectable with any SQLite browser |