Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

update

Re-scan files, infer new fields, and update the schema.

Usage

mdvs update [path] [--dry-run]
mdvs update [path] reinfer [fields..] [flags]

Flags

FlagDefaultDescription
path.Directory containing mdvs.toml
--dry-runPreview changes without writing anything

Global flags (-o, -v, --logs) are described in Configuration.

What it does

update re-scans the directory using the existing [scan] config, infers types and path patterns from the current files, and merges the results into mdvs.toml. Unlike init, it preserves all existing configuration — only the [fields] section changes.

Default mode

By default, update only discovers new fields — fields that appear in frontmatter but aren’t yet in mdvs.toml (either as [[fields.field]] entries or in the ignore list). Existing fields are protected: their types, allowed/required patterns, nullable flags, and constraints don’t change.

Fields that disappear (no longer in any file) are kept in mdvs.toml by default. This is conservative — removing a field from the schema is an explicit action.

reinfer subcommand

Re-infer field definitions from scratch. This is a subcommand of update with its own flags:

FlagDescription
fields..Fields to reinfer (all if none specified)
--with <kinds>Comma-separated constraint kinds to apply (categorical, range, none). Requires named fields.
--max-categories <N>Override max distinct values for categorical inference
--min-repetition <N>Override min average repetition for categorical inference
--dry-runPreview changes without writing anything

Reinfer specific fields:

mdvs update example_kb reinfer drift_rate priority

The named fields are removed from mdvs.toml and re-inferred from scratch, as if they’d never been seen. All other fields stay protected. Fails if a named field isn’t in mdvs.toml.

Without --with, reinfer applies the default heuristic (categorical detection — see Constraints). Use --with to override:

# Force categorical (skip heuristic threshold)
mdvs update example_kb reinfer title --with=categorical

# Infer min/max from observed numeric values
mdvs update example_kb reinfer sample_count --with=range

# Strip all constraints
mdvs update example_kb reinfer status --with=none

--with takes a comma-separated list. Incompatible kinds (e.g., range,categorical on the same field) are rejected at parse time. --with=none cannot be combined with other kinds. --with requires named fields.

Reinfer all fields:

mdvs update example_kb reinfer

When no fields are specified, all [[fields.field]] entries are removed and rebuilt from the current files. Fields that no longer exist in any file are reported as removed.

All other config sections ([scan], [embedding_model], [chunking], [search], [update]) are preserved. This is the key difference from init --force, which rewrites the entire mdvs.toml.

Output

Compact (default)

When the schema is already up to date:

Scanned 43 files — no changes (37 unchanged) (dry run)

When new fields are discovered, they appear in an “Added” section with the same key-value format as init:

Scanned 44 files — 1 field(s) changed (37 unchanged) (dry run)

Added (1):
┌ category ────────────────┬───────────────────────────────────────────────────┐
│ type                     │ String                                            │
├──────────────────────────┼───────────────────────────────────────────────────┤
│ files                    │ 3 out of 44                                       │
├──────────────────────────┼───────────────────────────────────────────────────┤
│ nullable                 │ false                                             │
├──────────────────────────┼───────────────────────────────────────────────────┤
│ required                 │ (none)                                            │
├──────────────────────────┼───────────────────────────────────────────────────┤
│ allowed                  │ projects/alpha/notes/**                           │
└──────────────────────────┴───────────────────────────────────────────────────┘

When reinfer detects a type change, the “Changed” section shows old and new values with an arrow:

Scanned 43 files — 1 field(s) changed (36 unchanged)

Changed (1):
┌ drift_rate ──────────────┬───────────────────────────────────────────────────┐
│ type                     │ Float → String                                    │
└──────────────────────────┴───────────────────────────────────────────────────┘

When a reinferred field no longer exists in any file:

Scanned 43 files — 1 field(s) changed (36 unchanged)

Removed (1):
┌ category ────────────────┬───────────────────────────────────────────────────┐
│ previously allowed       │ projects/alpha/notes/**                           │
└──────────────────────────┴───────────────────────────────────────────────────┘

Verbose (-v)

Verbose output adds pipeline timing lines before the result:

Read config: example_kb/mdvs.toml (2ms)
Scan: 44 files (3ms)
Infer: 38 field(s) (0ms)
Write config: example_kb/mdvs.toml (1ms)
Scanned 44 files — 1 field(s) changed (37 unchanged)

Added (1):
┌ category ────────────────┬───────────────────────────────────────────────────┐
│ type                     │ String                                            │
...

The field tables are identical in both modes — verbose only adds the step lines showing processing times.

Exit codes

CodeMeaning
0Success (changes written, or no changes needed)
2Pipeline error (missing config, scan failure, build failure)

Errors

ErrorCause
no mdvs.toml foundConfig doesn’t exist — run mdvs init first
field '<name>' is not in mdvs.tomlreinfer names a field that doesn’t exist
--with requires named fields--with flag used without specifying fields
--with: <X> and <Y> are mutually exclusiveIncompatible constraint kinds in the same --with list
--with=none cannot be combined with other kindsnone mixed with other kinds in --with
field name conflicts with internal columnNew field name collides with reserved names