Skip to content

Shellishack/mnem

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mnem: Git for Knowledge Graphs

License: Apache-2.0 CI crates.io PyPI npm MSRV 1.95 Runs on Linux macOS Windows WASM

English  ·  中文  ·  Español


mnem.mp4

  1. The problem
  2. Benchmarks
  3. Install
  4. Quickstart
  5. Integrate
  6. What it is
  7. Commands
  8. Python API
  9. GraphRAG
  10. vs others
  11. Docs
  12. Contributing

The problem

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.


Benchmarks

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 $\color{green}{\textbf{0.966}}$ $\color{green}{\textbf{0.966}}$
LongMemEval 500 Q: R@10 0.962 $\color{green}{\textbf{0.982}}$ $\color{green}{\textbf{0.982}}$
LoCoMo 1986 Q: R@5 0.466 0.508 $\color{green}{\textbf{0.726}}$
LoCoMo 1986 Q: R@10 0.676 0.603 $\color{green}{\textbf{0.855}}$
ConvoMem 250 conv.: avg recall 0.558 0.929 $\color{green}{\textbf{0.976}}$
MemBench simple/roles 100: R@5 0.410 0.840 $\color{green}{\textbf{0.960}}$
MemBench highlevel/movie 100: R@5 0.970 0.950 $\color{green}{\textbf{1.000}}$
FinanceBench 150 Q: hit@5† 0.033 0.767 $\color{green}{\textbf{0.973}}$

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.

Query speed

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.sh

Methodology, raw artifacts, per-bench breakdowns: benchmarks/ and docs/src/benchmarks/.


Install

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-cli
mnem --version    # confirm install

Note

--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 / RHEL
cargo install --locked mnem-cli --features bundled-embedder

# CUDA-accelerated embedder (Linux, NVIDIA GPU)
cargo install --locked mnem-cli --features bundled-embedder-cuda

If mnem is not found after install, ~/.cargo/bin is not on $PATH.

rustup install: source the env (or open a new terminal):

source ~/.cargo/env

System Rust (apt/dnf): add to PATH permanently:

echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
Windows

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-directml
npm / 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 --version

Downloads 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 --version

Ships 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 serve

The 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 / RHEL
git clone https://github.com/Uranid/mnem
cd mnem
cargo install --path crates/mnem-cli --features bundled-embedder

Requires 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 checklist

Full install matrix: docs/src/install.md.

Embedding mnem inside a Python app? The pip install mnem-cli above ships the CLI binary as a wheel. The native Python API (import mnem) lives in a separate package. Jump to Python API (mnem-py) ↓ for pip install mnem-py and snippets.


Quickstart

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.


mnem integrate - wire into any agent host

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 one

What gets wired:

  • MCP server (mcpServers.mnem) - the agent gets full mnem tool access via mnem mcp --repo <graph>; defaults to the global graph (~/.mnemglobal/.mnem)
  • UserPromptSubmit hook (Claude Code only) - runs mnem retrieve before 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.


What it is

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.

What you get

Each item below leads with the plain-English benefit, then the technical detail. Tags: unique = unique to mnem in agent-memory today  ·  rare = rare (1-2 peers, usually paid)  ·  (no tag) = standard, done well.

Memory that behaves like git

  • unique   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
  • unique   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
  • unique   Skills become a queryable graph, not flat markdown. Replace AGENTS.md and .cursorrules with a versioned, branchable, mergeable graph. Export your graph, import a teammate's, diff the two, merge the parts you want.

Retrieval that shows its work

  • unique   Nothing disappears silently at your token budget. Every retrieve emits tokens_used, candidates_seen, and dropped counters as first-class response fields. No other agent-memory system exposes this.
  • rare   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.

Built to run anywhere

  • unique   Runs in a browser tab. mnem-core has no tokio, no filesystem, no network. The same retrieval code compiles unchanged to wasm32: Chrome, Cloudflare Workers, Lambda cold-start. Graphiti and mem0 are Python + external-DB stacks; they cannot ship to the edge.
  • rare   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.
  • rare   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 init and you're retrieving. mem0 and Graphiti both need an external LLM endpoint at ingest. → Install
  • rare   Swap 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
  • rare   One core, four front doors. CLI, HTTP, MCP, and Python all wrap the same engine. mnem integrate wires the MCP server into Claude Code, Cursor, Codex, Gemini CLI, anything speaking MCP. → CLI reference  ·  MCP

Trust signals

  • rare   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
  • rare   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.

When mnem is the right fit

  • 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).

Commands

Every command accepts --help for the full flag reference.

Init and health

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 size

Adding knowledge

mnem 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 chunking
mnem 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 nodes
mnem 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 graph

The ingest pipeline is deterministic: no LLM at ingest time, same bytes in always produce the same CIDs out. Audit-friendly and fuzz-tested.

Retrieving knowledge

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.

The global graph

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 graph

The mnem integrate command sets up the agent to read local first and fall back to global automatically - no manual switching required during normal use.

Status and inspection

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 names

History

mnem 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 CID

Branching and merging

mnem 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 HEAD

Remote operations

mnem 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)

Query and graph traversal

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 type

Named refs

mnem 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 ref

Embeddings

mnem 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 provider

Low-level block access

mnem 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)

Export and import

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 stdin

Configuration

mnem 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 values

Known 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.

Repository registry

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 exist

Servers

mnem 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)

Benchmarks

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 run

Shell completions

mnem 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/_mnem

Full CLI reference: docs/src/cli.md.


Python API (mnem-py)

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 truncation

Full API surface - query, update_node, delete_node, on-disk persistence, label filtering: crates/mnem-py/README.md.


GraphRAG

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.

Stages and flags

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.

Quick examples

# 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

When to enable

  • 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 --rerank on top
  • Keyphrase-enriched ingest: mnem ingest --extractor keybert at ingest time

Full retrieval architecture: docs/src/cli.md (retrieve flags)


Compared to others

Full matrix: docs/src/comparisons/README.md.


When NOT to use mnem

  • 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.


Crates

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

Documentation


Contributing

Issues and PRs welcome. Start here:

License

Apache-2.0. See NOTICE for third-party attributions.


Unintegrate / remove

mnem unintegrate                  # interactive: pick which hosts to remove mnem from
mnem unintegrate claude-code      # remove one host
mnem unintegrate --all            # remove all wired hosts

Run 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.

About

Git for Knowledge Graphs: versioned agent memory with hybrid GraphRAG retrieval. Runs entirely offline, no LLM required.

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages

  • Rust 94.3%
  • Python 4.3%
  • Shell 0.8%
  • PowerShell 0.2%
  • Dockerfile 0.2%
  • JavaScript 0.2%