mnem.mp4
- The problem
- Benchmarks
- Install
- Quickstart
- Integrate
- What it is
- Commands
- Python API
- GraphRAG
- vs others
- Docs
- Contributing
A transcript is not a memory.
You already have a mental model for this: git. Commits with history you can diff and revert, branches you can merge, a log of every decision and why. Your agent's memory gives you none of that. It's a transcript pasted back into the prompt, or a search index you can't inspect or edit. Conventions live in flat .cursorrules files - useful, but not queryable or versionable. And sessions are isolated: plan a migration with Claude Code today, open Cursor tomorrow, and that agent has never heard of it.
mnem brings the git model to agent knowledge. Every write is a content-addressed commit - same bytes, same CID, any machine. Skills, decisions, and notes live in a versioned, branchable, mergeable graph: diff what changed between sessions, revert a bad batch of facts, merge knowledge from two agents the same way you'd merge a branch.
Retrieval is hybrid and transparent: vector + keyword + graph traversal in one pass, with an explicit token budget - mnem reports exactly what it found, what it skipped, and how many tokens were used. Swap the embedder, reranker, or LLM with one config line. One mnem integrate wires it into Claude Code, Cursor, Codex, Gemini CLI, or any MCP host. Single ~40 MB binary. No daemon, no cloud, no API keys.
Close the laptop. Open it tomorrow. Your agent remembers.
Measured head-to-head against mem0 and MemPalace on six public datasets. mnem leads on all of them.
ONNX MiniLM-L6-v2 embedder, same bytes on every system. No LLM rerank. Reproduce: bash benchmarks/harness/run_bench.sh.
| Benchmark | mem0 | MemPalace | mnem |
|---|---|---|---|
| LongMemEval 500 Q: R@5 | 0.946 | ||
| LongMemEval 500 Q: R@10 | 0.962 | ||
| LoCoMo 1986 Q: R@5 | 0.466 | 0.508 | |
| LoCoMo 1986 Q: R@10 | 0.676 | 0.603 | |
| ConvoMem 250 conv.: avg recall | 0.558 | 0.929 | |
| MemBench simple/roles 100: R@5 | 0.410 | 0.840 | |
| MemBench highlevel/movie 100: R@5 | 0.970 | 0.950 | |
| FinanceBench 150 Q: hit@5† | 0.033 | 0.767 |
mem0 columns: our reproduction under the same harness (mem0 doesn't publish R@K headlines on these datasets). MemPalace columns: public headline numbers cross-verified under our harness. Raw artefacts: benchmarks/results/v0.1.0/. † FinanceBench uses Ollama bge-large (1024-dim) on all systems; MemPalace shown at best configuration (bge-large direct ChromaDB); mem0 applies LLM memory extraction before storage. Full methodology: benchmarks/results/analysis/financebench.md.
| Benchmark | mean retrieve |
|---|---|
| LongMemEval 500 Q | 711 ms |
| LoCoMo 1986 Q | 333 ms |
| ConvoMem 250 conv. | 398 ms |
| MemBench simple/roles 100 | 1874 ms (e2e) |
| MemBench highlevel/movie 100 | 491 ms (e2e) |
| FinanceBench 150 Q | 2087 ms (global) |
(e2e) = end-to-end mean when the adapter doesn't expose phase timing. (global) = corpus-wide scan with no per-session label scope.
Reproduce
mnem bench fetch longmemeval # download datasets (one-time, 264 MB)
mnem bench # TUI; select benchmarks interactively
mnem bench run --benches longmemeval --limit 50 --non-interactive
mnem bench results ./bench-out # re-render results from a prior run
# Legacy bash harness (canonical path for headline numbers)
bash benchmarks/harness/run_bench.shMethodology, raw artifacts, per-bench breakdowns: benchmarks/ and docs/src/benchmarks/.
Pick whichever one you already have. Any one works. Full per-platform notes below.
# if you have Cargo (Rust): recommended for dev machines
cargo install --locked mnem-cli --features bundled-embedder
# if you have pip (Python)
pip install mnem-cli
# if you have npm (Node.js)
npm install -g mnem-climnem --version # confirm installNote
--features bundled-embedder ships an in-process ONNX MiniLM-L6-v2 so mnem retrieve works with zero configuration. Omit the flag if you want to bring your own embedder (Ollama, OpenAI, Cohere) via .mnem/config.toml.
macOS / Linux
No Cargo? Install via rustup (also installs rustc).
# C++ stdlib required to link the bundled ONNX Runtime (Linux only)
sudo apt-get install g++ # Debian / Ubuntu / WSL
# sudo dnf install gcc-c++ # Fedora / RHELcargo install --locked mnem-cli --features bundled-embedder
# CUDA-accelerated embedder (Linux, NVIDIA GPU)
cargo install --locked mnem-cli --features bundled-embedder-cudaIf mnem is not found after install, ~/.cargo/bin is not on $PATH.
rustup install: source the env (or open a new terminal):
source ~/.cargo/envSystem Rust (apt/dnf): add to PATH permanently:
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc && source ~/.bashrcWindows
No Cargo? Install via rustup (also installs rustc).
cargo install --locked mnem-cli --features bundled-embedder
# DirectML-accelerated embedder (any GPU vendor on Windows)
cargo install --locked mnem-cli --features bundled-embedder-directmlnpm / Node.js
No npm? Install Node.js (npm is bundled, Node 18+ required).
npm install -g mnem-cli
mnem --version
# or without a global install (one-shot)
npx mnem-cli --versionDownloads the prebuilt native binary for your platform at install time. Node 18+ required. Bundled embedder included - no Ollama or API key needed.
pip (PyPI)
No pip? Install Python (pip is bundled with Python 3.4+).
pip install mnem-cli
mnem --versionShips the mnem binary as a manylinux / macOS / Windows wheel with the bundled embedder pre-baked.
Docker
No Docker? Install Docker Desktop.
docker run --rm -p 9876:9876 ghcr.io/uranid/mnem:latest http serveThe image includes the bundled embedder. Run mnem mcp inside the container for the MCP server surface.
From source
# C++ stdlib required to link the bundled ONNX Runtime (Linux only)
sudo apt-get install g++ # Debian / Ubuntu / WSL
# sudo dnf install gcc-c++ # Fedora / RHELgit clone https://github.com/Uranid/mnem
cd mnem
cargo install --path crates/mnem-cli --features bundled-embedderRequires Rust 1.95+. If needed: rustup install 1.95 && rustup default 1.95.
mnem --version
mnem doctor # checks embedder + store + config, prints a green/yellow/red checklistFull install matrix: docs/src/install.md.
Embedding mnem inside a Python app? The
pip install mnem-cliabove ships the CLI binary as a wheel. The native Python API (import mnem) lives in a separate package. Jump to Python API (mnem-py) ↓ forpip install mnem-pyand snippets.
mkdir my-graph && cd my-graph
mnem init
mnem ingest README.md
mnem retrieve "what does this project do"Five minutes from zero. See docs/src/quickstart.md for the full walkthrough.
One command wires the MCP server entry, the UserPromptSubmit hook (for hosts that support it), and the mnem system prompt into the host's project-rules file. Restart the host and the agent starts using mnem automatically.
mnem integrate # interactive: detect installed hosts and prompt
mnem integrate claude-code # wire a specific host, skip interactive detection
mnem integrate --all # wire every detected host without prompting
mnem integrate --check # report wired state for all hosts; nothing changes
mnem integrate --dry-run # preview what would be written without changing anything
mnem integrate --show claude-code # print the MCP JSON block for manual copy-paste
mnem integrate --no-hooks # skip UserPromptSubmit hook wiring
mnem integrate --no-system-prompt # skip system prompt wiring
mnem integrate --target-repo ~/notes # point the MCP server at a specific graph, not the global oneWhat gets wired:
- MCP server (
mcpServers.mnem) - the agent gets full mnem tool access viamnem mcp --repo <graph>; defaults to the global graph (~/.mnemglobal/.mnem) - UserPromptSubmit hook (Claude Code only) - runs
mnem retrievebefore each message, auto-injecting relevant memory into context - System prompt - mnem usage instructions injected into the host's project-rules file
The hook always queries your project's .mnem/ first (walking up from the current directory), then falls back to mnem global retrieve automatically. The hook and system prompt behave the same regardless of which default knowledge graph you choose during setup. Use --target-repo only if you want the MCP server to point somewhere other than the global graph.
Auto-detects and configures:
- Claude Code
- Claude Desktop
- Cursor
- Continue
- Zed
- Gemini CLI
Any other MCP-aware host works via a hand-edited mcpServers entry pointing at mnem mcp --repo <path> - see docs/src/mcp.md.
The agent gets the full mnem toolset as native tools: retrieve, commit, ingest, tombstone, traverse, global graph access, and more. No extra daemon, no port to manage. Full tool reference: docs/src/mcp.md.
A content-addressed knowledge graph with hybrid GraphRAG retrieval, versioned commits, and deterministic ingest, built as a persistent memory substrate for AI agents.
Every node carries a cryptographic identity derived from DAG-CBOR + BLAKE3: the same content produces the same CID on any machine. Retrieval fuses vector (HNSW), sparse (BM25/SPLADE), and multi-hop graph traversal via RRF in a single pass, and every response reports exactly what candidates were seen and what got dropped at your token budget. Ingest is LLM-free. Single binary. No cloud. Compiles to wasm32.
Each item below leads with the plain-English benefit, then the technical detail.
Tags: = unique to mnem in agent-memory today ·
= rare (1-2 peers, usually paid) · (no tag) = standard, done well.
Branch, diff, and merge, like git, but for what your agent knows. Every write is a versioned commit with signed Ed25519 history. Two agents (or two machines) writing the same scope offline reconcile through a 3-way graph + embedding merge, not "last write wins". → Core concepts
The same input always lands at the same address, on any computer. Every node, tree, sidecar, and commit is content-addressed via canonical DAG-CBOR + BLAKE3. Identical content collapses to one CID. Determinism and replay come for free, not as a slogan. → Core concepts
Skills become a queryable graph, not flat markdown. Replace
AGENTS.mdand.cursorruleswith a versioned, branchable, mergeable graph. Export your graph, import a teammate's, diff the two, merge the parts you want.
Nothing disappears silently at your token budget. Every retrieve emits
tokens_used,candidates_seen, anddroppedcounters as first-class response fields. No other agent-memory system exposes this.Best-in-class recall on every public benchmark. Beats open-source peers by +0.218 R@5 on LoCoMo, +0.120 on MemBench, +0.047 on ConvoMem under the same embedder. Matches MemPalace on LongMemEval (R@5 0.966). All numbers reproducible with the shipped harness. → Benchmarks
- Searches by meaning, by keyword, and by relationship, in one pass. Hybrid GraphRAG: vector (HNSW) + sparse (BM25/SPLADE) + multi-hop graph traversal, fused via RRF. Graph traversal is optional: on when multi-hop helps, off when dense saturates.
Runs in a browser tab.
mnem-corehas no tokio, no filesystem, no network. The same retrieval code compiles unchanged towasm32: Chrome, Cloudflare Workers, Lambda cold-start. Graphiti and mem0 are Python + external-DB stacks; they cannot ship to the edge.One ~40 MB binary. No daemon, no cloud, no account. Embedded redb store, runs fully offline. Same image powers the CLI and the HTTP server.
Plug-and-play in seconds. Bundled ONNX MiniLM-L6-v2 runs in-process: no Ollama, no API keys, no cold-start network call. Just
mnem initand you're retrieving. mem0 and Graphiti both need an external LLM endpoint at ingest. → InstallSwap any provider with one line of config. Embedder, sparse encoder, reranker, and LLM are all config-driven. Switch local ONNX to hosted Cohere with one flag. No fork, no rebuild. → Embedding providers
One core, four front doors. CLI, HTTP, MCP, and Python all wrap the same engine.
mnem integratewires the MCP server into Claude Code, Cursor, Codex, Gemini CLI, anything speaking MCP. → CLI reference · MCP
Same bytes in always produce the same CIDs out. Deterministic ingest: no LLM at ingest, parse + chunk + extract is statistical (KeyBERT optional). Audit-friendly, fuzz-tested, byte-identical across machines. → Ingest pipeline
Property + fuzz tested at the infra-DB tier. Parsers are property-tested and fuzz-harnessed; CAR round-trip and merge-commit are byte-identical. Trust signal usually only seen in foundational databases.
- Knowledge accumulates across many sessions and someone needs to reason over the history.
- Two agents (or two machines) edit the same memory and need to reconcile cleanly.
- Audits matter: same input, same output, replayable on any computer.
- Deployment is edge, offline, or air-gapped (browser, Cloudflare Workers, Lambda cold-start).
Every command accepts --help for the full flag reference.
mnem init # create a new graph in the current directory
mnem doctor # probe embedder + store + config; green/yellow/red checklist
mnem stats # nodes, edges, refs, embedder health, repo sizemnem ingest notes.md # parse a file into Doc + Chunk + Entity nodes
mnem ingest --recursive docs/ # ingest a directory recursively
mnem ingest --chunker recursive report.pdf # PDF with sliding-window chunkingmnem add node -s "Alice leads the infra team" # label defaults to "Node"
mnem add node --label Fact -s "Alice leads the infra team" # add a single fact node
mnem add edge --from <uuid> --to <uuid> --label works_at # connect two nodesmnem get <uuid> # fetch a node by UUID: ntype, summary, props
mnem get <uuid> --content # also print the full content body
mnem tombstone <uuid> # soft-delete: excluded from retrieval, kept in audit log
mnem tombstone <uuid> --reason "superseded by newer decision" # with reason recorded in op-log
mnem delete <uuid> # hard-delete: no audit trail
mnem global get <uuid> # look up a node in the global graph
mnem global tombstone <uuid> # tombstone a node in the global graphThe ingest pipeline is deterministic: no LLM at ingest time, same bytes in always produce the same CIDs out. Audit-friendly and fuzz-tested.
mnem retrieve "what did we decide about the API design" # searches local .mnem/ first, falls back to global
mnem -R ~/notes retrieve "query" # target a specific graph explicitly-R <path> is a global flag that redirects any command to a specific repository directory. It overrides the walk-up search from the current directory and any default set via mnem integrate. Applies to all subcommands: mnem -R ~/notes status, mnem -R ~/notes log, etc.
Hybrid retrieval: vector (HNSW) + sparse (BM25/SPLADE) + graph traversal, fused via RRF. See GraphRAG for tuning flags.
Note
mnem has two scopes: the local graph (.mnem/ in your project directory) and the global graph (~/.mnemglobal/.mnem/). The global graph is for cross-project, cross-session facts that should follow you everywhere.
When to use local vs global:
Use local .mnem/ for |
Use mnem global for |
|---|---|
| Project-specific facts, decisions, code context | People, preferences, facts that span all projects |
| Per-repo memory that travels with the repo | Knowledge you want every session and every agent to see |
| Anything you'd commit alongside the code | Cross-session continuity |
mnem global is a full mirror of mnem but operates exclusively on the global graph:
mnem global retrieve "what is Alice's current role" # search the global graph only
mnem global ingest contacts.md # ingest a file into the global graph
mnem global add node --label Entity:Person \
--prop name=Alice -s "Alice leads the infra team" # add a node to the global graphThe mnem integrate command sets up the agent to read local first and fall back to global automatically - no manual switching required during normal use.
mnem status # op-head CID, head commit, all named refs, label counts, MERGING marker
mnem stats # one-line: op, commit, content CID, ref count, label namesmnem log # walk op-log backwards from HEAD, default last 20 entries
mnem log -n 50 # show last 50 entries
mnem log --oneline # compact one-line-per-op format
mnem log --format json # machine-readable JSON stream
mnem show # decode and pretty-print the current op-head block
mnem show <cid> # decode any block by CID (Node, Edge, Commit, Operation, View, ...)
mnem diff <op-a-cid> <op-b-cid> # ref deltas + node/edge structural diff between two ops
mnem diff HEAD <cid> # diff current op against a specific op CIDmnem branch list # list all refs/heads/* branches; * marks current
mnem branch create <name> # create branch at current HEAD
mnem branch create <name> <start> # branch from a ref name, branch name, or CID
mnem branch create <name> --from HEAD # explicit --from form; same resolution as above
mnem branch delete <name> # delete a local branch pointer
mnem merge <branch> # 3-way merge <branch> into current HEAD
mnem merge <branch> --strategy=ours # auto-resolve conflicts: keep current side
mnem merge <branch> --strategy=theirs # auto-resolve conflicts: take incoming side
mnem merge <branch> --dry-run # preview outcome without persisting anything
mnem merge --continue # finish after editing .mnem/MERGE_CONFLICTS.json
mnem merge --abort # cancel, restore HEAD from .mnem/ORIG_HEAD
mnem pull # fast-forward origin/main into HEAD (default)
mnem pull <remote> <branch> # fast-forward <remote>/<branch> into HEADmnem remote add <name> <url> # register a remote (stores in .mnem/config.toml)
mnem remote add <name> <url> \
--token-env MNEM_REMOTE_ORIGIN_TOKEN # name the env var that holds the bearer token
mnem remote list # list all configured remotes with their URLs
mnem remote show <name> # show URL + capabilities for one remote
mnem remote remove <name> # remove a remote entry
mnem fetch # fetch from origin (default)
mnem fetch <remote> # fetch from a named remote; token via env var
mnem push # push HEAD to origin/main (default)
mnem push <remote> <branch> # push a specific branch to a named remote
mnem clone <url> [<dir>] # clone a CAR archive into <dir>; file:// and bare .car paths supported
mnem clone file:///tmp/repo.car ./copy # clone from a local file URL
mnem clone ./repo.car ./copy # bare path shorthand (must end in .car)mnem query --where name=Alice # exact property match, default 10 results
mnem query --where kind=Person -n 25 # increase result limit
mnem query --where kind=Person \
--with-outgoing knows # match nodes + follow outgoing "knows" edges
mnem query --where status=active \
--with-outgoing depends_on \
--with-outgoing depends_on # repeat --with-outgoing to chain hops
mnem blame <node-uuid> # list all incoming edges to a node
mnem blame <node-uuid> --etype authored # filter to one edge typemnem ref list # list all refs (refs/heads/*, refs/remotes/*, ...)
mnem ref set <name> <target-cid> # point a ref at a specific commit CID
mnem ref delete <name> # delete a named refmnem embed # backfill embeddings for every node missing a vector
mnem embed --force # re-embed even nodes that already have a vector
mnem embed --label Person # restrict to nodes of one label
mnem embed --dry-run # count what would be embedded without calling the provider
mnem reindex # alias for embed; preferred name after C7 rename
mnem reindex --label Doc # restrict to one label
mnem reindex --since <commit> # only nodes added/changed after <commit>
mnem reindex --force # re-embed already-indexed nodes
mnem reindex --dry-run # count without calling the providermnem cat-file <cid> # emit raw DAG-CBOR bytes for a block to stdout
mnem cat-file <cid> --json # decode to DAG-JSON and pretty-print (pipe into jq)mnem export <path> # export HEAD as a CAR v1 archive
mnem export - # write CAR to stdout (pipe over SSH etc.)
mnem export --from refs/heads/main out.car # export from a specific ref
mnem export --from <cid> backup.car # export from a specific commit CID
mnem import <path> # import a CAR archive into the current repo
mnem import - # read CAR from stdinmnem config set user.name Alice # set author name
mnem config set user.email alice@example.com
mnem config set embed.provider ollama # embedder: openai | ollama
mnem config set embed.model nomic-embed-text
mnem config set embed.base_url http://localhost:11434 # override provider endpoint
mnem config get embed.provider # print the current value of a key
mnem config unset embed.provider # remove a key
mnem config list # print all set keys and their valuesKnown keys: user.name, user.email, user.key, user.agent_id, embed.provider, embed.model, embed.api_key_env, embed.base_url. API keys live in environment variables, never in config.
mnem repos list # list all repos registered with mnem integrate
mnem repos set-default <path> # mark a repo as the default for mnem without -R
mnem repos prune # remove registry entries for paths that no longer existmnem mcp # start the MCP JSON-RPC server over stdio
mnem mcp --repo ~/notes # point the MCP server at a specific graph
mnem http serve # start the HTTP JSON API (loopback by default)mnem bench # interactive TUI; select benchmarks to run
mnem bench run --benches longmemeval --limit 50 # run a specific benchmark suite
mnem bench fetch longmemeval # download benchmark datasets
mnem bench results ./bench-out # re-render results from a prior runmnem completions bash # emit bash completion script
mnem completions zsh # zsh
mnem completions fish # fish
mnem completions powershell # PowerShell
mnem completions elvish # Elvish
# Install (bash):
mnem completions bash > ~/.local/share/bash-completion/completions/mnem
# Install (zsh):
mnem completions zsh > ~/.zsh/completions/_mnemFull CLI reference: docs/src/cli.md.
Use mnem-py when you want to read and write a mnem graph directly from Python - without the CLI binary. Same retrieval engine, PyO3 bindings.
pip install mnem-py
pip install sentence-transformers # brings ~200 MB of deps (torch, transformers)mnem-py stores and retrieves by dense vector: you compute embeddings in Python and hand them to mnem. SentenceTransformer("all-MiniLM-L6-v2") downloads a ~23 MB model from HuggingFace Hub on first use and caches it in ~/.cache/huggingface/ - all subsequent calls are fully local with no network required.
import pymnem
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2") # downloaded once, ~23 MB
MODEL_NAME = "all-MiniLM-L6-v2" # key mnem uses to match stored vectors
repo = pymnem.Repo.init_memory() # in-memory; open_or_init() for disk
# Write: compute an embedding for each node and attach it
with repo.transaction(author="agent", message="seed") as tx:
for text in ["Alice lives in Berlin", "Bob moved to Paris"]:
tx.add_node(ntype="Memory", summary=text)
tx.add_embedding_f32(MODEL_NAME, model.encode(text).tolist())
# Retrieve: compute a query vector with the same model, mnem ranks under token budget
query_vec = model.encode("Alice Berlin").tolist()
result = repo.retrieve(vector=query_vec, model=MODEL_NAME, token_budget=500, limit=5)
for item in result:
print(f"{item.score:.3f} {item.summary}")
# result.tokens_used / result.tokens_budget - no silent truncationFull API surface - query, update_node, delete_node, on-disk persistence, label filtering: crates/mnem-py/README.md.
mnem ships GraphRAG built in. One knob per stage, opt-in per query, never required. Vector search alone handles most queries well - turn graph stages on when queries span multiple documents, require multi-hop reasoning, or need compositional answers.
| Stage | Flag | What it does |
|---|---|---|
| Vector lane | always on | HNSW over per-commit dense embeddings (default 384-d MiniLM). |
| Sparse lane | config-driven | BM25 + SPLADE-onnx, fused with vector via Reciprocal Rank Fusion. Toggled by [sparse] block in config.toml. |
| Vector candidate pool | --vector-cap <N> |
Lift the dense pool size from default 256. Higher = better long-tail recall, +cost. |
| Result limit | --limit <N> |
Final returned set (default 10). Short form: -n. |
| Graph expansion | --graph-expand <N> |
Add N neighbours of top-K seeds via authored edges. Audit-recommended default 20 when graph is on. |
| Graph mode | --graph-mode <decay|ppr> |
decay (default) = exponential weight by hop. ppr = Personalised PageRank over the hybrid adjacency index, paper-grade scoring for multi-hop. |
| Community filter | --community-filter |
Run Leiden community detection; drop low-coverage communities before fusion. Default coverage threshold: 0.5. |
| KeyBERT extraction | mnem ingest --extractor keybert |
Ingest-time keyphrase enrichment. Strengthens sparse + community signals. Pass at ingest, not retrieve. |
| Summarisation | --summarize |
Centroid + MMR summary of the top-K, with diversity. |
| Cross-encoder rerank | --rerank <provider:model> |
Post-fusion reorder. Supports cohere:rerank-english-v3.0, voyage:rerank-1, local. |
# Dense baseline
mnem retrieve "what does this project do"
# Add multi-hop graph traversal
mnem retrieve "..." --graph-expand 20
# Full stack: graph-expand + community-filter + PPR + rerank
mnem retrieve "..." --graph-expand 20 --community-filter --graph-mode ppr --rerank cohere:rerank-english-v3.0
# Stack a cross-encoder reranker on top
mnem retrieve "..." --graph-expand 20 --community-filter --rerank cohere:rerank-english-v3.0
# Ingest with KeyBERT keyphrase enrichment (strengthens sparse + community signals)
mnem ingest --extractor keybert notes.md- Single-document corpus, simple queries: leave graph off, vector search alone is enough
- Multi-hop / compositional questions:
--graph-expand 20 - Long history with cross-document references: add
--community-filter - Recall ceiling needed: stack
--rerankon top - Keyphrase-enriched ingest:
mnem ingest --extractor keybertat ingest time
Full retrieval architecture: docs/src/cli.md (retrieve flags)
- mnem vs mem0 - agent memory layer, OSS leader
- mnem vs MemPalace - methodology peer
- mnem vs Supermemory - closed-cloud incumbent
- mnem vs Cognee - KG-for-agents alternative
- mnem vs Letta - agent-memory framework
- mnem vs graphify - lightweight graph tool
Full matrix: docs/src/comparisons/README.md.
- You need transactional OLTP. mnem is append-only with versioned history; row-level UPDATE/DELETE semantics aren't the model.
- You need sub-50 ms cloud-scale retrieval at 10k+ QPS. mnem is local-first. Multi-region sharded retrieval is on the roadmap, not in v1.
Looking for hosted memory, multi-region replicas, shared graphs across teams, or a managed remote layer? A sibling project bringing those to mnem is in active development - watch this space.
| Crate | Role |
|---|---|
mnem-cli |
mnem binary - one command for everything |
mnem-core |
graph model, retrieval, indexing, sidecars |
mnem-http |
HTTP JSON server |
mnem-mcp |
MCP server (stdio) |
mnem-py |
PyO3 Python bindings |
mnem-embed-providers |
ONNX bundled, Ollama, OpenAI, Cohere |
mnem-sparse-providers |
BM25, SPLADE-onnx |
mnem-rerank-providers |
Cohere, Voyage |
mnem-llm-providers |
OpenAI, Anthropic, Ollama |
mnem-ingest |
parse + chunk + extract pipeline |
mnem-extract |
entity extraction (KeyBERT, statistical NER) |
mnem-ner-providers |
NER provider trait + built-in providers (RuleNer, NullNer) |
mnem-bench |
benchmark harness (LongMemEval, LoCoMo, etc.) |
mnem-graphrag |
community summarisation, centroid + MMR |
mnem-ann |
HNSW wrapper |
mnem-backend-redb |
redb-backed store |
mnem-transport |
CAR codec + remote framing |
- Quickstart - five-minute walkthrough
- Install - per-platform install matrix
- CLI reference - every subcommand and flag
- MCP server - tools exposed, client wiring
- Core concepts - CIDs, commits, labels
- Configuration - env vars, config.toml
- Benchmarks methodology
- Reproduce benchmarks
- Embedding providers
- Migrations
Issues and PRs welcome. Start here:
CONTRIBUTING.md- branch conventions, review etiquette, how to ship a PRCODE_OF_CONDUCT.md- rules of engagement (Contributor Covenant 2.1)SECURITY.md- vulnerability disclosure policy
Apache-2.0. See NOTICE for third-party attributions.
mnem unintegrate # interactive: pick which hosts to remove mnem from
mnem unintegrate claude-code # remove one host
mnem unintegrate --all # remove all wired hostsRun mnem unintegrate --help for all options.
⭐ Find mnem useful? A star is the strongest signal we get from a satisfied builder - it helps the next agent developer find this repo when they're stuck on memory. We read every issue, every PR, every mention. Tell us what you built.