⚠️ Experimental. plugmem is mostly an AI-built experiment — written with the help of a small local model (Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf) and various Claude models, in roughly equal measure. Expect non-professional design choices, rough edges, broken behavior, or mistakes. Use it at your own risk.
An embeddable memory database for local LLM agents — you link it into your
program like SQLite, in-process and single-file. plugmem stores short
facts — with a subject entity, tags, optional metadata, an optional
embedding and two time axes — and answers a query with a ranked,
token-budgeted block ready to paste into a prompt. It runs in-process from one
snapshot file plus an append-only journal — no server, no daemon, one machine.
The core is no_std, so the same engine runs natively and in WebAssembly.
It is meant for a local agent on your own device or inside your own project — one process, one file — not a multi-tenant service fielding queries from many users.
It is not a vector database. A vector is one of four recall sources — lexical (BM25), vector, entity graph and time — fused with reciprocal-rank fusion; tags act as filters. What plugmem is actually about:
- bitemporal facts —
revise/forget, "what was true then" vs now, revision chains kept intact, physical erasure onmaintain; - an entity graph — typed edges between entities, relational knowledge, not just nearest-neighbor vectors;
- opaque per-fact metadata — an optional key→value map (a URI to the real payload in another store, a mime type, an external key); the engine stores and returns it but never interprets it — big blobs live outside, by reference;
- conflict surfacing on
remember— a new fact comes back with the live facts it may duplicate or contradict; the engine never merges on its own, the caller decides; - a compact rendered block — the result is selected greedily under a token budget, ready for the prompt;
- embeddable everywhere — single-threaded
no_std + alloccore, zero-allocation recall after warm-up, one file, no server; built and tested onwasm32v1-noneand a real 32-bit wasm runtime in CI.
Where it fits — and where it doesn't. plugmem holds the memory of a local agent or an embedded system: one process, one file, nothing to run. It targets a single machine, with ~100k active facts as the interactive design center and ~1M facts as a tested upper-bound profile. At ~100k, the reference workload keeps full hybrid recall sub-millisecond; at ~1M, the database remains usable but hybrid recall and maintenance become materially slower. These are measured operating points, not hard format limits or release guarantees. It is not a distributed vector store. For nearest-neighbour search over tens of millions of embeddings, sharded across a cluster or behind a managed API, use a dedicated one (Qdrant, Milvus, Weaviate, Pinecone, pgvector). plugmem trades that scale for zero infrastructure and recall that combines keyword, meaning, relationships and time, not vectors alone.
If you write Rust and just want a working memory, use
plugmem-host — it has everything. The other crates
are for narrower needs.
| You want | Use | Why |
|---|---|---|
| A memory in a Rust program — the common case | plugmem-host (std) |
Everything included: files, locking, read-only mmap, HTTP embedders, integrity, cross-process concurrency. One dependency — it re-exports the engine. |
A memory in Rust with no std or your own storage (browser, wasm host, custom file layer) |
plugmem-core (no_std) |
The engine only. You bring the Storage trait, the clock, file I/O and embedding — so you also manage when the file opens and how memory loads. |
| Just the flat byte-pool containers, to build your own index/store | plugmem-arena (no_std) |
The storage substrate, engine-agnostic. |
| A memory from a terminal or shell script | plugmem-cli (plugmem) |
One file, no server; plugmem repl keeps the engine open for host speed. |
| A memory for an LLM agent or a non-Rust program | plugmem-mcp |
Long-lived stdio JSON-RPC; language-independent. Don't front your own Rust with it — embed host instead. |
| A memory in JavaScript / TypeScript (Node) | plugmem-napi |
The engine as a native Node addon (napi-rs), in-process and typed for TS. On npm as plugmem. |
Rust programs use the library (host, or core for specialists) — embedded
in-process, like linking SQLite. Other languages and agents come in through
mcp (or napi for Node/TS) — not the CLI, which is the human/scripting door.
| Crate | What it is |
|---|---|
plugmem-arena |
flat byte-pool storage structures (no_std, wasm-first) |
plugmem-core |
the engine: data model, indexes, recall, snapshots (no_std) |
plugmem-host |
OS glue: files, locking, mmap read-only, embedder clients (std) |
plugmem-cli |
command-line surface, one-shot + interactive repl |
plugmem-napi |
native Node.js addon (napi-rs), on npm as plugmem |
plugmem-mcp |
MCP server (stdio JSON-RPC) for agents |
plugmem-testgen |
deterministic corpus generator for tests and benches |
Recall is not a vector lookup — it fuses four sources with reciprocal-rank fusion and a recency boost (tags filter; they are not a source):
| Source | Algorithm | What it finds |
|---|---|---|
| Lexical | BM25 (Robertson idf) over a Unicode (UAX #29) tokenizer | exact terms / keyword overlap |
| Semantic | int8-quantized cosine — a flat two-phase scan below a threshold, an HNSW graph above | meaning / nearest neighbours |
| Graph | entity graph with typed edges, breadth-first from query anchors | relational knowledge |
| Temporal | range scans over a recorded_at-ordered index; bitemporal validity |
"what was true then", time windows |
The following is a like-for-like native, file-backed benchmark using the same
deterministic synthetic workload at both sizes (dim=0, so no embedding
service is involved). Recall values are p50 latencies after the database has
been checkpointed and maintained; the 1M SVGs live in
plugmem-host/assets.
The size labels refer to ingested operations, not the final number of live facts. After maintenance, the two runs contain approximately 86k and 860k active facts respectively.
| Measurement | 100k operations | 1M operations |
|---|---|---|
Active facts after maintain |
86,010 | 860,204 |
Pool bytes after maintain |
56.8 MB | 382.0 MB |
| Streaming load | 7.88 s (12,689 ops/s) | 148.32 s (6,742 ops/s) |
| Text-only recall p50 | 52 µs | 1.91 ms |
| Full hybrid recall p50 | 636 µs | 4.89 ms |
| Checkpoint | 69 ms | 550 ms |
maintain |
0.68 s | 13.85 s |
The 1M run holds roughly 10× as many active facts while the pool is 6.7× larger. Total load time is 18.8× higher, but the per-operation load cost grows by 1.9×; full hybrid recall grows by 7.7×. These are machine-specific trend measurements, not release guarantees. Reproduce both columns with:
cargo run --release -p plugmem-host --example bench_database -- 100000 --diagnose-recall | tee database-benchmark-100k.tsv
cargo run --release -p plugmem-host --example bench_database -- 1000000 --diagnose-recall | tee database-benchmark-1m.tsv
cat database-benchmark-100k.tsv database-benchmark-1m.tsv > database-benchmark-scale.tsv
cargo run -p plugmem-bench-charts -- database-benchmark-scale.tsv --force
The lexical tokenizer is ICU4X-backed: it applies Unicode NFKC normalization, locale-neutral lowercase mapping, UAX #29 word boundaries, language-aware segmentation for complex scripts, Latin search folding and CJK bigrams. Its generic Unicode path reuses scratch buffers and performs no tokenizer-internal allocations after warm-up. ICU4X's dictionary/LSTM path may allocate a temporary boundary cache for scripts such as Thai and Khmer in exchange for better word segmentation. The tokenizer emits canonical lexical terms; it does not perform stemming or lemmatization.
Two binaries — the plugmem-cli CLI (crate plugmem-cli) and the plugmem-mcp
server (crate plugmem-mcp) — built for Linux, Windows and macOS (x64 &
arm64) on every tagged release.
Pick the one method that's convenient — you don't need more than one. They all install the same binaries. Quick guide:
| If you… | Use |
|---|---|
| are on macOS / Linux with Homebrew | Homebrew |
| don't want a Rust toolchain | installer script, or the Windows .msi |
| want managed install/uninstall on Windows | .msi |
have cargo and want a cross-platform install |
cargo binstall |
| want to compile it yourself | from source |
From the m62624/homebrew-plugmem
tap; brew upgrade / brew uninstall then manage it like any formula:
$ brew install m62624/plugmem/plugmem-cli # the `plugmem-cli` CLI
$ brew install m62624/plugmem/plugmem-mcp # the `plugmem-mcp` serverEach binary has its own script on the
Releases page; latest always
points at the newest tag.
# Linux / macOS (POSIX sh)
$ curl --proto '=https' --tlsv1.2 -LsSf https://github.com/m62624/plugmem/releases/latest/download/plugmem-cli-installer.sh | sh
$ curl --proto '=https' --tlsv1.2 -LsSf https://github.com/m62624/plugmem/releases/latest/download/plugmem-mcp-installer.sh | shDownload plugmem-cli-*.msi or plugmem-mcp-*.msi from the
Releases page. Double-click to
install; it registers the app in "Add or remove programs", so upgrades and
uninstalls go through the normal Windows UI.
If you prefer a script over a GUI installer:
> powershell -ExecutionPolicy Bypass -c "irm https://github.com/m62624/plugmem/releases/latest/download/plugmem-cli-installer.ps1 | iex"
> powershell -ExecutionPolicy Bypass -c "irm https://github.com/m62624/plugmem/releases/latest/download/plugmem-mcp-installer.ps1 | iex"cargo-binstall downloads the prebuilt binary instead of compiling. It reads the release's cargo-dist manifest, so it just works on every OS/arch above — no extra config:
$ cargo binstall plugmem-cli # the `plugmem-cli` binary
$ cargo binstall plugmem-mcp # the `plugmem-mcp` binaryNeeds a Rust toolchain; compiles locally and works on any platform Rust targets. Both crates are published to crates.io, so you can build straight from there:
$ cargo install plugmem-cli # the `plugmem-cli` binary
$ cargo install plugmem-mcp # the `plugmem-mcp` binary…or from a local checkout of this repo:
$ cargo install --path crates/plugmem-cli
$ cargo install --path crates/plugmem-mcpInstalled with cargo binstall / cargo install (either resolves to cargo's
own install tracking, so plain cargo uninstall works):
$ cargo uninstall plugmem-cli # removes the `plugmem-cli` binary
$ cargo uninstall plugmem-mcpInstalled with Homebrew: brew uninstall plugmem-cli plugmem-mcp.
Installed from a Windows .msi: uninstall from "Add or remove programs"
(or Settings → Apps), exactly like any other Windows app.
Installed with the shell/PowerShell scripts: cargo-dist does not ship an
uninstaller, so remove the binaries and their install receipts by hand. By default
the binaries land in ~/.cargo/bin (note: cargo uninstall won't touch these —
cargo didn't track them), and a receipt is written per app.
# Linux / macOS
$ rm -f ~/.cargo/bin/plugmem-cli ~/.cargo/bin/plugmem-mcp
$ rm -rf ~/.config/plugmem-cli ~/.config/plugmem-mcp # install receipts# Windows (PowerShell)
> Remove-Item "$env:USERPROFILE\.cargo\bin\plugmem-cli.exe","$env:USERPROFILE\.cargo\bin\plugmem-mcp.exe" -ErrorAction SilentlyContinue
> Remove-Item "$env:LOCALAPPDATA\plugmem-cli","$env:LOCALAPPDATA\plugmem-mcp" -Recurse -ErrorAction SilentlyContinueIf you pointed the installer somewhere else (PLUGMEM_CLI_INSTALL_DIR /
PLUGMEM_MCP_INSTALL_DIR, or CARGO_DIST_FORCE_INSTALL_DIR), delete from that
directory instead. The installer may also have added the bin dir to your PATH —
prune that line from your shell profile if nothing else uses it.
MIT.
