# CHANGELOG ## Unreleased ### Breaking Changes - **Note formatting is removed.** The `format_on_save`, `formatter_command`, `formatters` and `formatter_timeout` settings, their `BASIC_MEMORY_*` environment variables, the `bm format` command and the bundled mdformat dependency are gone. Since 1.0 accepts a note's bytes before writing the file, `format_on_save` had stopped running for `bm_write` and `bm_edit` (#2005). Formatting the file after the write would make it differ from the accepted note, so the next sync would record it as an outside edit and the agent's next `expected_checksum` would conflict. Notes are now stored exactly as written. Old keys in `config.json` are ignored. To format notes, run your formatter from your editor, or over the project folder yourself. ## v1.0.0 (2026-10-29) Basic Memory 1.0 is a clean-house release. The MCP server exposes only the `bm_*` tools, the CLI is built on those same tools, and the pre-1.0 tools, commands and compatibility code are removed rather than aliased. `docs/1.0.md` and `bm man tools-migration` map every old tool and command to its replacement. ### Breaking Changes - **SPEC-35.2: the MCP server exposes only the 1.0 `bm_*` tools**: `bm_read`, `bm_write`, `bm_edit`, `bm_delete`, `bm_move`, `bm_search`, `bm_context`, `bm_list`, `bm_find`, `bm_project`, `bm_schema` and `bm_man`, plus the separate, opt-in `bm_project_delete`. They replace the earlier tools one for one or by command: `read_note`/`read_content`/`view_note`/`cat` become `bm_read`, `search_notes`/`grep` become `bm_search`, `build_context` becomes `bm_context`, `recent_activity` and the project tools become `bm_project`, and the schema tools become `bm_schema`. The old tools and their modules are deleted, with no aliases. Arguments change too: `project` takes a name, a workspace-qualified name or an external ID; search takes `mode`, `filters`, `items`, `since` and `all_projects`; edits take `command`; context takes `identifier` and `since`. Refusals are MCP tool errors with a typed `error` (`NOT_FOUND`, `ALREADY_EXISTS`, `REVISION_CONFLICT`, `LOCKED`, `OUTSIDE_PROJECT`, ...). Update MCP allowlists, agent instructions, hooks and recorded fixtures, then restart clients so they reload the tool schemas (#1838, #1839, #1849, #1944, #1947, #1959, #1962, #1963, #1964). - **Every project-scoped tool requires `project`.** `bm_read`, `bm_write`, `bm_edit`, `bm_move`, `bm_delete`, `bm_list`, `bm_find`, `bm_context` and `bm_schema` require a nonempty `project`, even with one project or a configured default. `bm_search` requires `project`, `projects` or `all_projects=true`, and `bm_project(command="recent")` requires `project`. A relative path no longer selects a project because it contains a slash. `bm_list(path="/")` lists the project's root; `bm_project(command="list")` lists projects (#1934). - **The ChatGPT `search`/`fetch` adapters are no longer in the local server.** The hosted Cloud server provides them (#1964). - **`bm tool` mirrors the `bm_*` tools.** One subcommand per tool (`read`, `write`, `edit`, `move`, `delete`, `list`, `find`, `search`, `context`, `project`, `schema`), with flags named after the tool's parameters (`--directory`, `--note-type`, `--command`, `--since`, `--mode`, `--items`, `--filters`). The subcommands `recent`, `projects`, `workspaces`, `validate`, `infer` and `diff` are removed, as are the old flags (`--folder`, `--operation`, `--after_date`, `--meta`), `--project-id` (`--project` takes an ID), `--plain`, and automatic JSON when piped. Output is the tool's text, or its JSON with `--json` (#1943). - **`bm cat`, `head`, `grep`, `ls`, `find` and `tree` run on the `bm_*` tools, and `bm tail` is removed** (use `bm tool project recent`) (#1960). Behavior changes: - `--plain`, the Rich tables and JSON-when-piped are gone; output is the tool's text, or `--json`. `--project-id` is gone; pass the ID to `--project`. - Without `--project`, the default project is used. A `/path` prefix no longer selects the project by itself, and a prefix that disagrees with `--project` is refused. - `bm ls /` lists the default project's root; `bm project list` lists projects. - `bm cat --lines` always counts the whole file, frontmatter included, and slices print numbered lines under a `Lines N-M of T` header. `bm head` loses `--frontmatter`/`--no-frontmatter` and prints numbered lines. - `bm grep -C/--context-lines` becomes `-C/--lines`, and `grep -C` drops notes with no matching line. `bm grep` returns notes only. - `--page-size` is 1-100 on every verb, and `bm find --fields` prints the tool's text. New flags: `bm grep --path`, `bm ls --glob`, `bm ls --sort`. - **`bm cloud sync`, `bisync` and `bisync-reset` are removed.** They could delete cloud-only or local files. Use `bm cloud pull` and `bm cloud push`, which never delete on the destination and stop on conflicts until you pick `--on-conflict`. The old commands print the matching pull/push command and exit 1 without touching files (#1953, fixes #1845). - **`bm schema` resolves its project like `bm tool`.** `--project` accepts a `workspace/project` name or a project ID, an unknown project fails with the tool's error, and with no `--project` and no default project it exits 1 (#1959). - **LiteLLM is an optional extra.** The default install no longer includes the LiteLLM SDK. If you use LiteLLM embeddings or reranking, install `basic-memory[litellm]` (`441166185`). ### Features - **`bm_read` reads line ranges of plain text files**, such as `.txt` and logs, with `start_line`/`end_line` (#1960). - **Chat imports return the paths of the files they wrote** (#1878). - **`bm_man` and 1.0 manual pages**: every `bm_*` tool has a section 3 manual page, served over MCP and by `bm man` (`aa8bf2644`). - **`bm doctor` reports problems in your real projects, with the command that fixes each one.** It checks the project path, index readiness, search index integrity (duplicate, orphaned and missing rows) and note materialization, and only reads: it never changes a project, the config or the database. `--json` prints the full report. The write/index/search self-test runs in a sandbox with its own home, config and database. Cloud projects are listed as skipped (`e607f817d`, `60845266d`, `d52dbc986`). - **`memory-doctor` skill** teaches an agent to run `bm doctor` and walk you through its suggested fixes (`573c3dfab`). ### Bug Fixes - Startup project indexes were unowned background tasks that could outlive the server's database. They now run with the watcher, stop with it, and a project whose index fails is logged without stopping the watcher (#1967). - **#1956**: Title search ranks the note whose title equals the query first, ahead of longer titles that contain it. Thanks @Flynn-Kawolsky for the report and the minimal repro (#1957). - **#1852**: File events that arrived while the watcher reloaded its project list were dropped. They are now kept and indexed. Thanks @SWSAmor for the precise reproduction (#1951). - One project whose directory no longer exists stopped file watching for every project. The watcher now leaves that project out and logs it (#1971). - On SQLite, `a AND NOT b` returned no results; it now means `a NOT b`, as it already did on Postgres (#1972). - **#1826**: A note whose search rows were lost (a migration that recreated the search index, a dropped refresh) stayed unsearchable, with no vectors, because its unchanged file never reached an index batch. Each index pass now rebuilds missing search rows and their vectors, and project status counts those notes (#1954). - **#1862**: With an OpenAI-compatible endpoint that returns unnormalized vectors (such as Volcengine Ark), every semantic match fell below the similarity floor, so vector and hybrid search returned nothing on SQLite. The OpenAI provider now normalizes vectors; with a custom `api_base`, the next index pass re-embeds stored vectors automatically. Thanks @MbappeWU, who diagnosed this and proposed the fix in #1869 (#1948). - Search ranking weights a note's title above its body in the SQLite bm25 score and keeps weighted scores across metadata filters (`56ba5a96a`, `e2a1a0780`, `6eda1221c`). - Relation sources are re-embedded after a forward reference resolves (#1884). - Ignore rules for a directory apply to the files under it, nested directory rules match by ancestry, and a byte-order mark at the start of an ignore file is skipped (#1929, #1949). - Moves keep the configured project root (#1930). A timed-out search is reported as a tool error (#1942). Malformed `memory://` context locators return 400 (#1885). The JSON project list honors a server's project constraint (#1937). - Tool output reads better: retry hints name the project as the call did, filter-only results show no score, `tag:` queries are repeated as typed, and section errors end their list with a period (#1974). - The OpenClaw plugin works on OpenClaw 2026.10 (#1966). - **#1817**: Files copied into a newly created project's folder before the watcher reloaded were never indexed, and the watcher ignored projects added after startup. The watcher now reloads project config, and after it attaches to a new project it runs a catch-up index pass, including while hidden-file activity continues. Thanks @TPSJASPER (#1861, #1866). - **#1850, #1853**: On SQLite, deleting a large set of vector chunks failed with "Expression tree is too large", and an interrupted search-index migration left a scratch table that blocked the next startup. Deletes now run in batches of 200, and the migration drops a leftover scratch table before rebuilding. Thanks @MbappeWU (#1857, #1859, #1865). - A stale read from object storage could save an older version of a note as a new accepted version, silently rolling the note back. A version that a newer accepted change replaced is now promoted only after an authoritative re-read confirms it (`a5b557acd`). A move that was superseded by a later one now cleans up its old file (`2e2c1be8e`). - **#1798**: `bm doctor` offers a recovery for note saves left in flight by a process that exited. While file indexing still has work owed, duplicate, missing and orphaned search rows are warnings that the index pass may clear; they become errors once indexing settles. - FastAPI is upgraded to 0.162.0, with the read cache keeping request identities stable on the new version. This replaces the 0.139.0 pin from v0.24.1 (`2f66021c1`). - **#1811**: Creating a local project with the name of an existing one but a different path is refused with `ALREADY_EXISTS`, naming both paths, instead of reporting success. The same path stays an idempotent re-index. Cloud creates skip the check, since hosted paths come from the project name (`efd157061`, `e03c2f28f`). - Search normalizes recognized project prefixes in queries (`9a0211f96`). - OpenClaw keeps explicit search filters and ignores empty tag shortcuts (`20cbcb538`, `bef49f458`). Tau prefers its native tool registrations (`2506147f9`). - Recovery guidance in tool errors and the manuals now name the `bm_*` tools (#1864, #1868). ### Security These come from a security review of the codebase (CodeRabbit deep scan). - Project boundaries are enforced where imports and storage write files, against the resolved project root (#1931, `e46f1b4c5`). - Note YAML rejects aliases and merge keys, which could expand without bound (#1933). - ZIP imports, search queries, CSV previews, Markdown directive scanning, find/replace output, section heading suffixes and ChatGPT conversation graphs are bounded (#1939, #1927, #1926, `74e41b739`, `5f8a0303a`, #1916). - Atomic file writes stage privately, and rclone credentials are created with private permissions (#1925, `1b8713e49`, `df611b0dc`). - Literal directory prefixes are escaped before moves (#1915). Legacy directory uploads skip file symlinks, and upload destinations are validated after normalization (`d6d289d3e`, #1928). - `bm cloud api-key save` prompts for the key without echoing it, so the key no longer has to appear in shell history (#1938). ## v0.24.1 (2026-10-22) ### Bug Fixes - On a fresh install, `bm status` and other commands that load the API failed with `cannot import name 'get_flat_dependant' from 'fastapi.dependencies.utils'`. The read cache imports that FastAPI helper, FastAPI removed it in 0.140.7, and the `fastapi>=0.136.1` floor let new installs pick up 0.140.13 or later. FastAPI is now pinned to exactly 0.139.0, the version CI tests. Existing installs can work around it with `uv tool install basic-memory --with 'fastapi==0.139.0'`. Reported by lastguru. ## v0.24.0 (2026-10-22) ### Security - **GHSA-4gfv-c2mm-mvj2** (high): A web page could reach a `basic-memory mcp --transport sse` or `streamable-http` server bound to `127.0.0.1` through DNS rebinding and call every MCP tool, including reading and deleting notes. The HTTP transports have no authentication, and the server did not check the `Host` or `Origin` header, so binding to localhost was not enough. Both HTTP transports now reject a foreign `Host` or `Origin` on a loopback bind and bind to `127.0.0.1` by default (#1697, see Breaking Changes). Releases before v0.24.0 are affected. Stdio, the default transport, is not. - **GHSA-pqm2-2wxw-p5hx** (low): In hosted deployments a project's path is an object-storage prefix, but path validation still resolved it on the API host and followed the host's symlinks. A project named after a host directory, such as `etc`, let a caller learn which host paths are symlinks from whether a request was refused or returned "not found". No file contents were exposed. Remote project paths are now checked lexically and never touch the host filesystem. Local projects keep the symlink-aware check (#1807). - **#1804**: `build_context` and `recent_activity` accepted any `depth`, and `/memory/recent` had no limit on `page_size`, `page` or `max_related`. On a densely linked project one deep call could run until the client timed out, and any authenticated caller, including a read-only API key, could repeat it. `depth` is now 1-5 (the default stays 1), and `page_size` and `max_related` on `/memory/recent` are at most 100. The MCP tools refuse out-of-range values with an error naming the limit; the API returns 422. - **#1805**: Security floors for direct dependencies: pyjwt >= 2.15.0 (14 advisories, reached through FastMCP's bearer auth) and litellm >= 1.91.5. The lock refreshes aiohttp, urllib3, multidict, cryptography, certifi and yarl, and FastMCP moves to 4.1.3. Pillow cannot move to 13 while fastembed pins `pillow<13`, so `read_content` now decodes only PNG, JPEG and WebP and refuses other formats, GIF included (GHSA-74r2-7ff9-mjj2), before Pillow parses them. The Docker image requires Debian's October 2026 `ca-certificates` update and upgrades pip's own CA bundle. ### Breaking Changes - **#1805**: `read_content` shows only PNG, JPEG and WebP images. GIF, TIFF, BMP and other image files return "Unsupported image format" instead of a JPEG. Text, JSON and other binary files are unchanged. - **#1683**: A refused `write_note` is an MCP tool error (`isError`), as a failed `delete_note` or `move_note` is (#1641). This covers an existing note without `overwrite`, a revision conflict on `expected_checksum`, a note that moved, and a directory outside the project. Nothing is written in any of these cases. They used to come back as ordinary results, so a client checking `isError` counted a refused write as written. In JSON mode the error message is the same payload as before (`action: "conflict"`, `error: "NOTE_ALREADY_EXISTS"` and so on). `bm tool write-note` is unchanged: error on stderr, payload on stdout, exit status 1. - **#1688**: A failed or refused `edit_note` is an MCP tool error (`isError`), as a refused `write_note` is (#1683). A refused write, such as the "modified concurrently" conflict when two clients append to one note, came back as an ordinary result whose text said "Edit Failed", so a client checking `isError` counted the append as written and never retried it. A refusal comes only from a write that rolled back, so a refused append is never in the note. In JSON mode the error message is the same payload as before. `bm tool edit-note` prints the error and exits with status 1. This reinstates #1662, which was reverted when its concurrency test found appends reported as refused that had landed; #1688 fixed that cause first. Thanks to @sammywachtel. - **#1696**: Semantic search is always on, and the `semantic_search_enabled` setting is removed. FastEmbed and sqlite-vec are core dependencies, so the setting only mattered for installs that turned it off by hand; those installs now download the embedding model and build vectors. Old `config.json` files and `BASIC_MEMORY_SEMANTIC_SEARCH_ENABLED` are ignored rather than rejected. `bm reindex --embeddings` no longer refuses. `EmbeddingStatus` gains `vector_runtime_available`; `semantic_search_enabled` is still emitted as a deprecated alias of it, so older CLIs keep reading upgraded servers, and a status from an older server is still accepted. Where sqlite-vec cannot load (python.org Python on macOS), search still falls back to keyword-only, and a vector or hybrid query says semantic search is unavailable and points at the log. - **#1697**: `basic-memory mcp --transport streamable-http|sse` binds to `127.0.0.1` by default instead of `0.0.0.0`, so the unauthenticated HTTP server is no longer reachable from the network unless you ask for it. A non-loopback `--host` prints a warning. On a loopback bind, both HTTP transports also reject requests whose `Host` or `Origin` header is foreign (DNS rebinding), honoring FastMCP's `FASTMCP_HTTP_ALLOWED_HOSTS` / `_ORIGINS`. A non-loopback bind gets that check only when those allowlists are set. The Docker image already passes `--host 0.0.0.0` and keeps working as before (#1578). - **#1704**: `bm import document` resolves a relative path against the project root, not the current directory, matching `bm ls` and `bm cat`. A command that relied on the old behavior now fails with "File not found" and the resolved path. - **#1702**: `build_context(compact=True)` no longer loads observations, and compact JSON no longer has an `observations` key (text-mode compact already hid them). Primary results, relations and related results are unchanged (#1571). - **#1600**: `bm project remove` on a cloud-routed project always deletes the project's cloud files; there is no longer a way to keep them. It warns that the files can be recovered only from a cloud snapshot (`bm cloud snapshot list`) and asks for confirmation (`--yes` skips it). It no longer deletes the local sync directory as a side effect of `--delete-notes`; the new `--delete-local-files` flag does that. MCP `delete_project` on a cloud route also always deletes files, and `delete_notes` is now documented as local-only. Local projects behave as before. A cloud-only project removed without `--cloud` is now correctly treated as cloud-routed. - **#1476**: The POSIX read tools (`cat`, `grep`, `ls`, `find`, `tail`, `man`) are on by default, so an MCP client now sees six more tools alongside the existing rich tools, and the server instructions describe projects as mount points. Set `enable_posix_tools=false` (or `BASIC_MEMORY_ENABLE_POSIX_TOOLS=false`) to hide them. - **#1395**: Markdown notes always get a permalink. The `disable_permalinks` setting and `BASIC_MEMORY_DISABLE_PERMALINKS` are retired: an existing value is ignored rather than rejected, and the key is dropped from `config.json` when it is next normalized. Notes indexed without a permalink under the old setting are backfilled during ordinary scans, which writes a `permalink` into their frontmatter. Non-Markdown files are unchanged. - **#1495**: Reading a note that does not exist exits with status 1 from the CLI in every output mode, and JSON reads carry `error: "NOTE_NOT_FOUND"`. Scripts that relied on exit status 0 with null fields need to check the status instead. - **#1531**: `edit_note(operation="replace_section")` fails when the exact heading is not in the note, instead of appending a duplicate section and reporting success. A heading such as `## Open items #urgent` must be given in full; use `append` to create a new section on purpose. - **#1343**: `bm project add --cloud --visibility private` is refused. The cloud has only `workspace` and `shared` visibility, so `private` had created a team-visible project while reporting success. - **#1596**: `bm cloud sync`, `bm cloud bisync` and `bm cloud bisync-reset` are deprecated and will be removed in a future release. `bm cloud pull` / `bm cloud push` are the supported sync workflow on Personal and Team workspaces. The mirror commands are marked deprecated in `--help`, print a notice with the pull/push command on every run, still work on Personal workspaces, and on Team workspaces exit with that notice instead of a "Personal only" error. `bm project list` no longer shows Team projects with a local sync path as `cloud-only`: `sync_supported` is now true for every workspace, and `list_memory_projects` reports the same. Help examples no longer pass `--workspace Personal`. ### Features - **#1552**: `edit_note` can edit only the revision you read. Pass `expected_checksum` (the full `checksum` from a JSON `read_note`, `write_note` or `edit_note` result) and the edit applies only while the note is still that revision. Otherwise nothing is written and the tool error is a revision conflict carrying the current checksum (JSON `error: "NOTE_REVISION_CONFLICT"`, `currentChecksum`, with the note's title, permalink and file path while it still exists, the same shape as `write_note`'s, #1719). A guarded `append` or `prepend` on a missing note is a conflict, not an auto-create. The v2 `PATCH` entity route accepts the same `x-bm-cloud-note-base-checksum` header the `PUT` route does. - **#1552**: `read_note(include_content=False)` returns only a note's title, permalink, file path, full checksum and `updated_at`, without the body. Use it to refresh a stale `expected_checksum` without reading the whole note. - **#1642**: `write_note` can overwrite only the revision you read. Pass `expected_checksum` with `overwrite=True` (CLI: `--overwrite --expected-checksum`) and the note is replaced only while it is still that revision. Otherwise nothing changes and the result is a revision conflict carrying the current checksum (JSON `error: "NOTE_REVISION_CONFLICT"` and `currentChecksum`, with `checksum` null because nothing was written, and the note at the path named by its stored title and permalink, #1719). A checksum for a path no note owns is also a conflict, so a note deleted since you read it is not recreated. Without `expected_checksum`, `overwrite=True` still replaces unconditionally. - **#1636**: Note deletes record their actor in the accepted-change journal, as creates, updates, edits and moves already did. The delete route now asks the actor resolver like the other mutations (with a new `delete` mutation kind), so a runtime that identifies its callers can say who removed a note. With no resolver, which is every local install, the row is written exactly as before and deletes keep the `delete_note` source. Thanks to @sammywachtel (#1638). - **#1550**: `bm okf export DESTINATION --project NAME` writes a static OKF v0.2 bundle from a local project, and `bm okf check BUNDLE_PATH` validates one. Export keeps concept frontmatter, categorized observations and relative asset paths, rewrites wikilinks to standard Markdown links resolved the way the graph resolves them, and records the original relation types in a `bm.okf_export` extension. It generates per-folder `index.md` files and a dated root `log.md` from the accepted-write journal. Export stages beside the destination, validates before publishing, refuses to overwrite without `--replace`, and restores the previous bundle if publication fails. `okf check` reports per-file, per-rule diagnostics and exits nonzero on any violation, including unreadable or non-regular files. Both commands take `--json`. - **#1608**: Accepted note writes stamp `created_by` and `updated_by` into frontmatter when the runtime supplies an author, so the file itself says who wrote it. Cloud composes ` via ` for API-key writes. The keys are server-stamped: whatever a writer submits for them is overwritten. `created_by` is set once and carried forward, and a note written before this change never gains one. Unchanged authorship does not rewrite the file, moves and deletes do not restamp, and local runtimes, which supply no author, leave both keys untouched. - **#1558**: `QUERY /v2/search/` (and `POST /v2/search/` for clients that cannot send QUERY) searches an explicit set of projects in one database with one query. The body is the project search body plus `project_ids`, a required list of internal ids the caller has already authorized; an empty list answers no rows and there is no way to ask for every project. Full-text, vector, and hybrid retrieval run the same reader the project route runs, so one project here ranks exactly as its own route does, and results are one ranking over the union rather than merged per-project pages. Hits are hydrated only from projects in scope. Every search result, on both routes, now carries `project_id` and `project_external_id`. - **#1558**: `search_notes(search_all_projects=True)` runs one scoped query per database instead of one search per project, so a local vault with many projects is one query, and each cloud workspace is one query, with results attributed to their project by the server rather than by which request they came back on. A new `projects` parameter searches a chosen subset by name or external id; an unknown name is an error. Cross-database results are still merged by score, one failing database is skipped with a warning and an inexact total, and a retryable outage or a server too old to attribute its results fails the whole page. - **#1558**: Vector retrieval reads only the projects in scope and fills the window it asks for. The sqlite-vec table gains a `project_id` partition key, so a scoped nearest-neighbour query ranks each project's own vectors instead of taking the k nearest across the whole database and discarding the out-of-scope ones, which could leave a small project with an empty page for a query its notes answered. Existing local storage is carried into the partitioned table without re-embedding. On Postgres the nearest-neighbour statement now runs on the HNSW index (its tie-break sort keys had kept the planner on an exact scan of every vector), with `hnsw.ef_search` sized to the candidate window and an iterative scan that keeps going until the scope and manifest filters have admitted enough rows. That scan needs pgvector 0.8 or later; an older extension is reported as a dependency error instead of quietly returning short windows. - **#1558**: A vector or hybrid search with structured filters (note types, dates, categories, metadata, path prefixes, valid time) now fills its candidate window. The vector index ranks by similarity alone, so a window taken straight from it and filtered afterwards could hold few admitted rows while more sat just past it, and the page came back short although matches existed. The reader re-reads the window with a bounded geometric overfetch until it holds enough admitted rows, the ranking is exhausted, or its tail falls below the similarity threshold. Unfiltered searches read their window once, as before. - **#1512**: Word, PowerPoint, and CSV files get the same sidecar Markdown note a PDF gets. `bm import document ` indexes the project, extracts the file, and writes `..md` next to it plus a run note under `document-ingestion-runs/`, all through the existing parser-neutral document contract. Office formats run through Microsoft's `markitdown` converters (`basic-memory[documents]`) inside the same killable, byte-capped worker process as pdf-inspector; CSV renders a bounded stdlib preview with strict UTF-8. Re-running is a no-op while the source is unchanged, and the command refuses to overwrite a hand-written or enriched note at the sidecar path. PDF keeps pdf-inspector and works through the same command. - **#610**: The manual's SYNOPSIS blocks are now generated from the tool registry. `just man-regen` renders the MCP call on every section-3 page from the schema clients actually receive (required parameters first, then defaults, in schema order) and a test holds the shipped blocks byte-equal to the rendering -- change a tool signature without regenerating and CI points at the fix. Those pages declare `generated: registry`; curated sections stay hand-owned. The manual also gains `basic-memory-diagnostics(3)`, closing the one gap between the section-3 corpus and the tool registry. - Notes are readable as MCP resources. Every `memory://` URL Basic Memory hands out now answers the standard `resources/read`: `memory:///` returns the note's raw markdown, frontmatter included, with the identifier accepted as a permalink, title, or file path. Unknown notes point at `search_notes`; binary files point at `read_content`. `memory://man/...` keeps answering as the manual and `memory:////info` as project info, whichever template the server matches first. - **#610**: The manual ships in the package and is served over MCP. The 21 section-3 pages (one per MCP tool -- `search-notes(3)`, `write-note(3)`, ...) now live in `src/basic_memory/man/man3/` as canonical, portable notes. The MCP server exposes them as resources: `memory://man` is the index and `memory://man/` is a page, with every page also listed as a concrete resource so clients that browse `resources/list` see each one with its summary. Page references parse the way people and models actually write them -- `search-notes(3)`, `3/search-notes`, `search_notes`, `man3/search-notes.md` -- and the server instructions point agents at a tool's page before first use. `bm man ` prints a page as Markdown and `bm man list` is apropos; `bm man install` is unchanged. - **#1259**: `write_note` now tells the caller when a freshly created note looks like notes that already exist. On a server with semantic search enabled, a create probes the vector index with the new note's title and opening content and appends a "Similar existing notes" section listing the closest matches, phrased as a question -- did you mean to write to one of these? -- with the ways out spelled out: merge into the existing note with `edit_note` and delete the new one, link the two with a relation, or ignore it. JSON output carries the same list as `similar_notes`. No similarity scores are shown and nothing is overwritten on the caller's behalf: on the default embedding model a near-duplicate and a merely related note score in the same band, so the decision stays with the agent, which has the context the score does not. - **#1398**: POSIX-style read tools. MCP gains `cat`, `grep`, `ls`, `find`, `tail`, and `man` next to the rich tools, and the CLI gains the same verbs (`bm cat`, `bm head`, `bm grep`, `bm ls`, `bm find`, `bm tail`, `bm tree`) over one shared translation layer. Notes are indexed by heading, so `cat` can read one section, a line range, or a token budget instead of the whole note. Projects act as mount points: `ls /` lists them, and a path whose first segment names a project routes there, so the paths the tools return can be passed straight back. `find` takes metadata predicates (`status=active`, `confidence>0.6`) and a `--fields` projection of frontmatter values. **This ships an Alembic migration** adding the `note_section` table. - **#1501**: `read_note` accepts `start_line` / `end_line` and returns numbered lines with the next range to read, and `grep(context_lines=N)` returns merged match windows instead of whole notes, with `max_matches` bounding the lines per note. The CLI equivalents are `bm grep "retry" -C 3` and `bm tool read-note NAME --start-line 120 --end-line 180`. - **#686**: `search_notes(compact=True)` and `build_context(compact=True)` return identifiers, metadata, relation targets, and pagination without note content, so an agent can pick what to read before paying for the bodies. `bm tool search-notes` and `bm tool build-context` take `--compact`. Default responses are unchanged. - **#1426**: Observations can say when a claim holds (SPEC-82). An authored qualifier such as `- [decision] @effective:2026-06-10 The cache layer will use Redis.`, a range (`@effective[2026-06-10,2026-07-27)`), or a quoted multi-word date (`@occurred:"June 10, 2026"`) is indexed as valid time; the kinds are `effective`, `valid` (the default), `occurred`, `due`, and `mentioned`. `search_notes` gains `valid_at`, `valid_overlaps`, and `time_kind` filters, and a malformed filter is refused instead of ignored. Searches without them rank as before. A qualifier that does not parse stays in the observation text. **This ships an Alembic migration** adding the time index table. - **#1246**: Ordinary Markdown links to files in the project (`[Guide](../guides/Guide.md)`, reference-style links, `/`-rooted paths) become `links_to` relations, the way wikilinks do. External URLs, images, code, fragment-only links, and paths outside the project are ignored, and the authored Markdown is not rewritten. (PR #1514; see the #1514 fix below for how the paths resolve.) - **#1422**: Wiki projection. `bm wiki status`, `bm wiki validate`, and `bm wiki rebuild` (with `init` and `update` as aliases) generate root and per-folder `index.md` and `log.md` navigation pages for a local project, with `--project`, `--all`, `--json`, and `--dry-run`. The projector is deterministic, so local and cloud produce the same bytes; each `log.md` keeps the 25 most recent changes. It never overwrites a hand-written `index.md` or `log.md` (those are reported as conflicts), links empty folders from their parents, and does not recreate pages for a deleted folder. The change order comes from a new per-project accepted-change journal. **This ships an Alembic migration** (#1381, #1382, #1396, #1433, #1434, #1436, #1484). - **#1006**: PDF ingestion. `basic-memory[pdf]` adds a pdf-inspector extraction adapter that runs in a bounded worker process and turns a PDF into an extracted-text sidecar note plus a `type: document_ingestion_run` provenance note, under the same parser-neutral contract local and cloud share (#1178, #1377). Generated document bodies are searchable but cannot mint observations or relations from extracted text. - **#1366**: Document observations can cite the PDF page they came from. The enrichment contract (`enrich_document_markdown`) writes OKF-compatible `sources` entries and Markdown footnotes pointing at `file.pdf#page=N`, with an optional printed page label, and the page is checked against the extraction's page count. Provenance also keeps the extraction's page map, so a span of the raw text can be traced to its pages without re-parsing the PDF (#1490, #1519). - New extracted-text sidecars use `type: extracted_text`. Sidecars written earlier keep `type: document`; both are accepted, the stored value is preserved, and old sidecars still match their run notes and are reused on re-import. The per-page page map now lives only on the ingestion-run note (`document-ingestion-runs/.md`), and the sidecar keeps a summary without it, so a 424-page PDF's sidecar frontmatter drops from about 23 KB to about 1 KB. - **#1744**: An extracted-text sidecar is linked to its source file by a `derived_from` relation, projected from the validated `source.entity_external_id` in its frontmatter. The relation exists even while the sidecar's raw body semantics are disabled, and it does not change the extracted text or its page offsets. - Non-Markdown files (PDFs, images, Office documents) store `content_type` and `format` in their entity metadata at index time, and directory listings expose `format`. MIME types for every supported or extracted extension (docx, pptx, xlsx, webp, canvas, ...) are pinned before falling back to `mimetypes`, so slim images without `/etc/mime.types` no longer record Office files as `text/plain`. Metadata filters still match Markdown notes only. - **#993**: `locked: true` in a note's frontmatter makes it read-only to the note API. Edits, overwrites, deletes, and directory deletes that include it are refused with HTTP 423, and no API call can unlock it. Direct filesystem edits and deletes still win, and imports are not bound by the lock. See `docs/LOCKED_NOTES.md`. - **#1254**: `bm prune` removes index entries for files that the current `.bmignore` or `.gitignore` now excludes. It lists the entries first, takes `--dry-run` and `--yes`, and points cloud projects at `bm cloud prune`. Indexing does not do this on its own because an upgrade that changed the ignore defaults would otherwise drop notes. - **#1414**: `bm project add` indexes a local project before returning (`--no-wait` opts out), and `bm project index NAME` reindexes one. `bm status --json` reports readiness per stage (files, relations, embeddings) with a phase that tells a never-indexed project from an idle one, and `bm status --wait` now waits until every stage settles or `--timeout` passes. **This ships an Alembic migration** backfilling `last_indexed_at`. - **#1294**: Full-text search finds words inside unsegmented scripts (Chinese, Japanese, Korean, Thai, Lao, Tibetan, Myanmar, Khmer) on SQLite and Postgres, by indexing character unigrams and bigrams alongside the existing word index. **This ships an Alembic migration**; existing notes gain this recall after a reindex. - **#1336**: The `openai` embedding provider honors `semantic_embedding_api_base` and `semantic_embedding_api_key`, so it can point at any OpenAI-compatible endpoint (llama.cpp, vLLM, TEI, LM Studio, Ollama) without the experimental litellm path. Thanks to @mikemikimike (#1365). - **#610**: The manual's `## PARAMETERS` sections on section-3 pages are generated from the tool schemas (#1478), and the section-1 SYNOPSIS and OPTIONS blocks are generated from the Typer command tree (#1524, thanks to @FBISiri), with drift tests for both. - **#1455**: Search results carry `content_length` and `content_truncated`, metadata fields keep their JSON types (numbers, booleans, lists), and `bm ls --plain` and `bm find --plain` report further pages on stderr so stdout stays pipe-clean (#1456, #1457). - `bm install codex`, `bm install claude-code`, `bm install tau`, and `bm install pi` install the Basic Memory plugin or package for that host, with `--dry-run` and `--yes`. Codex and Claude Code installs delegate to the host's own plugin CLI, and `claude-code` takes `--scope user|project|local`; Tau and Pi copy the packaged resources and keep existing config. None of them touch the Basic Memory database (#1497, #1498, #1493, #1492). - **#1487**: Tau integration. Tau sessions recall the active branch's latest checkpoint, tasks, and decisions at startup, capture knowledge as work settles, and write an awaited checkpoint before compaction. Coding sessions are keyed by repository identity and write shared Coding Session, Session, Task, and Decision schemas that the Claude Code and Codex packages also use (#1489, #1493). - **#1488**: Pi integration. The `@basicmemory/pi-basic-memory` package adds `/bm-status`, `/bm-recall`, `/bm-capture`, and `bm_recall` / `bm_capture` tools, over either the `bm` CLI or `pi-mcp-adapter`, configured per project in `.pi/basic-memory.json`. Automatic recall and capture run only in a trusted workspace (`BASIC_MEMORY_PI_TRUST_WORKSPACE=1`), and `/bm-status` reports whether they are on, off, or blocked and why (#1492, #1509). - OpenClaw's `write_note` accepts `metadata`, `tags`, and `note_type`, and `edit_note` accepts `metadata`, matching the core MCP tools. Thanks to @lastguru-net (#1474). - The manual gains `comark(7)`, a quick reference for the Comark `::bm-*` components notes can embed (`bm man comark`, `memory://man/comark(7)`), and a new `memory-comark` skill teaches agents to author them: the component vocabulary, directive and body rules, live query pipelines, how to check numbers they cannot see rendered, and the coded errors a broken component shows. Component problems never block a write. The skill is registered in the OpenClaw manifest. - Skills: `memory-reflect` and `memory-defrag` work on a project's notes instead of `MEMORY.md`. Reflect folds recent activity into the notes each topic belongs in, writes a dated reflection note, and resumes from its last one. Defrag writes a plan note, applies what loses nothing, and merges or deletes only when told to. Both pass `expected_checksum` on every edit. The note-writing skills date facts with temporal qualifiers (`@effective`, `@due`, ...). The wheel ships the distributed skills under `basic_memory/data/skills`, so hosts that load skills from the installed package can use them. - New `memory-okf` skill: makes a project ready for OKF export with the note tools. It finds non-`.md` notes, notes at the Wiki's reserved `index.md`/`log.md` names and reserved export frontmatter, then fixes them with `move_note` and guarded writes. - New `memory-agents` skill: write, run and check Basic Memory Cloud agents (notes with `type: agent`), including their frontmatter, watch triggers, run logs and skip reasons. ### Bug Fixes - Fixes from the v0.24.0 release live run: - `build_context` refuses a `memory://` title URL that names more than one note, as `read_note` does, instead of building context for one of them. Pass the permalink. - `build_context` related results report `created_at` with a timezone offset, like primary results. - `delete_project(delete_notes=True)` on a local project reports that the files were deleted, instead of "did not report a completion status". - `write_note`'s "Similar existing notes" advisory skips notes the new note already links to. - `view_note` sets the note off with `` markers instead of `---`, which ran into the note's own frontmatter fence, and its instructions are no longer indented. - Vector and hybrid searches report `total` as the results seen through the current page, still with `total_is_exact: false`, instead of `0`. - `tail` rows carry `updated_at`, the time they are ordered by, and `bm tail` shows it. - `bm reindex --help` no longer says `--embeddings` requires semantic search (#1696). - Tool docs, the manual and the `list_memory_projects` footer no longer promise a "session's active project". MCP requests carry no session state under the current protocol, so a call without `project` always uses the default project, locally and in the cloud. `write_note` and `edit_note` end with `[Project: 'name']` instead of `[Session: Using project 'name']`, and say when no project was given and the default was used. - **#1726**: `bm reindex --embeddings` now finishes oversized notes before it reports success. Vector sync embeds at most 256 chunks of one note per pass and defers the rest, and the explicit reindex ran a single pass, then printed "Embeddings complete" and forced its progress bar to 100% with those chunks still missing from semantic search. A `--full` rerun cleared vectors and repeated the same first shard. The reindex now re-runs deferred notes until none remain, clearing vectors only once for `--full`. If a pass stops making progress, it reports how many notes still have pending chunks, says how to continue, and exits non-zero. Reported by @beru-ant-king; @lastguru-net independently reached the same fix in #1730. - **#1732**: An API edit no longer leaves a note's observations and relations without vectors. The accept path publishes only the note body as a temporary search row, and the observation and relation rows appear when the file is written and indexed in the background. The route also scheduled its own embed, which often ran first, embedded the body alone, and left nothing to embed the rest. A background index pass did not repair it, because the file looked unchanged. Now the materialization job embeds the note once, right after it indexes the written file, as cloud's materialize job already did. Routes no longer schedule vector sync for note writes, edits or moves. Embeds run in a separate bounded pool keyed by note, so a slow embedding provider no longer holds up other notes' file writes; one note's embeds still run in write order. Reported by @beru-ant-king with a reproducer. - **#1691**: Editing a note no longer re-embeds all of its observations and relations. Vector chunks were keyed by the search row id they were cut from, and every rewrite recreates those rows with new ids, so nothing matched the previous manifest: about 86 chunks per edit on large ledger notes. Chunks are now keyed by a hash of their text, so unchanged text keeps its embedding. **This ships an Alembic migration** that re-keys existing chunks in place; nothing is re-embedded by it. - **#1720**: CLI output prints project names, paths, and error messages as typed. Rich used to read bracketed text in them as markup: `proj [x]` printed as `proj `, `[bold]` restyled the line, and a value containing a closing tag such as `a[/b]c` crashed the command with `MarkupError`. The deprecated `bm cloud sync`, `bisync` and `bisync-reset` now print only their own deprecation notice, without Click's extra "DeprecationWarning: The command ... is deprecated." line. - **#1718**: `write_note`'s "Similar existing notes" advisory no longer suggests notes on unrelated topics. It used search's relevance floor (0.55), which the nearest neighbor of almost any note clears on the default model. On the default model it now lists only notes scoring 0.70 or higher: rewrites of an existing note scored 0.77 to 0.93, and unrelated neighbors at most 0.67. Other embedding models keep `semantic_min_similarity`, since their scores sit on a different scale. Hybrid search's handling of gibberish queries is unchanged; the measurements showed no threshold that separates it from real matches. - **#1716**: A note's `created_at` no longer resets on every edit, move or reindex. Without a frontmatter `created`, the parser falls back to the file's ctime, which each atomic rewrite or rename moves, and reindexing an existing note copied that time into the row. Now an existing row keeps its creation time, and only a declared frontmatter `created` changes it. A brand-new file still takes its file time. - **#1717**: `build_context` text output names the source of relations the primary note does not own. An incoming `relates_to` used to be listed bare under its target, so it read as a self-link; it now reads `- [[Brewing Notes]] relates_to [[Bean Origins]]`. Relations the note owns keep the bare form, and JSON output is unchanged. - **#1720**: `edit_note` `insert_after_section` no longer puts a blank line between an inserted list item and the section's list, which split one list in two. The item joins the list directly, below any blank line under the heading. A paragraph inserted above a paragraph still gets the blank line that keeps them apart. - **#1595**: `basic_memory_diagnostics` lists the `BASIC_MEMORY_*` environment variables that override `config.json`, redacted the same way as the file dump. It used to print only the file, which can disagree with what the server is using. Other `BASIC_MEMORY_*` variables are listed by name only. Env names now match config fields in any letter case, as pydantic-settings reads them: a lowercase `basic_memory_log_level` used to lose to the file value, or, when the file lacked the key, take effect and then get written into `config.json`. - **#1593**: The CLI's list of commands that skip startup initialization no longer names `sync` and `watch`, which are not commands. A test now keeps the list to registered commands. Thanks to @FBISiri. - **#1651**: A document import's ingestion-run note no longer says "exact storage materialization is pending", which read as a live status long after processing finished. New run notes say what they record and link the original file and its extracted-text note. Existing run notes keep their old text. - **#1653**: The `write_note` documentation now says what `overwrite=True` does to frontmatter: the body is replaced, keys the write sets replace the old values, and keys only the existing note has are kept. Existing frontmatter that cannot be parsed is discarded. Behavior is unchanged. - `bm tool edit-note --help` lists all six edit operations and documents `--section` for `replace_section`, `insert_before_section` and `insert_after_section`. Thanks to @xhkzdepartedream (#1708). - **#1604**: `bm cloud push` and `bm cloud pull` on Team workspaces are much faster. The project is listed with one `Depth: infinity` PROPFIND instead of one request per directory, and eight files transfer at once. File bodies stream to and from disk, so memory does not grow with file size. This needs a cloud service that answers recursive listings; against an older one, or a project too large for one listing, the command stops with a message naming the cause. - **#1654**: A Markdown file kept in step by a one-way sync tool (rclone sync, a backup script) is no longer re-indexed and rewritten forever. Indexing writes a `permalink` (and `title` and `type` with `ensure_frontmatter_on_sync`) into a file that arrived without them. The sync tool then copied its original back, which read as a change. The entity now also records the checksum the file arrived with (a new `entity.sync_checksum` column, added by a migration), and a file matching either checksum counts as already indexed. Frontmatter is still written. #1655 applies the same check to single-file indexing, using the checksum storage reports. - **#1667**: Moving a directory moves its notes the same way `move_note` does. The directory move used the old storage-first path, which moved the file and the entity row but left the note's accepted content at its old path and revision. Each note now moves as an accepted note move. Regular files still move their bytes, and per-file failures are reported as before (#1670). - **#1641**: A failed `delete_note` or `move_note` is reported as an MCP tool error. A refusal, for example from a read-only API key, came back as an ordinary result whose text said "Delete Failed" or "Move Failed", so clients read it as success. `delete_note` still returns `False` for a note that does not exist. - **#1683**: `read_content` never returns another file for a path that does not exist. It resolved through the fuzzy fallback, which matched any note sharing a word with the path (`disk/nope.txt` returned a note in `disk/`). It now resolves only exact paths, permalinks, titles and ids, and a miss is "Resource not found". - **#1683**: `NOT` excludes a term found anywhere in the note. `coffee NOT pour` returned a note whose title has "coffee" and whose body has "pour": SQLite evaluated `NOT` in each column separately, and the vector half of hybrid search ignores Boolean operators. A search that uses `AND`, `OR` or `NOT` without an explicit `search_type` now runs as full-text. - **#1683**: `read_note` with JSON output (and `cat`) returns `checksum`, the revision `write_note`'s `expected_checksum` compares, so an agent can overwrite only the revision it read. - **#1685**: `grep` matches keywords by default, so a pattern found in no note returns no results. It ranked by meaning whenever semantic search was on, and nearest-neighbour ranking always returns something: `grep("Ethio.ia")` listed unrelated notes. Pass `semantic=True` (`bm grep --semantic`) to rank by meaning. This replaces the `literal` parameter and the `-F` flag, and `context_lines` (`-C`) no longer needs either. - **#1681**: On Postgres, saving a note twice in quick succession no longer answers 500. Two refreshes of the same note's search rows could deadlock or collide on `search_index_pkey`, and the loser failed the save even though search rows are derived state. A refresh that loses that race now logs a warning and leaves the winner's rows for the next refresh. The save's search row is written after its accept commits rather than inside it, so a failed refresh can no longer roll back the note. Thanks to - **#1686**: The file watcher logs a warning when a new directory cannot be read. On Linux, notify drops the error when it cannot watch a new directory, so files written into it were never indexed and nothing said why. The warning names the directory and says to run `bm project index ` once its permissions are fixed. Thanks to @sammywachtel. - **#1676**: `search_notes` accepts the metadata filter shapes agents actually write. Bare operator names (`gte`, `in`) work as aliases for `$gte` and `$in`, one field can take several operators (`{"$gte": a, "$lte": b}`), and `$contains` (array contains) and `$exists` are new. An unknown operator's error now lists the valid ones. A rejected filter no longer leaves its count query running after the request returns: search and count run in one task group, so a failure cancels the other (#1675). - **#1657**: A full-text query that mixes a punctuated word with other words finds notes that contain all of them. `IT-644 cacheability` returned nothing: one punctuated word made SQLite quote the whole query as a single exact phrase, which only matches when the words are adjacent. Now only the punctuated word is quoted, and every word must match in any order: `"IT-644"* AND cacheability*`. Thanks to @dougvann. - **#1701**: Environment overrides are no longer written into `config.json`. Any config save (a project add, a migration, first run) wrote the merged settings, so a one-off `BASIC_MEMORY_*` variable became permanent. A save now keeps the file's own value for every env-overridden setting. Commands that name a setting still save it: `bm config set/unset`, `bm cloud api-key save`, `bm cloud workspace set-default`, `bm cloud logout`, `bm cloud promo` and `bm project default` (#1631, #1598). - **#1699**: A case-only rename (`config.md` to `Config.md`) on a case-insensitive filesystem no longer leaves a permanent ghost note. The index pass's delete check now matches the exact spelling against the directory listing, so the next pass removes the stale entry (#1627). - **#1700**: In a local project, a note too large to embed in one pass finishes embedding on later index passes without a manual `bm reindex`; #1691 already stopped unchanged observations from being re-embedded (#1605). The hosted runtime does not resume these notes yet. - **#1698**: Appending `---` or `===` after a paragraph with `edit_note` no longer turns the paragraph into a heading. When an append or prepend would form a setext heading over existing text, a blank line separates them; every other join, including list items and observations, is unchanged (#1585). - **#1705**: Note-tool fixes from the live run (#1634): - A line read that starts past the end of a note is an error ("start_line 500 is past the end of the document (17 lines)") instead of "Lines 500-17". - A link that climbs out of the project is no longer stored as an unresolved relation. - A `write_note` conflict after a move names the note that actually owns the path; the `already_exists` outcome gains `external_id` and `permalink`. - `recent_activity` describes its scope accurately, and an empty result from any tool returns an explicit `[]` text block. - **#1704**: CLI polish from the live run (#1635). `bm project add` and `bm project index` show embedding progress. `bm config set default_project` rejects an unknown project and accepts display names. `bm project index --help` shows user-facing text, the `.bmignore` path in help points at the real config directory, and a refused OKF export no longer prints a misleading summary. - **#1663**: An unhandled API error no longer stalls the server for seconds while it is logged, and logs no longer contain the values of local variables from tracebacks. Loguru's `diagnose` mode called `repr()` on every frame's locals, and each ASGI frame holds the whole request scope. The file, stdout and Logfire sinks still log the full traceback without those values. Test mode keeps them. Thanks to @sammywachtel (#1679). - **#1643**: Project status is served over `GET /v2/projects/{id}/status`. It was a POST, so a read-only API key got "This API key is read-only" on any empty search, because the empty-result guidance checks project status. `POST` remains as a hidden, deprecated alias for older clients. When workspace discovery fails in every workspace, the error gives each workspace's reason, such as a reached spending limit. - **#1645**: An empty search no longer says a project "has never been indexed" when it has indexed notes. Readiness required a completed full index pass, which a project indexed note by note (every project created in Basic Memory Cloud) never records. A project with files and no indexed notes still gets the "index first" guidance. - **#1656**: On Postgres, vector storage is created when the database is initialized, never while serving. Each embedding job ran `CREATE INDEX IF NOT EXISTS` on first use, which locks the table, so concurrent chunk and embedding writes queued behind it and timed out. Initializing an already-initialized database reads the catalog and takes no locks. - **#1659**: On Postgres, two processes initializing the same new database no longer race on `CREATE EXTENSION vector` and fail with a unique violation. Vector storage DDL takes a transaction advisory lock and rechecks the catalog inside it. Extension availability is checked directly, so a real error is no longer reported as "pgvector extension is unavailable". - **#1586**: `write_note` and `edit_note` report the note's real checksum instead of `checksum: unknown`. The typed client parsed a response model without checksum fields, and file materialization runs after the response is built, so neither value reached the tool. The tools now report the checksum recorded when the write was accepted, which is the value checksum-guarded edits compare against. Thanks to @tonydzi for the report and fix (#1617, landed as #1619). - **#1624**: A local project whose name is not already its permalink (`My Research`, `Gamma-Mixed`) is indexed at startup and watched again. Startup rewrites config keys to permalinks, but the database keeps the display name, and config was then looked up by that name with an exact match. The project was skipped as "not locally indexable" and treated as cloud-routed. Config entries are now matched by permalink. - **#1632**: On an install with no cloud credentials, an unknown or deleted project name reports "project not found" instead of "Cloud routing requested but no credentials found". Unknown names still route to cloud when cloud is available. - **#1628**: The MCP `man` tool no longer asks a local install for cloud credentials. Without a `manual` project, an unbundled page returns "No manual entry for ...", and query mode says it needs that project. - **#1626**: `build_context` resolves a `memory://` title URL to that note, and returns nothing for a URL that names no note. The routed URL carries the project prefix (`main/Cache Layer Design`), which the title and file-path lookups never matched. Titles therefore resolved only through a fuzzy search that often picked a note linking to the target, and a miss returned whatever ranked first. The resolver now tries the exact lookups on the remainder before any fuzzy match, and `build_context` no longer fuzzy matches at all. - **#1625**: `bm wiki` projects local projects that have had API or MCP writes. The projector waits until every accepted change is materialized, and the local runtime never recorded that, so a single write left the wiki `partial` for good. Local writes and deletes now mark their journal rows once the file work settles, as cloud does. - **#1629**: `read_content`, `cat` and `read_note` on `notes/foo.txt` return that file, not the same-stem `notes/foo.md`. An identifier with a non-Markdown extension now matches its exact file path before the extension-less permalink candidates. - **#1630**: When `BASIC_MEMORY_MCP_PROJECT` differs from the project name only in case (`ALPHA` for `alpha`), `search_notes(search_all_projects=True)` and `projects=[...]` find the project again, and `projects=["BETA"]` matches `beta`. Search scoping now compares project names by permalink, as routing does. - **#1633**: Tool descriptions, docstrings and error guidance now pass every argument after the first by keyword in their example calls. Several showed the old project-first positional order (`read_note("qa", "notes/x")` reads a note named `qa` from project `notes/x`), a retired `list_projects()` tool, or a `kind=` parameter that `search_notes` does not have. A test now checks every example against the registered tool signatures. - **#1549**: A note whose frontmatter sets a permalink that is not already a slug (`s/2026/09/ses_AbCdEfGhIj`) is reachable by `memory://` URL again, in `build_context` and `read_note`. The stored permalink is kept verbatim, but the resolver stripped the routed project prefix only from the slug form of the URL (`ses-ab-cd-ef-gh-ij`), so `build_context` returned an empty result and `read_note` found nothing. The resolver now tries the caller's own spelling of the path before its slug. - **#1621**: A failed search refresh no longer removes a note from search. Refreshing an entity deleted its old search rows in one committed transaction and wrote the replacement rows (and, on Postgres, their full-text chunks) in another, so a timeout while writing the replacement left an existing note with no search rows, and nothing rebuilt them until the note was edited or the project re-indexed. The delete and the replacement now commit together: a failure keeps the previous rows, and a failed first index leaves nothing partial behind to retry against. - **#1598**: Under `BASIC_MEMORY_PROJECT_ROOT`, a project name whose permalink contains `/` (such as `Research/2026`) is refused, so every project under a shared root stays a single top-level directory. Cloud stores and purges projects by that top-level prefix, and a nested name could overlap another project's files. The rule lives in `project_permalink`, which cloud calls when it creates projects. - **#1606**: Deleting a non-Markdown file (an image, a PDF) now removes it from storage. The delete runner compared the accepted checksum with a SHA-256 of the stored bytes, but an accepted checksum is not always a content hash (cloud records ETags), so the delete was skipped and the next reindex brought the file back. Storage now owns the compare-and-delete through `delete_file_if_matches`. This changes the `NoteFileDeleteStorage` protocol. - **#1601**: Wiki-projected `index.md` files no longer carry `bm_parse_semantics: false`, so the wikilinks they list become graph relations. `log.md` stays graph-silent. - **#1603**: Model-facing text (tool descriptions, server instructions, prompts, skills) was audited against the real tool contracts. Suggested calls use keyword arguments (a positional `delete_note` example would have deleted a note named after the project), skills use real parameter names and operations, and under-described tools such as `search_notes`, `grep`, `edit_note` and `move_note` now send their full contract to clients. Prompts no longer push agents to create notes unprompted. - **#1581**: The sqlite-vec stale-vector cleanup no longer stalls on large vaults. Its DELETE compared each chunk's `source_hash` against the outer vector row, which made the subquery correlated, so SQLite re-ran it once per vector: quadratic work that held the write lock long enough for concurrent writers to fail with `database is locked`. The subquery now joins the vector row by rowid, and the cleanup deletes the same rows in one pass. Thanks to @mikemikimike for the report and fix (#1584). - **#1609**: `read_note` on a Markdown file path that does not exist (`notes/x.md`) returns the ordinary not-found response again. Strict resolution already checks file path, permalink, and exact title, so a miss there confirms absence, and the tool no longer falls back to title and text search for an explicit path. That fallback was what surfaced the problem: in a project with no recorded full index pass, which is common for hosted projects whose notes read fine, an empty search answers with the "Project Index Required" guidance, and JSON reads raised it as `Fallback search failed: # Project Index Required` instead of `NOTE_NOT_FOUND`. Title and free-text identifiers keep the search fallback and the guidance. - **#1607**: `move_note` applies its cross-project guard to directory moves as well as file moves. The guard ran only after the directory branch had returned, so `work/moved` was refused for a note and accepted for a directory. The guard also no longer rejects a destination whose first folder is named after another project when that folder already holds notes in the current project: a knowledge base organised by domain has such folders, and an existing local folder is evidence of a same-project move. A first folder named after another project that does not exist locally is still rejected. - **#1514**: Markdown path links resolve against the note's own path at resolution time, the way wikilinks do, instead of at parse time from the file's location on disk. The parser had derived the note's project path with `relative_to` on the filesystem path, which raised for content parsed from anywhere outside the project root (a hosted note read from object storage, for one) and gave a wrong base for any other temporary location. The graph now stores the path as authored (`../guides/Guide.md`, `./same.md`, `/root.md`); both resolvers turn it into a project path from the source note, and background resolution keys path targets by their source note. Wikilinks spelled `[[../x.md]]` or `[[./x.md]]` resolve by the same rule. - **#1558**: `search_notes(search_all_projects=True)` and `projects=[...]` rank merged full-text hits by score strength instead of raw value. SQLite bm25 scores are negative with lower meaning better, so sorting raw values put the weakest hit first and cut every page from the wrong end of the ranking; page two repeated page one. Every hit on a page that spans projects now carries `project` (JSON) or a `- project:` line (text), so the next call can be routed to the right project. - **#1557**: A vector or hybrid search with reranking enabled retrieves once per request. A page reaching past the fixed reranked prefix used to run a second full retrieval (query embedding, vector query, and for hybrid a second FTS pass) only to rebuild that prefix. The prefix is now read from the request's own window at the fixed window's chunk bound, on the project route and the scoped `QUERY /v2/search/` route alike, so every page still reranks the same rows with the same passages. Hybrid tail rows are ordered by where each row first entered either ranking, counting vector chunks before they collapse into rows, so a deep page cannot move a row across one already returned. SQLite full-text results break score ties by row id, as Postgres already did, so a smaller window is always a prefix of a larger one. The `stable_pool_refetched` field is gone from the internal search trace. - **#1458**: A note whose file stem equals its project's name is now readable by its bare identifier. `split_project_permalink_prefix` matches a leading path segment against a project's permalink via `generate_permalink`, which drops file extensions -- so a single segment like `moby-dick.txt` in project `moby-dick` collapsed to the project's own permalink with an empty remainder, and `cat`/`find` refused it as "names a project, not a note" instead of resolving the note. A prefix claim that would leave no remainder now requires the raw segment to spell the permalink exactly, extension included; a claim that still has a remainder after it is unaffected, since project names never carry a real extension in that position. - **#1437**: An observation and a relation can no longer collide in the search index. A relation's permalink is `from/type/to` with the type authored by the user, so a note that says `- [decision] redis` and `- observations [[decision/redis]]` gives both rows the identical address; Postgres raised an `IntegrityError` on write, and SQLite -- whose FTS5 table has no unique index to object -- kept both under one address, then dropped one of them on the next single-row index pass. Nothing surfaced either way. The search index's uniqueness now includes the row kind, which the table's own primary key already carried, so the two rows stay separately addressable. **This ships an Alembic migration** replacing `uix_search_index_permalink_project` with `uix_search_index_permalink_type_project` on Postgres; no permalink changes and no data is dropped on upgrade, and SQLite's FTS5 index needs no schema change. - The `memory://{workspace}/{project}/info` resource is now actually readable over `resources/read`: it returned a Pydantic model, which the resource runtime rejects (`contents must be str, bytes, or list[ResourceContent]`), so every served read failed. It returns the validated response as JSON text now. Found by the new note-resource tests, which read through a real client session instead of calling the handler directly. - **#1344**: Deleting a note no longer erases the relations pointing at it. The `relation.to_id` foreign key is now `ON DELETE SET NULL` rather than `ON DELETE CASCADE`, and `Entity.incoming_relations` no longer cascades deletes through the ORM. Deleting a target leaves its inbound relations in the unresolved state the indexer already produces for a link to a note that does not exist yet -- `to_id` null, `to_name` holding the source's original link text -- so a broken-link report stops coming back clean over a vault full of them, and recreating the target re-links the references through the existing forward-reference pass. `from_id` keeps `CASCADE`: an entity does own the relations it declares. Rows already lost to the old behavior stay lost; re-index the affected notes to bring them back as unresolved. - **#1451**: A markdown file whose leading `---` block is not a YAML mapping (a letterhead between horizontal rules) is now indexed as plain markdown instead of being dropped. The parser already treated such a block as body; the indexer separately saw fences, tried to write a permalink into them, hit the "refusing to update malformed frontmatter" guard, and excluded the file while readiness reported idle. The guard stands: the file is never rewritten, and `remove_frontmatter` no longer strips such a block from search content. Frontmatter is now classified once, by the parser, as present, absent, or malformed, and only the first two are ever written to. - **#1334**: A fresh install that runs a CLI command first (`bm status`, `bm project add`) no longer fails with "Project not found" for the seeded `main` project; config projects are reconciled into the database on first use. - **#1340**: `bm project remove` on a cloud project also removes its local routing entry, so the name can be added again and no stub appears in `project list`. - **#1441**: `bm project add --cloud` creates the local sync directory before saving config, so a bad path leaves config unchanged; rerunning adopts the remote project already created. - **#1333**: `bm schema validate` and other commands exit on Python 3.12 and 3.13 instead of hanging after printing their result. Thanks to @WebKingdom for the diagnosis (#1346). - **#1338**: Every uv install path the project controls (`bm hook install`, `bm update`, the Hermes and OpenClaw bootstraps, `server.json`, README snippets) passes `--prerelease=allow`, which the v0.23.x FastMCP beta pin required. Development builds are no longer published to PyPI, because that flag made them outrank the stable release. - **#1506**: Core, the Codex hooks, and the Claude Code hooks move from the FastMCP 4.0.0b1 pre-release to stable FastMCP 4.0.3. Installed Codex hooks had exited before running because uv could not resolve the beta. - **#1339**: The Hermes plugin manifest declares `manifest_version: 1`, which the current Hermes installer accepts. - **#1341**: The Hermes and OpenClaw tool descriptions and prompts tell agents to call the write tool in the same turn when asked to remember something, never to claim a save without a tool result, and to quote the returned permalink. - **#1332**: A `[[wikilink]]` inside inline code no longer creates a relation. Thanks to @yaodong-shen (#1337). - **#1359**: Quoted Postgres searches such as `"incident response" OR "database recovery"` no longer raise a `to_tsquery` syntax error that aborted the transaction; quoted groups are searched as grouped terms and unmatched quotes are recovered. - **#1281**: Case-only renames (`config.md` to `Config.md`) stick on case-insensitive filesystems instead of being reverted by the next scan. - **#1351**: Deleting a note through the API or MCP refreshes the search rows of notes that linked to it, so relation search no longer returns the deleted note. - **#1335**: The entity-body vector is no longer split into one chunk per bullet. It splits on headings and the size budget, and oversized sections break at line boundaries. Per-fact vectors still come from the observation and relation rows. - **#1432**: MCP identifiers and `memory://` URLs resolve against the session's own projects, so a bare prefix no longer routes to another workspace and multi-segment project names are reachable. `find --meta` results round-trip as inputs (#1435, #1428). - **#1431**: A filtered vector or hybrid search no longer drops matches that fell outside the first 50,000 rows of the filter's match set, which had hidden the newest notes. - **#1388**: `BASIC_MEMORY_MCP_PROJECT` matches projects case-insensitively by permalink, so startup indexing and watching pick up a mixed-case name. - `edit_note(metadata={"type": ...})` changes an existing note's type, and append or prepend that creates a note honors the requested type (#1472). - `bm hook` installs and reads Claude Code hooks in the profile named by `CLAUDE_CONFIG_DIR` instead of always `~/.claude` (#1473). - **#1430**: On Windows, file-backed SQLite uses a bounded five-connection pool instead of `NullPool`, which failed concurrent writes with `database is locked`. - Moving a PDF or other non-Markdown file preserves its bytes; the move had tried to add frontmatter to it (#1485). - **#1378**: MCP API calls retry an HTTP 429 that carries a valid `Retry-After`, up to three attempts within a 30-second budget. Non-replayable request bodies are not retried. - `bm cloud pull` and `bm cloud push` over WebDAV (Team workspaces) wait out rate limits using `Retry-After` instead of aborting the transfer on the first 429 (#1532). - **#1479**: `write_note` decides between create, update, and conflict in one typed operation instead of matching exception text. A write to a vacant path whose permalink belongs to a moved note returns `NOTE_PATH_CONFLICT` with the note's current path, and locked-note refusals are reported as such. - **#1538**: A Markdown note indexed as a plain resource is repaired by the next scan. Thanks to @wangzhengzhuo05 (#1542). - **#1539**: `.bmignore` and `.gitignore` patterns honor escaped hashes (`\#*#`) and escaped or leading whitespace. Thanks to @wangzhengzhuo05 (#1540). - **#1537**: Emacs `#note.md#` autosave files are not indexed. - **#1534**: `search_notes` and `recent_activity` on a project that has never been indexed return "Project Index Required" guidance instead of an empty result. Thanks to @wangzhengzhuo05 (#1535). - **#1533**: An empty search for an unspaced CJK compound returns a `query_hint` suggesting a shorter word or spaces between words. - **#1390**: Relation search refresh cleanup deletes markers in batches of 500, so a backlog larger than asyncpg's 32,767-parameter limit no longer fails relation resolution. - Indexing converges under production load: a note rewritten faster than it indexes settles on the newer accepted write, a MIME-marked `.md` path with no note basename stays a resource, and a relation refresh for an entity whose content is gone no longer crash-loops (#1374). A file deleted between the existence probe and the checksum read is treated as absent instead of failing materialization (#1383). - **#1714**: Wiki projector pages are no longer embedded. A page counts as projector-owned while its current accepted revision came from the projector (`note_content.last_source`), not by file name. Vector sync deletes such a page's vectors, embeds nothing, and reports it as skipped. Full-text rows and relations are unchanged, so generated `index.md` links still feed the graph. A hand-written `index.md` is embedded as before, and a generated page someone edits is embedded on its next sync. In Cloud, the embedding jobs queued for projector writes become cheap deletes. - **#1275**: On macOS, file paths are normalized to NFC where they enter the index. macOS resolves NFC and NFD spellings to one file but reports whichever is on disk, and Syncthing keeps NFD names, so a flipped name could create a `-1` twin and make `edit_note` fail on the permalink constraint. Migration 0042 merges existing twins (macOS only). Linux and Windows keep byte-exact paths. **#1801**: the migration no longer fails with `no such module: vec0` when a vector table exists. - **#1775**: `edit_note` append/prepend that creates a missing note from a project-qualified identifier no longer nests it under a folder named after the project. The server decides where the note goes from the folders that already hold notes (indexed, accepted or on storage), refuses an identifier that two folders could match with `AMBIGUOUS_NOTE_PATH`, and refuses any reading outside the project before looking at a folder. - **#1769**: A full-document `PUT` of a note (Cloud's web editor) deletes frontmatter keys the request leaves out, instead of keeping them from the stored note. `write_note(overwrite=True)` still merges frontmatter. - **#1781**: A new note without a frontmatter `created` keeps the file's creation time instead of the time of the index run. Thanks to @ningyixi. - **#1778**: In a hosted session that can reach several workspaces, a POSIX refusal for a path naming a project in another workspace names that workspace and the spelling that reaches it, and `ls /` lists the accessible workspace slugs. A discovery failure no longer turns `ls /` or a refusal into an error. Local sessions make no new control-plane calls. - `move_note` can rename a `.markdown` note to `.md`. Other extension changes are still refused. - `write_note`'s similar-notes advisory skips notes with `generated:` in their frontmatter (Wiki indexes and logs, agent run logs). - **#1789**: A Wiki run reports source folders that differ only by letter case or Unicode normalization (`customers/CPC` and `customers/cpc`) instead of failing the whole run every time. - **#1790**: `bm import chatgpt` imports conversations that have no title, naming them `Untitled conversation `, instead of failing the import with `KeyError`. - **#1788**: Editing a note with many vector chunks updates the reused chunks' metadata in set-based batches instead of one statement per chunk. - **#1762**: Read-cache invalidation deletes the entries it retires instead of leaving them in Redis until their TTL. **#1761**: Read-cache hits are no longer recorded as error spans. - The Hermes plugin masks credentials on its capture path, including bearer tokens and quoted field names. - Skill tooling reads and writes skill files as UTF-8 with LF line endings, which fixes the Windows unit job. ### Internal - FastMCP 4.0.3 → 4.1.3 and mcp 2.0.0 → 2.3.0, including the Claude Code and Codex hook pins. FastMCP now applies its Host/Origin guard to the SSE transport, so `basic-memory mcp --transport sse` uses it instead of installing its own copy. Streamable HTTP sessions now expire after 30 idle minutes (the MCP SDK default); clients start a new one. - **#1672**: Indexing and embedding results report the work they did. `FileIndexResult`, `IndexedEntity` and `SyncedMarkdownFile` carry `indexed_bytes`, the stored bytes read and parsed (zero for a file that was already current). Embedding results carry `chunks_embedded`, the chunks actually sent to the embedder, and `sync_entity_vectors` returns a `VectorSyncBatchResult`. How indexing and embedding run is unchanged. - **#1660, #1671, #1673**: A note's storage echo is recognized instead of re-indexed. Materialization records the written object's storage checksum, storage and content checksums are compared only with their own kind, and an object whose content matches the note's accepted content counts as current even before its storage checksum is recorded. Index-file results carry the content checksum, so a live update for an accepted write matches its existing activity. Locally both checksums are the same sha256, so this only changes behavior where storage reports its own checksum (S3). - **#1661**: The accept transaction writes the pending relation-publication marker, so an accepted note is never visible without it, and a successful publication leaves exactly one unit of refresh work. A PUT that renames a note carries the previous path into materialization, as an explicit move does. The accepted-note runner tests run against a real database (#1668). - **#1658**: Alembic revisions after `z9a0b1c2d3e4` are named by sequential schema version (`0040`, `0041`, ...). `migrations.schema_version()` reports a revision's number and `migrations.next_revision_id()` assigns the next one. - **#1669**: CI balances the Postgres test shards by recorded durations and runs the Windows jobs only on `main`. - **#1613**: Note object metadata keeps an origin for `agent` and `mcp_client` actors, not only MCP clients, so cloud can attribute API-key writes to the key's name. `system` writers still carry no named origin. - **#1602**: Hot paths emit far fewer Logfire spans and INFO logs: per-sub-step read-cache and indexing spans collapse to one span per operation, and per-item INFO logs move to DEBUG. Counters and error logs are unchanged. - **#1558**: Search filter compilation now runs over an explicit `ProjectScope` instead of a repository-bound `project_id`. FTS term preparation and filter compilation moved out of the SQLite and Postgres repositories into `sqlite_search_query` and `postgres_search_query` as pure functions returning a `CompiledFilter`, and the filters both backends share (scope, permalink, directory, item type, category, note type, `after_date`, valid time, candidate keys) are compiled once in `search_filters`. The note-type and valid-time predicates match search rows on their full `(project_id, ...)` identity. Project repositories call the compilers with a scope of one; no query behavior changes. First step of the shared single/multi-project reader. - **#1558**: Full-text execution leaves the project repositories. `SQLiteFts` and `PostgresFts` run a compiled statement for any `ProjectScope` and own their engine's failure semantics (FTS5 syntax errors answer empty, Postgres retries a malformed strict tsquery relaxed inside a savepoint). `SearchRepositoryBase.search` and `count` are concrete: shared vector/hybrid dispatch, then the engine's `FtsBackend`. The base read path binds every statement to the repository's scope (manifest hydration, candidate row fetch, readiness and drop classification). `PreparedSearchQuery` moves to the repository layer with defaults, and the filter helpers both backends share move from the base into `search_filters`. No query behavior changes. - **#1558**: Retrieval leaves `SearchRepositoryBase`. `SearchReader` runs one prepared query over one `ProjectScope` in whichever mode it asks for, and `SemanticSearch` owns vector and hybrid retrieval (adapter lookup, manifest hydration, the structured filter pass, score fusion, reranking, pagination) over a `VectorRetrieval` that is present or absent rather than probed with `hasattr`. The repository keeps what only it knows (whether semantic search is enabled and its vector tables exist) and builds a reader per call from its current state. Hydrated chunks are a typed `HydratedChunk`, which retires the `best_distance` compatibility branch and the per-backend `_distance_to_similarity` hooks the adapters had already replaced. Test doubles construct the pipeline directly instead of subclassing the repository. No query behavior changes. - **#1558**: Vector adapters are bound to the database, not to a project. `VectorIndexScope` is the database namespace plus embedding schema; every write names the project it touches (`upsert(project_id, ...)`, `delete(project_id, ...)`, `delete_entity(project_id, ...)`, `delete_orphans(project_id, ...)`) and `search` takes a `ProjectScope`, so one sqlite-vec or pgvector adapter answers a query across any set of projects with one statement. Milvus keeps a collection per project and searches the collections in scope. `SemanticSearch` passes its scope through, so a project repository's vector search is unchanged. No query behavior changes. - **#1556**: A hybrid hit found only by full-text search returns `matched_chunk: null` and relies on the bounded `content` preview, instead of copying the whole note into `matched_chunk`; vector-matched passages are unchanged. Search stages (hybrid FTS, query embedding, vector lookup, hydration, fusion, reranking, cache) get their own trace spans. - **#1555**: The local FastEmbed reranker scores candidates in batches of eight with the ONNX CPU memory arena disabled, so hybrid searches stop leaving inference buffers resident after the request. - **#1446**: The first `bm status` on a never-indexed project no longer reads every file to hash it. - **#1454**: `QUERY /v2/projects/{project_id}/knowledge/entities/batch` returns accepted Markdown for up to 25 notes in one query, for hosted search hydration, and the search read cache now keeps entries for 30 minutes instead of 30 seconds. - **#1347**: The portable batch indexer applies the caller's metadata concurrency limit to the search-index refresh phase too, so cloud batch jobs stay within their database connection budget. - Extension seams for cloud: a subclass can write inside the accept transaction (#1483), completed schema validation has an overridable observer that reports the resolved schema identity (#1491, #1494), and `agent_runtime` is an accepted note source so managed-agent writes materialize (#1505). - **#1400**: The benchmarks package gains BEAM and xAFS dataset adapters and an agent-task harness that compares the rich and POSIX tool surfaces, with resumable scoring, configurable model endpoints, and secret redaction in saved errors. A multilingual embedding benchmark covers chunk boundaries and model-cache measurement. - **#1791** (#1793, #1794, #1795, #1802): Postgres search is faster on large projects. The admitted-chunk count reads the chunk manifest alone, FTS text conditions run only on GIN candidates, chunk candidates come from the GIN index, and multiword queries collect each operand's matches through GIN once. - **#1779**: A dev-mode `.envrc` keeps a development checkout's Basic Memory config separate from the installed one. ## v0.23.2 (2026-08-25) Patch release fixing case-duplicate folder creation. ### Bug Fixes - **#1326**: `write_note` and `move_note` no longer create case-duplicate folders (`schemas/` beside an existing `Schemas/`). When a requested directory is not an existing folder but matches exactly one existing folder case-insensitively, the note lands in the existing folder — nested paths resolve per segment; unknown folders are still created as given, and existing case-variant siblings keep today's exact behavior. Folders are resolved from the indexed database paths, so local and cloud runtimes behave identically, and content-only note updates skip resolution entirely. `move_note` reports the actual landing path on a case-corrected move instead of a false failure, while a basename divergence still fails honestly. ## v0.23.1 (2026-08-25) Fast-follow patch to v0.23.0 focused on PostgreSQL search parity and a search-destroying reindex bug. Postgres now indexes complete note bodies for full-text search (previously only titles and capped content stems, unlike SQLite), and the per-project search reindex no longer wipes every other project's search rows in the same database. Also adds a `#bm:links_to` directive for disambiguating prose wiki-links, and hardens `bm update` output after in-place upgrades. ### Features - Added the `#bm:links_to` directive: ending a list item with `#bm:links_to` forces the reference to the implicit `links_to` relation, so a single-token prose prefix (`- Mother [[Alice]] #bm:links_to`) is not parsed as an explicit relation type. The directive stays in the source file but is stripped from indexed observation and relation content. ### Bug Fixes - PostgreSQL full-text search now covers complete note bodies. Note content is indexed as bounded, overlapping chunks in a new `search_index_fts_chunks` table (a migration backfills existing notes), so deep content matches on Postgres the way it always has on SQLite FTS5. The work includes correct Boolean AND/NOT semantics across chunk boundaries, apostrophe and punctuated-operand handling (`can't`, `v0.13.0b2`, `auth-service`), metadata-filter composition, 100+ operand queries, and candidate preselection so both GIN indexes stay in play. - The per-project search reindex (`POST /search/reindex`) no longer drops the shared `search_index` table. Dropping it destroyed every project's search rows in the same database — and on Postgres nothing outside migrations recreates the table, so cloud tenants lost search entirely until manual repair. The rebuild now deletes only the reindexed project's rows (chunk rows cascade), and the chunks migration recreates a missing `search_index` so databases hit by the old behavior migrate cleanly. - **#1316**: `bm update` status output no longer crashes after an in-place upgrade removes the running install's files: rich's deferred Unicode width table is preloaded before upgrading, and status lines fall back to plain output instead of failing a completed update. - **#1323**: `bm doctor` no longer fails when `BASIC_MEMORY_PROJECT_ROOT` points at an existing project's directory. Doctor now asks the server for a disposable `doctor-*` project under the configured root — the only sanctioned exception to the nested-project guard — and cleanup deletes the project's directory along with its registration. - `bm doctor` waits for deferred note materialization before verifying the API-written file, matching the accepted-write contract instead of racing it. ## v0.23.0 (2026-08-23) Semantic search grows up and concurrent writes stop deadlocking. Search gains opt-in cross-encoder reranking, pluggable vector indexes with a first-party Milvus adapter, and a batch of embedding-correctness fixes; the indexing and persistence path is rebuilt around generation-versioned, compare-and-swap writes so concurrent multi-agent workloads can no longer deadlock or lose observations and relations. Day-to-day operation gets a real front door with `bm config`, Rich `bm tool` output, a diagnostics tool, an honest reindex, and a retrieval inspector — `bm inspect chunks` shows a note exactly as the index sees it and `bm inspect query` traces how a search ranked its results; `bm hook` brings harness lifecycle capture into the package; and cloud adds `bm cloud share`, `bm cloud prune`, an optional Redis read cache, and Team workspace `bm cloud push`/`pull` over permissioned WebDAV. Five database migrations run automatically on first start, including a one-time repair that dedupes duplicate observation rows and purges their stale full-text search entries. ### Breaking Changes - **#1111**: The `canvas` MCP tool is removed, along with the API resource write endpoints that backed it (**#1106**). Obsidian canvas generation is no longer available. - **#1145**: The `cloud_info` and `release_notes` MCP tools are removed. - **#1121**: Pre-v0.18.0 legacy HTTP API routes are dropped (**#1116**). Old clients still calling them now get 404s. - **#1035**: The ChatGPT-compatibility `search`/`fetch` tools now refuse non-OpenAI MCP clients with a clear rejection; other clients should use `search_notes`/`read_note` instead. - **#1061**: One-way `bm cloud sync` now deletes newly-`.bmignore`d files from the cloud instead of leaving them there forever (**#1032**). Intentional, but destructive relative to prior behavior — review your `.bmignore` before the first mirror after upgrading. - **#1002**: `bm status` is redesigned around project index status; scripts that scraped the old sync-report output will break. As part of this, the config keys `sync_delay`/`sync_changes` are renamed `index_delay`/`index_changes` — legacy config.json keys and `BASIC_MEMORY_SYNC_*` env vars are auto-migrated, no action needed. - The `sync_thread_pool_size` and `sync_max_concurrent_files` config keys are removed with no alias and are silently ignored if present; the closest replacement knob is the new `materialization_workers` setting. - **#1240**: `bm reindex --embeddings` now exits nonzero when entities fail to embed, surfaces the failures, and reports which index identity it wrote (**#1237**). Wrappers that relied on unconditional exit 0 must handle real failures. - **#1063**: `edit_note`'s `replace_section` is heading-level-aware and now replaces nested subsections by default instead of silently preserving content past the next heading; pass `replace_subsections=false` for the shallow behavior (**#1012**). - **#1082**: `list_directory` results are bounded and paginated (**#1048**). Consumers expecting one exhaustive listing must page. - **#1198**: The MCP server now runs on FastMCP 4.0.0b1 and MCP SDK v2 — a beta framework release. Downstream embedders pinning FastMCP 3.x must upgrade together. ### Features - **#1143**: Opt-in cross-encoder reranking of vector/hybrid search candidates (**#950**, **#618**, **#666**): `reranker_enabled` (default off) with a local FastEmbed ONNX reranker or LiteLLM API rerankers (Cohere, Jina, Voyage), plus candidates, timeout, char-cap, and API tuning knobs. - **#1141**: Pluggable semantic vector indexes on Postgres (SPEC-81): `semantic_vector_index` selects `pgvector` (default) or `milvus`, and a new index identity/readiness manifest lets vector search tell "no ready index" from "no results". SQLite keeps sqlite-vec. After switching backends, run `bm reindex --embeddings`. - **#1158**: First-party Milvus, Milvus Lite, and Zilliz Cloud vector index adapter via `pip install basic-memory[milvus]`; existing collections reload after restart (**#1185**), with identical rankings verified across sqlite-vec, pgvector, and Milvus Lite. - **#1043**: LiteLLM embeddings accept a custom `api_base` and direct `api_key` for OpenAI-compatible and self-hosted servers (**#1005**), and literal document/query prefixes support prefix-sensitive asymmetric models (**#1044**, **#1008**). - **#1249 / #1250**: New retrieval inspector (**#1155**). `bm inspect chunks ` 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 ""` captures an opt-in execution trace from the same search call that returns the results: FTS and vector candidates, fusion, filtering, reranking, and the final page window, with stable JSON output and `--show-misses` for rejected candidates. Ordinary search behavior and responses are unchanged. - **#1088**: New `bm config` command group: `list` (effective values with env overrides marked), `get`, `set` (validated through the config model), and `unset` (**#991**). - **#967**: Interactive `bm tool` commands render Rich panels, tables, and trees on a TTY, with a `cli_output_style` setting and per-invocation `--plain`/`--json` overrides; piped output stays machine-readable (**#678**). - **#963**: New `basic_memory_diagnostics` MCP tool reports version and system info for bug reports (**#187**). - **#1018**: The local Postgres backend is usable end to end: migrations, connection pooling, and default-project resolution. - SQLite write-path tuning is exposed via new `sqlite_synchronous`, `sqlite_mmap_size`, `sqlite_wal_autocheckpoint`, and `sqlite_page_size` settings. - **#1100**: `created`/`modified` frontmatter timestamps are honored as note timestamps (**#238**). Recency ordering can change after the first re-sync for notes carrying historical dates. - **#1079**: Notes written through the API/MCP persist their observations and relations immediately instead of waiting for the next file re-index (**#1076**). - **#1227 / #1220 / #1228**: Persistence is generation-versioned with compare-and-swap publication — a stale indexing pass can never clobber or deadlock against a newer write, so observations and relations stay intact under concurrent agent write load (**#1224**, **#1213**, **#1214**). - **#1204 / #1132 / #1131**: Relation resolution and vector prepare work are batched instead of serial, and a new `materialization_workers` setting (default 4) bounds concurrent write materializations. - **#1165**: Relation-derived search refreshes are durable, retryable work items (**#1163**), pending relations refresh from accepted content (**#1161**, **#1159**), and forward references back-resolve when their target note is created, without a full reindex (**#1015**). - **#1070**: Added the `bm hook` harness front door (SPEC-55, **#997**). Lifecycle verbs (`session-start`, `pre-compact`, `stop`) move plugin hook logic into the package behind per-harness stdin adapters. Default-on bounded envelope capture records lifecycle metadata into a local inbox WAL; `bm hook flush` archives it locally, `bm hook status` shows the surface, and `captureEvents: false` disables capture. `bm hook install` / `bm hook remove` wire hooks into user-level harness config for standalone users with ownership-tagged, surgical merging. The Claude Code and Codex plugin hooks are now zero-logic PEP 723 uv scripts invoking `basic-memory hook` in-process, with `BM_BIN` overriding the uv-managed environment for development. - **#1119**: Plugins surface hook capture setup and health (**#1117**), and Claude Code hook config falls back to user-level `~/.claude` settings (**#924**). - **#1123 / #1138 / #1142 / #1147**: Codex hooks and memory notes are reliable, checkpoints are authored and prompted after compaction, and checkpoints are directly resumable. - **#1124 / #1126 / #1050**: New skills: `bm-writing` with coding setup, `bm-decide`/`bm-orient`, and the shared `memory-onboarding` skill; coding session profiles are queryable (**#1125**). - **#965**: New `bm cloud share` command group: `create`, `list`, `update`, `revoke` (**#880**). - **#1061**: New `bm cloud prune` removes `.bmignore`d files from the cloud on demand (**#1032**; see Breaking Changes for the one-way sync behavior change). - **#1263**: Team-workspace `bm cloud push`/`pull` run over the service's permissioned WebDAV surface instead of tenant-wide storage credentials, so any member can sync the projects they have access to — previously only workspace owners could provision the required credentials and every other member got a 403 (**#1262**). Same flags and semantics: `--on-conflict` still defaults to `fail`, and transfers stay additive — nothing is ever deleted. Requires the updated cloud server, already deployed in production; the Personal rclone path is untouched. - **#1168 / #1172**: Optional Redis read caching accelerates standalone MCP reads via the `basic-memory[redis]` extra (`redis_url`, `redis_max_connections`) (**#980**). - **#1255**: Semantic note reads make the minimum number of API requests — exact-ID reads skip resolve and resource calls entirely — and ordinary read-cache entries live 300 seconds instead of 60. - **#1062 / #1074**: Cloud project deletion errors are surfaced, with an optional notes purge and a visible deletion job (**#1033**, **#1034**). - **#1145**: First-connect MCP onboarding: server instructions, empty-state guidance, and a `getting_started` prompt for new users. - **#1090**: `edit_note` accepts a `metadata` param to update frontmatter fields (**#1011**). - **#1075**: `move_note` returns the previous accepted path (**#1072**). - **#1040 / #1101 / #1103**: `external_id` is exposed in `list_directory`, `recent_activity`, search results, and `search_notes` markdown output. - **#1268**: `list_directory` accepts a `sort` parameter (`title_asc`, `title_desc`, `updated_asc`, `updated_desc`) with deterministic folders-first ordering applied before pagination (**#1267**); omitting it keeps the existing filename order. - **#1031 / #1036 / #1037**: MCP tool annotations are directory-compliant, destructive hints are explicit, and `edit_note` exposes its operation enum. ### Bug Fixes - **#1193 / #1202**: Two indexing deadlock families are eliminated: Entity/NoteContent lock-order inversions during materialization and Entity/Observation inversions between indexing and accepted writes (**#1187**, **#1199**, **#1209**). - A one-time migration dedupes historical duplicate observation rows and purges their orphaned full-text search entries (companion to **#1228**). - **#1247**: Incremental `bm reindex --search` purges stale search-index rows whose backing entity, observation, or relation is gone, so DB-only search divergence on unchanged files converges without a `--full` rebuild (**#1226**; the last loose end of the **#1214** repair). - **#1152 / #1160**: Moves record a durable vacate marker, so a byte-identical copy at the old path indexes as a new note instead of being skipped as a lingering move source. - **#1258**: A note accepted while a project scan is in flight can no longer be deleted as "externally removed" — destructive project-index deletes re-verify the database lineage and the path's current absence from storage at apply time (**#1256**). - **#1016**: Direct on-disk edits picked up by the file watcher are now vector-embedded, so externally edited notes no longer go missing from semantic search until a reindex (closed by the vector-sync overhaul, **#1129**–**#1131**, **#1141**). - **#1023**: FastEmbed embeddings are L2-normalized for non-bge models, so semantic search no longer silently degrades to FTS-only. - **#1071**: SQLite full-text search covers complete note content — previously content beyond ~6000 characters was invisible (**#1065**) — and CJK terms work in the relaxed FTS fallback (**#1022**). - **#1269**: Full-text query relaxation counts non-Latin tokens, so Cyrillic, Greek, Hebrew, Arabic, and other non-Latin queries relax to an OR retry instead of silently degrading hybrid search to vector-only ranking, and combining marks stay inside their word so Devanagari and Thai terms are not shredded into fragments (extends the CJK-only fix from **#1022**). - **#1069**: Unknown semantic/hybrid result totals are explicit in structured search responses (**#1068**). - **#1190**: `bm reindex --embeddings` warns when the project has no synced entities instead of silently no-opping (**#1184**). - **#1196**: A legacy pgvector embeddings schema no longer breaks `bm project info` (**#1195**). - **#1151**: Ambiguous identifier resolution fails loudly instead of returning the wrong note (**#1148**), and project-scoped entity resolution is separated from cross-project wikilink resolution (**#1192**, **#1170**). - **#1272**: Root-level wikilinks written as filename stems resolve via the `.md` file-path fallback, and a forgiving underscore/hyphen/case alias resolves links in directly edited vaults — tried only after every exact identity, and failing closed when two files collide on the same alias (**#1253**). - **#1189**: Note-type filters are case-canonicalized, so `Person` and `person` match the same population (**#1180**). - **#1081**: `write_note` rejects filename-convention twins (kebab-case vs Title Case) instead of creating duplicate notes (**#1077**). - **#1073**: `edit_note` with a `memory://` URL routes to the target project instead of creating phantom notes (**#1066**), and scoped `memory://` URL paths are preserved (**#1092**). - **#1299**: `build_context` bounds its traversal requests — primary pages cap at 50 results, related context at 100 per page, and negative `max_related` is rejected instead of acting as an unbounded SQL limit — so a traversal call can no longer become a multi-megabyte vault export (**#1296**). Callers paginate or follow returned `memory://` links. - **#1285**: Glob-filtered directory listings traverse subdirectories again: `file_name_glob` filters results instead of accidentally pruning recursion, so `*.md` with depth 2 finds files inside subdirectories. - **#1188**: Sync preserves malformed frontmatter instead of prepending a second frontmatter block that shadows `name`/`description` (**#1171**). - **#1239**: Timestamp-prefixed transcript lines and checkbox markers (`[x]`, `[/]`, `[>]`, `[?]`) no longer mint junk observation categories (**#1219**, **#1241**). - **#1271**: Transcript timestamp ranges like `[24:33.098 - 24:41.260]` no longer mint junk observation categories either — the remaining range-shaped case from **#1239** (**#1270**). - **#1291**: Prose bullets no longer mint typed relations: a sentence like `- Added [[Target]] to the roster` filed a relation *type* called `Added` and silently dropped the rest of the line, including any further links in it. An explicit relation now ends at its target or its `(context)`; anything else keeps every wikilink as a plain `links_to` edge (**#1260**). - **#1060**: `schema_validate` with no arguments validates all schema-covered types instead of type "unknown" (**#1013**), and invalid schema-validation modes are rejected instead of silently degrading to warn (**#1223**, **#1222**). - **#1085**: Re-adding a retained cloud project reindexes its existing notes (**#1084**). - **#1010**: `bm project list` shows configured cloud-mode projects even when uncredentialed (**#1003**), and deleting the default project auto-reassigns the default instead of refusing (**#1139**). - **#1273**: Re-selecting the project that is already the default no longer clears the default flag — a state that broke project discovery and every project-scoped MCP tool until a default was set again. - **#1290**: ChatGPT import no longer crashes on conversations missing `create_time` — timestamps fall back to `update_time`, then the earliest message time, so the whole archive imports (**#1276**); undecodable import uploads return a 400 with the parse error instead of a 500. - **#1298**: The update check no longer reports "up to date" when the Homebrew probe fails, no longer auto-runs `brew upgrade` for an update inferred from PyPI metadata, and names the actual Homebrew target version it will install. - **#1300 / #1302**: The multilingual-E5 prefix contract is documented — asymmetric FastEmbed models need `semantic_embedding_query_prefix` / `semantic_embedding_document_prefix`, which already drive reindex through the embedding identity — along with custom-model selection, the installed FastEmbed catalog, and dimensions (**#1264**). - **#1058 / #1094**: `bm doctor` never prints a blank failure message, and migrations adapt to existing event loops (**#1027**). - **#1080**: Loading config no longer recreates an empty `~/basic-memory` directory as a side effect (**#1029**). - **#1057**: Large projects no longer crash reindex on SQLite's bound-parameter limit (**#1045**). - **#1218 / #1216**: Windows: the MCP server no longer dies at startup on a log-cleanup race (**#1211**), note content no longer crashes log formatting during index retries (**#1212**), the watch service no longer crashes on mapped network drives (**#1047**), and a PermissionError during project scan no longer triggers mass index deletion (**#1007**). - **#1059 / #1179**: Hermes: `bm mcp` child processes no longer leak (**#1017**), and bm subprocesses no longer inherit Hermes's Python environment (**#1093**). - **#1274**: Hermes: commands and skills register through Hermes's own registration APIs instead of private PluginManager writes, preserving the lifecycle ownership that cleans them up on provider unload (**#1257**); the slash-command monkeypatch docs are split by Hermes version so modern installs skip the legacy collector workaround (**#1278**), and the install docs require a Hermes release with managed manifest-v2 installation instead of the nonexistent `--path` option (**#1280**, **#1303**). ### Maintenance - **#1113 / #1114**: Dependency injection is consolidated behind the v2 composition roots (**#1109**). - **#1122 / #1133–#1136 / #1229**: The largest service god-files are split into focused modules (**#1108**). - Removed the hook-specific redaction subsystem, its `detect-secrets` dependency, and the retired lifecycle projector compatibility module. - Kept Milvus as a first-party optional vector backend while removing the unused Python entry-point registry for separately packaged vector adapters. - **#1292 / #1293**: The dev-release pipeline publishes again via PyPI trusted publishing — its version gate imported a hardcoded module version and had silently skipped every dev publish since the 0.22.1 bump. - **#1304 / #1307**: The concurrent-write convergence benchmark is ported into the canonical `/benchmarks` package, and the read-load benchmark runs against the current MCP SDK's typed result fields. ## v0.22.1 (2026-06-12) Follow-up patch to v0.22.0. Fixes project and default-project resolution on fresh installs, MCP workspace routing, sync project selection, and CLI startup latency, plus a few MCP parity additions. ### Features - Added a `workspace` parameter to `write_note` for parity with `edit_note`. - **#826**: Added `title` and `tags` annotations to all MCP tool decorators (phase 1). - **#930**: `search_notes` now comma-splits `note_types`, `entity_types`, and `categories`. - **#971**: Added the manual-pages flow — manpage seed schema, flow docs, and verification fixes. ### Bug Fixes - Fresh installs no longer fail when the projects table is empty: resolve now points them at project setup, the first project is promoted to default when the config default is missing from the database, the promoted default state is returned from the project-create API, and a default can be set when none is currently set. An existing database default is preserved when repairing a missing config default. - **#949**: Sync skips projects without an absolute local path and excludes orphan DB projects that are absent from config. - **#952 / #981**: Resolved workspace display names and tenant ids in qualified project routes, closing out the manual verification findings. - `note_types`/`entity_types`/`categories` are normalized on the direct-call path, with non-string list elements rejected. - Vector-search hydration keys on `(type, id)` to prevent id collisions. - `file_utils` requires line-anchored frontmatter fences. - CLI startup is faster: FastAPI and app imports are deferred out of CLI startup, and rich/typer modules are preloaded before an in-place upgrade. - `config.json` is written atomically. - In-memory SQLite sessions are serialized so concurrent rollbacks cannot destroy writes. ### Maintenance - Release recipes route through PRs and wait for the release PR merge to land before tagging; the release runbook is refreshed and stripped of user-specific absolute paths. ## v0.22.0 (2026-06-11) Team-safe cloud sync. New additive `bm cloud push` and `bm cloud pull` commands work safely on shared Team workspaces, while the destructive mirror commands are gated to Personal workspaces. Also: a large batch of MCP tool fixes, search improvements, and embedding reliability work. ### Features - **#917**: Added Team-safe `bm cloud push` / `bm cloud pull`. Both are additive (they never delete on the destination) and abort on conflicts by default, git-style, with `--on-conflict {fail|keep-local|keep-cloud|keep-both}`. The destructive `bm cloud sync` / `bm cloud bisync` mirrors are now gated to Personal workspaces. - **#920**: Team push/pull uses per-workspace rclone remotes, so remotes and credentials stay scoped to each workspace. - **#908**: Search supports an observation category filter. - **#809**: Added an experimental LiteLLM embedding provider for semantic search (marked experimental, see **#899**). - **#907**: `bm tool write-note` accepts `--type`. - **#906**: `bm status` accepts `--wait` and `--timeout`. - Added the `bm tool delete-note` command. - **#905**: Improved workspace and cloud bisync command discoverability. ### Bug Fixes - **#931 / #946**: Truncated observation permalinks are disambiguated to prevent search-index collisions, and `build_context` resolves observations by the same permalink the search index uses (**#909**, **#929**). - **#934**: `edit_note` recovers when the file exists on disk but is not yet indexed (**#581**). - **#911 / #932 / #941**: Comma-separated tags are split consistently in `parse_tags` and the `search_notes` tags parameter, with input normalized for direct callers (**#910**). - **#933**: `read_note` accepts `page`/`page_size` for parity with sibling tools (**#883**). - **#914 / #904 / #916**: `move_note` resolves `memory://` URLs, stops falsely rejecting same-project moves as cross-project, no longer reports false success across project boundaries, and mismatch guidance points at the landing path. - **#915**: Navigation pagination is validated, and `recent_activity` shows the correct project. - **#913**: `bm tool` commands align with MCP behavior (error exit codes, overwrite handling, category support, defaults). - **#923**: `bm cloud setup` no longer overwrites an existing rclone remote (**#922**). - **#912**: The `note_types` search filter is case-insensitive. - `build_context` allows cross-project context traversal, `write_note` resolves overwrite conflicts, and sync uses strict deferred relation resolution. - Embedding reliability: FastEmbed vectors are L2-normalized (**#843**), corrupt FastEmbed model caches self-heal (**#900**), a single embedding provider is reused per process (**#903**), `sqlite-vec` loads for the embedding-status query (**#901**), and engine disposal no longer crashes on the Postgres backend (**#902**). ### Maintenance - Leaner, faster CI: testmon-selected branch builds, sharded Postgres jobs, and faster default test fixtures (**#928**, **#938**, **#945**). - Documented personal-vs-team cloud sync semantics (**#947**, closes **#851**). - Fixed npx skill install docs (**#927**). - Added `glama.json` to claim the Glama MCP directory listing (**#953**). ## v0.21.6 (2026-06-04) Monorepo consolidation plus a redesigned Claude Code plugin. The satellite repositories now live in the main `basic-memory` tree, and the plugin is rebuilt as a memory bridge with a guided setup interview, capture skills, and team workspaces. Codex, Hermes, and OpenClaw integration packages ship alongside it. ### Core - Consolidated the Basic Memory satellite repositories into the main `basic-memory` tree as the canonical source, discovery, documentation, issue, and release home. - Added root marketplace/package validation for the consolidated repository layout. - Added root and package-local justfile targets so Claude Code, Codex, skills, Hermes, and OpenClaw builds can be verified from the monorepo. - Removed the legacy `ui/` directory. ### API - Entity resolution now exposes the owning project on resolved entities so callers can route follow-up reads to the correct workspace/project. ### CLI - Added an "auto BM" GitHub CI workflow that captures notes from CI runs. - Exposed project sync-support metadata and surfaced copyable workspace identifiers in project listings. - `cloud login` now surfaces non-subscription errors instead of masking them. - Team workspaces block `rclone sync`, with the team-workspace guard limited to `bisync`. ### Claude Code - Rebuilt the Claude Code plugin as a memory bridge with SessionStart and PreCompact hooks, a bundled output style, and seeded note schemas. - Added the `/basic-memory:setup` bootstrap interview and the `/basic-memory:remember`, `/basic-memory:status`, and `/basic-memory:share` skills. - Added team workspace support with attribution for shared writes. - Prefixed plugin skills with `bm-` and installed the shared `memory-*` skills instead of duplicating them in the plugin. - Hooks fall back to `uvx`/`uv` when no CLI binary is on PATH. ### Codex - Added the Codex plugin under `plugins/codex/` with its native `.codex-plugin`, hooks, seeded schemas, and `bm-*` skills. ### Skills - Added the shared Basic Memory `SKILL.md` collection under top-level `skills/` and ported useful retired plugin skills into the `memory-*` set. - Fixed invalid picoschema enum YAML in the memory skills. ### Hermes - Added the Hermes memory provider plugin under `integrations/hermes/` with its native Python module, `plugin.yaml`, skill, tests, docs, and release metadata. ### OpenClaw - Added the OpenClaw plugin under `integrations/openclaw/` with its native npm/TypeScript package shape, tests, docs, and release metadata; skill bundling copies from the top-level `skills/` source. ## v0.21.5 (2026-05-26) Workspace/project routing fixes for MCP, plus a SQLite vector reindex stability fix. ### Bug Fixes - **#854**: MCP project listing now keeps duplicate cloud project rows distinct by workspace, so only the selected workspace row inherits local project state. - **#853**: `write_note` returns workspace-qualified permalinks for cloud workspace writes, allowing follow-up `memory://` reads to route back to the correct workspace/project. - **#852**: Full SQLite vector reindex now loads `sqlite-vec` before dropping `vec0` virtual tables, preventing reindex crashes. - **#838**: Local ASGI database initialization is preloaded so MCP routing can safely enter local project contexts. ## v0.21.1 (2026-05-16) CI-only release. No user-facing changes. ### Maintenance - **#833**: Replace `mislav/bump-homebrew-formula-action` with an inline bash bump step. The action's `resolveRedirect` HEAD-requests `api.github.com /repos/.../tarball/` expecting HTTP 302; GitHub now returns 303 for authenticated requests on that endpoint, which broke the v0.21.0 Homebrew job and required a manual tap bump. The inline step does the same work (curl + sha256sum, clone tap, sed-bump `url`/`sha256`, commit, push) without any third-party dependency. ## v0.21.0 (2026-05-16) Workspace-aware everywhere: every MCP tool and CLI command now routes through the same workspace/project model, the search and sync paths are noticeably faster, and a handful of long-standing parsing and routing footguns are gone. ### Breaking Changes - Relation parsing no longer treats unquoted multi-word text before a wikilink as a custom relation type. Use single-token relation types like `relates_to [[Target]]`, or quote multi-word relation types like `"relates to" [[Target]]` or `'relates to' [[Target]]`. - Bare list wikilinks like `- [[Target]]` now index as `links_to`. - Prose list items like `- some other thing [[Target]]` now index as `links_to`. - To preserve existing multi-word relation types on re-sync, quote them before upgrading. - See **#824**. ### Features - **#816**: `bm orphan` CLI command surfaces entities whose underlying markdown files are gone, with a flag to clean them out. - **#789**: Create projects directly by cloud workspace slug from MCP (`create_memory_project(workspace=...)`). - **#757**: Discover projects across every accessible cloud workspace in MCP's project list — no more per-workspace blind spots. - **#766**: MCP tools accept training-data-friendly parameter aliases (`q`/`search`/`text` for `query`, etc.) so models reach for them naturally. - **#776**: `bm db reset` refuses to run while a `basic-memory mcp` process is alive, so resets can no longer corrupt an open session. - **#791**: Search responses include result totals so pagers can stop guessing. - **#719**: Cloud `note_content` tenant schema primitive lands on the backend. - **#715**: `bm project add` accepts a `--visibility` flag for cloud projects. ### Bug Fixes #### Search and recent activity - **#832**: SQLite project deletion now sweeps `search_index`, `search_vector_chunks`, and `search_vector_embeddings`, so a project that reuses a recycled auto-increment id can't inherit the previous tenant's content. - **#812**: `recent_activity` orders and filters by `updated_at`, so edits bubble to the top instead of staying pinned to creation time. - **#807**: Multi-project `search_notes` is opt-in (`search_all_projects=True`); default search stays scoped to the resolved project. - **#785**: `recent_activity` caps responses and emits an explicit truncation footer instead of silently dropping rows. - **#713**: Eliminated an N+1 query in search result hydration. #### Workspace / project routing - **#822**: `bm project list` now includes projects from every workspace, not just the current one. - **#813**, **#808**, **#806**, **#803**, **#801**, **#795**, **#790**, **#778**, **#777**, **#722**, **#712**, **#704**: Workspace-qualified permalink routing is centralized and applied consistently across `edit_note`, `delete_project`, `build_context`, `memory://` URLs, factory-mode project listing, cloud uploads, and the API client. #### Sync - **#827**: `rclone bisync` filters from `.bmignore` are preserved across syncs. - **#815**: Watch service ignores hidden paths relative to the watched project, not just relative to `$HOME`. - **#814**: `scan` subprocesses no longer go through the shell, avoiding quoting issues with paths that contain special characters. - **#759**: Watch service stays inside `--project` scope. - **#746**: Canonical markdown is preserved during single-file sync. #### Parsing - **#796**: Picoschema modifier descriptions (`field?(modifier, description)`) parse correctly. - **#769**: Obsidian callout blocks are skipped by the observation parser instead of being mis-extracted as observations. #### CLI - **#775**: `bm project set-cloud` / `set-local` cleans up local DB state for the affected project. - **#773**: `bm cloud logout` clears `default_workspace`. - **#780**: `bm cloud setup` hint points at `bm cloud sync-setup`. - **#734**: `bm project info` shows cloud index freshness. - **#718**: Private cloud projects display under their `display_name` instead of raw UUID. - **#768**: `read_note` / `view_note` drop no-op pagination params from their signatures. #### Stability - **#774**: `sqlite-vec` failures during init degrade gracefully to keyword-only search instead of crashing startup. - **#733**: Delete-vector and cloud-sync cleanup is now consistent. - **#702**: Race conditions in concurrent `delete_entity` are resolved. - **#724**: `external_id` is preserved when entities are re-upserted during a re-index. - **#728**: Vector init no longer issues runtime `ALTER TABLE`. - **#744**: `BASIC_MEMORY_CONFIG_DIR` is honored across remaining call sites. - **#743**: FastEmbed cache lives under the data dir instead of `/tmp`. - **#752**: Cloud projects report `source=cloud` in factory mode. - Stripped null bytes from markdown content before DB insert. - Allowed long `relation_type` values in API responses. #### Installer - **#772**: Docker-compose config volume mounts under the `appuser` home. - **#695**: Bumped `brew outdated` timeout from 15s to 60s. ### Performance - **#828**: CLI startup no longer pulls in the local ASGI FastAPI app when it isn't needed. - **#751**, **#726**, **#717**, **#714**, single-file/batch indexing: marked speedups on the sync hot path; unchanged markdown is skipped entirely. - **#731**, **#723**: Vector sync is faster on both backends, with tuned fastembed defaults. ### Maintenance - **#825**: Dependency refresh + security hardening. - Updated to `fastmcp` 3.3.1. - **#754**: Removed in-house telemetry wrappers in favor of direct `logfire` usage. - **#736**: `ty` is now the default typechecker. - **#771**, **#770**, **#716**: New regression guards for vector-row cleanup, long relation types, and recent activity hydration. ## v0.20.3 (2026-03-26) ### Bug Fixes - **#698**: CLI cloud commands now use API key when configured - `get_authenticated_headers()` only checked OAuth tokens, ignoring `config.cloud_api_key` - All CLI cloud commands (`upload`, `status`, `snapshot`, `restore`, etc.) failed for API-key-only users while MCP tools worked fine - Now mirrors the same credential priority as MCP: API key first, OAuth fallback - Fixes `bm cloud upload --project` returning "project does not exist" when authenticated with `bmc_*` API key ## v0.20.2 (2026-03-10) ### Bug Fixes - Fix auto-update Homebrew detection: `brew outdated` exits 1 when a formula is outdated, not on error - Previously treated exit code 1 as a failure, causing "Automatic update check failed" instead of detecting the available update ## v0.20.1 (2026-03-10) ### Bug Fixes - **#661**: Fix `bm project list` MCP column to show transport type (stdio/https) instead of DB presence - Renamed "MCP (stdio)" column to "MCP" - Shows actual routing mode: `stdio` for local, `https` for cloud projects - Clears local path display for cloud-mode projects - **#662**: Invalidate config cache when file is modified by another process - Adds mtime-based cache validation to `ConfigManager.load_config()` - Long-lived processes (MCP stdio server) now detect external config changes - Fixes `bm project set-cloud` having no effect on running MCP server ## v0.20.0 (2026-03-10) ### Features - **#643**: Default-on auto-update system and `bm update` command - Automatic background update checks for CLI installs (uv tool, Homebrew) - Install-source detection (homebrew, uv_tool, uvx, unknown) with uvx skip behavior - Periodic check gating via `auto_update_last_checked_at` + `update_check_interval` config - Manager-specific update flows: Homebrew (`brew upgrade`) and uv tool (`uv tool upgrade`) - Silent, non-blocking MCP behavior via daemon thread before server run - Manual commands: `bm update` (force check + apply) and `bm update --check` (check only) - New config fields: `auto_update`, `update_check_interval`, `auto_update_last_checked_at` ## v0.19.2 (2026-03-09) ### Bug Fixes - **#657**: Coerce string params to list/dict in MCP tools - MCP clients that serialize `list`/`dict` arguments as JSON strings no longer fail Pydantic validation - Adds `BeforeValidator` coercion to `search_notes` (`entity_types`, `note_types`, `tags`, `metadata_filters`), `write_note` (`metadata`), and `canvas` (`nodes`, `edges`) - **#655**: Handle SQLite and Windows semantic search regressions - Fix embedding status query for non-semantic SQLite databases - Windows-safe log file rotation with per-process log filenames - Robust `setup_logging` that handles all environments cleanly ## v0.19.1 (2026-03-08) ### Bug Fixes - **#649**: Enforce strict entity resolution in destructive MCP tools (`edit_note`, `move_note`, `delete_note`) - Prevents fuzzy-match fallback from silently editing/moving/deleting the wrong note - DST-related timeframe validation fix (round instead of truncate days) ### Features - **#648**: Add `insert_before_section` and `insert_after_section` edit operations - Add `GET /knowledge/graph` endpoint for full graph visualization ### Dependencies - Bump authlib from 1.6.6 to 1.6.7 ## v0.19.0 (2026-03-07) ### Highlights - **Semantic vector search** for SQLite and Postgres with FastEmbed embeddings - **Schema system** for validating and inferring knowledge base structure - **Per-project cloud routing** with API key authentication - **Upgraded to FastMCP 3.0** with tool annotations - **CLI overhaul** with JSON output, workspace awareness, and project dashboard ### Features - **#550**: Add semantic vector search for SQLite and Postgres - FastEmbed-based embeddings with automatic backfill - Hybrid search combining full-text and vector similarity - Score-based fusion replacing RRF for better ranking - `min_similarity` override for tuning search precision - Semantic dependencies are now default, with optional extras fallback - **#549**: Schema system for Basic Memory - `schema_infer` — infer schema from existing notes - `schema_validate` — validate notes against a schema definition - `schema_diff` — compare schemas across projects - Frontmatter validation support (#597) - Read schema definitions from file instead of stale DB metadata (#635) - **#555**: Per-project local/cloud routing with API key auth - Individual projects route through cloud while others stay local - `basic-memory cloud set-key` and `basic-memory project set-cloud/set-local` - Stdio MCP honors per-project cloud routing (#590) - **#598**: Upgrade FastMCP 2.12.3 to 3.0.1 with tool annotations - **#585**: Add JSON output mode for MCP tools (default text) - `--json` output for CLI commands for scripting and CI - **#576**: Add workspace selection flow for MCP and CLI - Workspace-aware cloud project listing - CLI refactoring for workspace support - **#544**: Project-prefixed permalinks and memory URL routing - **#632**: Add overwrite guard to `write_note` tool - **#614**: `edit_note` append/prepend auto-creates note if not found - **#609**: Richer content context in search results - Return matched chunk text in search results (#601) - Improved content hit rate - **#602**: Add `created_by` and `last_updated_by` user tracking to Entity - **#600**: Rename `entity_type` to `note_type` across codebase - **#574**: Add `display_name` and `is_private` to ProjectItem - **#569**: Expose `external_id` in EntityResponse and link resolver - **#567**: Isolate default SQLite DB by config dir - **#560**: Enable `default_project_mode` by default - **#559**: Add `basic-memory watch` CLI command - **#546**: Add cloud discovery touchpoints to CLI and MCP - **#572**: CLI analytics via Umami event collector - Replace project info with htop-inspired dashboard - Merge `search_by_metadata` into `search_notes` with optional query - Add `--strip-frontmatter` to `basic-memory tool read-note` - Add `destination_folder` parameter to `move_note` tool ### Bug Fixes - **#644**: Fix default project resolution in cloud mode - ChatGPT search/fetch tools broken in cloud mode - `resolve_project_parameter` falls back to projects API - **#638**: Restore API backward compatibility for v0.18.x clients - **#637**: Create backup before config migration overwrites old format - **#636**: `list_workspaces` bypasses factory pattern on cloud MCP server - **#631**: `build_context` related_results schema validation failure - **#613**: Reduce excessive log volume by demoting per-request noise to DEBUG - **#612**: Handle quoted picoschema enum strings in YAML frontmatter - **#607**: Guard against closed streams in promo and missing vector tables - **#606**: Accept null for `expected_replacements` in `edit_note` - **#595**: `recent_activity` dedup and pagination across MCP tools - **#593**: Backend-specific distance-to-similarity conversion - **#582**: Use LinkResolver fallback in `build_context` for flexible identifier matching - **#577**: Replace RRF with score-based fusion in hybrid search - **#575**: Remove hardcoded "main" default from `default_project` - **#534**: Speed up `bm --version` startup - Fix semantic embeddings not generated on fresh DB or upgrade - Clarify `search_notes` parameter naming and fix `note_types` case sensitivity - Parse `tag:` prefix at MCP tool level to avoid hybrid search failure - Cap sqlite-vec knn k parameter at 4096 limit - Parameterize SQL queries in search repository type filters - Coerce list frontmatter values to strings for title and type fields - Avoid `Post(**metadata)` crash when frontmatter contains 'content' or 'handler' keys - Upgrade cryptography and python-multipart for security advisories ### Internal - **#594**: Add `ty` as supplemental type checker - Batched vector sync orchestration across repositories - FastEmbed parallel guardrails and provider caching - Improved cloud CLI status and error messages - CI coverage and Postgres test fixes ## v0.18.5 (2026-02-13) ### Bug Fixes - Strip NUL bytes from content before PostgreSQL search indexing ([`ec9b2c4`](https://github.com/basicmachines-co/basic-memory/commit/ec9b2c4)) ## v0.18.4 (2026-02-12) ### Bug Fixes - Use global `--header` flag for Tigris consistency on all rclone transactions ([`0eae0e1`](https://github.com/basicmachines-co/basic-memory/commit/0eae0e1)) - `--header-download` / `--header-upload` only apply to GET/PUT requests, missing S3 ListObjectsV2 calls that bisync issues first. Non-US users saw stale edge-cached metadata. - `--header` applies to ALL HTTP transactions (list, download, upload), fixing bisync for users outside the Tigris origin region. ## v0.18.2 (2026-02-11) ### Bug Fixes - **#562**: Use VIRTUAL instead of STORED columns in SQLite migration ([`344e651`](https://github.com/basicmachines-co/basic-memory/commit/344e651)) - Fixes compatibility issue with SQLite STORED generated columns ## v0.18.1 (2026-02-11) ### Features - **#552**: Add `--format json` to CLI tool commands ([`a47c9c0`](https://github.com/basicmachines-co/basic-memory/commit/a47c9c0)) - CLI tool commands now support `--format json` for machine-readable output - **#535**: Support `tag:` query shorthand in search ([`f1d50c2`](https://github.com/basicmachines-co/basic-memory/commit/f1d50c2)) - Use `tag:mytag` as a convenient shorthand in search queries - **#532**: Fast edit entities, refactors for webui, enhanced search ([`530cbac`](https://github.com/basicmachines-co/basic-memory/commit/530cbac)) - Performance improvements for entity editing and search operations ### Bug Fixes - **#558**: Add X-Tigris-Consistent headers to all rclone commands ([`8489a3d`](https://github.com/basicmachines-co/basic-memory/commit/8489a3d)) - Ensures consistent reads from Tigris object storage during sync - **#541**: Handle EntityCreationError as conflict ([`343a6e1`](https://github.com/basicmachines-co/basic-memory/commit/343a6e1)) - **#536**: Stabilize metadata filters on Postgres ([`009e849`](https://github.com/basicmachines-co/basic-memory/commit/009e849)) - **#533**: Fix recent_activity prompt defaults ([`24ca5f6`](https://github.com/basicmachines-co/basic-memory/commit/24ca5f6)) - **#530**: Prevent spurious `metadata: {}` in frontmatter output ([`e3ced49`](https://github.com/basicmachines-co/basic-memory/commit/e3ced49)) - Add POST legacy compat routes for v0.18.0 CLI ([`c46d7a6`](https://github.com/basicmachines-co/basic-memory/commit/c46d7a6)) - Restore legacy `/projects/projects` endpoint for older CLI versions ([`a0e754b`](https://github.com/basicmachines-co/basic-memory/commit/a0e754b)) ### Internal - **#538**: Add fast feedback loop tooling (`just fast-check`, `just doctor`, `just testmon`) ([`8072449`](https://github.com/basicmachines-co/basic-memory/commit/8072449)) ## v0.18.0 (2026-01-28) ### Features - **#527**: Add context-aware wiki link resolution with source_path support ([`0023e73`](https://github.com/basicmachines-co/basic-memory/commit/0023e73)) - Add `source_path` parameter to `resolve_link()` for context-aware resolution - Relative path resolution: `[[nested/note]]` from `folder/file.md` → `folder/nested/note.md` - Proximity-based resolution for duplicate titles (prefers notes in same folder) - Strict mode to disable fuzzy search fallback for wiki links - **#518**: Add directory support to move_note and delete_note tools ([`0b20801`](https://github.com/basicmachines-co/basic-memory/commit/0b20801)) - Add `is_directory` parameter to `move_note` and `delete_note` MCP tools - New `POST /move-directory` and delete directory API endpoints - Rename `folder` → `directory` parameter across codebase for consistency - **#522**: Local MCP cloud mode routing ([`8730067`](https://github.com/basicmachines-co/basic-memory/commit/8730067)) - Add `--local` and `--cloud` CLI routing flags - Local MCP server (`basic-memory mcp`) automatically uses local routing - Enables simultaneous use of local Claude Desktop and cloud-based clients - Environment variable `BASIC_MEMORY_FORCE_LOCAL=true` for global override ### Bug Fixes - **#524**: Fix MCP prompt rendering errors ([`e14ba92`](https://github.com/basicmachines-co/basic-memory/commit/e14ba92)) - Fix "Error rendering prompt recent_activity" error - Change `TimeFrame` to `str` in prompt type annotations for FastMCP compatibility ## v0.17.9 (2026-01-24) ### Bug Fixes - **#523**: Fix `remove_project()` checking stale config in cloud mode ([`17c0e0a`](https://github.com/basicmachines-co/basic-memory/commit/17c0e0a)) - In cloud mode, only check database `is_default` field (source of truth) - Config file can become stale when users set default project via v2 API ## v0.17.8 (2026-01-24) ### Bug Fixes - **#521**: Fix `get_default_project()` returning multiple results ([`6888eff`](https://github.com/basicmachines-co/basic-memory/commit/6888eff)) - Query incorrectly matched any project with non-NULL `is_default` (both True and False) - Now correctly checks for `is_default=True` only ## v0.17.7 (2026-01-24) ### Features - **#476**: Add SPEC-29 Phase 3 bucket snapshot CLI commands ([`369ad37`](https://github.com/basicmachines-co/basic-memory/commit/369ad37)) - New `basic-memory cloud snapshot` commands for managing cloud snapshots - Commands: `create`, `list`, `delete`, `show`, `browse` - **#515**: Add MCP registry publication files ([`7a502e6`](https://github.com/basicmachines-co/basic-memory/commit/7a502e6)) ### Bug Fixes - **#520**: Read default project from database in cloud mode ([`38616c3`](https://github.com/basicmachines-co/basic-memory/commit/38616c3)) - **#513**: Ensure external_id is set on entity creation ([`c7835a9`](https://github.com/basicmachines-co/basic-memory/commit/c7835a9)) ### Internal - **#514**: Remove OpenPanel telemetry ([`85835ae`](https://github.com/basicmachines-co/basic-memory/commit/85835ae)) - Update README links to point to basicmemory.com ([`2aaee73`](https://github.com/basicmachines-co/basic-memory/commit/2aaee73)) ## v0.17.6 (2026-01-17) ### Bug Fixes - **#510**: Fix Docker container Python symlink broken at runtime ([`1799c94`](https://github.com/basicmachines-co/basic-memory/commit/1799c94)) ### Internal - Remove logfire config and specs docs, reduce lifespan and sync logging to debug level ([`d1d433d`](https://github.com/basicmachines-co/basic-memory/commit/d1d433d), [`803f3ef`](https://github.com/basicmachines-co/basic-memory/commit/803f3ef)) ## v0.17.5 (2026-01-11) ### Bug Fixes - **#505**: Prevent CLI commands from hanging on exit (Python 3.14 compatibility) ([`863e0a4`](https://github.com/basicmachines-co/basic-memory/commit/863e0a4)) - Skip `nest_asyncio` on Python 3.14+ where it causes event loop issues - Simplify CLI test infrastructure for cross-version compatibility - Update pyright to 1.1.408 for Python 3.14 support - Fix SQLAlchemy rowcount typing for Python 3.14 ## v0.17.4 (2026-01-05) ### Bug Fixes - **#503**: Preserve search index across server restarts ([`26f7e98`](https://github.com/basicmachines-co/basic-memory/commit/26f7e98)) - Fixes critical bug where search index was wiped on every MCP server restart - Bug was introduced in v0.16.3, affecting v0.16.3-v0.17.3 - **User action**: Run `basic-memory reset` once after updating to rebuild search index ### Internal - **#502**: Major architecture refactor with composition roots and typed API clients ([`5947f04`](https://github.com/basicmachines-co/basic-memory/commit/5947f04)) - Add composition roots for API, MCP, and CLI entrypoints - Split deps.py into feature-scoped modules (config, db, projects, repositories, services, importers) - Add ProjectResolver for unified project selection - Add SyncCoordinator for centralized sync/watch lifecycle - Introduce typed API clients for MCP tools (KnowledgeClient, SearchClient, MemoryClient, etc.) ## v0.17.3 (2026-01-03) ### Features - **#485**: Add stable external_id (UUID) to Project and Entity models ([`a4000f6`](https://github.com/basicmachines-co/basic-memory/commit/a4000f6)) - Projects and entities now have immutable UUID identifiers - API v2 endpoints use external_id for stable references - Directory responses include external_id for entities ### Bug Fixes - **#501**: Update mcp dependency to support protocol version 2025-11-25 ([`c6baf58`](https://github.com/basicmachines-co/basic-memory/commit/c6baf58)) - Fixes "Unsupported protocol version" error when using Claude Code - Bump mcp from >=1.2.0 to >=1.23.1 - **#499**: Fix route ordering for cloud deployments ([`53c4c20`](https://github.com/basicmachines-co/basic-memory/commit/53c4c20)) - **#486**: Skip config file update for set_default_project in cloud mode ([`fd732aa`](https://github.com/basicmachines-co/basic-memory/commit/fd732aa)) - **#484**: Make RelationResponse.from_id optional to handle null permalinks ([`537e58a`](https://github.com/basicmachines-co/basic-memory/commit/537e58a)) - Use upsert to prevent IntegrityError during parallel search indexing ([`4ce2198`](https://github.com/basicmachines-co/basic-memory/commit/4ce2198)) - Use relative file paths in importers for cloud storage compatibility ([`8adf1f4`](https://github.com/basicmachines-co/basic-memory/commit/8adf1f4)) ### Internal - Refactor importers to use FileService for cloud compatibility ([`45ce181`](https://github.com/basicmachines-co/basic-memory/commit/45ce181)) - Strengthen integration test coverage, remove stdlib mocks ([`b4486d2`](https://github.com/basicmachines-co/basic-memory/commit/b4486d2)) ## v0.17.2 (2025-12-29) ### Bug Fixes - Allow recent_activity discovery mode in cloud mode ([`0bcda4a`](https://github.com/basicmachines-co/basic-memory/commit/0bcda4a)) - Add `allow_discovery` parameter to `resolve_project_parameter()` - Tools like `recent_activity` can now work across all projects in cloud mode - Fix circular import in project_context module ### Internal - Optimize release workflow by running lint/typecheck only (skip full tests) ([`0b5425f`](https://github.com/basicmachines-co/basic-memory/commit/0b5425f)) ## v0.17.1 (2025-12-29) ### Bug Fixes - **#482**: Only set BASIC_MEMORY_ENV=test during pytest runs ([`98fbd60`](https://github.com/basicmachines-co/basic-memory/commit/98fbd60)) - Fixes environment variable pollution affecting alembic migrations - Test environment detection now scoped to pytest execution only ## v0.17.0 (2025-12-28) ### Features - **#478**: Add anonymous usage telemetry with Homebrew-style opt-out ([`856737f`](https://github.com/basicmachines-co/basic-memory/commit/856737f)) - Privacy-respecting anonymous usage analytics - Easy opt-out via `BASIC_MEMORY_NO_ANALYTICS=1` environment variable - Helps improve Basic Memory based on real usage patterns - **#474**: Add auto-format files on save with built-in Python formatter ([`1fd680c`](https://github.com/basicmachines-co/basic-memory/commit/1fd680c)) - Automatic markdown formatting on file save - Built-in Python formatter for consistent code style - Configurable formatting options - **#447**: Complete Phase 2 of API v2 migration - MCP tools use v2 endpoints ([`1a74d85`](https://github.com/basicmachines-co/basic-memory/commit/1a74d85)) - All MCP tools now use optimized v2 API endpoints - Improved performance for knowledge graph operations - Foundation for future API enhancements ### Bug Fixes - Fix UTF-8 BOM handling in frontmatter parsing ([`85684f8`](https://github.com/basicmachines-co/basic-memory/commit/85684f8)) - Handles files with UTF-8 byte order marks correctly - Prevents frontmatter parsing failures - **#475**: Handle null titles in ChatGPT import ([`14ce5a3`](https://github.com/basicmachines-co/basic-memory/commit/14ce5a3)) - Gracefully handles conversations without titles - Improved import robustness - Remove MaxLen constraint from observation content ([`45d6caf`](https://github.com/basicmachines-co/basic-memory/commit/45d6caf)) - Allows longer observation content without truncation - Removes arbitrary 2000 character limit - Handle FileNotFoundError gracefully during sync ([`1652f86`](https://github.com/basicmachines-co/basic-memory/commit/1652f86)) - Prevents sync failures when files are deleted during sync - More resilient file watching - Use canonical project names in API response messages ([`c23927d`](https://github.com/basicmachines-co/basic-memory/commit/c23927d)) - Consistent project name formatting in all responses - Suppress CLI warnings for cleaner output ([`d71c6e8`](https://github.com/basicmachines-co/basic-memory/commit/d71c6e8)) - Cleaner terminal output without spurious warnings - Prevent DEBUG logs from appearing on CLI stdout ([`63b9849`](https://github.com/basicmachines-co/basic-memory/commit/63b9849)) - Debug logging no longer pollutes CLI output - **#473**: Detect rclone version for --create-empty-src-dirs support ([`622d37e`](https://github.com/basicmachines-co/basic-memory/commit/622d37e)) - Automatic rclone version detection for compatibility - Prevents errors on older rclone versions - **#471**: Prevent CLI commands from hanging on exit ([`916baf8`](https://github.com/basicmachines-co/basic-memory/commit/916baf8)) - Fixes CLI hang on shutdown - Proper async cleanup - Add cloud_mode check to initialize_app() ([`ef7adb7`](https://github.com/basicmachines-co/basic-memory/commit/ef7adb7)) - Correct initialization for cloud deployments ### Internal - Centralize test environment detection in config.is_test_env ([`3cd9178`](https://github.com/basicmachines-co/basic-memory/commit/3cd9178)) - Unified test environment detection - Disables analytics in test environments - Make test-int-postgres compatible with macOS ([`95937c6`](https://github.com/basicmachines-co/basic-memory/commit/95937c6)) - Cross-platform PostgreSQL testing support ## v0.16.3 (2025-12-20) ### Features - **#439**: Add PostgreSQL database backend support ([`fb5e9e1`](https://github.com/basicmachines-co/basic-memory/commit/fb5e9e1)) - Full PostgreSQL/Neon database support as alternative to SQLite - Async connection pooling with asyncpg - Alembic migrations support for both backends - Configurable via `BASIC_MEMORY_DATABASE_BACKEND` environment variable - **#441**: Implement API v2 with ID-based endpoints (Phase 1) ([`28cc522`](https://github.com/basicmachines-co/basic-memory/commit/28cc522)) - New ID-based API endpoints for improved performance - Foundation for future API enhancements - Backward compatible with existing endpoints - Add project_id to Relation and Observation for efficient project-scoped queries ([`a920a9f`](https://github.com/basicmachines-co/basic-memory/commit/a920a9f)) - Enables faster queries in multi-project environments - Improved database schema for cloud deployments - Add bulk insert with ON CONFLICT handling for relations ([`0818bda`](https://github.com/basicmachines-co/basic-memory/commit/0818bda)) - Faster relation creation during sync operations - Handles duplicate relations gracefully ### Performance - Lightweight permalink resolution to avoid eager loading ([`6f99d2e`](https://github.com/basicmachines-co/basic-memory/commit/6f99d2e)) - Reduces database queries during entity lookups - Improved response times for read operations ### Bug Fixes - **#464**: Pin FastMCP to 2.12.3 to fix MCP tools visibility ([`f227ef6`](https://github.com/basicmachines-co/basic-memory/commit/f227ef6)) - Fixes issue where MCP tools were not visible to Claude - Reverts to last known working FastMCP version - **#458**: Reduce watch service CPU usage by increasing reload interval ([`897b1ed`](https://github.com/basicmachines-co/basic-memory/commit/897b1ed)) - Lowers CPU usage during file watching - More efficient resource utilization - **#456**: Await background sync task cancellation in lifespan shutdown ([`efbc758`](https://github.com/basicmachines-co/basic-memory/commit/efbc758)) - Prevents hanging on shutdown - Clean async task cleanup - **#434**: Respect --project flag in background sync ([`70bb10b`](https://github.com/basicmachines-co/basic-memory/commit/70bb10b)) - Background sync now correctly uses specified project - Fixes multi-project sync issues - **#446**: Fix observation parsing and permalink limits ([`73d940e`](https://github.com/basicmachines-co/basic-memory/commit/73d940e)) - Handles edge cases in observation content - Prevents permalink truncation issues - **#424**: Handle periods in kebab_filenames mode ([`b004565`](https://github.com/basicmachines-co/basic-memory/commit/b004565)) - Fixes filename handling for files with multiple periods - Improved kebab-case conversion - Fix Postgres/Neon connection settings and search index dedupe ([`b5d4fb5`](https://github.com/basicmachines-co/basic-memory/commit/b5d4fb5)) - Optimized connection pooling for Postgres - Prevents duplicate search index entries ### Testing & CI - Replace py-pglite with testcontainers for Postgres testing ([`c462faf`](https://github.com/basicmachines-co/basic-memory/commit/c462faf)) - More reliable Postgres testing infrastructure - Uses Docker-based test containers - Add PostgreSQL testing to GitHub Actions workflow ([`66b91b2`](https://github.com/basicmachines-co/basic-memory/commit/66b91b2)) - CI now tests both SQLite and PostgreSQL backends - Ensures cross-database compatibility - **#416**: Add integration test for read_note with underscored folders ([`0c12a39`](https://github.com/basicmachines-co/basic-memory/commit/0c12a39)) - Verifies folder name handling edge cases ### Internal - Cloud compatibility fixes and performance improvements (#454) - Remove logfire instrumentation for cleaner production deployments - Truncate content_stems to fix Postgres 8KB index row limit ## v0.16.2 (2025-11-16) ### Bug Fixes - **#429**: Use platform-native path separators in config.json ([`6517e98`](https://github.com/basicmachines-co/basic-memory/commit/6517e98)) - Fixes config.json path separator issues on Windows - Uses os.path.join for platform-native path construction - Ensures consistent path handling across platforms - **#427**: Add rclone installation checks for Windows bisync commands ([`1af0539`](https://github.com/basicmachines-co/basic-memory/commit/1af0539)) - Validates rclone installation before running bisync commands - Provides clear error messages when rclone is not installed - Improves user experience on Windows - **#421**: Main project always recreated on project list command ([`cad7019`](https://github.com/basicmachines-co/basic-memory/commit/cad7019)) - Fixes issue where main project was recreated unnecessarily - Improves project list command reliability - Reduces unnecessary file system operations ## v0.16.1 (2025-11-11) ### Bug Fixes - **#422**: Handle Windows line endings in rclone bisync ([`e9d0a94`](https://github.com/basicmachines-co/basic-memory/commit/e9d0a94)) - Added `--compare=modtime` flag to rclone bisync to ignore size differences from line ending conversions - Fixes issue where LF→CRLF conversion on Windows was treated as file corruption - Resolves "corrupted on transfer: sizes differ" errors during cloud sync on Windows - Users will need to run `--resync` once after updating to establish new baseline ## v0.16.0 (2025-11-10) ### Features - **#417**: Add run_in_background parameter to sync endpoint ([`7ccec7e`](https://github.com/basicmachines-co/basic-memory/commit/7ccec7e)) - New `run_in_background` parameter for async sync operations - Improved API flexibility for long-running sync tasks - Comprehensive test coverage for background sync behavior - **#405**: SPEC-20 Simplified Project-Scoped Rclone Sync ([`0b3272a`](https://github.com/basicmachines-co/basic-memory/commit/0b3272a)) - Simplified and more reliable cloud synchronization - Project-scoped rclone configuration - Better error handling and status reporting - **#384**: Streaming Foundation & Async I/O Consolidation (SPEC-19) ([`e78345f`](https://github.com/basicmachines-co/basic-memory/commit/e78345f)) - Foundation for streaming support in future releases - Consolidated async I/O patterns across codebase - Improved performance and resource management - **#364**: Add circuit breaker for file sync failures ([`434cdf2`](https://github.com/basicmachines-co/basic-memory/commit/434cdf2)) - Prevents cascading failures during sync operations - Automatic recovery from transient errors - Better resilience in cloud sync scenarios - **#362**: Add --verbose and --no-gitignore options to cloud upload ([`7f9c1a9`](https://github.com/basicmachines-co/basic-memory/commit/7f9c1a9)) - Enhanced upload control with verbose logging - Option to bypass gitignore filtering when needed - Better debugging and troubleshooting capabilities - **#391**: Add delete_notes parameter to remove project endpoint ([`c9946ec`](https://github.com/basicmachines-co/basic-memory/commit/c9946ec)) - Option to delete notes when removing projects - Safer project cleanup workflows - Prevents accidental data loss ### Bug Fixes - **#420**: Skip archive files during cloud upload ([`49b2adc`](https://github.com/basicmachines-co/basic-memory/commit/49b2adc)) - Prevents uploading of zip, tar, gz and other archive files - Reduces storage usage and upload time - Better file filtering during cloud operations - **#419**: Rename write_note entity_type to note_type for clarity ([`1646572`](https://github.com/basicmachines-co/basic-memory/commit/1646572)) - Clearer parameter naming in write_note tool - Improved API consistency and documentation - Better developer experience - **#418**: Quote string values in YAML frontmatter to handle special characters ([`f0d7398`](https://github.com/basicmachines-co/basic-memory/commit/f0d7398)) - Fixes YAML parsing errors with special characters - More robust frontmatter handling - Prevents data corruption in edge cases - **#415**: Handle dict objects in write_resource endpoint ([`4614fd0`](https://github.com/basicmachines-co/basic-memory/commit/4614fd0)) - Fixes errors when writing dictionary resources - Better type handling in resource endpoints - Improved API robustness - **#414**: Replace Unicode arrows with ASCII for Windows compatibility ([`fc01f6a`](https://github.com/basicmachines-co/basic-memory/commit/fc01f6a)) - Fixes display issues on Windows terminals - Better cross-platform compatibility - Improved CLI user experience on Windows - **#411**: Windows CLI Unicode encoding errors ([`0ba6f21`](https://github.com/basicmachines-co/basic-memory/commit/0ba6f21)) - Resolves Unicode encoding issues on Windows - Better handling of international characters - Improved Windows platform support - **#410**: Various rclone fixes for cloud sync on Windows ([`c9946ec`](https://github.com/basicmachines-co/basic-memory/commit/c9946ec)) - Fixes cloud sync reliability on Windows - Better path handling for Windows filesystem - Improved rclone integration on Windows - **#402**: Normalize YAML frontmatter types to prevent AttributeError ([`a7d7cc5`](https://github.com/basicmachines-co/basic-memory/commit/a7d7cc5)) - Fixes AttributeError when reading frontmatter - More robust type normalization - Better error handling in markdown parsing - **#396**: Strip duplicate headers in edit_note replace_section ([`021af74`](https://github.com/basicmachines-co/basic-memory/commit/021af74)) - Prevents duplicate headers when replacing sections - Cleaner note editing behavior - Better content consistency - **#395**: Simplify search_notes schema by removing Optional wrappers ([`d775f7b`](https://github.com/basicmachines-co/basic-memory/commit/d775f7b)) - Cleaner API schema definition - Better type safety and validation - Improved developer experience - **#394**: Add explicit type annotations to MCP tool parameters ([`581b7b1`](https://github.com/basicmachines-co/basic-memory/commit/581b7b1)) - Better type safety in MCP tools - Improved IDE support and autocomplete - Clearer tool documentation - **#389**: Handle null, empty, and string 'None' title in markdown frontmatter ([`bb8da31`](https://github.com/basicmachines-co/basic-memory/commit/bb8da31)) - Fixes errors with malformed frontmatter titles - More robust title handling - Better error recovery - **#380**: Optimize sync memory usage to prevent OOM on large projects ([`4fd6d0c`](https://github.com/basicmachines-co/basic-memory/commit/4fd6d0c)) - Prevents out-of-memory errors on large knowledge bases - Better memory management during sync - Improved scalability - **#379**: Handle YAML parsing errors gracefully in update_frontmatter ([`32236cd`](https://github.com/basicmachines-co/basic-memory/commit/32236cd)) - Better error handling for malformed YAML - Graceful degradation instead of crashes - Improved robustness - **#377**: Preserve mtime on WebDAV upload ([`e6c8e36`](https://github.com/basicmachines-co/basic-memory/commit/e6c8e36)) - Maintains file modification times during upload - Better sync accuracy - Prevents unnecessary re-syncing - **#370**: Prevent deleted projects from being recreated by background sync ([`449b62d`](https://github.com/basicmachines-co/basic-memory/commit/449b62d)) - Fixes race condition with project deletion - Better lifecycle management - Prevents unwanted project recreation - **#369**: Use filesystem timestamps for entity sync instead of database operation time ([`b7497d7`](https://github.com/basicmachines-co/basic-memory/commit/b7497d7)) - More accurate sync detection - Better handling of external file modifications - Improved sync reliability - **#368**: Handle YAML parsing errors and missing entity_type in markdown files ([`d1431bd`](https://github.com/basicmachines-co/basic-memory/commit/d1431bd)) - Better error handling for malformed markdown - Graceful handling of missing metadata - Improved robustness - **#367**: Resolve UNIQUE constraint violation in entity upsert with observations ([`171bef7`](https://github.com/basicmachines-co/basic-memory/commit/171bef7)) - Fixes database constraint errors during sync - Better handling of duplicate observations - Improved data integrity - **#366**: Terminate sync immediately when project is deleted ([`729a5a3`](https://github.com/basicmachines-co/basic-memory/commit/729a5a3)) - Faster project deletion - Better resource cleanup - Improved user experience - **#357**: Make project creation endpoint idempotent ([`53fb13b`](https://github.com/basicmachines-co/basic-memory/commit/53fb13b)) - Prevents errors when creating existing projects - Better API reliability - Improved cloud integration - **#353**: Handle None text values in Claude conversations importer ([`bd6c834`](https://github.com/basicmachines-co/basic-memory/commit/bd6c834)) - Fixes import errors with empty messages - Better error handling in importers - Improved data migration ### Performance Improvements - Force full database sync after project sync/bisync operations ([`2ad0ee9`](https://github.com/basicmachines-co/basic-memory/commit/2ad0ee9)) - Ensures database consistency after cloud operations - Better sync reliability - Improved data integrity ### Documentation - Add free trial information to README ([`a7d7cc5`](https://github.com/basicmachines-co/basic-memory/commit/a7d7cc5), [`8aaddb6`](https://github.com/basicmachines-co/basic-memory/commit/8aaddb6)) - Updated README with Basic Memory Cloud trial info - Better onboarding experience - Clearer pricing information - Announce Basic Memory Cloud launch in README ([`d756531`](https://github.com/basicmachines-co/basic-memory/commit/d756531)) - Official cloud service announcement - Updated documentation for cloud features - Improved product positioning ### Migration Guide No manual migration required. Upgrade with: ```bash # Update via uv uv tool upgrade basic-memory # Or install fresh uv tool install basic-memory ``` **What's New in v0.16.0:** - Streaming foundation and consolidated async I/O (SPEC-19) - Simplified project-scoped rclone sync (SPEC-20) - Circuit breaker for sync failure resilience - Enhanced Windows platform support - Improved cloud upload with verbose and gitignore options - Better error handling across YAML parsing and frontmatter - Memory optimization for large projects - Archive file filtering during upload **Breaking Changes:** - `write_note` parameter renamed: `entity_type` → `note_type` for clarity ### Installation ```bash # Latest stable release uv tool install basic-memory # Update existing installation uv tool upgrade basic-memory # Docker docker pull ghcr.io/basicmachines-co/basic-memory:v0.16.0 ``` ## v0.15.2 (2025-10-14) ### Features - **#356**: Add WebDAV upload command for cloud projects ([`5258f45`](https://github.com/basicmachines-co/basic-memory/commit/5258f457)) - New `bm cloud upload` command for uploading local files/directories to cloud projects - WebDAV-based file transfer with automatic directory creation - Support for `.gitignore` and `.bmignore` pattern filtering - Automatic project creation with `--create-project` flag - Optional post-upload sync with `--sync` flag (enabled by default) - Human-readable file size reporting (bytes, KB, MB) - Comprehensive test coverage (28 unit tests) ### Migration Guide No manual migration required. Upgrade with: ```bash # Update via uv uv tool upgrade basic-memory # Or install fresh uv tool install basic-memory ``` **What's New:** - Upload local files to cloud projects with `bm cloud upload` - Streamlined cloud project creation and management - Better file filtering with gitignore integration ### Installation ```bash # Latest stable release uv tool install basic-memory # Update existing installation uv tool upgrade basic-memory # Docker docker pull ghcr.io/basicmachines-co/basic-memory:v0.15.2 ``` ## v0.15.1 (2025-10-13) ### Performance Improvements - **#352**: Optimize sync/indexing for 43% faster performance ([`c0538ad`](https://github.com/basicmachines-co/basic-memory/commit/c0538ad2perf0d68a2a3604e255c3f2c42c5ed)) - Significant performance improvements to file synchronization and indexing operations - 43% reduction in sync time for large knowledge bases - Optimized database queries and file processing - **#350**: Optimize directory operations for 10-100x performance improvement ([`00b73b0`](https://github.com/basicmachines-co/basic-memory/commit/00b73b0d)) - Dramatic performance improvements for directory listing operations - 10-100x faster directory traversal depending on knowledge base size - Reduced memory footprint for large directory structures - Exclude null fields from directory endpoint responses for smaller payloads ### Bug Fixes - **#355**: Update view_note and ChatGPT tools for Claude Desktop compatibility ([`2b7008d`](https://github.com/basicmachines-co/basic-memory/commit/2b7008d9)) - Fix view_note tool formatting for better Claude Desktop rendering - Update ChatGPT tool integration for improved compatibility - Enhanced artifact display in Claude Desktop interface - **#348**: Add permalink normalization to project lookups in deps.py ([`a09066e`](https://github.com/basicmachines-co/basic-memory/commit/a09066e0)) - Fix project lookup failures due to case sensitivity - Normalize permalinks consistently across project operations - Improve project switching reliability - **#345**: Project deletion failing with permalink normalization ([`be352ab`](https://github.com/basicmachines-co/basic-memory/commit/be352ab4)) - Fix project deletion errors related to permalink handling - Ensure proper cleanup of project resources - Improve error messages for deletion failures - **#341**: Correct ProjectItem.home property to return path instead of name ([`3e876a7`](https://github.com/basicmachines-co/basic-memory/commit/3e876a75)) - Fix ProjectItem.home to return correct project path - Resolve configuration issues with project paths - Improve project path resolution consistency - **#339**: Prevent nested project paths to avoid data conflicts ([`795e339`](https://github.com/basicmachines-co/basic-memory/commit/795e3393)) - Block creation of nested project paths that could cause data conflicts - Add validation to prevent project path hierarchy issues - Improve error messages for invalid project configurations - **#338**: Normalize paths to lowercase in cloud mode to prevent case collisions ([`07e304c`](https://github.com/basicmachines-co/basic-memory/commit/07e304ce)) - Fix path case sensitivity issues in cloud deployments - Normalize paths consistently across cloud operations - Prevent data loss from case-insensitive filesystem collisions - **#336**: Cloud mode path validation and sanitization (bmc-issue-103) ([`2a1c06d`](https://github.com/basicmachines-co/basic-memory/commit/2a1c06d9)) - Enhanced path validation for cloud deployments - Improved path sanitization to prevent security issues - Better error handling for invalid paths in cloud mode - **#332**: Cloud mode path validation and sanitization ([`7616b2b`](https://github.com/basicmachines-co/basic-memory/commit/7616b2bb)) - Additional cloud mode path fixes and improvements - Comprehensive path validation for cloud environments - Security enhancements for path handling ### Features - **#344**: Async client context manager pattern for cloud consolidation (SPEC-16) ([`8d2e70c`](https://github.com/basicmachines-co/basic-memory/commit/8d2e70cf)) - Refactor async client to use context manager pattern - Improve resource management and cleanup - Enable better dependency injection for cloud deployments - Foundation for cloud platform consolidation - **#343**: Add SPEC-15 for configuration persistence via Tigris ([`53438d1`](https://github.com/basicmachines-co/basic-memory/commit/53438d1e)) - Design specification for persistent configuration storage - Foundation for cloud configuration management - Tigris S3-compatible storage integration planning - **#334**: Introduce BASIC_MEMORY_PROJECT_ROOT for path constraints ([`ccc4386`](https://github.com/basicmachines-co/basic-memory/commit/ccc43866)) - Add environment variable for constraining project paths - Improve security by limiting project creation locations - Better control over project directory structure ### Documentation - **#335**: v0.15.0 assistant guide updates ([`c6f93a0`](https://github.com/basicmachines-co/basic-memory/commit/c6f93a02)) - Update AI assistant guide for v0.15.0 features - Improve documentation for new MCP tools - Better examples and usage patterns - **#339**: Add tool use documentation to write_note for root folder usage ([`73202d1`](https://github.com/basicmachines-co/basic-memory/commit/73202d1a)) - Document how to use empty string for root folder in write_note - Clarify folder parameter usage - Improve tool documentation clarity - Fix link in ai_assistant_guide resource ([`2a1c06d`](https://github.com/basicmachines-co/basic-memory/commit/2a1c06d9)) - Correct broken documentation links - Improve resource accessibility ### Refactoring - Add SPEC-17 and SPEC-18 documentation ([`962d88e`](https://github.com/basicmachines-co/basic-memory/commit/962d88ea)) - New specification documents for future features - Architecture planning and design documentation ### Breaking Changes **None** - This release maintains full backward compatibility with v0.15.0 ### Migration Guide No manual migration required. Upgrade with: ```bash # Update via uv uv tool upgrade basic-memory # Or install fresh uv tool install basic-memory ``` **What's Fixed:** - Significant performance improvements (43% faster sync, 10-100x faster directory operations) - Multiple cloud deployment stability fixes - Project path validation and normalization issues resolved - Better Claude Desktop and ChatGPT integration **What's New:** - Context manager pattern for async clients (foundation for cloud consolidation) - BASIC_MEMORY_PROJECT_ROOT environment variable for path constraints - Enhanced cloud mode path handling and security - SPEC-15 and SPEC-16 architecture documentation ### Installation ```bash # Latest stable release uv tool install basic-memory # Update existing installation uv tool upgrade basic-memory # Docker docker pull ghcr.io/basicmachines-co/basic-memory:v0.15.1 ``` ## v0.15.0 (2025-10-04) ### Critical Bug Fixes - **Permalink Collision Data Loss Prevention** - Fixed critical bug where creating similar entity names would overwrite existing files ([`2a050ed`](https://github.com/basicmachines-co/basic-memory/commit/2a050edee42b07294f5199902a60b626bfc47be8)) - **Issue**: Creating "Node C" would overwrite "Node A.md" due to fuzzy search incorrectly matching similar file paths - **Solution**: Added `strict=True` parameter to link resolution, disabling fuzzy search fallback during entity creation - **Impact**: Prevents data loss from false positive path matching like "edge-cases/Node A.md" vs "edge-cases/Node C.md" - **Testing**: Comprehensive integration tests and MCP-level permalink collision tests added - **Status**: Manually verified fix prevents file overwrite in production scenarios ### Bug Fixes - **#330**: Remove .env file loading from BasicMemoryConfig ([`f3b1945`](https://github.com/basicmachines-co/basic-memory/commit/f3b1945e4c0070d0282eaf98c085ef188c8edd2d)) - Clean up configuration initialization to prevent unintended environment variable loading - **#329**: Normalize underscores in memory:// URLs for build_context ([`f5a11f3`](https://github.com/basicmachines-co/basic-memory/commit/f5a11f3911edda55bee6970ed9e7c38f7fd7a059)) - Fix URL normalization to handle underscores consistently in memory:// protocol - Improve knowledge graph navigation with standardized URL handling - **#328**: Simplify entity upsert to use database-level conflict resolution ([`ee83b0e`](https://github.com/basicmachines-co/basic-memory/commit/ee83b0e5a8f00cdcc8e24a0f8c9449c6eaddf649)) - Leverage SQLite's native UPSERT for cleaner entity creation/update logic - Reduce application-level complexity by using database conflict resolution - **#312**: Add proper datetime JSON schema format annotations for MCP validation ([`a7bf42e`](https://github.com/basicmachines-co/basic-memory/commit/a7bf42ef495a3e2c66230985c3445cab5c52c408)) - Fix MCP schema validation errors with proper datetime format annotations - Ensure compatibility with strict MCP schema validators - **#281**: Fix move_note without file extension ([`3e168b9`](https://github.com/basicmachines-co/basic-memory/commit/3e168b98f3962681799f4537eb86ded47e771665)) - Allow moving notes by title alone without requiring .md extension - Improve move operation usability and error handling - **#310**: Remove obsolete update_current_project function and --project flag reference ([`17a6733`](https://github.com/basicmachines-co/basic-memory/commit/17a6733c9d280def922e37c2cd171e3ee44fce21)) - Clean up deprecated project management code - Remove unused CLI flag references - **#309**: Make sync operations truly non-blocking with thread pool ([`1091e11`](https://github.com/basicmachines-co/basic-memory/commit/1091e113227c86f10f574e56a262aff72f728113)) - Move sync operations to background thread pool for improved responsiveness - Prevent blocking during file synchronization operations ### Features - **#327**: CLI Subscription Validation (SPEC-13 Phase 2) ([`ace6a0f`](https://github.com/basicmachines-co/basic-memory/commit/ace6a0f50d8d0b4ea31fb526361c2d9616271740)) - Implement subscription validation for CLI operations - Foundation for future cloud billing integration - **#322**: Cloud CLI sync via rclone bisync ([`99a35a7`](https://github.com/basicmachines-co/basic-memory/commit/99a35a7fb410ef88c50050e666e4244350e44a6e)) - Add bidirectional cloud synchronization using rclone - Enable local-cloud file sync with conflict detection - **#315**: Implement SPEC-11 API performance optimizations ([`5da97e4`](https://github.com/basicmachines-co/basic-memory/commit/5da97e482052907d68a2a3604e255c3f2c42c5ed)) - Comprehensive API performance improvements - Optimized database queries and response times - **#314**: Integrate ignore_utils to skip .gitignored files in sync process ([`33ee1e0`](https://github.com/basicmachines-co/basic-memory/commit/33ee1e0831d2060587de2c9886e74ff111b04583)) - Respect .gitignore patterns during file synchronization - Prevent syncing build artifacts and temporary files - **#313**: Add disable_permalinks config flag ([`9035913`](https://github.com/basicmachines-co/basic-memory/commit/903591384dffeba9996a18463818bdb8b28ca03e)) - Optional permalink generation for users who don't need them - Improves flexibility for different knowledge management workflows - **#306**: Implement cloud mount CLI commands for local file access ([`2c5c606`](https://github.com/basicmachines-co/basic-memory/commit/2c5c606a394ab994334c8fd307b30370037bbf39)) - Mount cloud files locally using rclone for real-time editing - Three performance profiles: fast (5s), balanced (10-15s), safe (15s+) - Cross-platform rclone installer with package manager fallbacks - **#305**: ChatGPT tools for search and fetch ([`f40ab31`](https://github.com/basicmachines-co/basic-memory/commit/f40ab31685a9510a07f5d87bf24436c0df80680f)) - Add ChatGPT-specific search and fetch tools - Expand AI assistant integration options - **#298**: Implement SPEC-6 Stateless Architecture for MCP Tools ([`a1d7792`](https://github.com/basicmachines-co/basic-memory/commit/a1d7792bdb6f71c4943b861d1c237f6ac7021247)) - Redesign MCP tools for stateless operation - Enable cloud deployment with better scalability - **#296**: Basic Memory cloud upload ([`e0d8aeb`](https://github.com/basicmachines-co/basic-memory/commit/e0d8aeb14913f3471b9716d0c60c61adb1d74687)) - Implement file upload capabilities for cloud storage - Foundation for cloud-hosted Basic Memory instances - **#291**: Merge Cloud auth ([`3a6baf8`](https://github.com/basicmachines-co/basic-memory/commit/3a6baf80fc6012e9434e06b1605f9a8b198d8688)) - OAuth 2.1 authentication with Supabase integration - JWT-based tenant isolation for multi-user cloud deployments ### Platform & Infrastructure - **#331**: Add Python 3.13 to test matrix ([`16d7edd`](https://github.com/basicmachines-co/basic-memory/commit/16d7eddbf704abfe53373663e80d05ecdde15aa7)) - Ensure compatibility with latest Python version - Expand CI/CD testing coverage - **#316**: Enable WAL mode and add Windows-specific SQLite optimizations ([`c83d567`](https://github.com/basicmachines-co/basic-memory/commit/c83d567917267bb3d52708f4b38d2daf36c1f135)) - Enable Write-Ahead Logging for better concurrency - Platform-specific SQLite optimizations for Windows users - **#320**: Rework lifecycle management to optimize cloud deployment ([`ea2e93d`](https://github.com/basicmachines-co/basic-memory/commit/ea2e93d9265bfa366d2d3796f99f579ab2aed48c)) - Optimize application lifecycle for cloud environments - Improve startup time and resource management - **#319**: Resolve entity relations in background to prevent cold start blocking ([`324844a`](https://github.com/basicmachines-co/basic-memory/commit/324844a670d874410c634db520a68c09149045ea)) - Move relation resolution to background processing - Faster MCP server cold starts - **#318**: Enforce minimum 1-day timeframe for recent_activity ([`f818702`](https://github.com/basicmachines-co/basic-memory/commit/f818702ab7f8d2d706178e7b0ed3467501c9c4a2)) - Fix timezone-related issues in recent activity queries - Ensure consistent behavior across time zones - **#317**: Critical cloud deployment fixes for MCP stability ([`2efd8f4`](https://github.com/basicmachines-co/basic-memory/commit/2efd8f44e2d0259079ed5105fea34308875c0e10)) - Multiple stability improvements for cloud-hosted MCP servers - Enhanced error handling and recovery ### Technical Improvements - **Comprehensive Testing** - Extensive test coverage for critical fixes - New permalink collision test suite with 4 MCP-level integration tests - Entity service test coverage expanded to reproduce fuzzy search bug - Manual testing verification of data loss prevention - All 55 entity service tests passing with new strict resolution - **Windows Support Enhancements** ([`7a8b08d`](https://github.com/basicmachines-co/basic-memory/commit/7a8b08d11ee627b54af6f5ea7ab4ef9fcd8cf4ed), [`9aa4024`](https://github.com/basicmachines-co/basic-memory/commit/9aa40246a8ad1c3cef82b32e1ca7ce8ea23e1e05)) - Fix Windows test failures and add Windows CI support - Address platform-specific issues for Windows users - Enhanced cross-platform compatibility - **Docker Improvements** ([`105bcaa`](https://github.com/basicmachines-co/basic-memory/commit/105bcaa025576a06f889183baded6c18f3782696)) - Implement non-root Docker container to fix file ownership issues - Improved security and compatibility in containerized deployments - **Code Quality** - Enhanced filename sanitization with optional kebab case support - Improved character conflict detection for sync operations - Better error handling across the codebase - Path traversal security vulnerability fixes ### Documentation - **#321**: Corrected dead links in README ([`fc38877`](https://github.com/basicmachines-co/basic-memory/commit/fc38877008cd8c762116f7ff4b2573495b4e5c0f)) - Fix broken documentation links - Improve navigation and accessibility - **#308**: Update Claude Code GitHub Workflow ([`8c7e29e`](https://github.com/basicmachines-co/basic-memory/commit/8c7e29e325f36a67bdefe8811637493bef4bbf56)) - Enhanced GitHub integration documentation - Better Claude Code collaboration workflow ### Breaking Changes **None** - This release maintains full backward compatibility with v0.14.x All changes are either: - Bug fixes that correct unintended behavior - New optional features that don't affect existing functionality - Internal optimizations that are transparent to users ### Migration Guide No manual migration required. Upgrade with: ```bash # Update via uv uv tool upgrade basic-memory # Or install fresh uv tool install basic-memory ``` **What's Fixed:** - Data loss bug from permalink collisions is completely resolved - Cloud deployment stability significantly improved - Windows platform compatibility enhanced - Better performance across all operations **What's New:** - Cloud sync capabilities via rclone - Subscription validation foundation - Python 3.13 support - Enhanced security and stability ### Installation ```bash # Latest stable release uv tool install basic-memory # Update existing installation uv tool upgrade basic-memory # Docker docker pull ghcr.io/basicmachines-co/basic-memory:v0.15.0 ``` ## v0.14.2 (2025-07-03) ### Bug Fixes - **#204**: Fix MCP Error with MCP-Hub integration ([`3621bb7`](https://github.com/basicmachines-co/basic-memory/commit/3621bb7b4d6ac12d892b18e36bb8f7c9101c7b10)) - Resolve compatibility issues with MCP-Hub - Improve error handling in project management tools - Ensure stable MCP tool integration across different environments - **Modernize datetime handling and suppress SQLAlchemy warnings** ([`f80ac0e`](https://github.com/basicmachines-co/basic-memory/commit/f80ac0e3e74b7a737a7fc7b956b5c1d61b0c67b8)) - Replace deprecated `datetime.utcnow()` with timezone-aware alternatives - Suppress SQLAlchemy deprecation warnings for cleaner output - Improve future compatibility with Python datetime best practices ## v0.14.1 (2025-07-03) ### Bug Fixes - **#203**: Constrain fastmcp version to prevent breaking changes ([`827f7cf`](https://github.com/basicmachines-co/basic-memory/commit/827f7cf86e7b84c56e7a43bb83f2e5d84a1ad8b8)) - Pin fastmcp to compatible version range to avoid API breaking changes - Ensure stable MCP server functionality across updates - Improve dependency management for production deployments - **#190**: Fix Problems with MCP integration ([`bd4f551`](https://github.com/basicmachines-co/basic-memory/commit/bd4f551a5bb0b7b4d3a5b04de70e08987c6ab2f9)) - Resolve MCP server initialization and communication issues - Improve error handling and recovery in MCP operations - Enhance stability for AI assistant integrations ### Features - **Add Cursor IDE integration button** - One-click setup for Cursor IDE users ([`5360005`](https://github.com/basicmachines-co/basic-memory/commit/536000512294d66090bf87abc8014f4dfc284310)) - Direct installation button for Cursor IDE in README - Streamlined setup process for Cursor users - Enhanced developer experience for AI-powered coding - **Add Homebrew installation instructions** - Official Homebrew tap support ([`39f811f`](https://github.com/basicmachines-co/basic-memory/commit/39f811f8b57dd998445ae43537cd492c680b2e11)) - Official Homebrew formula in basicmachines-co/basic-memory tap - Simplified installation process for macOS users - Package manager integration for easier dependency management ## v0.14.0 (2025-06-26) ### Features - **Docker Container Registry Migration** - Switch from Docker Hub to GitHub Container Registry for better security and integration ([`616c1f0`](https://github.com/basicmachines-co/basic-memory/commit/616c1f0710da59c7098a5f4843d4f017877ff7b2)) - Automated Docker image publishing via GitHub Actions CI/CD pipeline - Enhanced container security with GitHub's integrated vulnerability scanning - Streamlined container deployment workflow for production environments - **Enhanced Search Documentation** - Comprehensive search syntax examples for improved user experience ([`a589f8b`](https://github.com/basicmachines-co/basic-memory/commit/a589f8b894e78cce01eb25656856cfea8785fbbf)) - Detailed examples for Boolean search operators (AND, OR, NOT) - Advanced search patterns including phrase matching and field-specific queries - User-friendly documentation for complex search scenarios - **Cross-Project File Management** - Intelligent move operations with project boundary detection ([`db5ef7d`](https://github.com/basicmachines-co/basic-memory/commit/db5ef7d35cc0894309c7a57b5741c9dd978526d4)) - Automatic detection of cross-project move attempts with helpful guidance - Clear error messages when attempting unsupported cross-project operations ### Bug Fixes - **#184**: Preserve permalinks when editing notes without frontmatter permalinks ([`c2f4b63`](https://github.com/basicmachines-co/basic-memory/commit/c2f4b632cf04921b1a3c2f0d43831b80c519cb31)) - Fix permalink preservation during note editing operations - Ensure consistent permalink handling across different note formats - Maintain note identity and searchability during incremental edits - **#183**: Implement project-specific sync status checks for MCP tools ([`12b5152`](https://github.com/basicmachines-co/basic-memory/commit/12b51522bc953fca117fc5bc01fcb29c6ca7e13c)) - Fix sync status reporting to correctly reflect current project state - Resolve inconsistencies where sync status showed global instead of project-specific information - Improve project isolation for sync operations and status reporting - **#180**: Handle Boolean search syntax with hyphenated terms ([`546e3cd`](https://github.com/basicmachines-co/basic-memory/commit/546e3cd8db98b74f746749d41887f8a213cd0b11)) - Fix search parsing issues with hyphenated terms in Boolean queries - Improve search query tokenization for complex term structures - Enhanced search reliability for technical documentation and multi-word concepts - **#174**: Respect BASIC_MEMORY_HOME environment variable in Docker containers ([`9f1db23`](https://github.com/basicmachines-co/basic-memory/commit/9f1db23c78d4648e2c242ad1ee27eed85e3f3b5d)) - Fix Docker container configuration to properly honor custom home directory settings - Improve containerized deployment flexibility with environment variable support - Ensure consistent behavior between local and containerized installations - **#168**: Scope entity queries by project_id in upsert_entity method ([`2a3adc1`](https://github.com/basicmachines-co/basic-memory/commit/2a3adc109a3e4d7ccd65cae4abf63d9bb2338326)) - Fix entity isolation issues in multi-project setups - Prevent cross-project entity conflicts during database operations - Strengthen project boundary enforcement at the database level - **#166**: Handle None from_entity in Context API RelationSummary ([`8a065c3`](https://github.com/basicmachines-co/basic-memory/commit/8a065c32f4e41613207d29aafc952a56e3a52241)) - Fix null pointer exceptions in relation processing - Improve error handling for incomplete relation data - Enhanced stability for knowledge graph traversal operations - **#164**: Remove log level configuration from mcp_server.run() ([`224e4bf`](https://github.com/basicmachines-co/basic-memory/commit/224e4bf9e4438c44a82ffc21bd1a282fe9087690)) - Simplify MCP server startup by removing redundant log level settings - Fix potential logging configuration conflicts - Streamline server initialization process - **#162**: Ensure permalinks are generated for entities with null permalinks during move operations ([`f506507`](https://github.com/basicmachines-co/basic-memory/commit/f50650763dbd4322c132e4bdc959ce4bf074374b)) - Fix move operations for entities without existing permalinks - Automatic permalink generation during file move operations - Maintain database consistency during file reorganization ### Technical Improvements - **Comprehensive Test Coverage** - Extensive test suites for new features and edge cases - Enhanced test coverage for project-specific sync status functionality - Additional test scenarios for search syntax validation and edge cases - Integration tests for Docker CI workflow and container publishing - Comprehensive move operations testing with project boundary validation - **Docker CI/CD Pipeline** - Production-ready automated container publishing ([`74847cc`](https://github.com/basicmachines-co/basic-memory/commit/74847cc3807b0c6ed511e0d83e0d560e9f07ec44)) - Automated Docker image building and publishing on release - Multi-architecture container support for AMD64 and ARM64 platforms - Integrated security scanning and vulnerability assessments - Streamlined deployment pipeline for production environments - **Release Process Improvements** - Enhanced automation and quality gates ([`a52ce1c`](https://github.com/basicmachines-co/basic-memory/commit/a52ce1c8605ec2cd450d1f909154172cbc30faa2)) - Homebrew formula updates limited to stable releases only - Improved release automation with better quality control - Enhanced CI/CD pipeline reliability and error handling - **Code Quality Enhancements** - Improved error handling and validation - Better null safety in entity and relation processing - Enhanced project isolation validation throughout the codebase - Improved error messages and user guidance for edge cases - Strengthened database consistency guarantees across operations ### Infrastructure - **GitHub Container Registry Integration** - Modern container infrastructure - Migration from Docker Hub to GitHub Container Registry (ghcr.io) - Improved security with integrated vulnerability scanning - Better integration with GitHub-based development workflow - Enhanced container versioning and artifact management - **Enhanced CI/CD Workflows** - Robust automated testing and deployment - Automated Docker image publishing on releases - Comprehensive test coverage validation before deployment - Multi-platform container building and publishing - Integration with GitHub's security and monitoring tools ### Migration Guide This release includes several behind-the-scenes improvements and fixes. All changes are backward compatible: - **Docker Users**: Container images now served from `ghcr.io/basicmachines-co/basic-memory` instead of Docker Hub - **Search Users**: Enhanced search syntax handling - existing queries continue to work unchanged - **Multi-Project Users**: Improved project isolation - all existing projects remain fully functional - **All Users**: Enhanced stability and error handling - no breaking changes to existing workflows ### Installation ```bash # Latest stable release uv tool install basic-memory # Update existing installation uv tool upgrade basic-memory # Docker (new registry) docker pull ghcr.io/basicmachines-co/basic-memory:latest ``` ## v0.13.7 (2025-06-19) ### Bug Fixes - **Homebrew Integration** - Automatic Homebrew formula updates - **Documentation** - Add git sign-off reminder to development guide ## v0.13.6 (2025-06-18) ### Bug Fixes - **Custom Entity Types** - Support for custom entity types in write_note ([`7789864`](https://github.com/basicmachines-co/basic-memory/commit/77898644933589c2da9bdd60571d54137a5309ed)) - Fixed `entity_type` parameter for `write_note` MCP tool to respect value passed in - Frontmatter `type` field automatically respected when no explicit parameter provided - Maintains backward compatibility with default "note" type - **#139**: Fix "UNIQUE constraint failed: entity.permalink" database error ([`c6215fd`](https://github.com/basicmachines-co/basic-memory/commit/c6215fd819f9564ead91cf3a950f855241446096)) - Implement SQLAlchemy UPSERT strategy to handle permalink conflicts gracefully - Eliminates crashes when creating notes with existing titles in same folders - Seamlessly updates existing entities instead of failing with constraint errors - **Database Migration Performance** - Eliminate redundant migration initialization ([`84d2aaf`](https://github.com/basicmachines-co/basic-memory/commit/84d2aaf6414dd083af4b0df73f6c8139b63468f6)) - Fix duplicate migration calls that slowed system startup - Improve performance with multiple projects (tested with 28+ projects) - Add migration deduplication safeguards with comprehensive test coverage - **User Experience** - Correct spelling error in continue_conversation prompt ([`b4c26a6`](https://github.com/basicmachines-co/basic-memory/commit/b4c26a613379e6f2ba655efe3d7d8d40c27999e5)) - Fix "Chose a folder" → "Choose a folder" in MCP prompt instructions - Improve grammar and clarity in user-facing prompt text ### Documentation - **Website Updates** - Add new website and community links to README ([`3fdce68`](https://github.com/basicmachines-co/basic-memory/commit/3fdce683d7ad8b6f4855d7138d5ff2136d4c07bc)) - **Project Documentation** - Update README.md and CLAUDE.md with latest project information ([`782cb2d`](https://github.com/basicmachines-co/basic-memory/commit/782cb2df28803482d209135a054e67cc32d7363e)) ### Technical Improvements - **Comprehensive Test Coverage** - Add extensive test suites for new features - Custom entity type validation with 8 new test scenarios - UPSERT behavior testing with edge case coverage - Migration deduplication testing with 6 test scenarios - Database constraint handling validation - **Code Quality** - Enhanced error handling and validation - Improved SQLAlchemy patterns with modern UPSERT operations - Better conflict resolution strategies for entity management - Strengthened database consistency guarantees ### Performance - **Database Operations** - Faster startup and improved scalability - Reduced migration overhead for multi-project setups - Optimized conflict resolution for entity creation - Enhanced performance with growing knowledge bases ### Migration Guide This release includes automatic database improvements. No manual migration required: - Existing notes and entity types continue working unchanged - New `entity_type` parameter is optional and backward compatible - Database performance improvements apply automatically - All existing MCP tool behavior preserved ### Installation ```bash # Latest stable release uv tool install basic-memory # Update existing installation uv tool upgrade basic-memory ``` ## v0.13.5 (2025-06-11) ### Bug Fixes - **MCP Tools**: Renamed `create_project` tool to `create_memory_project` for namespace isolation - **Namespace**: Continued namespace isolation effort to prevent conflicts with other MCP servers ### Changes - Tool functionality remains identical - only the name changed from `create_project` to `create_memory_project` - All integration tests updated to use the new tool name - Completes namespace isolation for project management tools alongside `list_memory_projects` ## v0.13.4 (2025-06-11) ### Bug Fixes - **MCP Tools**: Renamed `list_projects` tool to `list_memory_projects` to avoid naming conflicts with other MCP servers - **Namespace**: Improved tool naming specificity for better MCP server integration and isolation ### Changes - Tool functionality remains identical - only the name changed from `list_projects` to `list_memory_projects` - All integration tests updated to use the new tool name - Better namespace isolation for Basic Memory MCP tools ## v0.13.3 (2025-06-11) ### Bug Fixes - **Projects**: Fixed case-insensitive project switching where switching succeeded but subsequent operations failed due to session state inconsistency - **Config**: Enhanced config manager with case-insensitive project lookup using permalink-based matching - **MCP Tools**: Updated project management tools to store canonical project names from database instead of user input - **API**: Improved project service to handle both name and permalink lookups consistently ### Technical Improvements - Added comprehensive case-insensitive project switching test coverage with 5 new integration test scenarios - Fixed permalink generation inconsistencies where different case inputs could generate different permalinks - Enhanced project URL construction to use permalinks consistently across all API calls - Improved error handling and session state management for project operations ### Changes - Project switching now preserves canonical project names from database in session state - All project operations use permalink-based lookups for case-insensitive matching - Enhanced test coverage ensures reliable case-insensitive project operations ## v0.13.2 (2025-06-11) ### Features - **Release Management**: Added automated release management system with version control in `__init__.py` - **Automation**: Implemented justfile targets for `release` and `beta` commands with comprehensive quality gates - **CI/CD**: Enhanced release process with automatic version updates, git tagging, and GitHub release creation ### Development Experience - Added `.claude/commands/release/` directory with automation documentation - Implemented release validation including lint, type-check, and test execution - Streamlined release workflow from manual process to single-command automation ### Technical Improvements - Updated package version management to use actual version numbers instead of dynamic versioning - Added release process documentation and command references - Enhanced justfile with comprehensive release automation targets ## v0.13.1 (2025-06-11) ### Bug Fixes - **CLI**: Fixed `basic-memory project` project management commands that were not working in v0.13.0 (#129) - **Projects**: Resolved case sensitivity issues when switching between projects that caused "Project not found" errors (#127) - **API**: Standardized CLI project command endpoints and improved error handling - **Core**: Implemented consistent project name handling using permalinks to avoid case-related conflicts ### Changes - Renamed `basic-memory project sync` command to `basic-memory project sync-config` for clarity - Improved project switching reliability across different case variations - Removed redundant server status messages from CLI error outputs ## v0.13.0 (2025-06-11) ### Overview Basic Memory v0.13.0 is a **major release** that transforms Basic Memory into a true multi-project knowledge management system. This release introduces fluid project switching, advanced note editing capabilities, robust file management, and production-ready OAuth authentication - all while maintaining full backward compatibility. **What's New for Users:** - 🎯 **Switch between projects instantly** during conversations with Claude - ✏️ **Edit notes incrementally** without rewriting entire documents - 📁 **Move and organize notes** with full database consistency - 📖 **View notes as formatted artifacts** for better readability in Claude Desktop - 🔍 **Search frontmatter tags** to discover content more easily - 🔐 **OAuth authentication** for secure remote access - ⚡ **Development builds** automatically published for beta testing **Key v0.13.0 Accomplishments:** - ✅ **Complete Project Management System** - Project switching and project-specific operations - ✅ **Advanced Note Editing** - Incremental editing with append, prepend, find/replace, and section operations - ✅ **View Notes as Artifacts in Claude Desktop/Web** - Use the view_note tool to view a note as an artifact - ✅ **File Management System** - Full move operations with database consistency and rollback protection - ✅ **Enhanced Search Capabilities** - Frontmatter tags now searchable, improved content discoverability - ✅ **Unified Database Architecture** - Single app-level database for better performance and project management ### Major Features #### 1. Multiple Project Management **Switch between projects instantly during conversations:** ``` 💬 "What projects do I have?" 🤖 Available projects: • main (current, default) • work-notes • personal-journal • code-snippets 💬 "Switch to work-notes" 🤖 ✓ Switched to work-notes project Project Summary: • 47 entities • 125 observations • 23 relations 💬 "What did I work on yesterday?" 🤖 [Shows recent activity from work-notes project] ``` **Key Capabilities:** - **Instant Project Switching**: Change project context mid-conversation without restart - **Project-Specific Operations**: Operations work within the currently active project context - **Project Discovery**: List all available projects with status indicators - **Session Context**: Maintains active project throughout conversation - **Backward Compatibility**: Existing single-project setups continue to work seamlessly #### 2. Advanced Note Editing **Edit notes incrementally without rewriting entire documents:** ```python # Append new sections to existing notes edit_note("project-planning", "append", "\n## New Requirements\n- Feature X\n- Feature Y") # Prepend timestamps to meeting notes edit_note("meeting-notes", "prepend", "## 2025-05-27 Update\n- Progress update...") # Replace specific sections under headers edit_note("api-spec", "replace_section", "New implementation details", section="## Implementation") # Find and replace with validation edit_note("config", "find_replace", "v0.13.0", find_text="v0.12.0", expected_replacements=2) ``` **Key Capabilities:** - **Append Operations**: Add content to end of notes (most common use case) - **Prepend Operations**: Add content to beginning of notes - **Section Replacement**: Replace content under specific markdown headers - **Find & Replace**: Simple text replacements with occurrence counting - **Smart Error Handling**: Helpful guidance when operations fail - **Project Context**: Works within the active project with session awareness #### 3. Smart File Management **Move and organize notes:** ```python # Simple moves with automatic folder creation move_note("my-note", "work/projects/my-note.md") # Organize within the active project move_note("shared-doc", "archive/old-docs/shared-doc.md") # Rename operations move_note("old-name", "same-folder/new-name.md") ``` **Key Capabilities:** - **Database Consistency**: Updates file paths, permalinks, and checksums automatically - **Search Reindexing**: Maintains search functionality after moves - **Folder Creation**: Automatically creates destination directories - **Project Isolation**: Operates within the currently active project - **Link Preservation**: Maintains internal links and references #### 4. Enhanced Search & Discovery **Find content more easily with improved search capabilities:** - **Frontmatter Tag Search**: Tags from YAML frontmatter are now indexed and searchable - **Improved Content Discovery**: Search across titles, content, tags, and metadata - **Project-Scoped Search**: Search within the currently active project - **Better Search Quality**: Enhanced FTS5 indexing with tag content inclusion **Example:** ```yaml --- title: Coffee Brewing Methods tags: [coffee, brewing, equipment] --- ``` Now searchable by: "coffee", "brewing", "equipment", or "Coffee Brewing Methods" #### 5. Unified Database Architecture **Single app-level database for better performance and project management:** - **Migration from Per-Project DBs**: Moved from multiple SQLite files to single app database - **Project Isolation**: Proper data separation with project_id foreign keys - **Better Performance**: Optimized queries and reduced file I/O ### Complete MCP Tool Suite #### New Project Management Tools - **`list_projects()`** - Discover and list all available projects with status - **`switch_project(project_name)`** - Change active project context during conversations - **`get_current_project()`** - Show currently active project with statistics - **`set_default_project(project_name)`** - Update default project configuration - **`sync_status()`** - Check file synchronization status and background operations #### New Note Operations Tools - **`edit_note()`** - Incremental note editing (append, prepend, find/replace, section replace) - **`move_note()`** - Move notes with database consistency and search reindexing - **`view_note()`** - Display notes as formatted artifacts for better readability in Claude Desktop #### Enhanced Existing Tools All existing tools now support: - **Session context awareness** (operates within the currently active project) - **Enhanced error messages** with project context metadata - **Improved response formatting** with project information footers - **Project isolation** ensures operations stay within the correct project boundaries ### User Experience Improvements #### Installation Options **Multiple ways to install and test Basic Memory:** ```bash # Stable release uv tool install basic-memory # Beta/pre-releases uv tool install basic-memory --pre ``` #### Bug Fixes & Quality Improvements **Major issues resolved in v0.13.0:** - **#118**: Fixed YAML tag formatting to follow standard specification - **#110**: Fixed `--project` flag consistency across all CLI commands - **#107**: Fixed write_note update failures with existing notes - **#93**: Fixed custom permalink handling in frontmatter - **#52**: Enhanced search capabilities with frontmatter tag indexing - **FTS5 Search**: Fixed special character handling in search queries - **Error Handling**: Improved error messages and validation across all tools ### Breaking Changes & Migration #### For Existing Users **Automatic Migration**: First run will automatically migrate existing data to the new unified database structure. No manual action required. **What Changes:** - Database location: Moved to `~/.basic-memory/memory.db` (unified across projects) - Configuration: Projects defined in `~/.basic-memory/config.json` are synced with database **What Stays the Same:** - All existing notes and data remain unchanged - Default project behavior maintained for single-project users - All existing MCP tools continue to work without modification ### Documentation & Resources #### New Documentation - [Project Management Guide](docs/Project%20Management.md) - Multi-project workflows - [Note Editing Guide](docs/Note%20Editing.md) - Advanced editing techniques #### Updated Documentation - [README.md](README.md) - Installation options and beta build instructions - [CONTRIBUTING.md](CONTRIBUTING.md) - Release process and version management - [CLAUDE.md](CLAUDE.md) - Development workflow and CI/CD documentation - [Claude.ai Integration](docs/Claude.ai%20Integration.md) - Updated MCP tool examples #### Quick Start Examples **Project Switching:** ``` 💬 "Switch to my work project and show recent activity" 🤖 [Calls switch_project("work") then recent_activity()] ``` **Note Editing:** ``` 💬 "Add a section about deployment to my API docs" 🤖 [Calls edit_note("api-docs", "append", "## Deployment\n...")] ``` **File Organization:** ``` 💬 "Move my old meeting notes to the archive folder" 🤖 [Calls move_note("meeting-notes", "archive/old-meetings.md")] ``` ## v0.12.3 (2025-04-17) ### Bug Fixes - Add extra logic for permalink generation with mixed Latin unicode and Chinese characters ([`73ea91f`](https://github.com/basicmachines-co/basic-memory/commit/73ea91fe0d1f7ab89b99a1b691d59fe608b7fcbb)) Signed-off-by: phernandez - Modify recent_activity args to be strings instead of enums ([`3c1cc34`](https://github.com/basicmachines-co/basic-memory/commit/3c1cc346df519e703fae6412d43a92c7232c6226)) Signed-off-by: phernandez ## v0.12.2 (2025-04-08) ### Bug Fixes - Utf8 for all file reads/write/open instead of default platform encoding ([#91](https://github.com/basicmachines-co/basic-memory/pull/91), [`2934176`](https://github.com/basicmachines-co/basic-memory/commit/29341763318408ea8f1e954a41046c4185f836c6)) Signed-off-by: phernandez ## v0.12.1 (2025-04-07) ### Bug Fixes - Run migrations and sync when starting mcp ([#88](https://github.com/basicmachines-co/basic-memory/pull/88), [`78a3412`](https://github.com/basicmachines-co/basic-memory/commit/78a3412bcff83b46e78e26f8b9fce42ed9e05991)) ## v0.12.0 (2025-04-06) ### Bug Fixes - [bug] `#` character accumulation in markdown frontmatter tags prop ([#79](https://github.com/basicmachines-co/basic-memory/pull/79), [`6c19c9e`](https://github.com/basicmachines-co/basic-memory/commit/6c19c9edf5131054ba201a109b37f15c83ef150c)) - [bug] Cursor has errors calling search tool ([#78](https://github.com/basicmachines-co/basic-memory/pull/78), [`9d581ce`](https://github.com/basicmachines-co/basic-memory/commit/9d581cee133f9dde4a0a85118868227390c84161)) - [bug] Some notes never exit "modified" status ([#77](https://github.com/basicmachines-co/basic-memory/pull/77), [`7930ddb`](https://github.com/basicmachines-co/basic-memory/commit/7930ddb2919057be30ceac8c4c19da6aaa1d3e92)) - [bug] write_note Tool Fails to Update Existing Files in Some Situations. ([#80](https://github.com/basicmachines-co/basic-memory/pull/80), [`9bff1f7`](https://github.com/basicmachines-co/basic-memory/commit/9bff1f732e71bc60f88b5c2ce3db5a2aa60b8e28)) - Set default mcp log level to ERROR ([#81](https://github.com/basicmachines-co/basic-memory/pull/81), [`248214c`](https://github.com/basicmachines-co/basic-memory/commit/248214cb114a269ca60ff6398e382f9e2495ad8e)) - Write_note preserves frontmatter fields in content ([#84](https://github.com/basicmachines-co/basic-memory/pull/84), [`3f4d9e4`](https://github.com/basicmachines-co/basic-memory/commit/3f4d9e4d872ebc0ed719c61b24d803c14a9db5e6)) ### Documentation - Add VS Code instructions to README ([#76](https://github.com/basicmachines-co/basic-memory/pull/76), [`43cbb7b`](https://github.com/basicmachines-co/basic-memory/commit/43cbb7b38cc0482ac0a41b6759320e3588186e43)) - Updated basicmachines.co links to be https ([#69](https://github.com/basicmachines-co/basic-memory/pull/69), [`40ea28b`](https://github.com/basicmachines-co/basic-memory/commit/40ea28b0bfc60012924a69ecb76511daa4c7d133)) ### Features - Add watch to mcp process ([#83](https://github.com/basicmachines-co/basic-memory/pull/83), [`00c8633`](https://github.com/basicmachines-co/basic-memory/commit/00c8633cfcee75ff640ff8fe81dafeb956281a94)) - Permalink enhancements ([#82](https://github.com/basicmachines-co/basic-memory/pull/82), [`617e60b`](https://github.com/basicmachines-co/basic-memory/commit/617e60bda4a590678a5f551f10a73e7b47e3b13e)) - Avoiding "useless permalink values" for files without metadata - Enable permalinks to be updated on move via config setting ## v0.11.0 (2025-03-29) ### Bug Fixes - Just delete db for reset db instead of using migrations. ([#65](https://github.com/basicmachines-co/basic-memory/pull/65), [`0743ade`](https://github.com/basicmachines-co/basic-memory/commit/0743ade5fc07440f95ecfd816ba7e4cfd74bca12)) Signed-off-by: phernandez - Make logs for each process - mcp, sync, cli ([#64](https://github.com/basicmachines-co/basic-memory/pull/64), [`f1c9570`](https://github.com/basicmachines-co/basic-memory/commit/f1c95709cbffb1b88292547b0b8f29fcca22d186)) Signed-off-by: phernandez ### Documentation - Update broken "Multiple Projects" link in README.md ([#55](https://github.com/basicmachines-co/basic-memory/pull/55), [`3c68b7d`](https://github.com/basicmachines-co/basic-memory/commit/3c68b7d5dd689322205c67637dca7d188111ee6b)) ### Features - Add bm command alias for basic-memory ([#67](https://github.com/basicmachines-co/basic-memory/pull/67), [`069c0a2`](https://github.com/basicmachines-co/basic-memory/commit/069c0a21c630784e1bf47d2b7de5d6d1f6fadd7a)) Signed-off-by: phernandez - Rename search tool to search_notes ([#66](https://github.com/basicmachines-co/basic-memory/pull/66), [`b278276`](https://github.com/basicmachines-co/basic-memory/commit/b27827671dc010be3e261b8b221aca6b7f836661)) Signed-off-by: phernandez ## v0.10.1 (2025-03-25) ### Bug Fixes - Make set_default_project also activate project for current session to fix #37 ([`cbe72be`](https://github.com/basicmachines-co/basic-memory/commit/cbe72be10a646c0b03931bb39aff9285feae47f9)) This change makes the 'basic-memory project default ' command both: 1. Set the default project for future invocations (persistent change) 2. Activate the project for the current session (immediate change) Added tests to verify this behavior, which resolves issue #37 where the project name and path weren't changing properly when the default project was changed. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude - Make set_default_project also activate project for current session to fix #37 ([`46c4fd2`](https://github.com/basicmachines-co/basic-memory/commit/46c4fd21645b109af59eb2a0201c7bd849b34a49)) This change makes the 'basic-memory project default ' command both: 1. Set the default project for future invocations (persistent change) 2. Activate the project for the current session (immediate change) Added tests to verify this behavior, which resolves issue #37 where the project name and path weren't changing properly when the default project was changed. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude Signed-off-by: phernandez - Move ai_assistant_guide.md into package resources to fix #39 ([`390ff9d`](https://github.com/basicmachines-co/basic-memory/commit/390ff9d31ccee85bef732e8140b5eeecd7ee176f)) This change relocates the AI assistant guide from the static directory into the package resources directory, ensuring it gets properly included in the distribution package and is accessible when installed via pip/uv. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude - Move ai_assistant_guide.md into package resources to fix #39 ([`cc2cae7`](https://github.com/basicmachines-co/basic-memory/commit/cc2cae72c14b380f78ffeb67c2261e4dbee45faf)) This change relocates the AI assistant guide from the static directory into the package resources directory, ensuring it gets properly included in the distribution package and is accessible when installed via pip/uv. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude Signed-off-by: phernandez - Preserve custom frontmatter fields when updating notes ([`78f234b`](https://github.com/basicmachines-co/basic-memory/commit/78f234b1806b578a0a833e8ee4184015b7369a97)) Fixes #36 by modifying entity_service.update_entity() to read existing frontmatter from files before updating them. Custom metadata fields such as Status, Priority, and Version are now preserved when notes are updated through the write_note MCP tool. Added test case that verifies this behavior by creating a note with custom frontmatter and then updating it. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude - Preserve custom frontmatter fields when updating notes ([`e716946`](https://github.com/basicmachines-co/basic-memory/commit/e716946b4408d017eca4be720956d5a210b4e6b1)) Fixes #36 by modifying entity_service.update_entity() to read existing frontmatter from files before updating them. Custom metadata fields such as Status, Priority, and Version are now preserved when notes are updated through the write_note MCP tool. Added test case that verifies this behavior by creating a note with custom frontmatter and then updating it. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude Signed-off-by: phernandez ### Chores - Remove duplicate code in entity_service.py from bad merge ([`681af5d`](https://github.com/basicmachines-co/basic-memory/commit/681af5d4505dadc40b4086630f739d76bac9201d)) Signed-off-by: phernandez ### Documentation - Add help docs to mcp cli tools ([`731b502`](https://github.com/basicmachines-co/basic-memory/commit/731b502d36cec253d114403d73b48fab3c47786e)) Signed-off-by: phernandez - Add mcp badge, update cli reference, llms-install.md ([`b26afa9`](https://github.com/basicmachines-co/basic-memory/commit/b26afa927f98021246cd8b64858e57333595ea90)) Signed-off-by: phernandez - Update CLAUDE.md ([#33](https://github.com/basicmachines-co/basic-memory/pull/33), [`dfaf0fe`](https://github.com/basicmachines-co/basic-memory/commit/dfaf0fea9cf5b97d169d51a6276ec70162c21a7e)) fix spelling in CLAUDE.md: environment typo Signed-off-by: Ikko Eltociear Ashimine ### Refactoring - Move project stats into project subcommand ([`2a881b1`](https://github.com/basicmachines-co/basic-memory/commit/2a881b1425c73947f037fbe7ac5539c015b62526)) Signed-off-by: phernandez ## v0.10.0 (2025-03-15) ### Bug Fixes - Ai_resource_guide.md path ([`da97353`](https://github.com/basicmachines-co/basic-memory/commit/da97353cfc3acc1ceb0eca22ac6af326f77dc199)) Signed-off-by: phernandez - Ai_resource_guide.md path ([`c4732a4`](https://github.com/basicmachines-co/basic-memory/commit/c4732a47b37dd2e404139fb283b65556c81ce7c9)) - Ai_resource_guide.md path ([`2e9d673`](https://github.com/basicmachines-co/basic-memory/commit/2e9d673e54ad6a63a971db64f01fc2f4e59c2e69)) Signed-off-by: phernandez - Don't sync *.tmp files on watch ([#31](https://github.com/basicmachines-co/basic-memory/pull/31), [`6b110b2`](https://github.com/basicmachines-co/basic-memory/commit/6b110b28dd8ba705ebfc0bcb41faf2cb993da2c3)) Fixes #30 Signed-off-by: phernandez - Drop search_index table on db reindex ([`31cca6f`](https://github.com/basicmachines-co/basic-memory/commit/31cca6f913849a0ab8fc944803533e3072e9ef88)) Signed-off-by: phernandez - Improve utf-8 support for file reading/writing ([#32](https://github.com/basicmachines-co/basic-memory/pull/32), [`eb5e4ec`](https://github.com/basicmachines-co/basic-memory/commit/eb5e4ec6bd4d2fe757087be030d867f4ca1d38ba)) fixes #29 Signed-off-by: phernandez ### Chores - Remove logfire ([`9bb8a02`](https://github.com/basicmachines-co/basic-memory/commit/9bb8a020c3425a02cb3a88f6f02adcd281bccee2)) Signed-off-by: phernandez ### Documentation - Add glama badge. Fix typos in README.md ([#28](https://github.com/basicmachines-co/basic-memory/pull/28), [`9af913d`](https://github.com/basicmachines-co/basic-memory/commit/9af913da4fba7bb4908caa3f15f2db2aa03777ec)) Signed-off-by: phernandez - Update CLAUDE.md with GitHub integration capabilities ([#25](https://github.com/basicmachines-co/basic-memory/pull/25), [`fea2f40`](https://github.com/basicmachines-co/basic-memory/commit/fea2f40d1b54d0c533e6d7ee7ce1aa7b83ad9a47)) This PR updates the CLAUDE.md file to document the GitHub integration capabilities that enable Claude to participate directly in the development workflow. ### Features - Add Smithery integration for easier installation ([#24](https://github.com/basicmachines-co/basic-memory/pull/24), [`eb1e7b6`](https://github.com/basicmachines-co/basic-memory/commit/eb1e7b6088b0b3dead9c104ee44174b2baebf417)) This PR adds support for deploying Basic Memory on the Smithery platform. Signed-off-by: bm-claudeai ## v0.9.0 (2025-03-07) ### Chores - Pre beta prep ([#20](https://github.com/basicmachines-co/basic-memory/pull/20), [`6a4bd54`](https://github.com/basicmachines-co/basic-memory/commit/6a4bd546466a45107007b5000276b6c9bb62ef27)) fix: drop search_index table on db reindex fix: ai_resource_guide.md path chore: remove logfire Signed-off-by: phernandez ### Documentation - Update README.md and CLAUDE.md ([`182ec78`](https://github.com/basicmachines-co/basic-memory/commit/182ec7835567fc246798d9b4ad121b2f85bc6ade)) ### Features - Add project_info tool ([#19](https://github.com/basicmachines-co/basic-memory/pull/19), [`d2bd75a`](https://github.com/basicmachines-co/basic-memory/commit/d2bd75a949cc4323cb376ac2f6cb39f47c78c428)) Signed-off-by: phernandez - Beta work ([#17](https://github.com/basicmachines-co/basic-memory/pull/17), [`e6496df`](https://github.com/basicmachines-co/basic-memory/commit/e6496df595f3cafde6cc836384ee8c60886057a5)) feat: Add multiple projects support feat: enhanced read_note for when initial result is not found fix: merge frontmatter when updating note fix: handle directory removed on sync watch - Implement boolean search ([#18](https://github.com/basicmachines-co/basic-memory/pull/18), [`90d5754`](https://github.com/basicmachines-co/basic-memory/commit/90d5754180beaf4acd4be38f2438712555640b49)) ## v0.8.0 (2025-02-28) ### Chores - Formatting ([`93cc637`](https://github.com/basicmachines-co/basic-memory/commit/93cc6379ebb9ecc6a1652feeeecbf47fc992d478)) - Refactor logging setup ([`f4b703e`](https://github.com/basicmachines-co/basic-memory/commit/f4b703e57f0ddf686de6840ff346b8be2be499ad)) ### Features - Add enhanced prompts and resources ([#15](https://github.com/basicmachines-co/basic-memory/pull/15), [`093dab5`](https://github.com/basicmachines-co/basic-memory/commit/093dab5f03cf7b090a9f4003c55507859bf355b0)) ## Summary - Add comprehensive documentation to all MCP prompt modules - Enhance search prompt with detailed contextual output formatting - Implement consistent logging and docstring patterns across prompt utilities - Fix type checking in prompt modules ## Prompts Added/Enhanced - `search.py`: New formatted output with relevance scores, excerpts, and next steps - `recent_activity.py`: Enhanced with better metadata handling and documentation - `continue_conversation.py`: Improved context management ## Resources Added/Enhanced - `ai_assistant_guide`: Resource with description to give to LLM to understand how to use the tools ## Technical improvements - Added detailed docstrings to all prompt modules explaining their purpose and usage - Enhanced the search prompt with rich contextual output that helps LLMs understand results - Created a consistent pattern for formatting output across prompts - Improved error handling in metadata extraction - Standardized import organization and naming conventions - Fixed various type checking issues across the codebase This PR is part of our ongoing effort to improve the MCP's interaction quality with LLMs, making the system more helpful and intuitive for AI assistants to navigate knowledge bases. 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: phernandez - Add new `canvas` tool to create json canvas files in obsidian. ([#14](https://github.com/basicmachines-co/basic-memory/pull/14), [`0d7b0b3`](https://github.com/basicmachines-co/basic-memory/commit/0d7b0b3d7ede7555450ddc9728951d4b1edbbb80)) Add new `canvas` tool to create json canvas files in obsidian. --------- Co-authored-by: phernandez - Incremental sync on watch ([#13](https://github.com/basicmachines-co/basic-memory/pull/13), [`37a01b8`](https://github.com/basicmachines-co/basic-memory/commit/37a01b806d0758029d34a862e76d44c7e5d538a5)) - incremental sync on watch - sync non-markdown files in knowledge base - experimental `read_resource` tool for reading non-markdown files in raw form (pdf, image) ## v0.7.0 (2025-02-19) ### Bug Fixes - Add logfire instrumentation to tools ([`3e8e3e8`](https://github.com/basicmachines-co/basic-memory/commit/3e8e3e8961eae2e82839746e28963191b0aef0a0)) - Add logfire spans to cli ([`00d23a5`](https://github.com/basicmachines-co/basic-memory/commit/00d23a5ee15ddac4ea45e702dcd02ab9f0509276)) - Add logfire spans to cli ([`812136c`](https://github.com/basicmachines-co/basic-memory/commit/812136c8c22ad191d14ff32dcad91aae076d4120)) - Search query pagination params ([`bc9ca07`](https://github.com/basicmachines-co/basic-memory/commit/bc9ca0744ffe4296d7d597b4dd9b7c73c2d63f3f)) ### Chores - Fix tests ([`57984aa`](https://github.com/basicmachines-co/basic-memory/commit/57984aa912625dcde7877afb96d874c164af2896)) - Remove unused tests ([`2c8ed17`](https://github.com/basicmachines-co/basic-memory/commit/2c8ed1737d6769fe1ef5c96f8a2bd75b9899316a)) ### Features - Add cli commands for mcp tools ([`f5a7541`](https://github.com/basicmachines-co/basic-memory/commit/f5a7541da17e97403b7a702720a05710f68b223a)) - Add pagination to build_context and recent_activity ([`0123544`](https://github.com/basicmachines-co/basic-memory/commit/0123544556513af943d399d70b849b142b834b15)) - Add pagination to read_notes ([`02f8e86`](https://github.com/basicmachines-co/basic-memory/commit/02f8e866923d5793d2620076c709c920d99f2c4f)) ## v0.6.0 (2025-02-18) ### Chores - Re-add sync status console on watch ([`66b57e6`](https://github.com/basicmachines-co/basic-memory/commit/66b57e682f2e9c432bffd4af293b0d1db1d3469b)) ### Features - Configure logfire telemetry ([#12](https://github.com/basicmachines-co/basic-memory/pull/12), [`6da1438`](https://github.com/basicmachines-co/basic-memory/commit/6da143898bd45cdab8db95b5f2b75810fbb741ba)) Co-authored-by: phernandez ## v0.5.0 (2025-02-18) ### Features - Return semantic info in markdown after write_note ([#11](https://github.com/basicmachines-co/basic-memory/pull/11), [`0689e7a`](https://github.com/basicmachines-co/basic-memory/commit/0689e7a730497827bf4e16156ae402ddc5949077)) Co-authored-by: phernandez ## v0.4.3 (2025-02-18) ### Bug Fixes - Re do enhanced read note format ([#10](https://github.com/basicmachines-co/basic-memory/pull/10), [`39bd5ca`](https://github.com/basicmachines-co/basic-memory/commit/39bd5ca08fd057220b95a8b5d82c5e73a1f5722b)) Co-authored-by: phernandez ## v0.4.2 (2025-02-17) ## v0.4.1 (2025-02-17) ### Bug Fixes - Fix alemic config ([`71de8ac`](https://github.com/basicmachines-co/basic-memory/commit/71de8acfd0902fc60f27deb3638236a3875787ab)) - More alembic fixes ([`30cd74e`](https://github.com/basicmachines-co/basic-memory/commit/30cd74ec95c04eaa92b41b9815431f5fbdb46ef8)) ## v0.4.0 (2025-02-16) ### Features - Import chatgpt conversation data ([#9](https://github.com/basicmachines-co/basic-memory/pull/9), [`56f47d6`](https://github.com/basicmachines-co/basic-memory/commit/56f47d6812982437f207629e6ac9a82e0e56514e)) Co-authored-by: phernandez - Import claude.ai data ([#8](https://github.com/basicmachines-co/basic-memory/pull/8), [`a15c346`](https://github.com/basicmachines-co/basic-memory/commit/a15c346d5ebd44344b76bad877bb4d1073fcbc3b)) Import Claude.ai conversation and project data to basic-memory Markdown format. --------- Co-authored-by: phernandez ## v0.3.0 (2025-02-15) ### Bug Fixes - Refactor db schema migrate handling ([`ca632be`](https://github.com/basicmachines-co/basic-memory/commit/ca632beb6fed5881f4d8ba5ce698bb5bc681e6aa)) ## v0.2.21 (2025-02-15) ### Bug Fixes - Fix osx installer github action ([`65ebe5d`](https://github.com/basicmachines-co/basic-memory/commit/65ebe5d19491e5ff047c459d799498ad5dd9cd1a)) - Handle memory:// url format in read_note tool ([`e080373`](https://github.com/basicmachines-co/basic-memory/commit/e0803734e69eeb6c6d7432eea323c7a264cb8347)) - Remove create schema from init_db ([`674dd1f`](https://github.com/basicmachines-co/basic-memory/commit/674dd1fd47be9e60ac17508476c62254991df288)) ### Features - Set version in var, output version at startup ([`a91da13`](https://github.com/basicmachines-co/basic-memory/commit/a91da1396710e62587df1284da00137d156fc05e)) ## v0.2.20 (2025-02-14) ### Bug Fixes - Fix installer artifact ([`8de84c0`](https://github.com/basicmachines-co/basic-memory/commit/8de84c0221a1ee32780aa84dac4d3ea60895e05c)) ## v0.2.19 (2025-02-14) ### Bug Fixes - Get app artifact for installer ([`fe8c3d8`](https://github.com/basicmachines-co/basic-memory/commit/fe8c3d87b003166252290a87cbe958301cccf797)) ## v0.2.18 (2025-02-14) ### Bug Fixes - Don't zip app on release ([`8664c57`](https://github.com/basicmachines-co/basic-memory/commit/8664c57bb331d7f3f7e0239acb5386c7a3c6144e)) ## v0.2.17 (2025-02-14) ### Bug Fixes - Fix app zip in installer release ([`8fa197e`](https://github.com/basicmachines-co/basic-memory/commit/8fa197e2ec8a1b6caaf6dbb39c3c6626bba23e2e)) ## v0.2.16 (2025-02-14) ### Bug Fixes - Debug inspect build on ci ([`1d6054d`](https://github.com/basicmachines-co/basic-memory/commit/1d6054d30a477a4e6a5d6ac885632e50c01945d3)) ## v0.2.15 (2025-02-14) ### Bug Fixes - Debug installer ci ([`dab9573`](https://github.com/basicmachines-co/basic-memory/commit/dab957314aec9ed0e12abca2265552494ae733a2)) ## v0.2.14 (2025-02-14) ## v0.2.13 (2025-02-14) ### Bug Fixes - Refactor release.yml installer ([`a152657`](https://github.com/basicmachines-co/basic-memory/commit/a15265783e47c22d8c7931396281d023b3694e27)) - Try using symlinks in installer build ([`8dd923d`](https://github.com/basicmachines-co/basic-memory/commit/8dd923d5bc0587276f92b5f1db022ad9c8687e45)) ## v0.2.12 (2025-02-14) ### Bug Fixes - Fix cx_freeze options for installer ([`854cf83`](https://github.com/basicmachines-co/basic-memory/commit/854cf8302e2f83578030db05e29b8bdc4348795a)) ## v0.2.11 (2025-02-14) ### Bug Fixes - Ci installer app fix #37 ([`2e215fe`](https://github.com/basicmachines-co/basic-memory/commit/2e215fe83ca421b921186c7f1989dc2cb5cca278)) ## v0.2.10 (2025-02-14) ### Bug Fixes - Fix build on github ci for app installer ([`29a2594`](https://github.com/basicmachines-co/basic-memory/commit/29a259421a0ccb10cfa68e3707eaa506ad5e55c0)) ## v0.2.9 (2025-02-14) ## v0.2.8 (2025-02-14) ### Bug Fixes - Fix installer on ci, maybe ([`edbc04b`](https://github.com/basicmachines-co/basic-memory/commit/edbc04be601d234bb1f5eb3ba24d6ad55244b031)) ## v0.2.7 (2025-02-14) ### Bug Fixes - Try to fix installer ci ([`230738e`](https://github.com/basicmachines-co/basic-memory/commit/230738ee9c110c0509e0a09cb0e101a92cfcb729)) ## v0.2.6 (2025-02-14) ### Bug Fixes - Bump project patch version ([`01d4672`](https://github.com/basicmachines-co/basic-memory/commit/01d46727b40c24b017ea9db4b741daef565ac73e)) - Fix installer setup.py change ci to use make ([`3e78fcc`](https://github.com/basicmachines-co/basic-memory/commit/3e78fcc2c208d83467fe7199be17174d7ffcad1a)) ## v0.2.5 (2025-02-14) ### Bug Fixes - Refix virtual env in installer build ([`052f491`](https://github.com/basicmachines-co/basic-memory/commit/052f491fff629e8ead629c9259f8cb46c608d584)) ## v0.2.4 (2025-02-14) ## v0.2.3 (2025-02-14) ### Bug Fixes - Workaround unsigned app ([`41d4d81`](https://github.com/basicmachines-co/basic-memory/commit/41d4d81c1ad1dc2923ba0e903a57454a0c8b6b5c)) ## v0.2.2 (2025-02-14) ### Bug Fixes - Fix path to installer app artifact ([`53d220d`](https://github.com/basicmachines-co/basic-memory/commit/53d220df585561f9edd0d49a9e88f1d4055059cf)) ## v0.2.1 (2025-02-14) ### Bug Fixes - Activate virtualenv in installer build ([`d4c8293`](https://github.com/basicmachines-co/basic-memory/commit/d4c8293687a52eaf3337fe02e2f7b80e4cc9a1bb)) - Trigger installer build on release ([`f11bf78`](https://github.com/basicmachines-co/basic-memory/commit/f11bf78f3f600d0e1b01996cf8e1f9c39e3dd218)) ## v0.2.0 (2025-02-14) ### Features - Build installer via github action ([#7](https://github.com/basicmachines-co/basic-memory/pull/7), [`7c381a5`](https://github.com/basicmachines-co/basic-memory/commit/7c381a59c962053c78da096172e484f28ab47e96)) * feat(ci): build installer via github action * enforce conventional commits in PR titles * feat: add icon to installer --------- Co-authored-by: phernandez ## v0.1.2 (2025-02-14) ### Bug Fixes - Fix installer for mac ([`dde9ff2`](https://github.com/basicmachines-co/basic-memory/commit/dde9ff228b72852b5abc58faa1b5e7c6f8d2c477)) - Remove unused FileChange dataclass ([`eb3360c`](https://github.com/basicmachines-co/basic-memory/commit/eb3360cc221f892b12a17137ae740819d48248e8)) - Update uv installer url ([`2f9178b`](https://github.com/basicmachines-co/basic-memory/commit/2f9178b0507b3b69207d5c80799f2d2f573c9a04)) ## v0.1.1 (2025-02-07) ## v0.1.0 (2025-02-07) ### Bug Fixes - Create virtual env in test workflow ([`8092e6d`](https://github.com/basicmachines-co/basic-memory/commit/8092e6d38d536bfb6f93c3d21ea9baf1814f9b0a)) - Fix permalink uniqueness violations on create/update/sync ([`135bec1`](https://github.com/basicmachines-co/basic-memory/commit/135bec181d9b3d53725c8af3a0959ebc1aa6afda)) - Fix recent activity bug ([`3d2c0c8`](https://github.com/basicmachines-co/basic-memory/commit/3d2c0c8c32fcfdaf70a1f96a59d8f168f38a1aa9)) - Install fastapi deps after removing basic-foundation ([`51a741e`](https://github.com/basicmachines-co/basic-memory/commit/51a741e7593a1ea0e5eb24e14c70ff61670f9663)) - Recreate search index on db reset ([`1fee436`](https://github.com/basicmachines-co/basic-memory/commit/1fee436bf903a35c9ebb7d87607fc9cc9f5ff6e7)) - Remove basic-foundation from deps ([`b8d0c71`](https://github.com/basicmachines-co/basic-memory/commit/b8d0c7160f29c97cdafe398a7e6a5240473e0c89)) - Run tests via uv ([`4eec820`](https://github.com/basicmachines-co/basic-memory/commit/4eec820a32bc059a405e2f4dac4c73b245ca4722)) ### Chores - Rename import tool ([`af6b7dc`](https://github.com/basicmachines-co/basic-memory/commit/af6b7dc40a55eaa2aa78d6ea831e613851081d52)) ### Features - Add memory-json importer, tweak observation content ([`3484e26`](https://github.com/basicmachines-co/basic-memory/commit/3484e26631187f165ee6eb85517e94717b7cf2cf)) ## v0.0.1 (2025-02-04) ### Bug Fixes - Fix versioning for 0.0.1 release ([`ba1e494`](https://github.com/basicmachines-co/basic-memory/commit/ba1e494ed1afbb7af3f97c643126bced425da7e0)) ## v0.0.0 (2025-02-04) ### Chores - Remove basic-foundation src ref in pyproject.toml ([`29fce8b`](https://github.com/basicmachines-co/basic-memory/commit/29fce8b0b922d54d7799bf2534107ee6cfb961b8))