What's the best way to search markdown notes and PDFs in the same vault?
What's the best way to search Markdown notes and PDFs in the same vault? Run xerj autoindex on the vault folder. It reads attachments too. In a captured run a phrase found only inside a PDF attachment returned 1 hit, a phrase only inside a DOCX returned 1 hit, and wikilinks became edges carrying the line that made them.
Key number: Omnisearch, the in-app alternative, has 2,189 GitHub stars and released 1.32.0 on 2026-10-24. (as of 2026-10-30 · source: github.com/scambier/obsidian-omnisearch)
TL;DR Run xerj autoindex on the vault folder. It reads the attachments beside the notes. A phrase that exists only inside a PDF or a DOCX comes back as a hit at that file. Wikilinks become edges that carry the line that made them.
Notes and attachments in one index
- 01 vault7 filesMarkdown notes with
[[wikilinks]], a.obsidian/folder, 1 PDF and 1 DOCX. - 02 walk7 walked, 6 read
.obsidian/is pruned as a hidden folder. - 03 searchPDF and DOCX textA phrase only in the PDF: 1 hit at
p1-s0. A phrase only in the DOCX: 1 hit. - 04 linkEdges with quotes
same_dir,sequence,wikilinkandpathcite.
Owns [[Runbooks/Restart procedure]].The line that created the link travels with the edge.Escalate per ![[attachments/pangolin-escalation-matrix.pdf]] if theThe embed resolves to the PDF the search hit.Act as a coding agent. Read https://xerj.org/llms.txt, start a local XERJ node, run `xerj autoindex ./vault --url http://127.0.0.1:9200 --prefix ob --progress plain`, then POST a match_phrase on body for a string that exists only inside a PDF attachment and a second one for a string only inside a DOCX attachment, read the autoindex-catalog for any file whose status is junk, and report the hit paths and the junk reasons.
xerj autoindex ./vault --url http://127.0.0.1:9200 --prefix ob --progress plain
Index a vault folder, including the attachments folder beside the notes.
curl -s -XPOST http://127.0.0.1:9200/ob-*/_search -H 'content-type: application/json' -d '{"query":{"match_phrase":{"body":"pangolin escalation matrix"}},"size":5,"_source":["ax_path","ax_format","ax_locator","title"],"track_total_hits":true}'
Find a phrase that exists only inside the PDF attachment.
curl -s -XPOST http://127.0.0.1:9200/.xerj-memory-amber-obsidian-edges/_search -H 'content-type: application/json' -d '{"query":{"exists":{"field":"src"}},"size":50,"track_total_hits":true}'
Read every edge the vault produced, with the detector and the evidence quote.
curl -s -XPOST http://127.0.0.1:9200/autoindex-catalog/_search -H 'content-type: application/json' -d '{"query":{"term":{"doc_kind":"file"}},"size":500,"_source":["path","format","status","records","reason"],"sort":[{"path":"asc"}]}'
List every file the run read, with the family it was given and why any file was refused.
Index the vault folder
The first command above indexes the whole vault, notes and attachments together. Dataset names are inferred from the folder, so read the index list the run prints. A query against ob-* covers whatever it created.
The captured vault was written by the fixture generator gen_fixtures.py in the real on-disk layout. Obsidian never ran on the host, so this tests the file layout, not the app.
Attachment text comes back with a locator
| Query | Hits | Path returned | ax_format |
|---|---|---|---|
match_phrase on body for pangolin escalation matrix | 1 | attachments/pangolin-escalation-matrix.pdf | pdf |
match_phrase on body for capybara change window | 1 | attachments/capybara-change-window.docx | docx |
Each phrase exists in exactly one binary file and nowhere in the notes. The PDF hit carries ax_locator p1-s0, page 1, passage 0, so an agent can open the file at the right place instead of reading all of it. The second command above is the PDF query.
Wikilinks become edges
The edges land in .xerj-memory-amber-obsidian-edges, and the third command above reads them. Every wikilink edge carries an evidence.quote. The detectors are structural: they match wikilinks, Markdown links, shared folders and path citations, and none reads meaning from the text.
A note that reads as YAML can be refused
The sniffer picks a family from content, never from the extension. A note that opens with --- front matter is classified by the body under it, so ordinary Markdown with title: and tags: is indexed as prose.
A note whose lines mostly read as YAML is different. When 60 percent or more of its non-blank lines read as YAML and the text also parses as YAML, it lands in the yaml family. The YAML extractor got nothing from such a note, and it was dropped with 0 documents. Try a note of your own:
The 60 percent line test
For the example: 3 of 4 non-blank lines read as YAML (75%), which is over the 60% line.
key: value or starts with - , except - [ ] and - [x] task items. Under 3 non-blank lines the share is 0. The sniffer also needs the text to parse as YAML, which this checker does not test.In this vault, Index.md was refused with the reason no records extracted (yaml candidate family, 1 junk lines). The only signal at the terminal was junk_files=1, so read autoindex-catalog after every run. The last command above lists every file with its family and any refusal reason.
XERJ or Omnisearch
Omnisearch is a plugin for a person searching inside Obsidian, and it keeps that job. XERJ indexes the folder from outside, so an agent can query it over HTTP or MCP with the app closed. The Omnisearch comparison covers the trade.
What this capture does not show
No Obsidian app, plugin or sync service was involved. XERJ has no connector and fetches nothing over the network, so copy or mount the vault to local disk first.
XERJ ran single-node, with no replication and no failover. The default embedder is lexical feature hashing, so a paraphrase that shares no words with the query does not match. Neural embeddings are opt-in through --embed-mode neural.
Every number here comes from RUN-B, captured on 2026-08-21 with a ci-test profile build, so no wall-clock figure is published as a performance number.
FAQ
What's the best way to search markdown notes and PDFs in the same vault?
Index the vault folder itself, notes and attachments together. In the captured run a phrase that exists only inside pangolin-escalation-matrix.pdf returned 1 hit at that path.
Can I search an Obsidian vault including PDFs and Word attachments, not just notes?
Yes. A phrase that exists only inside capybara-change-window.docx returned 1 hit at that path, and the DOCX extractor produced 1 document from the file.
I have a pile of markdown notes. How do I search them properly?
Point xerj autoindex at the folder and query the index it creates. Wikilinks between notes also become edges, and each wikilink edge carries the line of text that created it.
How do I search notes and attached PDFs as one library?
One run over the vault root covers both. Every hit carries ax_path and ax_locator, so a match inside an attachment names the file and the position, such as p1-s0.
Does this replace Omnisearch inside Obsidian?
No. Omnisearch is a plugin for a person working inside the app, and it keeps that job. XERJ indexes the vault folder from outside so an agent can query it without the app open.
Why did one of my notes return no results?
A note whose non-blank lines mostly read as YAML, such as key: value lines or - bullets, can be classified as yaml and refused with 0 documents. Front matter on its own no longer does it. Read the autoindex-catalog for the reason string.
Does XERJ connect to Obsidian itself?
No. XERJ reads the vault folder from local disk. The captured node opened 0 non-loopback connections over its whole life, so no application or service was contacted.
Evidence
- A file gets the yaml family when 60% or more of its non-blank lines read as YAML (yaml_line_ratio >= 0.6) and the text parses as a YAML stream; the 3 of 4 example is 75%. —
engine/crates/xerj-autoindex/src/sniff.rs
Related
- I downloaded a bunch of papers as PDFs. How do I search across them?
- How do I search through a folder of contracts in .docx?
- How do I index Markdown into the Elasticsearch API?
- Can ChatGPT search a folder on my laptop, or do I need something else?
- How do I search an Obsidian vault from outside Obsidian?
- Why does my Notion export duplicate titles? · same intent: logs and docs
- I have a folder of PDFs, Word docs, and markdown. How do I search all of them at once? · same intent: logs and docs
- What's the best local desktop search for a folder of PDFs and docs? · same intent: logs and docs