Provider
Defines a block once, in a *.t.md template file.
mdt keeps the same words in your README, your doc comments, and your docs site. Write a block once with {@name}, drop {=name} wherever it belongs, and let mdt update do the copying.
<!-- {@install} --> <!-- {/install} -->
Edit the provider. Watch the copies drift.
<!-- {=install} --> <!-- {/install} -->
//! <!-- {=install|trim|linePrefix:"//! ":true} --> //! <!-- {/install} -->
<!-- {=install|trim|codeBlock:"text"} --> <!-- {/install} -->
$ mdt checkCheck passed: all consumer blocks are up to date.
The whole language
mdt tags are HTML comments, so they vanish when markdown renders. No build step in your docs, no new file format, nothing to learn past this row of cards.
Where it works
Consumers work inside source comments, so your doc comments, your README, and your docs site can all quote the same paragraph. A transformer adds the comment marker to every line.
//! <!-- {=clientDocs|trim|linePrefix:"//! ":true} --> //! A fast HTTP client. //! //! Supports async and blocking modes. //! <!-- {/clientDocs} --> pub struct Client;
/** * <!-- {=clientDocs|trim|linePrefix:" * ":true} --> * A fast HTTP client. * * Supports async and blocking modes. * <!-- {/clientDocs} --> */ export class Client {}
/// <!-- {=clientDocs|trim|linePrefix:"/// ":true} --> /// A fast HTTP client. /// /// Supports async and blocking modes. /// <!-- {/clientDocs} --> class Client {}
class Client:
"""
<!-- {=clientDocs|trim|indent:" "} -->
A fast HTTP client.
Supports async and blocking modes.
<!-- {/clientDocs} -->
"""
// <!-- {=clientDocs|trim|linePrefix:"// ":true} --> // A fast HTTP client. // // Supports async and blocking modes. // <!-- {/clientDocs} --> type Client struct{}
Also JavaScript, Java, Kotlin, Swift, C, C++, and C#, plus any extension you add. Source file support →
Small, sharp tools
Pull values from your manifests, reshape a block for each place it lands, and fail the build the moment two copies disagree.
Point mdt at package.json, Cargo.toml, or any data file. The version in your docs is the version you ship.
# mdt.toml [data] pkg = "package.json" <!-- {@install} --> npm i my-lib@{{ pkg.version }} <!-- {/install} -->
One block, many shapes. Trim it, fence it, indent it, prefix every line, or replace text on the way out.
<!-- {=install|trim |codeBlock:"sh"} --> ```sh npm i my-lib@0.9.7 ``` <!-- {/install} -->
mdt check exits non-zero when any copy is stale and tells you exactly which block, in which file. Add one line to your workflow.
# .github/workflows/ci.yml - run: npx -y @m-d-t/cli check Check failed. block `install` at readme.md:3:1 Run `mdt update`.
Built for agents
Agents are great at editing docs and terrible at remembering the four other places the same sentence lives. mdt gives them one place to write and a command that proves nothing drifted.
mdt skill --install .claude/skills$ mdt check Check failed. stale consumers: 2 Stale consumers: block `install` at readme.md:3:1 block `install` at src/lib.rs:1:5 $ mdt update Updated 2 block(s) in 2 file(s). $ mdt check Check passed: all consumer blocks are up to date.