OMGDB DOCS
// For agents

Native Markdown

Import a Markdown file as one queryable document — typed frontmatter fields, addressable sections with byte offsets, and editable section and frontmatter content.


OMGDB treats Markdown as a first-class input. A .md file — a spec, a note, a piece of documentation — can be imported as a single document where the YAML-ish frontmatter becomes typed, queryable top-level fields and the heading structure is captured under _sections, each section carrying a stable id and byte offsets into the stored body. The raw Markdown body is stored too, so nothing is lost. This is the knowledge layer an agent reads from — and, through the md-set-section and md-patch-frontmatter commands, writes back to: notes and specs land as ordinary documents you can query by their frontmatter and edit section by section.

Import is exposed through the CLI command omgdb import-md. Internally it parses the file, builds a document, inserts it, and prints the new _id.

Importing a file

omgdb create app.omgdb
omgdb import-md app.omgdb docs spec.md
# -> prints the new document's _id as canonical JSON

The command takes three positional arguments: the store path, the target collection, and the path to the Markdown file. The whole file becomes exactly one document in the named collection.

ArgumentDescription
<path>Store path, e.g. app.omgdb.
<collection>Collection the document is inserted into.
<file>Path to the .md file to parse and import.

The document shape

A parsed Markdown file is converted into a document with three parts:

  1. Frontmatter fields — each key: value line from the frontmatter block is lifted to a top-level field, typed where possible.
  2. body — the raw Markdown after the frontmatter, stored verbatim as a string.
  3. _sections — an array of section objects, one per ATX heading, in document order. Each records a stable sectionId, a slug, the heading level and text, the section’s text body, and four byte offsets into body (startByte, endByte, textStartByte, textEndByte).

Frontmatter parsing

Frontmatter is recognized only when the file begins with a literal --- fence line and a matching closing --- fence follows. Inside the block, each non-empty line is split on its first : into a key and a value. The value is parsed as JSON when possible and otherwise kept as a string:

  • views: 10 becomes an integer (I64).
  • tags: ["rag", "db"] becomes an array.
  • title: Hello World stays a string (unquoted prose is not valid JSON, so it falls back to a string).

Limitation: Frontmatter is a minimal line-based subset, not a full YAML parser. It splits on the first : per line and parses each value as JSON-or-string. Block scalars, nested maps, and multi-line values are not supported. A file with no --- fences yields no frontmatter fields, and the entire text becomes body.

Sections and the source map

Every ATX heading (# through ######) starts a new section. A line is treated as a heading only when, after trimming leading whitespace, it begins with 1–6 # characters immediately followed by a single space. Each section records:

FieldDescription
sectionIdStable unique identifier derived from the heading slug. Duplicate headings get numeric suffixes: api, api-2, api-3. This is the handle section edits address.
slugThe (non-unique) slug of the heading text.
levelHeading level, 1 for # through 6 for ######.
headingThe heading text, with the leading #s stripped.
textThe body text under the heading, up to the next heading.
startByte / endByteByte offsets of the section’s full source (heading line included) inside body.
textStartByte / textEndByteByte offsets of just the section body source, after the heading line.

The byte offsets are a source map: slicing body between a section’s offsets yields exactly that section’s original Markdown, so a section can always be mapped back to its precise position in the file — which is what makes surgical section edits possible.

Note: Despite the “section tree” phrasing, _sections is a flat, ordered array. Heading levels are recorded in the level field, but no parent/child nesting is built. Any content before the first heading is not captured in a section (it still lives in body).

Example

Given this spec.md:

---
title: Hello World
views: 10
tags: ["rag", "db"]
---
# Intro

the intro text

## Details

more text

Importing it produces a document of this shape:

{
  "title": "Hello World",
  "views": 10,
  "tags": ["rag", "db"],
  "body": "# Intro\n\nthe intro text\n\n## Details\n\nmore text\n",
  "_sections": [
    { "sectionId": "intro",   "slug": "intro",   "level": 1, "heading": "Intro",
      "text": "the intro text\n", "startByte": 0,  "endByte": 25,
      "textStartByte": 8,  "textEndByte": 25 },
    { "sectionId": "details", "slug": "details", "level": 2, "heading": "Details",
      "text": "more text",        "startByte": 25, "endByte": 47,
      "textStartByte": 36, "textEndByte": 47 }
  ]
}

Note that title came through as a string, views as a number, and tags as an array — each frontmatter line was typed according to whether its value parsed as JSON.

Editing sections and frontmatter

Imported documents are not read-only snapshots. Two commands rewrite them through ordinary op-log-backed replacements — the edit is a replace op in the log like any other write, _id is preserved, and body and _sections are re-derived so the source map stays exact.

md-set-section

Replaces the body under one section, addressed by its stable sectionId:

omgdb md-set-section app.omgdb docs '{"$oid":"..."}' intro "updated intro text"
# or, for multiline content:
omgdb md-set-section app.omgdb docs '{"$oid":"..."}' intro --file new-intro.md

The heading line is preserved; the replacement text becomes the section body (a trailing newline is added if missing, so the next heading can never be joined onto the new text). The document is reparsed after the edit, so headings inserted by the replacement text become addressable sections of their own, with fresh offsets. An unknown section id fails with Markdown section `intro` was not found. The command prints the full replacement document.

md-patch-frontmatter

Inserts, replaces, or removes frontmatter fields without touching the body:

omgdb md-patch-frontmatter app.omgdb docs '{"$oid":"..."}' \
  '{"title":"Updated","published":true}' --remove views

Removals apply first, then the patch’s key/value pairs are inserted or replaced (existing field order is preserved where possible). null is a normal stored value — use --remove (repeatable) to delete a field. The generated fields _id, body, and _sections are reserved: patching or removing them fails with frontmatter field `body` is reserved.

Both edits are also exposed over MCP as the write-scope tools markdown_set_section (path, collection, id, sectionId, text) and markdown_patch_frontmatter (path, collection, id, patch, optional remove), so an agent can maintain a knowledge base through the same audited path.

Querying frontmatter

Because frontmatter fields are stored as ordinary top-level fields, they are queryable like any other field — no special syntax. After import you can find on a frontmatter value:

omgdb find app.omgdb docs '{"title":"Hello World"}'
# result contains "Intro" and "_sections"

The same applies to the typed fields. A numeric frontmatter field works with the comparison operators, and an array field works with array operators:

omgdb find app.omgdb docs '{"views":{"$gte":10}}'
omgdb find app.omgdb docs '{"tags":"rag"}'

The _sections array travels with the document, so the heading structure is available to read back, and the raw body is always present for full-text or downstream processing.

Limitations

Limitation: Import is one-shot. OMGDB does not watch or re-sync the source .md file after import — subsequent edits go through md-set-section / md-patch-frontmatter (or an ordinary replace), not the original file.

Note: Heading-aware chunking into embeddings is not part of import. Embedding-based retrieval is provided by the vector layer — see vector search. A field holding Markdown text can be declared as the markdown type in a validation spec.

See also

  • Data model — how documents, types, and field paths work, including the conventions imported Markdown follows.
  • Vector search — embedding and retrieval over imported content.
  • Query operators — filtering on the frontmatter fields produced by import.

View this page as raw Markdown →