Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions content/02.whats-new/05.changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ The operator surface expands with **`bm inspect`** — a [retrieval inspector](/

Team workspaces gain working **`bm cloud push`**/**`pull`**: transfers now run over the cloud's permissioned WebDAV API with per-project access checks, so every member can sync — previously these commands required owner-only storage credentials on Team workspaces. `list_directory` learns title and updated-time sorting for one-read folder navigation.

The reliability tail is substantial too: incremental full-text reindexing clears stale rows, glob-filtered directory listings still traverse subfolders, root-level wikilinks resolve by filename with collision-safe case and separator aliases, transcript time ranges no longer become observation categories, and repeatedly selecting the current default project remains safe.

Underneath those features, the indexing and persistence core moves to generation-versioned relations and observations, compare-and-swap materialization, consistent lock ordering, and batched resolution. Observations and relations now land with accepted writes, eliminating the deadlock and stale-projection failures that appeared under concurrent agent workloads.

This release also removes MCP tools and legacy API routes and changes several CLI, config, sync, edit, and pagination contracts. Read [What's New in v0.23](/whats-new/v0-23) for the highlights and [Upgrade to v0.23](/whats-new/v0-23-upgrade) before upgrading an integration or automation.
Expand Down
29 changes: 22 additions & 7 deletions content/02.whats-new/06.v0-23-upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Milvus requires the `basic-memory[milvus]` extra. Standalone Redis read caching

- 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.
- `list_directory` is bounded and paginated. Consumers must use `page` and `page_size` instead of assuming one exhaustive response. It also supports title/update sorting, and `file_name_glob` now filters returned files without pruning traversal through nonmatching folders.
- `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.
Expand Down Expand Up @@ -58,8 +58,19 @@ When old and new names are both set, the new name wins.

- 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.
- 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 `Person` and `person` now match the same population.
- Root-level wikilinks can resolve through a note's `.md` filename 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 --search` reconciles 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](https://github.com/basicmachines-co/basic-memory/blob/main/integrations/hermes/MONKEYPATCH.md); modern Hermes versions must not replace the lifecycle-aware collector with the legacy workaround.

## Let migrations finish

Expand All @@ -73,18 +84,22 @@ Five revisions run automatically on first start:

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
## Configure custom FastEmbed model prompts

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](https://github.com/basicmachines-co/basic-memory/issues/1264)). The prefix configuration below is the supported setup for these models; per-model-family automatic defaults are tracked separately in [#1284](https://github.com/basicmachines-co/basic-memory/issues/1284). Set the literal prefixes yourself:
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:

```bash
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. 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.
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.

## Known issues in v0.23.0

### macOS file-identity edge cases

Expand Down
6 changes: 6 additions & 0 deletions content/07.concepts/1.knowledge-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ addresses the concerns raised in [[Security Review Q4]].

Relations can link to notes that don't exist yet. When those notes are created later, the connections are already in place.

### How wikilinks resolve

Basic Memory tries exact identities first: permalink, title, and file path. At the project root, a filename-stem link such as `[[alpha_note]]` can resolve `alpha_note.md` even when the note's frontmatter title is different.

If no exact identity matches, Basic Memory can try a Unicode case-insensitive file-path alias that treats underscores and hyphens as equivalent. The fallback must identify exactly one note; `[[alpha-note]]` remains unresolved when multiple files collapse to the same alias. This forgiving lookup applies only to link resolution—writes and updates keep their exact identity rules and never use the alias to choose a file to overwrite or move.

For relation-type conventions and how inline references index, see [Observations and Relations](/concepts/observations-and-relations).

---
Expand Down
11 changes: 11 additions & 0 deletions content/07.concepts/3.observations-and-relations.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ Observation categories are semantic labels, not task state or transcript time. B

Timestamp-shaped prefixes on transcript lines are also ignored as categories. Use a descriptive label such as `[decision]`, `[status]`, or `[follow-up]` when you want the line indexed as an observation.

That includes both a single clock value and a spaced range:

```markdown
[24:33.098] Speaker: We should keep the existing API.
[24:33.098 - 24:41.260] Speaker: The migration can happen later.
```

Only clock-shaped transcript markers are excluded. A descriptive category that happens to contain time-like text is still treated as a category.

### Tags within observations

The `#hashtags` at the end of an observation line add extra searchability:
Expand Down Expand Up @@ -96,6 +105,8 @@ because it aligns with our [[Team Standards]].

These inline references also create connections in the knowledge graph. The difference is that relations in a list with a leading word have explicit types (`depends_on`, `relates_to`), while inline references create a generic `links_to` connection. Both are useful.

Wikilinks resolve exact permalinks, titles, and paths first. Root-level filename stems receive the same `.md` fallback as nested paths. If exact resolution fails, a unique case-insensitive filename alias can bridge underscore/hyphen differences; aliases that match more than one note stay unresolved. See [Knowledge Format](/concepts/knowledge-format#how-wikilinks-resolve) for examples and write-identity rules.

## Why this matters

Observations and relations aren't just formatting — they're what makes Basic Memory's search and navigation powerful.
Expand Down
19 changes: 19 additions & 0 deletions content/07.concepts/7.semantic-search.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,23 @@ See [Configuration](/reference/configuration) for the full config reference.
- Model: `BAAI/bge-small-en-v1.5`
- Dimensions: 384

#### Configure a custom FastEmbed model

Choose a model from FastEmbed's installed catalog and set its actual output dimensions. Some asymmetric models also require different literal prompts for indexed passages and search queries; Basic Memory does not infer these model-specific prefixes.

For example, configure multilingual E5 with its 1024 dimensions and required `passage: ` / `query: ` prefixes:

```bash
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_document_prefix "passage: "
bm config set semantic_embedding_query_prefix "query: "
bm reindex --embeddings
```

The trailing spaces are part of the model input. Rebuild embeddings after changing the model, dimensions, or either prefix so document and query vectors use the same contract. The default BGE model is symmetric and does not need prefixes.

### OpenAI

- Requires an [OpenAI API subscription](https://platform.openai.com/api-keys) and `OPENAI_API_KEY` environment variable
Expand Down Expand Up @@ -414,6 +431,8 @@ bm reindex -p my-project

`bm reindex --embeddings` exits nonzero if any embedding fails. Treat that as an incomplete vector index and fix the reported provider or index error before retrying.

An incremental `bm reindex --search` also reconciles stale full-text rows, including orphaned entries for files whose contents have not changed. Try it before a full rebuild when text search returns content that was removed from disk or the current index.

---

## Inspecting retrieval
Expand Down
4 changes: 3 additions & 1 deletion content/10.reference/2.mcp-tools-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,16 @@ List directory contents with optional depth, glob filter, and sorting.
|---|---|---|---|
| `dir_name` | string | No | Directory path to list (root if omitted) |
| `depth` | integer | No | How many levels deep to list |
| `file_name_glob` | string | No | Glob pattern to filter files (e.g., `*.md`, `schemas/*`) |
| `file_name_glob` | string | No | Glob pattern to filter returned files (e.g., `*.md`, `schemas/*`). Nonmatching directories are still traversed within `depth` |
| `sort` | string | No | Ordering: `title_asc`, `title_desc`, `updated_asc`, or `updated_desc`. Omit for the default filename ordering |
| `page` | integer | No | One-indexed page; default `1` |
| `page_size` | integer | No | Nodes per page; default `10`, maximum `200`. Aliases: `limit`, `per_page` |
| `output_format` | `"text"` or `"json"` | No | JSON includes structured pagination metadata |

Large listings are bounded. Continue with the next `page` instead of assuming one response contains every file. File nodes include `external_id` in both text and JSON output.

Glob filtering applies to returned nodes, not traversal. For example, `depth=2` with `file_name_glob="*.md"` still finds Markdown files inside a folder whose own name does not match `*.md`.

Explicit sorts (v0.23) order folders before files, apply deterministically before pagination, and use note titles for `title_*` modes. Folders have no canonical update timestamp, so `updated_*` modes keep folders name-ascending while still listing them first.

### `list_workspaces`
Expand Down
Loading