Upgrade 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.
bm doctor and bm update reliability, and case-duplicate folder creation.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 statusnow reports project index status instead of the old sync-report tree. Scripts that parse its human output must switch to--jsonand the new shape.bm reindex --embeddingsexits nonzero when embedding fails. Treat that exit as a real failed rebuild instead of assuming success.- Interactive
bm toolcommands render Rich output on a TTY. Piped output remains machine-readable; pass--jsonwhen a script requires a stable contract. - The new top-level groups are
bm configandbm hook. The top-level command set otherwise remains intact;bm syncwas already absent in v0.22.1.
Update MCP clients
- The
canvas,cloud_info, andrelease_notesMCP tools are removed. Obsidian Canvas generation and the API resource-write endpoints behind it are no longer available. - The ChatGPT compatibility tools
searchandfetchnow accept OpenAI MCP clients only. Other clients must usesearch_notesandread_note. list_directoryis bounded and paginated. Consumers must usepageandpage_sizeinstead of assuming one exhaustive response. It also supports title/update sorting, andfile_name_globnow filters returned files without pruning traversal through nonmatching folders.replace_sectionis heading-level-aware. By default it replaces the selected section through the next heading of the same or higher level, including nested subsections. Setreplace_subsections=falseto preserve nested subsections.- Ambiguous identifiers now raise an error instead of returning a best guess, and
write_noterejects filename-convention twins instead of creating a duplicate. - FastMCP moves to
4.0.0b1with 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:
| Old | New |
|---|---|
sync_delay | index_delay |
sync_changes | index_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.
createdandmodifiedfrontmatter timestamps are authoritative. Historical values can change recency ordering after the first reindex.- Single transcript timestamps, spaced timestamp ranges, and Markdown checkbox markers are no longer indexed as observation categories.
- Note-type filters are case-canonicalized, so values such as
Personandpersonnow match the same population. - Root-level wikilinks can resolve through a note's
.mdfilename even when its title differs. A unique case-insensitive underscore/hyphen filename alias is tried only after exact identities; ambiguous aliases remain unresolved.
Review late-release fixes
Several v0.23 fixes require no migration or configuration change but affect operator expectations:
- Incremental
bm reindex --searchreconciles stale full-text rows, including orphaned rows attached to unchanged files. - Re-selecting the current default project is idempotent and no longer leaves the workspace without a default.
- Directory scans recheck a note's lineage and current path before applying a deletion, protecting notes accepted while a scan is running.
- Standalone semantic note reads make fewer API requests, and the normal read-cache lifetime increases from 60 seconds to 5 minutes.
- The Hermes integration preserves command and skill registration ownership. Follow the version-specific Hermes patch guidance; modern Hermes versions must not replace the lifecycle-aware collector with the legacy workaround.
Let migrations finish
Six revisions run automatically when upgrading from v0.22.1 to the latest v0.23 patch:
- A durable note-file vacate record distinguishes moves from byte-identical copies.
- The semantic manifest gains vector-index identity and readiness state.
- Relation-derived search refreshes become durable, retryable work items.
- Relations and their search refreshes gain generation ownership.
- A one-time repair removes duplicate observations and orphaned observation rows from full-text search.
- On PostgreSQL, a child full-text index stores bounded, overlapping chunks of complete note bodies and backfills existing notes. SQLite needs no equivalent schema change because it already indexes full content.
The observation 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. Let the PostgreSQL migration and index build finish before testing deep full-text matches.
Configure custom FastEmbed model prompts
Basic Memory does not infer model-specific prompts for custom FastEmbed models. Configure the selected model's dimensions and any required document/query prefixes explicitly. For example, multilingual E5 uses 1024-dimensional vectors, passage: for indexed content, and query: for search queries:
bm config set semantic_embedding_provider fastembed
bm config set semantic_embedding_model intfloat/multilingual-e5-large
bm config set semantic_embedding_dimensions 1024
bm config set semantic_embedding_query_prefix "query: "
bm config set semantic_embedding_document_prefix "passage: "
bm reindex --embeddings
The trailing spaces are meaningful and preserved. Rebuild embeddings after changing the model, dimensions, or either prefix so stored document vectors and new query vectors use the same contract. The symmetric default model (bge-small-en-v1.5) needs no prefixes.
Review the v0.23.1 and v0.23.2 fixes
The patch releases do not add breaking API changes, but they correct several behaviors worth knowing about:
- PostgreSQL searches complete note bodies. v0.23.1 backfills the new full-text chunks automatically. Boolean queries and punctuated terms work across the complete text, not only titles and capped content stems.
- Reindexing is project-scoped. Rebuilding search for one project no longer drops search rows belonging to sibling projects in the same database. The migration also repairs a missing shared search table if the old destructive path removed it.
- Use
#bm:links_toto disambiguate prose. End a list item with the directive when a single word before a wikilink is prose rather than a relation type:- Mother [[Alice]] #bm:links_to. The directive remains readable in Markdown but is removed from indexed content. bm doctorandbm updateare safer. Doctor waits for deferred materialization and can create its disposable project underBASIC_MEMORY_PROJECT_ROOT; update status output survives an in-place package replacement.- Folder casing resolves consistently. In v0.23.2,
write_note(directory="schemas")and note moves land in an existing uniqueSchemas/folder instead of creating a case-duplicate sibling. Resolution happens segment by segment for nested folders and behaves the same locally and in Cloud.
Known issues in v0.23
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 breakingedit_noteon the affected notes (#1275). - Case-only renames: on a case-insensitive APFS volume, renaming
config.mdtoConfig.mdviamove_noteis 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.
The v0.23.2 folder-casing fix applies to the destination folders used by normal note writes and moves. It does not rename existing folders, merge existing case-variant siblings, or fix case-only and Unicode-normalization-only renames.
Continue setup
- Semantic Search — enable and tune reranking.
- Run Postgres with Milvus — start local Postgres, configure Milvus, and switch indexes safely.
- Configuration — review every new v0.23 setting.
- CLI Reference — update commands and output contracts.

