Basic Memory
Concepts

Documents and PDFs

How Basic Memory turns PDFs, Word, PowerPoint, and CSV files into searchable Markdown notes that stay linked to the original file.

Knowledge doesn't only live in notes. Reports, slide decks, papers, and spreadsheets sit in the same folders, and until now your AI could see them only as opaque files. As of v0.24, Basic Memory can extract a document's text into a Markdown note that sits next to the original file, so search finds what's inside the document and your AI can read it like any other note.


How it works

Put the file in a project, then import it:

bm import document reports/q3-review.pdf

Basic Memory indexes the project, extracts the file, and writes two notes:

NotePathPurpose
Extracted textreports/q3-review.pdf.mdThe document's text as Markdown, next to the source file
Ingestion rundocument-ingestion-runs/<run-id>.mdProvenance: which extractor ran, with what settings, against which bytes

The original file is never modified. The extracted-text note is an ordinary Markdown file: full-text and semantic search index it, read_note reads it, and you can open it in any editor.

reports/
├── q3-review.pdf        # the original, unchanged
└── q3-review.pdf.md     # extracted text, searchable
document-ingestion-runs/
└── 748d4356-....md      # what produced it

Re-running the import is a no-op while the source file is unchanged. Basic Memory won't overwrite a note you wrote or edited by hand at the sidecar path.

The path is resolved against the project root, not your current directory, and the file must already be inside the project. To import something from ~/Downloads, copy it into the project folder first. Use --project to pick a project other than the default. Full options are in the CLI Reference.

Supported formats

FormatExtensionInstall
PDF.pdfbasic-memory[pdf]
Word.docxbasic-memory[documents]
PowerPoint.pptxbasic-memory[documents]
CSV.csvIncluded — no extra needed

Document extraction is optional so the default install stays small. Add the extras you need:

uv tool install 'basic-memory[pdf,documents]'

PDFs are extracted with pdf-inspector; Word and PowerPoint files with Microsoft's markitdown converters. Both run in a separate worker process with time and size limits, so a malformed or huge file can't hang Basic Memory. A CSV becomes a bounded preview — the header and the first 200 rows as a Markdown table — rather than a full dump, and must be valid UTF-8.


What the extracted note looks like

The note's frontmatter records where the text came from:

---
title: q3-review.pdf
type: extracted_text
schema: schema/document-extraction
tags: [document, pdf, generated]
source:
  media_type: application/pdf
  file_path: reports/q3-review.pdf
  checksum: sha256:...
extraction:
  engine: firecrawl/pdf-inspector
  status: complete
  page_count: 12
  pages_needing_ocr: []
ingestion:
  stage: raw
  run_id: 748d4356-...
bm_parse_semantics: false
---

<!-- Page 1 -->

Q3 Business Review
...
  • type: extracted_text marks it as derived text. Sidecars written by earlier versions use type: document; both are valid and Basic Memory never rewrites one into the other.
  • source identifies the exact file and the checksum of the bytes that were extracted.
  • extraction summarizes the result — status, page counts, and any scanned pages that need OCR. The full per-page map lives on the ingestion-run note, which keeps long PDFs' sidecar frontmatter small.
  • Page markers (<!-- Page N -->) keep PDF page boundaries visible in the text.

Extracted text stays graph-quiet

Raw extracted text is searchable, but it doesn't add observations or relations to your knowledge graph — bm_parse_semantics: false. A PDF that happens to contain - [note] ... or [[Something]] won't flood your graph with accidental facts and links.

The one connection every extracted-text note does get is a derived_from relation to its source file. Basic Memory adds it from the note's source frontmatter at index time, so build_context can walk from the text to the original PDF and back. Don't write this relation into the body yourself.


Page citations

Basic Memory defines the citation format below, but v0.24 doesn't yet ship a command or tool that enriches an extracted document. Today bm import document produces the raw extracted text only.

When an extracted document is enriched — its raw text turned into structured observations — each observation can cite the PDF page it came from. The citation is written as a Markdown footnote plus a matching sources entry in frontmatter, following the Open Knowledge Format provenance convention:

## Observations

- [fact] Revenue increased 14% quarter over quarter. [^document-page-2]

[^document-page-2]: [PDF page 2](/reports/q3-review.pdf#page=2)
sources:
  - id: document-page-2
    resource: /reports/q3-review.pdf#page=2
    title: q3-review.pdf, p. iv
    locator:
      page: 2
      page_label: iv

page is the physical page in the PDF (the one a viewer jumps to with #page=2); page_label is the optional printed page number. Page numbers are checked against the extraction's page count, and the link is built from the source file's path rather than supplied by an AI, so a citation always points at the real file. Enriched documents turn semantic parsing back on, so their observations join the graph like any other note's.


Other files in your project

Files you don't extract are still part of the project. Images, PDFs, and other non-Markdown files are indexed as file entries you can list, read with read_content, link to, and move. As of v0.24 each one also records its content type and format. Moving one preserves its bytes exactly, and deleting one through Basic Memory removes it from storage.

Metadata filters in search_notes apply to Markdown notes only.


Next steps

Knowledge Format

The structure of a Markdown note.

CLI Reference

bm import document and the other import commands.

Semantic Search

How extracted text is indexed and found.

What's New in v0.24

Everything in this release.