# markdownlint-rs
[](https://github.com/swanysimon/markdownlint-rs/actions/workflows/ci.yml)
[](https://crates.io/crates/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](https://github.com/DavidAnson/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](https://github.com/DavidAnson/markdownlint) compatibility
- 🔨 **Auto-fix**: Automatically fix many common issues with `--fix`
- 🌳 **Gitignore Support**: Respects `.gitignore` files by default
- 📦 **Cross-platform**: Linux (x86_64, ARM64), macOS (Intel, Apple Silicon), Windows
## Compatibility
markdownlint-rs aims for full compatibility with [markdownlint-cli2](https://github.com/DavidAnson/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](https://github.com/swanysimon/markdownlint-rs/releases):
**Linux (x86_64)**:
```bash
curl -LO https://github.com/swanysimon/markdownlint-rs/releases/latest/download/mdlint-linux-x86_64.tar.gz
tar xzf mdlint-linux-x86_64.tar.gz
sudo mv mdlint /usr/local/bin/
```
**Linux (ARM64)**:
```bash
curl -LO https://github.com/swanysimon/markdownlint-rs/releases/latest/download/mdlint-linux-aarch64.tar.gz
tar xzf mdlint-linux-aarch64.tar.gz
sudo mv mdlint /usr/local/bin/
```
**macOS (Intel)**:
```bash
curl -LO https://github.com/swanysimon/markdownlint-rs/releases/latest/download/mdlint-macos-x86_64.tar.gz
tar xzf mdlint-macos-x86_64.tar.gz
sudo mv mdlint /usr/local/bin/
```
**macOS (Apple Silicon)**:
```bash
curl -LO https://github.com/swanysimon/markdownlint-rs/releases/latest/download/mdlint-macos-aarch64.tar.gz
tar xzf mdlint-macos-aarch64.tar.gz
sudo mv mdlint /usr/local/bin/
```
**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):
```bash
# Linux/macOS
sha256sum -c mdlint-*.sha256
# Windows (PowerShell)
$expected = (Get-Content mdlint-*.sha256).Split()[0]
$actual = (Get-FileHash mdlint.exe).Hash.ToLower()
if ($expected -eq $actual) { "OK" } else { "FAILED" }
```
### From crates.io
```bash
cargo install markdownlint-rs
```
### From Source
```bash
git clone https://github.com/swanysimon/markdownlint-rs.git
cd markdownlint-rs
cargo build --release
sudo cp target/release/mdlint /usr/local/bin/
```
### Docker
Pull from GitHub Container Registry:
```bash
docker pull ghcr.io/swanysimon/markdownlint-rs:latest
```
Run on files in the current directory:
```bash
docker run --rm -v "$PWD:/workspace" ghcr.io/swanysimon/markdownlint-rs:latest
```
Run with auto-fix:
```bash
docker run --rm -v "$PWD:/workspace" ghcr.io/swanysimon/markdownlint-rs:latest --fix
```
Run with custom config:
```bash
docker run --rm -v "$PWD:/workspace" ghcr.io/swanysimon/markdownlint-rs:latest --config .markdownlint.json
```
**Available tags:**
- `latest` - Latest stable release
- `1.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:
```bash
mdlint
```
Lint specific files or directories:
```bash
mdlint README.md docs/
```
Lint with auto-fix:
```bash
mdlint --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:**
```bash
mdlint --config .markdownlint.json
```
**Output as JSON:**
```bash
mdlint --format json
```
**Lint specific glob patterns:**
```bash
mdlint "**/*.md" "!node_modules/**"
```
**Fix issues automatically:**
```bash
mdlint --fix docs/
```
**Disable color output (for CI):**
```bash
mdlint --no-color
```
## 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):
1. `.markdownlint-cli2.jsonc`
2. `.markdownlint-cli2.yaml`
3. `.markdownlint-cli2.json`
4. `.markdownlint.jsonc`
5. `.markdownlint.json`
6. `.markdownlint.yaml`
7. `package.json` (in `markdownlint-cli2` key)
### Configuration File Format
**JSONC/JSON** (`.markdownlint-cli2.jsonc`):
```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`):
```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):
1. Command-line options (`--config`, `--fix`, etc.)
2. Local directory config (`.markdownlint-cli2.jsonc` in current dir)
3. Parent directory configs (walking up to root)
4. Default configuration
Arrays (like `globs` and `ignores`) are **extended**, not replaced.
### Rule Configuration
Each rule can be configured in multiple ways:
```jsonc
{
"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](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md) 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:
```bash
## Supported Rules
markdownlint-rs implements 54 rules compatible with markdownlint:
| 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](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md) 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](CONTRIBUTING.md) for:
- Development setup
- Code quality standards
- How to add new rules
- Release process
## License
MIT License - see [LICENSE](LICENSE) for details.
## Acknowledgments
- [markdownlint](https://github.com/DavidAnson/markdownlint) by David Anson - Original rule definitions
- [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) - Configuration format and behavior
- [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) - Markdown parsing
## Resources
- [Documentation](https://github.com/swanysimon/markdownlint-rs/tree/main/.github)
- [Issue Tracker](https://github.com/swanysimon/markdownlint-rs/issues)
- [Changelog](https://github.com/swanysimon/markdownlint-rs/releases)
- [markdownlint Rules Reference](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md)