Skip to content

Repository files navigation

Markdown DB Engine

Markdown DB Engine is a transactional content database whose formal business Records are Markdown files. Applications use typed queries, Schema, indexes and transactions; humans and Agents can edit ordinary Markdown Workspaces and explicitly Merge reviewed changes back into the Runtime Database.

It is designed for articles, knowledge bases, CMS content, Agent Memory and project archives. It is not a high-frequency event store or a distributed SQL database.

Requirements

  • Node.js 22 or newer
  • ESM for the TypeScript/JavaScript SDK
  • A local filesystem for the Runtime Database and Workspaces

Quick start

Start the Local Server and open the Web UI without installing globally:

npx md-db-engine serve ./content.mddb --open

On a new Database, the terminal prints a generated first Owner Credential exactly once. Paste that owner:secret value into the Web UI sign-in form. The Server listens only on 127.0.0.1:3000 unless you explicitly configure another address.

The Database remains in ./content.mddb. Stopping or upgrading the npm package does not delete that directory.

Useful options:

npx md-db-engine serve ./content.mddb --port 4100
npx md-db-engine serve ./content.mddb --bootstrap-username owner --bootstrap-secret "$MDDB_OWNER_SECRET"
npx md-db-engine serve --help

Embedded TypeScript SDK

Install the package in an application:

npm install md-db-engine

Create, query and reopen a Database:

import { openDatabase } from 'md-db-engine'

const database = await openDatabase({ path: './content.mddb' })
const articles = database.collection('articles')

await articles.insert({
  id: 'hello',
  title: 'Hello',
  status: 'draft',
  body: '# Hello\n\nMarkdown is the formal Record body.',
})

const result = await articles.find({
  where: { field: 'status', operator: 'eq', value: 'draft' },
  orderBy: [{ field: 'title', direction: 'asc' }],
  limit: 20,
})

console.log(result.records)
await database.close()

For ordinary Document Collections, title is a required system field and becomes the safe default Markdown filename, while id remains the stable Record identity. For example, the Record above is stored as Hello.md. Titles must be unique inside a Collection after filename sanitization, Unicode normalization, and case folding; a conflict is rejected instead of receiving an opaque suffix. Table and Records layouts keep their grouped filenames.

Transactions can span Collections:

await database.transaction(async (transaction) => {
  await transaction.collection('articles').patch('article-id', {
    status: 'published',
  })
  await transaction.collection('authors').patch('author-id', {
    publishedCount: 4,
  })
})

Only one Writer Host can open a Runtime Database at a time. When the Local Server is running, other applications must use the Remote SDK or HTTP API instead of calling openDatabase() for the same directory.

Global CLI and Local Server

Install the command for long-running local use:

npm install --global md-db-engine
md-db-engine serve ./content.mddb --open

Standard command information:

md-db-engine --help
md-db-engine --version
md-db-engine serve --help

Query the running Server:

md-db-engine query \
  --endpoint http://127.0.0.1:3000 \
  --credentials 'owner:replace-with-your-secret' \
  --collection articles \
  --limit 20 \
  --json

Embedded CLI operations use --database; Remote operations use --endpoint and a Credential.

Markdown Workspace

Export a freely editable Workspace:

md-db-engine workspace export \
  --database ./content.mddb \
  --workspace ./workspace \
  --json

Edit files under ./workspace with VS Code, Obsidian, shell tools or an Agent. The Runtime Database does not watch the directory and does not receive unreviewed changes.

Review and apply changes explicitly:

md-db-engine merge plan \
  --database ./content.mddb \
  --workspace ./workspace \
  --json

md-db-engine merge apply \
  --database ./content.mddb \
  --workspace ./workspace \
  --yes \
  --json

A Merge Plan detects additions, changes, deletions, moves, Schema changes and concurrent conflicts. Apply rejects a stale Plan if either the Runtime or Workspace changed after planning.

Migrate an Obsidian Vault or Markdown knowledge base

Migration is a one-time scan → preview → apply workflow. The source Vault is not modified by Scan or Preview, and Apply writes only the eligible Markdown identities, generated Schema, and signed Workspace metadata.

First, inspect the Vault and write the suggested configuration to a separate review directory:

md-db-engine init scan ./my-vault \
  --output ./my-vault-migration-review

Review ./my-vault-migration-review/init-report.md and edit mddb.init.yaml. Its include/exclude rules decide the one-time import set; they do not become permanent database configuration.

Preview the exact eligible and pending files without changing the Vault:

md-db-engine init preview ./my-vault \
  --config ./my-vault-migration-review/mddb.init.yaml \
  --plan ./my-vault-migration-review/migration-plan.json

After reviewing the generated Plan, apply it to a new Runtime Database path:

md-db-engine init apply ./my-vault \
  --plan ./my-vault-migration-review/migration-plan.json \
  --database ./databases/my-vault.mddb \
  --yes

Apply creates an external byte-for-byte backup before changing the Vault, adds UUIDv7 id, collection, and a filename-derived title when missing, preserves existing Frontmatter and Body text, creates the Runtime Database, and establishes signed .mddb/ metadata. Ambiguous or invalid files remain unchanged in the pending list while the eligible set commits atomically.

After migration, Manifest entries define the managed Record set. Unmanaged templates, drawings, reports, and ordinary Markdown remain in the Vault without blocking Workspace operations. A new file joins normal Merge discovery when it declares a valid collection; Merge generates a missing UUIDv7 id and filename-derived title, then writes them back only after Apply succeeds. The one-time migration config is no longer consulted.

If the Local Server is running, submit Obsidian changes through the Server instead of opening the same Database again:

md-db-engine merge plan \
  --endpoint http://127.0.0.1:3000 \
  --credentials 'owner:replace-with-your-secret' \
  --workspace ./my-vault \
  --json

md-db-engine merge apply \
  --endpoint http://127.0.0.1:3000 \
  --credentials 'owner:replace-with-your-secret' \
  --workspace ./my-vault \
  --yes \
  --json

Images, PDFs and other binary assets remain in the Vault or external asset storage; the Runtime Database manages the selected Markdown Records and does not copy those binaries.

Agent Skills

The npm package includes two installable Skills under skills/dist/:

  • mddb-vault-migration.skill analyzes an existing Vault, prepares semantic Collection rules and Preview, pauses for explicit Apply approval, then verifies Backup, Runtime and Workspace behavior.
  • mddb-app-builder.skill inspects the real Schema, chooses Embedded or Remote SDK, creates an application boundary and verifies Query, Mutation, tests and production build.

Extract the target .skill package with the Skill installer supported by your Coding Agent, or copy the corresponding source directory from node_modules/md-db-engine/skills/ into that Agent's local Skills directory. Installation paths differ by Agent product; the bundled SKILL.md remains the portable entry point.

Backup, integrity and recovery

md-db-engine check --database ./content.mddb --json
md-db-engine backup --database ./content.mddb --json
md-db-engine upgrade --database ./content.mddb --yes --json
md-db-engine index rebuild --database ./content.mddb --yes --json

Restore always writes to a new directory:

md-db-engine restore \
  --database ./content.mddb \
  --snapshot <snapshot-id> \
  --target ./recovered.mddb \
  --yes \
  --json

Server configuration

The serve command accepts flags or the corresponding environment variables:

CLI option Environment variable Purpose
<database> MDDB_DATABASE Default Runtime Database directory
--database-root MDDB_DATABASE_ROOT Managed Database root
--host MDDB_HOST Listen address
--port MDDB_PORT Listen port
--bootstrap-username MDDB_BOOTSTRAP_USERNAME First Owner username
--bootstrap-secret MDDB_BOOTSTRAP_SECRET First Owner secret
--allowed-origins MDDB_ALLOWED_ORIGINS Browser origins
--tls-key MDDB_TLS_KEY TLS private key path
--tls-certificate MDDB_TLS_CERTIFICATE TLS certificate path
--authentication MDDB_AUTHENTICATION=true External listener authentication gate
--access-log MDDB_ACCESS_LOG=true JSON access log

An external listener is rejected unless TLS, Authentication, Allowed Origins and Access Log are all configured. Keep the default Loopback address for ordinary local use.

Secrets must not enter source control, Workspace files or access logs. Prefer environment variables or a Secret Manager rather than command flags for persistent credentials.

Public interfaces

  • Package root: Embedded and Remote TypeScript SDK
  • md-db-engine/server: programmatic Local Server API
  • md-db-engine/cli: programmatic non-interactive CLI adapter
  • /v1/openapi.json: OpenAPI 3.1 HTTP contract
  • /v1/events: committed transaction events over SSE
  • md-db-engine: installable command

License

Apache-2.0. See LICENSE.

About

A markdown-native database engine for AI-powered content.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages