Basic Memory v0.24
Basic Memory v0.24 shipped in October 2026 (v0.24.0 release notes). Install v0.24.1 or later: it pins FastAPI so fresh installs start cleanly. The theme is an agent-grade knowledge base. Agents can browse notes the way they browse a codebase. Writes are guarded so two agents can't silently overwrite each other. PDFs and Office files become searchable notes, and observations can say when they're true.
Read notes like a filesystem
Six POSIX-style read tools now ship on by default next to the rich tools: cat, grep, ls, find, tail, and man. Projects act as mount points: ls / lists them, and a path whose first segment names a project routes to it, so any path a tool returns can be passed straight back.
catreads a whole note, one section by heading, a line range, or up to a token budget. Notes are indexed by heading, so an agent can read the part it needs and skip the rest of the notegrepfinds keyword matches and returns match windows with surrounding context lines. Passsemantic=Trueto rank by meaning insteadfindfilters by metadata predicates (status=active,confidence>0.6) and can project frontmatter fieldstailshows the most recently updated notes, andlsbrowses folders
The CLI gains the same verbs: bm cat, bm head, bm grep, bm ls, bm find, bm tail, and bm tree. Set enable_posix_tools=false to hide the MCP versions. See the MCP Tools Reference and CLI Reference.
Cheaper discovery
- Compact results.
search_notes(compact=True)andbuild_context(compact=True)return identifiers, metadata, and relation targets without note bodies. An agent can pick what to read before it pays for the content - Line reads.
read_noteacceptsstart_lineandend_lineand returns numbered lines - Metadata-only reads.
read_note(include_content=False)returns the title, permalink, path, checksum, andupdated_atwithout the body
Writes that don't clobber each other
When several agents share a knowledge base, one of them will eventually overwrite something it never read. v0.24 makes that impossible when the agent asks for it:
- Revision guards. Pass
expected_checksumtoedit_note, or towrite_notetogether withoverwrite=True. The write applies only while the note is still the revision you read. Otherwise nothing changes and you get aNOTE_REVISION_CONFLICTwith the current checksum.read_noteandcatreturn that checksum in JSON output - Refusals are errors. A refused
write_note,edit_note,delete_note, ormove_notenow comes back as an MCP tool error (isError) instead of an ordinary result, so a client checkingisErrornever mistakes a refused write for a successful one - Similar-note advisory. When a new note looks like notes that already exist,
write_notelists them and asks whether you meant to update one of them. JSON output carries them assimilar_notes. Nothing is merged automatically - Locked notes.
locked: truein frontmatter makes a note read-only to the API and MCP tools: edits, overwrites, and deletes are refused with HTTP 423. Edits made directly on disk still work - Authorship. When the runtime knows who is writing, accepted writes stamp
created_byandupdated_byinto frontmatter. In Basic Memory Cloud, API-key writes read<member> via <key name>. Local installs don't supply an author and leave these keys untouched
Documents become notes
PDFs, Word documents, PowerPoint decks, and CSV files can be imported as searchable Markdown:
pip install "basic-memory[pdf,documents]"
bm import document reports/q3-review.pdf
Each import writes an extracted-text sidecar note next to the file (q3-review.pdf.md) that links back to the source with a derived_from relation, plus a provenance run note under document-ingestion-runs/. Extraction runs in a bounded worker process. Re-importing an unchanged file is a no-op, and the import refuses to overwrite a sidecar you've edited. See Documents and PDFs.
Observations that know when they're true
An observation can now carry a time qualifier:
- [decision] @effective:2026-06-10 The cache layer will use Redis.
- [milestone] @due:2026-11-01 Ship the importer
- [event] @occurred:"June 10, 2026" Kickoff with the design team
The kinds are effective, valid (the default), occurred, due, and mentioned, and ranges like @effective[2026-06-10,2026-07-27) work too. search_notes adds valid_at, valid_overlaps, and time_kind filters, so "what was true on June 15?" is a query rather than a guess. See Observations and Relations.
A richer graph
- Markdown links are relations. Ordinary links to files in the project (
[Guide](../guides/Guide.md), reference-style links,/-rooted paths) becomelinks_torelations, as wikilinks already did. External URLs and images are ignored, and your Markdown is never rewritten - Deleting a note keeps the links to it. Inbound relations become unresolved instead of being erased, so broken-link reports stay honest and recreating the note re-links them
- Notes as MCP resources. Every
memory://URL answers the standard MCPresources/readwith the note's raw Markdown
Search across projects in one query
search_notes(search_all_projects=True) now runs one scoped query per database instead of one search per project, and a new projects=[...] parameter searches a chosen subset. Results are ranked together, not merged page by page, and each hit says which project it came from. Vector search ranks only the projects in scope, so a small project is no longer crowded out of a shared index.
Other search improvements:
- Semantic search is always on. The
semantic_search_enabledsetting is gone. FastEmbed and sqlite-vec are core dependencies - CJK and other unsegmented scripts. Full-text search finds words inside Chinese, Japanese, Korean, Thai, Lao, Tibetan, Myanmar, and Khmer text
- Filtered vector search fills its page. A vector or hybrid search with filters keeps reading until it has enough matching rows, instead of returning a short page
- Better metadata filters.
gte/inwork without the$, one field can take several operators, and$containsand$existsare new - Any OpenAI-compatible embedding endpoint. The
openaiprovider honorssemantic_embedding_api_baseandsemantic_embedding_api_key, so it works with llama.cpp, vLLM, TEI, LM Studio, and Ollama
See Semantic Search and Metadata Search.
A manual your agent can read
Basic Memory now ships its own manual and serves it over MCP. There is one section-3 page per tool (search-notes(3), write-note(3), and so on), plus reference pages such as comark(7). The server instructions point agents at a tool's page before they first use it. Read the manual with the man tool, with memory://man/<page> resources, or with bm man <topic> in a terminal. The synopses and parameter lists are generated from the live tool schemas, so the manual can't drift from the tools.
Wiki pages and OKF export
bm wikigenerates deterministicindex.mdandlog.mdnavigation pages for each folder, and never overwrites hand-written onesbm okf exportwrites a project as a static OKF v0.2 bundle (wikilinks become standard Markdown links), andbm okf checkvalidates one
Install into your agent in one command
bm install claude-code # or: codex, tau, pi
bm install installs the Basic Memory plugin or package for each host, with --dry-run and --yes. v0.24 also adds integrations for Tau and Pi, which recall prior sessions at startup and capture knowledge as work settles. They share Coding Session, Task, and Decision schemas with the Claude Code and Codex packages. See Tau, which currently needs a Tau build with upstream support, and Pi.
Operations
bm project addwaits for indexing before it returns (--no-waitopts out), andbm project index NAMEreindexes one projectbm status --jsonreports readiness per stage (files, relations, embeddings), andbm status --waitwaits until every stage settlesbm pruneremoves index entries for files your.bmignoreor.gitignorenow excludes- Faster Team push and pull. One recursive listing, eight concurrent transfers, streaming file bodies, and backoff on rate limits
- Safer HTTP transport.
bm mcp --transport streamable-httpbinds to127.0.0.1by default and rejects DNS-rebinding requests
Security fixes
v0.24.0 fixes a high-severity DNS-rebinding issue (GHSA-4gfv-c2mm-mvj2) in the HTTP transports. All earlier releases are affected if you run --transport sse or streamable-http. Stdio, the default, is not. The release also caps graph traversal depth at 5, raises dependency floors, and limits read_content images to PNG, JPEG, and WebP. See the Changelog for details.
Upgrading
v0.24 runs a dozen database migrations automatically on first start. It also changes several MCP and CLI contracts: refused writes are tool errors, the POSIX tools are on by default, read_content returns only PNG, JPEG, and WebP images, bm cloud sync is deprecated, and the HTTP transport no longer listens on every interface.
For the complete list of changes, see the Changelog and the v0.24.0 release on GitHub.

