Basic Memory
What's New

Upgrade to v0.23

Breaking changes, migrations, and required actions when upgrading Basic Memory from v0.22.1 to v0.23.

v0.23 applies database migrations automatically, but integrations and operator scripts need review. Complete the actions below before relying on existing automation.

Rebuild vectors after changing indexes

If you change semantic_vector_index between pgvector and milvus, rebuild the configured vector store:

bm reindex --embeddings

The default incremental run is enough. Before it finishes, vector search returns no results and hybrid search quietly serves full-text results only. See Run Postgres with Milvus for the full switch and recovery procedure.

Milvus requires the basic-memory[milvus] extra. Standalone Redis read caching requires basic-memory[redis]. Reranking remains off by default and downloads its local model on the first reranked search.

Update CLI automation

  • bm status now reports project index status instead of the old sync-report tree. Scripts that parse its human output must switch to --json and the new shape.
  • bm reindex --embeddings exits nonzero when embedding fails. Treat that exit as a real failed rebuild instead of assuming success.
  • Interactive bm tool commands render Rich output on a TTY. Piped output remains machine-readable; pass --json when a script requires a stable contract.
  • The new top-level groups are bm config and bm hook. The top-level command set otherwise remains intact; bm sync was already absent in v0.22.1.

Update MCP clients

  • The canvas, cloud_info, and release_notes MCP tools are removed. Obsidian Canvas generation and the API resource-write endpoints behind it are no longer available.
  • The ChatGPT compatibility tools search and fetch now accept OpenAI MCP clients only. Other clients must use search_notes and read_note.
  • list_directory is bounded and paginated. Consumers must use page and page_size instead of assuming one exhaustive response.
  • replace_section is heading-level-aware. By default it replaces the selected section through the next heading of the same or higher level, including nested subsections. Set replace_subsections=false to preserve nested subsections.
  • Ambiguous identifiers now raise an error instead of returning a best guess, and write_note rejects filename-convention twins instead of creating a duplicate.
  • FastMCP moves to 4.0.0b1 with MCP SDK v2. Downstream embedders pinned to FastMCP 3.x must upgrade with Basic Memory.

Update HTTP clients

Resource write endpoints and pre-v0.18.0 legacy routes are removed. Old clients that still call those routes receive 404 responses. The current v2 API remains the supported surface.

Update configuration

Basic Memory automatically migrates these config-file keys and legacy environment variables:

OldNew
sync_delayindex_delay
sync_changesindex_changes

When old and new names are both set, the new name wins.

sync_thread_pool_size and sync_max_concurrent_files are removed without aliases and are silently ignored in config.json. Remove them. materialization_workers is the nearest replacement for bounding local write materialization, but it is not a one-for-one thread-pool setting.

Review behavior changes

bm cloud sync is a one-way mirror and now deletes a previously synced cloud file when that file becomes ignored by .bmignore. Preview the exact deletion set with bm cloud sync --name <project> --dry-run, or use the additive bm cloud push and bm cloud pull workflow.
  • Deleting the default project now chooses a new default instead of refusing the deletion.
  • created and modified frontmatter timestamps are authoritative. Historical values can change recency ordering after the first reindex.
  • Timestamp-shaped labels and Markdown checkbox markers are no longer indexed as observation categories.
  • Note-type filters are case-canonicalized, so values such as Person and person now match the same population.

Let migrations finish

Five revisions run automatically on first start:

  1. A durable note-file vacate record distinguishes moves from byte-identical copies.
  2. The semantic manifest gains vector-index identity and readiness state.
  3. Relation-derived search refreshes become durable, retryable work items.
  4. Relations and their search refreshes gain generation ownership.
  5. A one-time repair removes duplicate observations and orphaned observation rows from full-text search.

The final repair is not reversible through a downgrade. Markdown files remain the source of truth and the index is rebuildable, but back up memory.db before the upgrade if you want a pre-migration database snapshot.

Known issues in v0.23.0

Asymmetric FastEmbed models need manual prefixes

The FastEmbed provider does not apply query/passage prefixes automatically, so asymmetric embedding models — notably the intfloat/multilingual-e5 family, the strongest local option for multilingual notes — run off-label and retrieval quality collapses without them (#1264). The prefix configuration below is the supported setup for these models; per-model-family automatic defaults are tracked separately in #1284. Set the literal prefixes yourself:

bm config set semantic_embedding_query_prefix "query: "
bm config set semantic_embedding_document_prefix "passage: "

The trailing spaces are meaningful and preserved. Both prefixes are part of the embedding provider identity, so setting or changing them re-embeds your notes — run bm reindex --embeddings afterwards. The symmetric default model (bge-small-en-v1.5) needs no prefixes.

macOS file-identity edge cases

Two open issues can produce duplicate entities for a single file on macOS:

  • Unicode normalization (NFC/NFD): APFS preserves whichever byte form a filename was written with, and some cross-platform sync tools (notably Syncthing) rewrite names to the other form. File-path lookups are byte-wise, so the same file can be indexed twice, accumulating -1-suffixed permalinks and breaking edit_note on the affected notes (#1275).
  • Case-only renames: on a case-insensitive APFS volume, renaming config.md to Config.md via move_note is refused as "destination already exists"; case-only folder renames can silently not change the folder's case on disk and leave duplicate index entries behind (#1281).

Workarounds: avoid case-only and normalization-only renames from MCP tools (rename through an intermediate name instead), and run bm reindex --full -p <project> to collapse duplicates if they appear.

Continue setup