Editors & LSP
mdv lsp brings live diagnostics, hover docs, and completion for mdv directives into VS Code, Neovim, Helix, or any LSP-capable editor.
A good flight deck tells you about the fault while your hand is still on the switch.
mdv checkis the post-flight report;mdv lspis the instrument panel — the same validator, wired into your editor, flagging the line as you type it.
The server
The mediva CLI ships a language server. Any LSP-capable editor can start it:
mdv lsp --stdioWhat lights up:
- Diagnostics as you type — the exact
mdv checkverdicts (same compile + validate chain, including the configrules:baseline and any per-fileoverrides:— resolved per open document, same asmdv checkresolves them per target), debounced per keystroke. The one honest exception: asources.declareentry that is an executable loader (a bare function or{ load }) resolves CLI-side only — see the no-acquisition policy below. Contract errors (unknown-rule, bad options) surface on the.mdv.mdfile at the schema's own line numbers, document findings on the document. - Grounded rules, live —
covers.in=,entitiesIn=,groundedIn=,quotesMatch=, mask|in:and friends validate in-editor against their sources, under a strict no-acquisition policy: the server reads contract-relative files,sources.declarepath entries and typed object-projection declarations ({path, members}/{path, markdown}/{path, entries}/{path, records}— no code runs, just a typed read), and already-materializedgroundoutputs (unsaved buffers included) — it never runs anything that produces or fetches data (groundshell commands,declareloader functions, resolver endpoints). Config-imported parse callbacks (plugin source loaders, token extractors) do run over those bytes, exactly as they already do during validation itself. What the policy declines degrades to the rule's honest no-op plus a note on the declaring schema line:source-missing/source-invalid(errors),source-unbound/source-not-materialized(warnings pointing atmdv sources doctor/sync),source-cli-only/source-stale(info). Editing a source file revalidates its dependents. - Hover docs — any directive token (
section,required,minWords=) shows its summary, allowed value shape, a copy-pasteable example, and a reference link. The value side answers too: a source ref hovers with how it's bound (materialized / declared path / declared projection — with its kind, resolved path, and requiredness / loader) and whether it's active or dormant for the open contract, plus what the trailing?and#fragmentmean; inside a mask,|filternames explain themselves and<token>names show their declared fragment regex. - Completion — inside
<!-- mdv: … -->: tags in first position, then rules (filtered to the tag's kind), structure atoms, and severity overrides; assignment rules insert with=. After a source-takingkey=, the config's bindable logical names and./path segments complete; enum rules complete their allowed values. - Go to definition —
<name>inside a mask jumps to its file-local<!-- mdv: fragment … -->declaration.
Schema discovery mirrors check: a sibling X.mdv.md governs X.md, else a directory
_template.mdv.md. The governing mediva.config.mjs is discovered per document with the
CLI's nearest-ancestor walk-up (bounded by the git root), so nested projects and multi-root
workspaces each bind their own config. Editing a schema revalidates every open document it
governs. A broken config never kills the server — it degrades to built-in rules and reports one
warning on the config file it actually found.
Deliberate CI divergences: a CI run replaying a --source-snapshot capture validates the
capture, while the editor always validates live files; declare loader functions and ground
producers resolve only CLI-side (see the no-acquisition policy above). Hover is pointer/touch only for
now.
See the grounded templates guide for the full source model — the four
projection shapes, requiredness, and the exact/folded/mention compare modes a source's
identity policy can select.
VS Code
The vscode-mediva extension (in-repo at packages/vscode-mediva, marketplace publish pending)
bundles the directive grammar and starts the server automatically:
mediva.serverPathsetting, if set;- the workspace's
node_modules/.bin/mdv(trusted workspaces only); mdvonPATH.
No binary → highlighting still works (TextMate injection), with a status-bar hint. Develop-install:
cd packages/vscode-mediva && npm run build
code --extensionDevelopmentPath="$PWD"Neovim
vim.lsp.config("mediva", {
cmd = { "mdv", "lsp", "--stdio" },
filetypes = { "markdown" },
root_markers = { "mediva.config.mjs", ".git" },
})
vim.lsp.enable("mediva")Helix
# ~/.config/helix/languages.toml
[language-server.mediva]
command = "mdv"
args = ["lsp", "--stdio"]
[[language]]
name = "markdown"
language-servers = ["marksman", "mediva"]