mdt

User Guide

CI Integration

mdt check is the whole gate. It exits non-zero when anything is wrong:

  • 0: every consumer is linked to a provider and up to date.
  • 1: a consumer is stale, an orphan (no provider), or its provider fails to render, or a file drifted from its formatter output.
  • 2: validation errors (unclosed, unmatched, nested, or invalid tags, unknown transformers, duplicate providers) or config and data errors.

Warnings, such as unused providers, are printed but never fail the check.

Install mdt in CI

Use the prebuilt binary from npm and pin the version you use locally (mdt --version):

sh
npx -y @m-d-t/cli@0.9.5 check --format github

Or install it once for several steps:

sh
npm install -g @m-d-t/cli@0.9.5

cargo install mdt_cli also works, but it builds from source and takes minutes.

GitHub Actions

yaml
name: docs
on:
  pull_request:
    branches: [main]

jobs:
  check-docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: check documentation sync
        run: npx -y @m-d-t/cli@0.9.5 check --format github

Annotations

--format github prints one annotation per problem, which GitHub shows inline on the pull request. Failures are ::error, warnings are ::warning:

::error file=readme.md,line=3,col=1::Consumer block `install` is out of date; run `mdt update`
::error file=readme.md,line=3,col=1::consumer `installguide` at readme.md:3:1 has no provider (did you mean `installGuide`?)
::error file=readme.md,line=6,col=1::Template render failed for block `badges`: argument count mismatch: provider `badges` declares 1 parameter(s), but consumer passes 2
::error file=readme.md,line=1,col=1::Formatter-normalized file output is out of date; run `mdt update`
::warning file=.templates/docs.t.md,line=1,col=1::provider block `installGuide` has no consumers

Validation errors, such as mdt::invalid_tag or mdt::nested_block, are annotated the same way. A one-line summary goes to stderr.

Annotation paths are relative to the repository checkout — the nearest enclosing git work tree — so annotations land on the right file whether mdt runs from the checkout root, with --path packages/lib, or from inside a sub-project (a step with working-directory:). Outside a git repository, paths are relative to the working directory.

Errors that stop the scan before any file is checked (an invalid mdt.toml, duplicate providers, an unreadable file) print one file-less ::error annotation carrying the error message. The step still fails with exit 2.

Show the diff

--diff adds a unified diff for each stale consumer to the text output, so the log shows exactly what changed:

sh
mdt check --diff

Diagnostics on failure

mdt info and mdt doctor explain config resolution, orphan and unused blocks, parser diagnostics, and cache health. Run them only when the check fails:

yaml
- name: mdt diagnostics
  if: failure()
  run: |
    npx -y @m-d-t/cli@0.9.5 info
    npx -y @m-d-t/cli@0.9.5 doctor

JSON output

For other tools, use --format json:

sh
mdt check --format json

mdt check --format json prints one object with every key present:

KeyEntries
oktrue when every consumer is linked and current
staleStale consumers: file, block, line, column
stale_filesFiles a formatter would change: file
orphansConsumers with no provider: file, block, line, column, suggestions
errorsRender errors: file, block, line, column, message
diagnosticsErrors and warnings: severity, code, file, line, column, message

A clean project:

json
{
	"diagnostics": [],
	"errors": [],
	"ok": true,
	"orphans": [],
	"stale": [],
	"stale_files": []
}

A stale consumer, an orphan, and an unused-provider warning:

json
{
	"diagnostics": [
		{
			"code": "mdt::unused_provider",
			"column": 1,
			"file": ".templates/template.t.md",
			"line": 11,
			"message": "provider block `unused` has no consumers",
			"severity": "warning"
		}
	],
	"errors": [],
	"ok": false,
	"orphans": [
		{
			"block": "intor",
			"column": 1,
			"file": "readme.md",
			"line": 7,
			"suggestions": ["intro"]
		}
	],
	"stale": [{ "block": "intro", "column": 1, "file": "readme.md", "line": 3 }],
	"stale_files": []
}

When validation errors (such as an unclosed or nested block) stop the check, the same object is printed with ok: false and the errors in diagnostics, and the exit status is 2. Errors that stop the scan itself (config and data errors, duplicate providers, unreadable files) print only the error report on stderr, also with exit status 2.

Formatters in CI

If mdt.toml has [[formatters]], mdt check runs those commands. Install the same formatters at the same versions you use locally, or CI reports formatter drift that does not exist on your machine. A formatter that fails or is missing is an error (exit 2).

Monorepos

Each directory with its own mdt.toml, .mdt.toml, or .config/mdt.toml is a separate project that the root scan skips. Check each one:

yaml
- name: check docs
  run: |
    npm install -g @m-d-t/cli@0.9.5
    mdt check
    mdt check --path packages/lib-a
    mdt check --path packages/lib-b

See Monorepo setups for a loop that finds every sub-project.

Pre-commit hook

mdt hook install writes the hook for you; re-running it is a no-op, and it refuses to clobber a different existing hook unless you pass --force:

sh
mdt hook install

The hook it installs is:

sh
#!/bin/sh
# Installed by `mdt hook install`; remove this file to uninstall.
if ! mdt check; then
echo "mdt check failed. Run 'mdt update' or fix the errors above before committing."
exit 1
fi

With the pre-commit framework, use the hook this repository publishes instead:

yaml
repos:
  - repo: https://github.com/ifiokjr/mdt
    rev: v0.9.6 # use the latest release tag
    hooks:
      - id: mdt-check

The hook and the framework entry both run plain mdt check from the repository root. Monorepos whose mdt projects live in sub-directories should call mdt check --path per project in CI instead; see Monorepo setups.

This repository's workflows

mdt's own docs site is built and deployed by docs-pages.yml on every push to main. Performance regressions are caught by benchmark.yml; see Benchmarking and regressions.

Edit this page on GitHub