mkdlint
A fast Markdown linter written in Rust, inspired by markdownlint.
Features
- 54 lint rules (MD001-MD060) enforcing Markdown best practices
- 🎉 Automatic fixing for 44 rules (81.5% coverage) with
--fixflag - 💡 Helpful suggestions for all rules with actionable guidance
- Language Server Protocol (LSP) — real-time linting in VS Code, Neovim, and other editors
- GitHub Action — native integration with SARIF Code Scanning
- Rich error display with source context and colored underlines pointing to errors
- Multiple output formats — text (default), JSON, or SARIF
- Configuration via JSON, YAML, or TOML files with auto-discovery
- High performance — parallel file processing with optimized rules
- Library + CLI — use as a Rust crate or standalone command-line tool
Auto-Fix Showcase
mkdlint can automatically fix 44 out of 54 rules (81.5%)! Here are some examples:
Before Auto-Fix

[link](http://example.com)
http://example.com
$ npm install
$ echo "commands with dollar signs"
After mkdlint --fix

[link](http://example.com)
<http://example.com>
npm install
echo "commands with dollar signs"
What Gets Fixed Automatically
- Headings: spacing, levels, ATX style consistency
- Links & Images: alt text, bare URLs, unused references
- Lists: indentation, marker consistency, spacing
- Code: fence styles, dollar sign prefixes, language tags
- Whitespace: trailing spaces, blank lines, tabs
- Tables: pipe consistency, surrounding blank lines
- And much more!
Installation
CLI Tool
# From crates.io
# From source
Language Server (LSP)
# Install with LSP feature
# The binary will be available as: mkdlint-lsp
GitHub Action
Add to your workflow:
- uses: 192d-Wing/mkdlint/.github/actions/mkdlint@main
with:
files: '.'
See GitHub Action documentation for full details.
As a library dependency
[]
= "0.6"
# With async support
= { = "0.6", = ["async"] }
# With LSP support
= { = "0.6", = ["lsp"] }
CLI Usage
Basic Commands
# Lint files
# Lint with auto-fix
# Lint a directory recursively
# Lint from stdin
|
# List all available rules with descriptions
Configuration Management
# Initialize a new config file with defaults
# Initialize with custom path and format
# Use a specific config file
# Enable/disable specific rules on the fly
# Combine multiple rule overrides
Output Control
# Output in JSON format (machine-readable)
# Output in SARIF format (for CI/CD integration)
# Quiet mode - only show filenames with errors
# Verbose mode - show detailed error statistics
# Disable colored output (for CI environments)
Advanced Usage
# Ignore specific files/patterns
# Combine multiple options
# Fix with specific rules disabled
# Stdin with fix output to stdout
|
Example Output
mkdlint provides rich error display with source context:
README.md: 42: MD009/no-trailing-spaces Trailing spaces [Expected: 0; Actual: 3]
42 |
42 | This line has trailing spaces
| ^^^
README.md: 58: MD034/no-bare-urls Bare URL used
58 |
58 | Visit https://example.com for more info.
| ^^^^^^^^^^^^^^^^^^^
Commands
| Command | Description |
|---|---|
mkdlint [FILES...] |
Lint markdown files (default command) |
mkdlint init |
Create a new configuration file with defaults |
Options
| Flag | Description |
|---|---|
-f, --fix |
Automatically fix violations where possible |
-c, --config <PATH> |
Path to configuration file (.json, .yaml, or .toml) |
-o, --output-format <FORMAT> |
Output format: text (default), json, or sarif |
--ignore <PATTERN> |
Glob pattern to ignore (can be repeated) |
--stdin |
Read input from stdin instead of files |
--list-rules |
List all available linting rules with descriptions |
--enable <RULE> |
Enable specific rule (can be repeated) |
--disable <RULE> |
Disable specific rule (can be repeated) |
-v, --verbose |
Show detailed output with error statistics |
-q, --quiet |
Quiet mode - only show filenames with errors |
--no-color |
Disable colored output |
--no-inline-config |
Disable inline configuration comments |
Language Server Protocol (LSP)
mkdlint includes a full-featured Language Server for real-time linting in your editor.
VS Code Setup
-
Install the LSP binary:
-
Configure VS Code (
.vscode/settings.json): -
Features:
- Real-time diagnostics as you type
- Quick-fix code actions (auto-fix on Ctrl+.)
- "Fix All" command - Fix all issues in a document at once
- Respects your
.markdownlint.jsonconfig - Debounced linting (300ms) for performance
Neovim Setup
require..
Other Editors
Any editor with LSP support can use mkdlint-lsp. The server uses stdio for communication and supports:
textDocument/didOpen,didChange,didSave,didClosetextDocument/codeAction(for individual auto-fixes)workspace/executeCommand(for "Fix All" command)- Full document synchronization
Usage Tips:
- Use quick-fix (Ctrl+.) to fix individual issues
- Use "Fix All" command to apply all fixes at once
- All 34 auto-fixable rules are supported
CI/CD Integration
Use mkdlint in your CI/CD with native GitHub Code Scanning integration:
name: Lint Markdown
on:
jobs:
lint:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: 192d-Wing/mkdlint/.github/actions/mkdlint@main
with:
files: '.'
fix: true # Optional: auto-fix issues
Features:
- Pre-built binaries for Linux, macOS, Windows (x86_64, aarch64)
- Automatic binary caching (10-100x faster subsequent runs)
- SARIF output with automatic Code Scanning upload
- Auto-fix support with commit integration
- Cargo fallback if binary download fails
See full documentation for all options.
Library Usage
use ;
let options = LintOptions ;
let results = lint_sync.unwrap;
for in results.iter
Auto-fixing
use ;
use HashMap;
let content = "# Title\n\nSome text \n";
let mut strings = new;
strings.insert;
let options = LintOptions ;
let results = lint_sync.unwrap;
if let Some = results.get
Configuration
Create a .markdownlint.json (or .yaml / .toml) file:
Rules can be enabled/disabled by name ("MD013") or alias ("line-length"). Pass a boolean to enable/disable, or an object to configure options.
Rules
| Rule | Alias | Description | Fixable |
|---|---|---|---|
| MD001 | heading-increment | Heading levels should increment by one | Yes |
| MD003 | heading-style | Heading style | |
| MD004 | ul-style | Unordered list style | Yes |
| MD005 | list-indent | Inconsistent indentation for list items | Yes |
| MD007 | ul-indent | Unordered list indentation | Yes |
| MD009 | no-trailing-spaces | Trailing spaces | Yes |
| MD010 | no-hard-tabs | Hard tabs | Yes |
| MD011 | no-reversed-links | Reversed link syntax | Yes |
| MD012 | no-multiple-blanks | Multiple consecutive blank lines | Yes |
| MD013 | line-length | Line length | |
| MD014 | commands-show-output | Dollar signs used before commands | Yes |
| MD018 | no-missing-space-atx | No space after hash on atx heading | Yes |
| MD019 | no-multiple-space-atx | Multiple spaces after hash on atx heading | Yes |
| MD020 | no-missing-space-closed-atx | No space inside hashes on closed atx heading | Yes |
| MD021 | no-multiple-space-closed-atx | Multiple spaces inside hashes on closed atx heading | Yes |
| MD022 | blanks-around-headings | Headings should be surrounded by blank lines | Yes |
| MD023 | heading-start-left | Headings must start at the beginning of the line | Yes |
| MD024 | no-duplicate-heading | No duplicate heading content | |
| MD025 | single-title | Single title / single h1 | |
| MD026 | no-trailing-punctuation | Trailing punctuation in heading | Yes |
| MD027 | no-multiple-space-blockquote | Multiple spaces after blockquote symbol | Yes |
| MD028 | no-blanks-blockquote | Blank line inside blockquote | Yes |
| MD029 | ol-prefix | Ordered list item prefix | Yes |
| MD030 | list-marker-space | Spaces after list markers | Yes |
| MD031 | blanks-around-fences | Fenced code blocks should be surrounded by blank lines | Yes |
| MD032 | blanks-around-lists | Lists should be surrounded by blank lines | Yes |
| MD033 | no-inline-html | Inline HTML | |
| MD034 | no-bare-urls | Bare URL used | Yes |
| MD035 | hr-style | Horizontal rule style | Yes |
| MD036 | no-emphasis-as-heading | Emphasis used instead of a heading | Yes |
| MD037 | no-space-in-emphasis | Spaces inside emphasis markers | Yes |
| MD038 | no-space-in-code | Spaces inside code span elements | Yes |
| MD039 | no-space-in-links | Spaces inside link text | Yes |
| MD040 | fenced-code-language | Fenced code blocks should have a language specified | Yes |
| MD041 | first-line-heading | First line in a file should be a top-level heading | Yes |
| MD042 | no-empty-links | No empty links | Yes |
| MD044 | proper-names | Proper names should have correct capitalization | Yes |
| MD045 | no-alt-text | Images should have alternate text | |
| MD046 | code-block-style | Code block style | |
| MD047 | single-trailing-newline | Files should end with a single trailing newline | Yes |
| MD048 | code-fence-style | Code fence style | Yes |
| MD049 | emphasis-style | Emphasis style | Yes |
| MD050 | strong-style | Strong style | Yes |
| MD051 | link-fragments | Link fragments should be valid | |
| MD052 | reference-links-images | Reference links and images should use a label that is defined | |
| MD053 | link-image-reference-definitions | Link and image reference definitions should be needed | |
| MD054 | link-image-style | Link and image style | |
| MD058 | blanks-around-tables | Tables should be surrounded by blank lines | Yes |
| MD059 | emphasis-marker-style-math | Emphasis marker style in math | |
| MD060 | dollar-in-code-fence | Dollar signs in fenced code blocks |
Bold entries indicate auto-fix added in v0.2.0. Bold+Italic entries are new in v0.3.0 and v0.4.0.
License
Apache-2.0