mdxquery

why

grepping text for structural questions about a Markdown corpus is approximate: it misses frontmatter semantics, heading hierarchy, and component usage, and silently returns stale results after files change. a parsed, rebuildable index makes the same questions deterministic and current; source documents stay the only canonical authority — the index owns nothing and can be discarded at any time.

rule

treat Markdown and MDX as a queryable interface. mdxquery parses source once into a derived local SQLite index, then answers deterministic read-only SQL questions about frontmatter, headings, components, links, and content blocks. source is canonical; the index is disposable and rebuildable.

ruling

one query language

sqlite syntax only. one local query model is easier for agents, joins with project sqlite ledgers, and needs no mongodb server, credentials, or alternate predicate semantics.

installation and first use

npm install -g mdxquery
mdxquery index ./data
mdxquery query "SELECT path, frontmatter_json FROM documents"

the CLI finds the nearest git root and writes the index to <git-root>/.agents/db/mdxquery.sqlite. it is a derived cache: rebuild when MDX changes, never hand-edit, never treat it as the authority for a document's meaning.

query model

in-process sqlite with normalized tables:

tableone row meanskey fields
documentsone Markdown or MDX file.id, path, hash, kind, frontmatter_json, body, indexed_at
frontmatterone declared metadata field.document_id, key, value_json
headingsone ordered heading.document_id, ordinal, depth, text
componentsone parsed MDX component.document_id, ordinal, name, props_json
linksone link or anchor.document_id, ordinal, href, text
blocksone semantic AST block.document_id, kind, ordinal, text
document_searchone FTS5 record per document.document_id, path, text

frontmatter is normalized so agents write simple SQL instead of repeated JSON extraction; documents.frontmatter_json stays only as a lossless derived record.

-- Find approved standards.
SELECT document.path, title.value_json AS title
FROM documents AS document
JOIN frontmatter AS kind ON kind.document_id = document.id
JOIN frontmatter AS status ON status.document_id = document.id
JOIN frontmatter AS title ON title.document_id = document.id
WHERE kind.key = 'kind'
AND kind.value_json = '"standard"'
AND status.key = 'status'
AND status.value_json = '"approved"'
AND title.key = 'title';
-- Find every document that needs Accordion support.
SELECT DISTINCT document.path
FROM documents AS document
JOIN components ON components.document_id = document.id
WHERE components.name = 'Accordion';

parser contract

  • parse with an MDX-aware parser: record AST node type, component name and props, heading depth, link target.
  • never query rendered HTML, regex-match components, or derive frontmatter from headings.
  • a parse failure returns a typed diagnostic with path and source location; never insert a partial document.
CLI contractmdxquery index <path> parses Markdown/MDX and atomically refreshes the repository-owned index. mdxquery query <read-only-sql> executes read-only SQL against it. output is always JSON.
freshnessindex rebuilds from source and stores each source SHA-256 in documents.hash. always run it after a document change before treating a query result as current.

procedure-ledger integration

an MDX procedure and its execution ledger use two complementary sqlite stores:

mdxquery .agents/db/mdxquery.sqlite -> What knowledge and procedure documents say
ledger .agents/db/procedure.sqlite -> What work is planned, applying, blocked, or verified

query standards and procedure structure with mdxquery first, then join that knowledge with the ledger's open findings. select one smallest vertical slice, record the run, update MDX contracts first, apply the refactor, append verification evidence. neither database replaces the other.

do not

  • offer mongodb syntax as a second query language for the same document index.
  • query MDX with string scans, regex component matching, or rendered HTML.
  • allow mutating SQL against the derived MDX index through the normal CLI.
  • hand-edit index rows or let a stale index masquerade as source truth.
  • conflate MDX knowledge facts with the mutable execution ledger.
  • query a stale index without rebuilding; always run mdxquery index after document changes.

good and bad

bad

# grep-based discovery with stale source
rg -n "status: approved" gurus | sed -n 's/.*title: //p'

guesses at YAML structure, cannot join headings or components, silently produces stale answers. an agent auditing readiness from this reads outdated results: selects the wrong slice, misses real blockers in approved files, skips standards that became unapproved. the stale answer compounds — wrong work routed, wrong audit report, resources wasted on misdirected investigation.

good

# parsed index rebuilt from current source
mdxquery index ./data
mdxquery query "SELECT path FROM documents WHERE kind = 'standard' AND status = 'approved'"

the index is rebuilt from parsed source before every query: an agent querying approved standards gets the current decision state, a status change flows into the next result immediately, and no decision rests on an outdated fact.

search pages

go to any page