markdownlint-rs
A fast, flexible, configuration-based command-line interface for linting Markdown files, written in Rust.
Project Status: Active development. Compatible with markdownlint-cli2 configuration and rule behavior.
Features
- ✨ Fast: Written in Rust for performance
- 🔧 Flexible: Supports multiple configuration formats (JSONC, YAML, package.json)
- 📏 54 Built-in Rules: Comprehensive Markdown linting with markdownlint compatibility
- 🔨 Auto-fix: Automatically fix many common issues with
--fix - 🌳 Gitignore Support: Respects
.gitignorefiles by default - 📦 Cross-platform: Linux (x86_64, ARM64), macOS (Intel, Apple Silicon), Windows
Compatibility
markdownlint-rs aims for full compatibility with markdownlint-cli2:
- ✅ Same configuration file formats and locations
- ✅ Same rule behavior and naming (MD001-MD059)
- ✅ Same configuration options for rules
- ✅ Compatible exit codes
Installation
From GitHub Releases (Recommended)
Download the latest release for your platform from the releases page:
Linux (x86_64):
Linux (ARM64):
macOS (Intel):
macOS (Apple Silicon):
Windows:
Download mdlint-windows-x86_64.exe.zip from the releases page and extract it to a directory in your PATH.
Verify checksum (optional but recommended):
# Linux/macOS
# Windows (PowerShell)
) { }
From crates.io
From Source
Docker
Pull from GitHub Container Registry:
Run on files in the current directory:
Run with auto-fix:
Run with custom config:
Available tags:
latest- Latest stable release1.x.x- Specific version (e.g.,1.0.0)1.x- Latest patch version in minor release (e.g.,1.0)1- Latest minor version in major release
The Docker image supports both linux/amd64 and linux/arm64 platforms.
Usage
Basic Usage
Lint all Markdown files in the current directory:
Lint specific files or directories:
Lint with auto-fix:
Command-Line Options
mdlint [OPTIONS] [PATTERNS]...
Arguments:
[PATTERNS]... Glob patterns for files to lint (defaults to current directory)
Options:
--config <PATH> Path to configuration file
--fix Apply fixes to files
--no-globs Ignore globs from configuration
--format <FORMAT> Output format: default or json [default: default]
--no-color Disable color output
-h, --help Print help
-V, --version Print version
Examples
Lint with custom config file:
Output as JSON:
Lint specific glob patterns:
Fix issues automatically:
Disable color output (for CI):
Configuration
markdownlint-rs discovers configuration files automatically by searching up from the current directory:
Configuration File Locations
The tool searches for these files in order (first found wins per directory level):
.markdownlint-cli2.jsonc.markdownlint-cli2.yaml.markdownlint-cli2.json.markdownlint.jsonc.markdownlint.json.markdownlint.yamlpackage.json(inmarkdownlint-cli2key)
Configuration File Format
JSONC/JSON (.markdownlint-cli2.jsonc):
{
// Rule configuration
"config": {
"default": true, // Enable all rules by default
"MD013": false, // Disable line length rule
"MD003": { "style": "atx" } // Configure heading style
},
// File selection
"globs": ["**/*.md"],
"ignores": ["node_modules/**", "dist/**"],
// Options
"fix": false,
"gitignore": true,
"noInlineConfig": false
}
YAML (.markdownlint-cli2.yaml):
config:
default: true
MD013: false
MD003:
style: atx
globs:
- "**/*.md"
ignores:
- "node_modules/**"
- "dist/**"
fix: false
gitignore: true
Configuration Hierarchies
Configurations are discovered by walking up the directory tree. When multiple configs are found, they are merged with the following precedence (highest to lowest):
- Command-line options (
--config,--fix, etc.) - Local directory config (
.markdownlint-cli2.jsoncin current dir) - Parent directory configs (walking up to root)
- Default configuration
Arrays (like globs and ignores) are extended, not replaced.
Rule Configuration
Each rule can be configured in multiple ways:
{
"config": {
"MD001": true, // Enable rule
"MD002": false, // Disable rule
"MD003": { "style": "atx" }, // Configure with options
"MD007": { "indent": 4 }, // Set specific parameters
"default": true // Enable all rules by default
}
}
See the markdownlint rules documentation for details on each rule and its configuration options.
Exit Codes
- 0: Success - no linting errors found
- 1: Linting errors found
- 2: Runtime error (invalid config, file not found, etc.)
Use exit codes in CI/CD pipelines:
||
Supported Rules
markdownlint-rs implements 54 rules compatible with markdownlint:
| Rule | Description | Fixable |
|---|---|---|
| MD001 | Heading levels should only increment by one level at a time | ❌ |
| MD003 | Heading style | ❌ |
| MD004 | Unordered list style | ❌ |
| MD005 | Inconsistent indentation for list items at the same level | ❌ |
| MD007 | Unordered list indentation | ❌ |
| MD009 | Trailing spaces | ✅ |
| MD010 | Hard tabs | ✅ |
| MD011 | Reversed link syntax | ❌ |
| MD012 | Multiple consecutive blank lines | ✅ |
| MD013 | Line length | ❌ |
| MD018 | No space after hash on atx style heading | ✅ |
| MD019 | Multiple spaces after hash on atx style heading | ✅ |
| MD022 | Headings should be surrounded by blank lines | ✅ |
| MD023 | Headings must start at the beginning of the line | ✅ |
| MD025 | Multiple top-level headings in the same document | ❌ |
| ... | See markdownlint rules for full list | ... |
Differences from markdownlint-cli2
While markdownlint-rs aims for compatibility, there are some intentional differences:
- No JavaScript custom rules: Use Rust API instead (future feature)
- No markdown-it plugins: Uses CommonMark-compliant parser with standard extensions
- Faster execution: Compiled binary vs Node.js runtime
- Single binary: No npm/node dependencies required
Contributing
Contributions are welcome! See CONTRIBUTING.md for:
- Development setup
- Code quality standards
- How to add new rules
- Release process
License
MIT License - see LICENSE for details.
Acknowledgments
- markdownlint by David Anson - Original rule definitions
- markdownlint-cli2 - Configuration format and behavior
- pulldown-cmark - Markdown parsing