---
title: CLI Reference
description: Complete reference for the omgdb command-line binary — every subcommand grouped by task, with synopses, flags, and examples.
---

The OMGDB command-line interface is a single binary named `omgdb`. It wraps the embedded engine end to end: create a store, write and query documents, manage indexes, plan auditable mutations, embed and search text, edit imported Markdown in place, and serve the database to coding agents over [MCP](/docs/mcp/). Errors are structured and specific — a typo'd collection name gets a did-you-mean hint, an unknown operator is named — so a human or an agent can repair a failed call without guesswork.

Almost every command follows the same shape: a subcommand, the store directory, then any positional or flag arguments. Documents, `_id`s, filters, projections, pipelines, and update specs are **always passed as JSON strings**. Multi-word commands use kebab-case (`import-jsonl`, `create-index`, `plan-update`).

```sh
omgdb <command> <store-path> [args...]
```

This page is the authoritative reference for the `omgdb` binary. There is no `omg` binary, and there are no `init`, `ask`, `import`, or `debug-query` commands — the real equivalents are below.

## Command summary

### Store lifecycle

| Command | Description |
| --- | --- |
| [`create`](#create) | Create a store; optionally define collections from a JSON or YAML spec. |
| [`pack`](#pack) | Bundle a store into a single `.omgdb` archive. |
| [`unpack`](#unpack) | Unpack a `.omgdb` archive into a fresh store. |

### Writing data

| Command | Description |
| --- | --- |
| [`insert`](#insert) | Insert one JSON document; prints the assigned `_id`. |
| [`insert-many`](#insert-many) | Atomically insert a JSON array of documents in one transaction. |
| [`import-jsonl`](#import-jsonl) | Stream a JSON Lines file into a collection in atomic batches. |
| [`update-one`](#update-one) | Update the first matching document atomically, with optional explicit-seed upsert. |
| [`update-many`](#update-many) | Update every matching document in one bounded atomic commit. |
| [`find-one-and-update`](#find-one-and-update) | Atomically update the first match and print its before/after images. |
| [`delete`](#delete) | Delete one document by exact `_id`. |
| [`delete-many`](#delete-many) | Delete every matching document in one bounded atomic commit. |
| [`bulk-write`](#bulk-write) | Run an ordered program of CRUD operations as one atomic transaction. |

### Collections

| Command | Description |
| --- | --- |
| [`create-collection`](#create-collection) | Create an explicitly cataloged collection, including an empty one. |
| [`list-collections`](#list-collections) | List every known collection in stable name order. |
| [`drop-collection`](#drop-collection) | Drop a collection with all of its documents and index metadata. |

### Reading & querying

| Command | Description |
| --- | --- |
| [`get`](#get) | Fetch one document by its `_id`. |
| [`find`](#find) | Find documents matching a [query filter](/docs/query-operators/), with sort, skip, limit, pagination, and projection. |
| [`count-documents`](#count-documents) | Count matching documents through the direct query planner. |
| [`distinct`](#distinct) | Deterministic distinct values for a dotted field path. |
| [`cursor-open`](#cursor-open) | Open a persistent read cursor and print its first batch. |
| [`cursor-next`](#cursor-next) | Read the next batch from a persistent cursor. |
| [`cursor-close`](#cursor-close) | Close a persistent cursor and remove its state. |
| [`aggregate`](#aggregate) | Run an [aggregation pipeline](/docs/aggregation/). |
| [`inspect`](#inspect) | List collections and their document counts. |
| [`describe`](#describe) | Print a Markdown manual of the database. |
| [`dump`](#dump) | Print a deterministic canonical export of every document. |
| [`explain`](#explain) | Explain how a query will run (index scan vs full scan). |
| [`diagnose`](#diagnose) | Per-predicate selectivity — the "why-not" debugger. |

### Indexes & schema

| Command | Description |
| --- | --- |
| [`create-index`](#create-index) | Create a secondary [index](/docs/indexes/) — single-field, compound, unique, or partial, optionally with a stable name. |
| [`list-indexes`](#list-indexes) | List a collection's ordinary indexes in stable name order. |
| [`drop-index`](#drop-index) | Drop one ordinary index by stable name. |
| [`suggest-indexes`](#suggest-indexes) | Suggest indexes the planner can actually use for a query. |
| [`validate`](#validate) | List documents that violate [validation rules](/docs/schema-validation/). |

### Full-text search

Documented in depth on the [full-text search](/docs/search/) page.

| Command | Description |
| --- | --- |
| [`define-search-index`](/docs/search/#defining-a-search-index) | Define a versioned, op-log-backed search index from a typed JSON definition. |
| [`search`](/docs/search/#querying) | Typed lexical, semantic, or hybrid search (`--mode`), with `--filter`, highlights, and `--explain`. |
| [`search-index-status`](/docs/search/#the-derived-index-is-honest-about-itself) | Report derived generation state: boundary, digests, counts, rebuild reason. |
| [`rebuild-search-index`](/docs/search/#the-derived-index-is-honest-about-itself) | Force a verified rebuild of one derived generation. |
| [`drop-search-index`](/docs/search/#defining-a-search-index) | Drop one named search-index definition — also an op-log operation. |
| [`models`](/docs/search/#local-models) | `pull` / `list` / `inspect` pinned, checksum-verified local embedding models. |

### Safe mutations

| Command | Description |
| --- | --- |
| [`plan-update`](#plan-update) | Dry-run an [update](/docs/agent-mutations/); returns a token, writes nothing. |
| [`apply`](#apply) | Apply a planned change by token. |
| [`rollback`](#rollback) | Roll back a previously applied change. |

### Vectors & context

| Command | Description |
| --- | --- |
| [`vsearch`](#vsearch) | Semantic [vector search](/docs/vector-search/) over a text field. |
| [`context`](#context) | Build a token-budgeted [context pack](/docs/context-packs/) with citations. |
| [`vsync`](#vsync) | Persist embeddings into `<collection>.__vectors`. |
| [`vstale`](#vstale) | List `_id`s whose embeddings are stale. |

### Markdown

| Command | Description |
| --- | --- |
| [`import-md`](#import-md) | Import a [Markdown](/docs/markdown/) file as a document. |
| [`md-set-section`](#md-set-section) | Replace the body under one section id and refresh `_sections`. |
| [`md-patch-frontmatter`](#md-patch-frontmatter) | Patch frontmatter fields on an imported Markdown document. |

### Operations

| Command | Description |
| --- | --- |
| [`verify`](#verify) | Re-prove the whole database: op-log replay plus every derived cache. |
| [`repair`](#repair) | Recover a corrupt op-log. |
| [`compact`](#compact) | Compact the op-log to its minimal form. |
| [`mcp`](#mcp) | Run an [MCP](/docs/mcp/) server over stdio. |

## Store lifecycle

### create

Create (open) a store at `<path>`. With `--from`, the spec file defines each named collection up front — [validation rules](/docs/schema-validation/) plus any `unique` entries, which become unique indexes.

```sh
omgdb create <path> [--from <spec>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--from <PATH>` | Spec file of the form `{"collections":{"<name>":{"required":[..],"fields":{..},"refs":{..},"unique":[..]}}}`. Parsed as YAML when the file ends in `.yaml`/`.yml`, JSON otherwise. | none |

On success it prints `created store at <path>`; with `--from` it also reports how many collections and unique indexes were defined.

```sh
# spec.json: {"collections":{"users":{"required":["name"],"fields":{"age":"long"},"unique":["email"]}}}
omgdb create app.omgdb --from spec.json
```

### pack

Bundle a store directory into a single, legible `.omgdb` archive at `<output>`. The archive includes `oplog.ndjson` plus the `pending/` and `changes/` sidecars in deterministic order; transient `LOCK`, `*.bak`, and `*.repairing` files are excluded. Prints `packed <path> into <output>`.

```sh
omgdb pack <path> <output>
```

### unpack

Unpack a `.omgdb` archive into a fresh store directory. Prints `unpacked <n> file(s) into <path>`. It refuses if `<path>` already contains a store, and rejects archives with bad magic or unsafe entry paths.

```sh
omgdb unpack <input> <path>
```

> **Note:** `unpack` takes the archive first and the destination second — the reverse of `pack`.

## Writing data

### insert

Insert a JSON object document into `<collection>`. The assigned `_id` (an ObjectId unless you supply your own) is printed as canonical JSON.

```sh
omgdb insert <path> <collection> <json>
```

```sh
omgdb insert app.omgdb users '{"name":"ana","age":30}'   # prints {"$oid":"..."}
```

### insert-many

Atomically insert a JSON array of documents in a single durable transaction — all of them commit or none do. Prints the assigned `_id`s as a JSON array.

```sh
omgdb insert-many <path> <collection> <json-array>
```

```sh
omgdb insert-many app.omgdb users '[{"name":"ana"},{"name":"bob"}]'
```

### import-jsonl

Stream a UTF-8 JSON Lines file into a collection using atomic batch commits — one fsync per batch, not per document. This is the bulk-load path: it loads 50,000 documents in about 2 seconds. Prints `{"inserted":N,"batches":M}`.

```sh
omgdb import-jsonl <path> <collection> <file> [--batch-size <N>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--batch-size <N>` | Documents per atomic commit/fsync. | `1000` |

### delete

Delete one document by exact `_id` (given as JSON). Prints `{"deleted":true}` or `{"deleted":false}` when nothing matched.

```sh
omgdb delete <path> <collection> <id>
```

```sh
omgdb delete app.omgdb users '{"$oid":"..."}'
```

### update-one

Apply [update operators](/docs/update-operators/) to the canonical-`_id` first document matching a filter, atomically. Prints `{"matchedCount":N,"modifiedCount":N}` (plus `upsertedId` after an upsert). The change is appended to the log as a replace record inside a transaction frame — history, not an overwrite.

```sh
omgdb update-one <path> <collection> <filter> <update> [--array-filters <json>] [--upsert-document <json>] [--max-scanned-documents <n>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--array-filters <json>` | `arrayFilters` array for `$[id]` positional paths. | none |
| `--upsert-document <json>` | Explicit no-match insert seed — OMGDB never synthesizes a document from the filter. The update is applied to the seed before insert; prints `upsertedId`. | none |
| `--max-scanned-documents <n>` | Maximum visible documents decoded and tested against the filter; exceeding it is an error, never a partial answer. | 100000 |

```sh
omgdb update-one app.omgdb users '{"name":"lin"}' '{"$set":{"role":"lead"}}'
# {"matchedCount":1,"modifiedCount":1}

# Explicit-seed upsert: inserts the seed (with the update applied) only when nothing matches.
omgdb update-one app.omgdb users '{"name":"zoe"}' '{"$set":{"role":"dev"}}' \
  --upsert-document '{"name":"zoe","age":25}'
# {"matchedCount":0,"modifiedCount":0,"upsertedId":{"$oid":"..."}}
```

### update-many

Update every matching document in one bounded atomic commit: either the complete selected set commits, or nothing is appended.

```sh
omgdb update-many <path> <collection> <filter> <update> [--array-filters <json>] [--max-scanned-documents <n>] [--max-mutations <n>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--array-filters <json>` | `arrayFilters` array for `$[id]` positional paths. | none |
| `--max-scanned-documents <n>` | Maximum visible documents tested against the filter. | 100000 |
| `--max-mutations <n>` | Maximum documents that may be mutated atomically. | 10000 |

```sh
omgdb update-many app.omgdb users '{"active":true}' '{"$set":{"reviewed":true}}'
# {"matchedCount":2,"modifiedCount":2}
```

### find-one-and-update

Atomically update the canonical-`_id` first matching document and print its `before` and `after` images along with the counts — one durable commit, no read-then-write race.

```sh
omgdb find-one-and-update <path> <collection> <filter> <update> [--array-filters <json>] [--max-scanned-documents <n>]
```

```sh
omgdb find-one-and-update app.omgdb users '{"name":"ana"}' '{"$inc":{"age":1}}'
# {"matchedCount":1,"modifiedCount":1,"before":{...,"age":36,...},"after":{...,"age":37,...}}
```

### delete-many

Delete every matching document in one bounded atomic commit. Prints `{"deletedCount":N}`.

```sh
omgdb delete-many <path> <collection> <filter> [--max-scanned-documents <n>] [--max-mutations <n>]
```

```sh
omgdb delete-many app.omgdb sessions '{"expired":true}'
```

### bulk-write

Execute one versioned, ordered program of CRUD operations as a single atomic transaction. Later steps read earlier writes from the same request; the whole program commits or nothing does. Unordered execution and implicit upsert synthesis are intentionally unsupported. Operations: `insert_one`, `replace_one_by_id`, `delete_one_by_id`, `update_one`, `update_many`, `delete_many`.

```sh
omgdb bulk-write <path> <request>
```

```sh
omgdb bulk-write app.omgdb '{"version":1,"operations":[
  {"operation":"insert_one","arguments":{"collection":"orders","document":{"item":"monitor","price":320}}},
  {"operation":"update_many","arguments":{"collection":"orders","filter":{"price":{"$lt":100}},"update":{"$set":{"budget":true}}}}
]}'
# {"version":1,"insertedCount":1,"matchedCount":2,"modifiedCount":2,"deletedCount":0,"upsertedCount":0,
#  "results":[{"operation":"insert_one","value":{"insertedId":{"$oid":"..."}}}, ...]}
```

The request accepts optional `maxOperations` (default 1024), `maxScannedDocumentsPerOperation` (default 100000), and `maxMutations` (default 10000, across the whole batch) limits; exceeding a limit is an error before anything is written.

## Collections

### create-collection

Create an explicitly cataloged collection — including an empty one, which then shows up in `list-collections`, `inspect`, and `describe` before its first document. Prints `{"collection":"<name>","created":true|false}`.

```sh
omgdb create-collection <path> <collection>
```

### list-collections

List every known collection — cataloged, indexed, or holding documents — in stable name order.

```sh
omgdb list-collections <path> [--json]
```

```sh
omgdb list-collections app.omgdb --json
# ["orders","users"]
```

### drop-collection

Drop a collection with all of its documents and index metadata, as one authoritative op-log operation. Destructive, so it requires `--yes`. Prints `{"collection":"<name>","dropped":true|false}`.

```sh
omgdb drop-collection <path> <collection> --yes
```

## Reading & querying

### get

Fetch a single document by its `_id` — an ObjectId `{"$oid":"..."}` or a bare scalar such as `7`. Prints the document as canonical JSON; exits non-zero with `document not found` on a miss.

```sh
omgdb get <path> <collection> <id>
```

### find

Find documents matching a MongoDB-style JSON [filter](/docs/query-operators/) (positional, defaults to `{}` — match all). Each match prints as one canonical-JSON line; an unknown operator is named in the error.

```sh
omgdb find <path> <collection> [filter] [--sort <json>] [--skip <N>] [--limit <N>]
           [--after-id <json>] [--after-sort-key <json>] [--project <json>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--sort <json>` | Sort spec (`{"field":1,"other":-1}`), applied before skip/limit. | none |
| `--skip <N>` | Matching documents to skip before printing. | `0` |
| `--limit <N>` | Maximum number of documents to print. | unlimited |
| `--after-id <json>` | Cursor token: only matches whose `_id` sorts after this value. | none |
| `--after-sort-key <json>` | Sorted-pagination cursor key; requires `--sort`. | none |
| `--project <json>` | Projection: `{"field":1}` to include, `{"field":0}` to exclude. | none |

`--after-id` cannot be combined with `--sort` (use `--after-sort-key` for sorted pagination), and the two `--after-*` flags are mutually exclusive.

> **Note:** querying a collection that does not exist keeps MongoDB's empty-result semantics, but `find` also prints a warning on stderr with a did-you-mean hint, so a typo never fails silently.

```sh
omgdb find app.omgdb users '{"age":{"$gte":25}}' --sort '{"age":-1}' --limit 10
```

### count-documents

Count documents matching a filter through the same direct query planner as `find` — an omitted filter counts the whole collection. Prints the bare count.

```sh
omgdb count-documents <path> <collection> [filter]
```

```sh
omgdb count-documents app.omgdb users '{"age":{"$gte":30}}'
# 2
```

### distinct

Deterministic distinct values for a dotted field path, in canonical value order, optionally pre-filtered. Exceeding `--max-values` (default 10000) is an error, never truncation.

```sh
omgdb distinct <path> <collection> <field> [filter] [--max-values <n>]
```

```sh
omgdb distinct app.omgdb users role
# ["admin","lead"]
```

### cursor-open

Open a persistent read cursor over a filter and print its first batch as JSON (`{token, collection, count, exhausted, lastId, sort, lastSortKey, batch}`). Cursor state lives in a sidecar file under the store, so it survives across processes.

```sh
omgdb cursor-open <path> <collection> [filter] [--batch-size <N>] [--sort <json>] [--project <json>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--batch-size <N>` | Matching documents per batch. | `100` |
| `--sort <json>` | Sort spec, persisted in the cursor. | none |
| `--project <json>` | Projection, persisted in the cursor. | none |

### cursor-next

Read the next batch from a persistent cursor by its token. `--batch-size` overrides (and persists) the cursor's stored batch size.

```sh
omgdb cursor-next <path> <token> [--batch-size <N>]
```

### cursor-close

Close a persistent cursor and remove its sidecar state. Prints `closed cursor <token>`.

```sh
omgdb cursor-close <path> <token>
```

```sh
omgdb cursor-open app.omgdb users '{}' --batch-size 500   # prints {"token":"...","batch":[...],...}
omgdb cursor-next app.omgdb <token>
omgdb cursor-close app.omgdb <token>
```

### aggregate

Run an [aggregation pipeline](/docs/aggregation/) given as a JSON array of stages. Each output document prints as one canonical-JSON line.

```sh
omgdb aggregate <path> <collection> <pipeline>
```

```sh
omgdb aggregate app.omgdb emp '[{"$group":{"_id":"$dept","total":{"$sum":"$sal"}}},{"$sort":{"_id":1}}]'
```

### inspect

Print each collection and its document count — text lines by default, `{"collections":[{"name":..,"count":..},..]}` with `--json`.

```sh
omgdb inspect <path> [--json]
```

### describe

Print a Markdown manual of the database: collections, inferred schema, and sample documents. See [introspection](/docs/introspection/).

```sh
omgdb describe <path>
```

### dump

Print a deterministic canonical export of every document. Useful for diffs and golden snapshots.

```sh
omgdb dump <path>
```

### explain

Explain how a query filter will be executed — index scan versus full scan. If the collection does not exist, `explain` refuses with a did-you-mean hint instead of producing confidently wrong advice.

```sh
omgdb explain <path> <collection> <filter>
```

### diagnose

Diagnose why a query matches what it does — per-predicate selectivity, printed as canonical JSON. Like `explain`, it errors with a did-you-mean hint on a missing collection.

```sh
omgdb diagnose <path> <collection> <filter>
```

```sh
omgdb diagnose app.omgdb userz '{"age":{"$gte":25}}'
# Error: collection `userz` does not exist — did you mean `users`? (existing: users)
```

## Indexes & schema

### create-index

Create a secondary [index](/docs/indexes/) on one field — or a compound index by listing several fields, used for equality-prefix and range planning. `--unique` rejects duplicate values (or tuples); `--partial` restricts the index to documents matching a predicate; `--name` gives the index a stable explicit identity for `list-indexes`/`drop-index` (omitted, a deterministic name is derived from the definition).

```sh
omgdb create-index <path> <collection> <field> [<field>...] [--name <name>] [--unique] [--partial <json>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--name <name>` | Stable explicit index name. | derived deterministic name |
| `--unique` | Reject duplicate present scalar values/tuples for this index. | off |
| `--partial <json>` | Partial-index predicate over supported query operators. | none |

```sh
omgdb create-index app.omgdb users email --name email_idx --unique
omgdb create-index app.omgdb events type ts        # compound index on (type, ts)
omgdb create-index app.omgdb users age --partial '{"active":true}'
```

### list-indexes

List a collection's ordinary indexes — name, fields, uniqueness, partial predicate — in stable name order.

```sh
omgdb list-indexes <path> <collection> [--json]
```

```sh
omgdb list-indexes app.omgdb users --json
# [{"name":"email_idx","collection":"users","fields":["email"],"unique":true}]
```

### drop-index

Drop one ordinary index by its stable name, as an authoritative op-log operation replayed like any other.

```sh
omgdb drop-index <path> <collection> <name>
```

### suggest-indexes

Suggest indexes the current planner can actually use for a query filter — optionally sort-aware, so compound suggestions cover an ORDER-BY-shaped query too. Prints a JSON array of suggestions.

```sh
omgdb suggest-indexes <path> <collection> <filter> [--sort <json>]
```

```sh
omgdb suggest-indexes app.omgdb events '{"type":"click"}' --sort '{"ts":-1}'
```

### validate

List documents in `<collection>` that violate its [validation rules](/docs/schema-validation/). Prints `valid: no violations` when clean; otherwise one `<id>: <reason>` line per offender, and exits non-zero.

```sh
omgdb validate <path> <collection>
```

## Safe mutations

The `plan-update` → `apply` → `rollback` trio is the auditable change workflow: plan first, apply by token, reverse by change id. See [agent mutations](/docs/agent-mutations/).

### plan-update

Dry-run an update: compute the changes without writing anything. Takes a filter and an [update spec](/docs/update-operators/) (`$set`, `$inc`, array operators, positional `$`), and prints a plan summary — a `token`, the match count, and a before/after sample.

```sh
omgdb plan-update <path> <collection> <filter> <update> [--array-filters <json>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--array-filters <json>` | JSON array of `arrayFilters` for `$[id]` filtered positional updates. | none |

```sh
omgdb plan-update app.omgdb users '{"age":{"$gte":25}}' '{"$set":{"active":true}}'
```

### apply

Apply a previously planned change by its `<token>`. Prints the apply result, including a change id, as canonical JSON.

```sh
omgdb apply <path> <token>
```

### rollback

Roll back a previously applied change by its `<change_id>`. Prints `rolled back <n> document(s)`.

```sh
omgdb rollback <path> <change_id>
```

## Vectors & context

The vector commands use the engine's offline, deterministic, dependency-free embedder — not an external service — so relevance is approximate. See [vector search](/docs/vector-search/) and [context packs](/docs/context-packs/).

### vsearch

Semantic search: rank documents by similarity of a text field to a query. Prints `<score>\t<document>` per hit.

```sh
omgdb vsearch <path> <collection> <field> <query> [--k <N>] [--filter <json>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--k <N>` | Number of results to return. | `5` |
| `--filter <json>` | Structured pre-filter on candidates (hybrid search). | none |

### context

Build a token-budgeted [context pack](/docs/context-packs/) for a task: the most relevant chunks of a text field, with citations, printed as canonical JSON (`citations`, `chunks`, `budgetTokens`).

```sh
omgdb context <path> <collection> <field> <query> [--budget <N>] [--filter <json>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--budget <N>` | Approximate token budget for the bundle. | `1000` |
| `--filter <json>` | Structured pre-filter on candidates (hybrid retrieval). | none |

### vsync

Persist embeddings for a text field into the sidecar collection `<collection>.__vectors`, with provenance; already-fresh embeddings are skipped. The vectors form an ordinary, inspectable collection.

```sh
omgdb vsync <path> <collection> <field>
```

### vstale

List `_id`s whose persisted embedding is stale — missing, built from a different model, or built from text that has since changed. Ids go to stdout, a `<n> stale embedding(s)` summary to stderr.

```sh
omgdb vstale <path> <collection> <field>
```

## Markdown

### import-md

Import a [Markdown](/docs/markdown/) file as one document: YAML frontmatter becomes queryable fields, headings become stored sections under `_sections`. Prints the assigned `_id`.

```sh
omgdb import-md <path> <collection> <file>
```

### md-set-section

Replace the body under one imported-Markdown section (by its stable id from `_sections[].sectionId`) and refresh the stored document. Pass the replacement text positionally, or `--file` for multiline content — one or the other, not both. Prints the updated document.

```sh
omgdb md-set-section <path> <collection> <id> <section-id> [<text>] [--file <path>]
```

```sh
omgdb md-set-section app.omgdb docs '{"$oid":"..."}' overview "New section body."
```

### md-patch-frontmatter

Patch frontmatter fields on an imported Markdown document: insert or replace fields from a JSON object, remove fields with repeatable `--remove`. Prints the updated document.

```sh
omgdb md-patch-frontmatter <path> <collection> <id> <patch> [--remove <field>]...
```

```sh
omgdb md-patch-frontmatter app.omgdb docs '{"$oid":"..."}' '{"status":"final"}' --remove draft
```

## Operations

### verify

Re-prove the entire database: replay the op-log, check that it reproduces the live state, and check every derived cache and checkpoint against it — at 50,000 documents this takes about a second. On success it prints an `OK` summary line plus one status line per derived cache; a stale or malformed cache is a stderr `WARN` (it is derived and rebuildable, never data loss), and a skipped torn trailing record from an interrupted write is warned about too. Exits non-zero with `INCONSISTENT: ...` if replay does not reproduce the live state.

```sh
omgdb verify <path>
```

### repair

Recover a corrupt op-log. Because a corrupt store cannot be opened, `repair` operates directly on `<path>/oplog.ndjson` — but it takes the store lock first, and refuses to run while another process has the store open.

```sh
omgdb repair <path> [--truncate] [--yes]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--truncate` | Truncate the log to the recoverable prefix (otherwise only report). | off |
| `--yes` | Confirm the destructive truncate (required with `--truncate`). | off |

With no flags it is a non-destructive dry run: it prints `OK: log is intact` or `CORRUPT at byte <g> of <total>: <reason>` plus the recoverable prefix. With `--truncate --yes` it backs up the original to `oplog.ndjson.corrupt.bak`, then truncates to the recoverable prefix. `--truncate` without `--yes` refuses.

```sh
omgdb repair app.omgdb                      # dry run: report only
omgdb repair app.omgdb --truncate --yes     # backup, then truncate
omgdb verify app.omgdb                      # now OK
```

### compact

Compact the op-log to its minimal form, dropping superseded history. Prints `compacted: <before> -> <after> records`.

```sh
omgdb compact <path>
```

### mcp

Run an [MCP](/docs/mcp/) (Model Context Protocol) server over stdio, exposing the store to coding agents as scoped tools. It speaks newline-delimited JSON-RPC 2.0 and answers `initialize`, `tools/list`, and `tools/call`.

```sh
omgdb mcp [--scope <scope>]
```

| Flag | Description | Default |
| --- | --- | --- |
| `--scope <scope>` | Capability ceiling enforced on every tool call: `read` (alias `ro`), `read-write` (aliases `write`, `rw`), or `dangerous` (alias `all`). An invalid value aborts. | `read-write` |

A `read` server advertises and permits only the 23 read tools; `read-write` adds the 24 mutating tools; `dangerous` additionally unlocks `drop_collection`, the one tool that destroys a whole collection. The full tool contract — annotations, per-tool parameters, and a working wire example — is on the [MCP server](/docs/mcp/) page.
