Brain-inspired memory engine for your self-hosted AI stack. Runs on a Pi. Local-first with optional API-key auth.
Project description
🧠 Mnémlet
Mnémlet is for people who don't want Mem0. Not because Mem0 is bad software — it's excellent. But because you want your AI's memory to live on your own hardware, not someone else's cloud. You want a system that forgets what doesn't matter instead of hoarding everything forever. You want to open a file on disk and see what your agent actually knows about you. You want zero API bills and full control.
This is a values choice, not a feature checklist. If that resonates, welcome.
Built for r/selfhosted and r/LocalLLaMA — people running AI on Pis, homelabs, old laptops, and local servers.
Pronounced
/ˈnɛm.lɛt/("NEM-let") — from Greek mnēmē (memory) + -let (diminutive: small). The CLI command ismnemlet(ASCII), the project name is Mnémlet.
What Mnémlet Does
Mnémlet is a self-hosted memory engine for AI agents. It learns what matters, forgets the rest, and consolidates knowledge while you sleep — all on hardware you control.
- 🧠 Exponential decay + interaction-weighting — Memories you recall and update stay sharp. What you ignore fades. No infinite hoarding.
- 😴 Sleep Engine — Nightly consolidation runs while you're away: deduplicate, rescore stale memories, cluster related knowledge, and generate a morning briefing. Like your brain during REM sleep.
- 🔌 MCP-native with 14 tools —
mnemlet_ingest/mnemlet_recall/mnemlet_searchfor the basics,mnemlet_context/mnemlet_explainfor context packs with provenance,mnemlet_remember/mnemlet_forget/mnemlet_replace/mnemlet_confirmfor memory review, plusmnemlet_status/mnemlet_namespaces/mnemlet_update/mnemlet_decay_config/mnemlet_exportfor admin. Works with OpenWebUI, OpenClaw, Claude Code, Cursor, or any MCP client. - 🛡️ v0.3 Trust / Security / Privacy — API-key auth, Secret Guard write protection, sanitized Audit logs, namespace trust policies, and backup/restore for local-first operators.
- 📂 Inspectable Markdown vault — Every memory as a
.mdfile with YAML frontmatter. Open in Obsidian.grepit.gitit. No black box database lock-in. - 🤖 Optional local LLM — Plug in Gemma3:4b via Ollama. Runs CPU-only on a Pi. Enhances sleep consolidation (contradiction detection, summarization).
- 🔍 Hybrid search — BM25 (SQLite FTS5) + vector similarity (ChromaDB). Both local, both free.
- 🥧 Pi-ready — 450 MB RAM baseline, ~4 GB with LLM. Runs on a Raspberry Pi 5 (16 GB recommended for the full stack).
- 💰 Zero API costs — Local ONNX embeddings (all-MiniLM-L6-v2). No OpenAI key, no cloud embedding service, no per-call charges. SearXNG optionally self-hosted for web enrichment.
- 🐍 Python SDK, REST API, CLI — install from the GitHub tag for now, then
mnemlet serve. PyPI follows after final release approval.
Honest Comparison
No checkmark bingo. Here's where Mnémlet shines, and where it doesn't.
| Mnémlet | Mem0 | MemPalace | Engram | NeoCortex | |
|---|---|---|---|---|---|
| Self-hosted | ✅ | ⚠️ (platform) | ✅ | ✅ | ❌ (API-only) |
| Decay / Forgetting | ✅ (deep) | ❌ | ❌ | ❌ | ✅ |
| Sleep / Consolidation | ✅ | ❌ | ❌ | ❌ | ❌ |
| Local LLM support | ✅ | ❌ | ❌ | ❌ | ❌ |
| Vector search | ✅ | ✅ | ✅ | ❌ (FTS5 only) | ✅ |
| Inspectable vault | ✅ (Markdown) | ❌ | ❌ | ⚠️ (beta) | ❌ |
| TUI Dashboard | ❌ | ❌ | ❌ | ✅ | ❌ |
| Cloud sync | ❌ | ✅ | ❌ | ✅ | ✅ |
| MCP tools | 14 | ~10 | 29 | 19 | ❌ (API) |
| Language | Python | Python | Python | Go | HTTP API |
| License | MIT | Apache 2.0 | MIT | MIT | MIT |
| Pi-friendly RAM | ✅ (450 MB) | ❌ | ✅ | ✅ | ❌ |
If your priority is cloud sync, a polished dashboard, or an ecosystem with 50k stars — use Mem0 or MemPalace. They're great at those things.
If your priority is local-first, brain-inspired forgetting, sleep consolidation, and running on hardware you own — that's the gap Mnémlet fills.
Quickstart
Install
pip install git+https://github.com/christoph/mnemlet.git
PyPI release follows after final v0.3 release approval.
Start the server
For local development you can run without a key while bound to localhost:
mnemlet serve
# → http://localhost:4050
Do not expose a no-key server beyond your own machine.
Recommended setup for daily use:
mnemlet auth generate-key
export MNEMLET_API_KEY="mnemlet_..."
mnemlet serve
Store your first memory
curl -X POST http://localhost:4050/api/v1/ingest \
-H 'Content-Type: application/json' \
-H "X-Mnemlet-Key: $MNEMLET_API_KEY" \
-d '{"content":"I prefer dark mode in all editors","namespace":"preferences","importance":0.9}'
Retrieve it
curl -X POST http://localhost:4050/api/v1/recall \
-H 'Content-Type: application/json' \
-H "X-Mnemlet-Key: $MNEMLET_API_KEY" \
-d '{"query":"editor preferences","namespace":"preferences"}'
Python SDK
Python SDK example is for localhost no-key development only. Authenticated server mode currently needs REST or MCP with X-Mnemlet-Key. SDK auth support has not landed yet.
from mnemlet.client import MnemletClient
c = MnemletClient()
c.ingest("Hello world")
results = c.recall("Hello")
print(results)
Connect your agents
Add to any MCP client config:
{"mcpServers": {"mnemlet": {"url": "http://localhost:4050/mcp", "headers": {"X-Mnemlet-Key": "mnemlet_..."}}}}
OpenWebUI and OpenCode should pass the same token as X-Mnemlet-Key when connecting to REST or MCP. Prefer an environment variable such as MNEMLET_API_KEY in the client process or secret store; do not paste real tokens into public configs, screenshots, or issue reports.
Backup and restore
mnemlet backup --output ~/mnemlet-backups
mnemlet restore --input ~/mnemlet-backups/mnemlet-backup-...tar.gz --yes
Backups include the Markdown vault, SQLite database, Chroma data, and redacted configuration metadata. Stop your server or ensure it is idle before restoring.
Benchmarks
Mnémlet includes a reproducible public benchmark suite with synthetic, commit-safe memory cases.
Run it locally:
mnemlet benchmark quick --dataset public --output benchmark-results/latest --format json,md,csv
The report includes hit@K, MRR, precision@K, false-positive rate, forbidden-hit rate, and latency percentiles. Public claims should cite the dataset, command, environment, and generated report.
Private real-world benchmarks can be stored under benchmarks/private/, which is ignored by git.
How It Works
The Brain Model
Every memory has a retention_score (0.0–1.0) that follows exponential decay:
score(t) = score₀ × e^(-λ × t)
| Memory type | λ value | Half-life |
|---|---|---|
| Preferences / identity | 0.001 | ~2 years |
| Project knowledge | 0.01 | ~69 days |
| Daily chat context | 0.05 | ~14 days |
| Transient / ephemeral | 0.5 | ~1.4 days |
Interactions boost retention: recall +0.15, update +0.20, create +0.10, reference +0.08.
What this means in practice:
Your agent remembers that you prefer dark mode and use Python → these facts have high retention, decaying slowly (~2 year half-life). They stay sharp across months of sessions without you ever re-stating them.
Your agent quickly forgets that you asked about today's weather or checked a one-off API syntax → these are transient memories that fade within days (~1.4 day half-life). You never have to manually "clean up" stale context.
When a preference changes — you switch from tabs to spaces — the new memory gets a +0.20 update boost, while the old one decays below threshold and moves to cold storage. The system self-corrects.
When scores fall below configurable thresholds, memories move to cold storage or get purged.
The Sleep Engine
After 2 hours of inactivity, Mnémlet enters consolidation. Tasks run sequentially, locally, with zero API costs:
- Dedup — Merge near-duplicate memories created today
- Rescore — Apply time-decay and purge stale memories below threshold
- Cluster — Group semantically similar memories by namespace
- Briefing — Generate a morning context summary for the next session
You can trigger sleep manually via /api/v1/sleep/start or check status via /api/v1/sleep/status.
Inspectable Vault
~/.mnemlet/vault/
preferences/
2026-05/
a1b2c3d4.md ← Open in Obsidian!
projects/
mirofish/
2026-05/
e5f6g7h8.md
Every memory is a Markdown file with YAML frontmatter. You can read, edit, version-control, or delete memories with any text editor. No black box.
API Reference
| Endpoint | Method | Description |
|---|---|---|
/api/v1/health |
GET | Health check |
/api/v1/status |
GET | Memory counts, storage stats, decay info |
/api/v1/vault |
GET | Vault path and file count |
/api/v1/ingest |
POST | Store a memory |
/api/v1/recall |
POST | Retrieve relevant memories |
/api/v1/context |
POST | Build a context pack with abstention reasons |
/api/v1/remember |
POST | Store an intelligence memory with classifier policies |
/api/v1/forget/{memory_id} |
POST | Soft-forget a memory |
/api/v1/replace/{memory_id} |
POST | Replace memory content (preserves provenance) |
/api/v1/confirm/{memory_id} |
POST | Confirm a memory (retention boost) |
/api/v1/explain/{memory_id} |
GET | Explain a memory's provenance and status |
/api/v1/decay/run |
POST | Manual decay run + purge |
/api/v1/namespaces/{namespace}/decay |
GET/PUT | Per-namespace decay configuration |
/api/v1/sleep/status |
GET | Sleep engine state |
/api/v1/sleep/start |
POST | Start sleep cycle manually |
/api/v1/sleep/stop |
POST | Stop sleep cycle gracefully |
/mcp |
SSE | MCP server endpoint (14 tools) |
Configuration
# mnemlet.toml
[server]
host = "127.0.0.1"
port = 4050
[storage]
data_dir = "~/.mnemlet"
[llm]
enabled = false # Enable for Gemma3:4b via Ollama
provider = "ollama"
model = "gemma3:4b"
[search]
enabled = false # Enable for SearXNG web enrichment
provider = "searxng"
base_url = "http://localhost:8888"
Raspberry Pi
Mnémlet runs on a Raspberry Pi 5. The 16 GB model is recommended if you're running Ollama alongside it.
| Mode | RAM usage |
|---|---|
| Base (no LLM, no search) | ~450 MB |
| + SearXNG | ~650 MB |
| + Gemma3:4b (Ollama) | ~4 GB total |
This is the actual stack I run: Mnémlet + OpenWebUI + OpenCode + OpenClaw on two Pi 5s in my homelab.
Why I Built This
I wanted my AI agents to remember context between sessions — my preferences, project details, ongoing conversations. Existing options required cloud accounts, per-request pricing, or opaque storage. I couldn't open a database and see what the system actually knew about me.
So I built something that runs on hardware I own, stores memories as files I can read, and respects the fact that not everything is worth remembering forever.
What Mnémlet Is NOT
- Not a Mem0 competitor for enterprise teams. This is a solo tool, built for solo setups. It has single-key local auth, not multi-tenancy, a cloud offering, or VC funding behind it.
- Not a cloud service. There is no
app.mnemlet.ai. There never will be. If you want managed hosting, look at Mem0. - Not a production database. It's AA-battery-grade infrastructure — simple, local, sufficient for one person's context. Don't use it to store customer PII or medical records.
- Not a replacement for your notes app. The Markdown vault is inspectable, but it's not designed for manual note-taking. Use Obsidian for that. Use Mnémlet for agent memory.
FAQ
Why not just use Mem0 self-hosted? Mem0 is excellent. But its memory management uses LLM extraction — which costs tokens and discards raw context. Mnémlet stores verbatim content, applies brain-inspired decay without LLM calls, and surfaces a human-readable Markdown vault. The Sleep Engine runs on a Pi with zero API costs. If you want managed, production-grade memory with cloud features → Mem0. If you want local, transparent, brain-inspired memory that forgets naturally → Mnémlet.
Can I use Ollama running on a different host?
Yes. Set [llm] in mnemlet.toml: base_url = "http://192.168.1.100:11434". Mnémlet talks to any OpenAI-compatible API, including remote Ollama, LM Studio, or cloud endpoints. Local is just the default.
What happens to my memories when I update Mnémlet?
The Markdown vault is forward-compatible — .md files don't change format. SQLite migrations run automatically on startup. Internal schema changes are additive (new columns, new tables). If you're paranoid, back up ~/.mnemlet/ before upgrading.
Can I isolate memories between different AI agents?
Yes, via namespaces: /openwebui/christoph/, /openclaw/christoph/, /shared/. BUT — this is organizational isolation, not security isolation. Any MCP client with access to localhost:4050 can read all namespaces. If you need hard isolation, run separate Mnémlet instances on different ports. See SECURITY.md.
How do I uninstall Mnémlet cleanly?
pip uninstall mnemlet
rm -rf ~/.mnemlet
That's it. No system files, no daemons, no databases left behind. We respect your machine.
Maintainer Statement
I maintain this because I use it daily. It powers my homelab AI stack — OpenWebUI, OpenCode, and OpenClaw on two Raspberry Pi 5s. It lives as long as I use it. Bug reports and pull requests are welcome, but set expectations accordingly: this is a solo-dev, dogfooded project.
Roadmap
Honest forward look in ROADMAP.md. Short version: v0.3 adds the Trust / Security / Privacy layer (auth, audit log, secret guard, backup/restore).
Security
By default, Mnémlet binds to 127.0.0.1 only. Configure MNEMLET_API_KEY or [auth].api_key for API-key protection with the X-Mnemlet-Key header. Secret Guard blocks or warns on configured write-path secret-like content, and the Audit log records sanitized security and review actions. Do not expose Mnémlet directly to the public internet; put any remote access behind your own trusted network boundary.
License
Built with 🧠 on a Raspberry Pi.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mnemlet-0.3.0.tar.gz.
File metadata
- Download URL: mnemlet-0.3.0.tar.gz
- Upload date:
- Size: 416.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4af14fd58a1403ffb5016d03d7989676536e45c6c2bd39d91d497bb9fa781382
|
|
| MD5 |
e8aaa6c3d1d372544b8928776e3d868e
|
|
| BLAKE2b-256 |
39d5560fe1b15056885e144253469696a3129b836c6731b79627b0963a16e451
|
File details
Details for the file mnemlet-0.3.0-py3-none-any.whl.
File metadata
- Download URL: mnemlet-0.3.0-py3-none-any.whl
- Upload date:
- Size: 82.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db69bbcc2003970391eacb85adf5a6055fa64ca8419203278871abc57cf9397d
|
|
| MD5 |
7ee074b22e3e611264acfc6bd0ef460e
|
|
| BLAKE2b-256 |
c4fbee8d4966179c872d085b129cb8e2774d298a2ff93f7d024b695c11a75832
|