A fast, auto-fixing Markdown linter and formatter for docs, READMEs, and AI-generated content. Checks style, readability, structure, and cross-file integrity. One static Go binary.
One static Go binary checks 523 Markdown files in about 0.2 s. That is roughly 10x faster than Node markdownlint. It does more per file than the Rust linters; closing the rest of that gap is active work.
Numbers above come from a reproducible benchmark, not hand-typed copy.
mdsmith is one rule engine behind every surface: the CLI, the LSP server, and the VS Code extension all run the same checks. Neovim and other LSP-aware editors plug in through the same server; a Claude Code plugin is available for users of that editor. This page is the shared overview. The README includes it; the website renders it and links each card to a fuller page.
These features pay off on a single README and scale up to a docs monorepo.
Auto-fix Markdown formatting.
mdsmith fix rewrites whitespace, headings, code fences, bare
URLs, list indentation, and table alignment in place. It loops
until edits stabilize. mdsmith check is the read-only CI
sibling.
Live diagnostics wherever you write.
mdsmith lsp emits diagnostics, quick-fixes, and navigation. Any
LSP-aware editor can consume it. The VS Code extension and the
Claude Code plugin surface the same data.
Rename without breaking links. Rename a heading and every workspace anchor link to it is rewritten in one atomic edit. Link-ref labels rename with their uses. A colliding slug fails loudly instead of breaking links.
See the dependency graph.
mdsmith deps lists what a file pulls in, or what depends on it.
The LSP call-hierarchy walks the same <?include?>, <?catalog?>,
<?build?>, and link graph in your editor.
Cross-file integrity.
Built-in rules flag broken links and missing anchors, enforce
per-file section schemas, and keep Markdown in the right folders.
Schemas can be inline on a file kind or shared via proto.md
files.
These features show up when the repo grows past a handful of files: includes, catalogs, dependency graphs, release gates, and size budgets.
Size and readability limits. Cap file, section, and token-budget size. Enforce reading grade and sentence count. Flag verbatim copy-paste across files. Three rules ship on by default; two are opt-in.
Self-maintaining sections.
On mdsmith fix, <?toc?> rebuilds a heading TOC, <?catalog?>
generates an index from front matter, and <?include?> splices
in another file. A Git merge driver resolves conflicts in those
blocks.
Gate releases on doc status.
mdsmith list query selects files by a CUE expression on front
matter. mdsmith metrics rank ranks files by any shared metric.
Both pipe straight into a release script.
Fast on every run. A single static Go binary with no runtime to boot. The workspace walk runs in parallel and embeds are linted once, so CI and editor feedback stay instant.
Quality you can verify. The build, Go Report Card, and coverage badges at the top of the README report live project health. mdsmith lints its own docs with the rules it ships, and a coverage gate blocks merges that drop below the line.
File kinds and schemas.
Tag each file with a kind, then validate its headings and front
matter against a schema declared inline on the kind or shared via
a proto.md template. A whole directory obeys one contract.
Conventions and flavors.
Pin a convention to get a curated rule preset and a target
renderer flavor in one switch. MDS034 flags syntax the flavor
will not render. A placeholder vocabulary spares template tokens.
Build artifacts in sync.
<?build?> declares an artifact and a recipe. mdsmith fix
keeps the section body in sync with the recipe output. MDS040
shell-safety-checks the recipe without running it.
Git-native, conflict-free.
A merge driver auto-resolves conflicts inside generated blocks.
A pre-merge-commit hook re-runs mdsmith fix and re-stages the
result, so generated content never blocks a merge.
Config you can explain.
Config layers deep-merge rule by rule: defaults, convention,
kinds, then overrides. --explain and mdsmith kinds resolve
show which layer set each effective value.
Editors and agents.
A bundled VS Code extension and Claude Code plugins drive the
same mdsmith lsp server, so diagnostics, fix-on-save, and
navigation reach your editor and your coding agent unchanged.
Installs everywhere. One version-stamped Go binary ships through go install, npm, pip, uvx, mise, asdf, and GitHub Releases. No postinstall network call, so locked-down CI installs offline.
π How does it compare? See:
π Link handling internals. See:
CLI:
go install github.com/jeduden/mdsmith/cmd/mdsmith@latest
npm install -g @mdsmith/cli # or: npx @mdsmith/cli
pip install mdsmith # or: uvx mdsmith / pipx install mdsmithEditor extension (LSP-backed; runs mdsmith lsp):
code --install-extension jeduden.mdsmith # VS Code, Codespaces (Marketplace)
codium --install-extension jeduden.mdsmith # Cursor, VSCodium, Theia, Gitpod (Open VSX)Any LSP-aware editor (Neovim, Helix, JetBrains via the LSP
plugin) works by pointing at mdsmith lsp.
Claude Code plugin (inline diagnostics plus definition, references, symbol search, and call-hierarchy queries across your docs):
/plugin marketplace add jeduden/mdsmith
/plugin install mdsmith-lsp@mdsmith
/reload-plugins
More: the install guide covers direct downloads and mise (asdf pending). VS Code integration covers settings, code actions, and troubleshooting.
mdsmith <command> [flags] [files...]
| Command | Description |
|---|---|
check |
Lint Markdown files for style issues. |
deps |
List a file's dependency-graph edges (includes, links, catalogs, builds). |
export |
Write a portable, directive-free copy of a Markdown file. |
extract |
Emit a schema-conformant Markdown file as a JSON/YAML/msgpack data tree. |
fix |
Auto-fix lint issues in Markdown files in place. |
help |
Show built-in documentation for rules, metrics, and concept pages. |
init |
Generate a default .mdsmith.yml config in the current directory. |
kinds |
Inspect declared file kinds and resolve effective rule config per file. |
list |
Selection-style commands that walk the workspace and emit matches. |
list backlinks |
List workspace links that point at a file. |
list query |
Select Markdown files by a CUE expression on front matter. |
lsp |
Run a Language Server Protocol server on stdio for editor integrations. |
merge-driver |
Git merge driver that resolves conflicts inside generated sections. |
metrics |
List and rank shared Markdown metrics (file length, token estimate, readability, β¦). |
pre-merge-commit |
Install / manage a pre-merge-commit hook that runs mdsmith fix after a merge. |
rename |
Rename a heading or link-reference label and rewrite every dependent edit. |
version |
Print the mdsmith build version and exit. |
Files can be paths, directories (walked recursively for *.md
and *.markdown), or glob patterns. Directories respect
.gitignore by default;
use --no-gitignore to override. Explicitly named files are
never filtered by .gitignore.
mdsmith check docs/ # lint a directory
mdsmith fix README.md # auto-fix in place
mdsmith check -f json docs/ # JSON output
mdsmith metrics rank --by bytes --top 10 .See the CLI reference for shared flags, exit codes, output format, and configuration merge semantics. Individual subcommand pages above cover their own flags and examples.
Run mdsmith init to generate a .mdsmith.yml with every rule and its
defaults. Without a config, rules run with built-in defaults.
rules:
line-length:
max: 120
fenced-code-language: false
ignore:
- "vendor/**"
overrides:
- glob: ["CHANGELOG.md"]
rules:
no-duplicate-headings: falseRules are true (defaults), false (off), or an object with settings.
overrides apply per file pattern; later entries take precedence.
Config is discovered by walking up to the repo root; --config overrides.
Commit .mdsmith.yml so contributors share the same rule settings and
mdsmith upgrades become an explicit, reviewable change. Run
mdsmith version to see the build you have installed.
- Guides β directives, structure, migration
- Rule directory β every rule with status
- CLI reference
- Contributor guide β Go 1.24+, build, test, style
