Basic Memory
What's New

Basic Memory v0.23

Reranked semantic search, pluggable vector indexes with Milvus, deadlock-free concurrent indexing, and a retrieval inspector.

Basic Memory v0.23 shipped in August 2026 (v0.23.0 release notes). The theme is search you can trust: semantic search matures with cross-encoder reranking and pluggable vector indexes, the indexing core stops deadlocking under concurrent writers, and a new inspector shows exactly why a search returned what it did.

Search that ranks

Opt-in cross-encoder reranking

Vector and hybrid search can now rescore their leading candidates with a cross-encoder that reads the query and each candidate together:

bm config set reranker_enabled true

The default provider runs a local FastEmbed ONNX model — no API key, no per-query cost — and LiteLLM connects hosted rerankers from Cohere, Jina, and Voyage. On the LoCoMo long-conversation retrieval benchmark, reranking improved mean reciprocal rank from 0.616 to 0.719 — a 17% improvement in how high the right note lands in the results. Reranking is off by default and downloads its local model on the first reranked search. See Enable reranking.

Pluggable vector indexes, with first-party Milvus

Postgres deployments can now choose where vectors live: the new semantic_vector_index setting selects pgvector (the default) or Milvus, Milvus Lite, and Zilliz Cloud via pip install "basic-memory[milvus]". A vector-index identity and readiness manifest lets search tell "no ready index" apart from "no results", and SQLite keeps sqlite-vec. After switching backends, rebuild with bm reindex --embeddings. See Run Postgres with Milvus.

Embedding and full-text correctness

A batch of fixes makes search results more trustworthy across the board:

  • Notes edited directly on disk are vector-embedded when the file watcher picks them up — no more waiting for a reindex
  • FastEmbed embeddings are L2-normalized for non-BGE models, so semantic scores no longer silently degrade
  • SQLite full-text search covers complete note content (previously text beyond ~6,000 characters was invisible), and non-Latin queries — CJK, Cyrillic, Greek, Hebrew, Arabic, and more — relax correctly instead of silently degrading
  • bm reindex --embeddings exits nonzero on real failures and reports which index it wrote

Indexing that no longer deadlocks

Underneath search, the indexing and persistence core is rebuilt around generation-versioned relations and observations with compare-and-swap publication. A stale indexing pass can never clobber or deadlock against a newer write, and observations and relations land with the accepted write instead of waiting for the next file re-index. The deadlock and lost-observation failures that appeared under concurrent multi-agent write loads are gone, and a one-time migration repairs historical duplicate observation rows left behind by the old behavior.

See what search sees

The new retrieval inspector answers "why did search return that?" from the command line:

  • bm inspect chunks <note> shows a note exactly as the index sees it — its search rows, the vector chunks each row produced, and per-chunk ready/pending/stale/orphaned status — separating chunking problems from freshness problems in one command
  • bm inspect query "<query>" captures an execution trace from the same search call that returns the results: full-text and vector candidates, fusion, filtering, reranking, and the final page window, with stable JSON output and --show-misses for rejected candidates

See Retrieval inspection commands.

Team workspace push and pull for every member

bm cloud push and bm cloud pull now work on Team workspaces for every member. Transfers run over the cloud's permissioned WebDAV API with per-project access checks — previously these commands required owner-only storage credentials, and every other member got a 403. Flags and semantics are unchanged: transfers stay additive (nothing is ever deleted) and --on-conflict still defaults to fail. See Push and pull.

A real operator front door

Day-to-day operation gets first-class commands:

  • bm configlist effective settings with environment overrides marked, get, set (validated through the config model), and unset. See Configuration commands
  • Rich bm tool output — interactive commands render panels, tables, and trees on a TTY; piped output stays machine-readable, with --plain and --json overrides
  • basic_memory_diagnostics — a new MCP tool that reports version and system info for bug reports
  • bm status — redesigned around project index status
  • bm hook — harness lifecycle capture moves into the package: SessionStart and PreCompact handling for Claude Code and Codex, bounded envelope capture into a local inbox, and bm hook status, flush, install, and remove for standalone setups. See Harness Capture

Cloud additions

  • bm cloud share — create, list, update, and revoke public share links from the CLI. See Manage public share links
  • bm cloud prune — targeted cleanup that deletes cloud files matching this machine's .bmignore, without a full mirror sync. See Prune newly ignored cloud files
  • Optional Redis read cache — standalone MCP servers can cache reads via pip install "basic-memory[redis]" and redis_url. See Optional Redis read cache

Upgrading

Five database migrations run automatically on first start, including a one-time repair that removes duplicate observation rows and purges their stale full-text search entries. Most local setups need no manual action, but v0.23 also removes MCP tools and legacy API routes and changes several CLI, config, sync, and pagination contracts.

Before upgrading an integration or automation, read Upgrade to v0.23 for the breaking changes, required actions, and known issues.

For the complete list of changes, see the Changelog and the v0.23.0 release on GitHub.