mdlint
A Python Markdown linter that checks files for style and formatting violations.
- 50+ built-in rules covering headings, lists, whitespace, links, code blocks, and more
- Configurable via
.mdlint.tomlorpyproject.tomlwith per-rule settings - Multiple output formats including human-readable terminal output and JSON
- Gitignore-aware file discovery that respects
.gitignorepatterns - Auto-fix support via
--fixto automatically correct fixable violations - stdin support for integration with editors and CI pipelines
- Built-in rule documentation accessible from the CLI
- Online playground to try mdlint directly in the browser — no installation needed
- Parallel processing of files automatically when checking large projects
- Compatible with existing
markdownlintrule sets (Ruby and JavaScript implementations)
Installation
uv tool install mdlint
# OR
pip install --user mdlint
# OR run directly
uvx mdlint -h
Requires Python 3.10 or later.
Usage
Lint files or directories
# Lint current directory
mdlint check
# Lint specific files
mdlint check README.md docs/guide.md
# Lint a directory recursively
mdlint check docs/
# Lint from stdin
cat README.md | mdlint check -
Output formats
# Human-readable output (default)
mdlint check docs/
# JSON output
mdlint check --format json docs/
Auto-fix violations
# Fix violations in-place
mdlint check --fix docs/
# Fix stdin and output result to stdout
cat README.md | mdlint check --fix -
Not all rules support auto-fixing. When --fix is used, fixable violations are corrected automatically and any
remaining unfixable violations are still reported. The rules index in the documentation indicates which rules are
fixable.
View rule documentation
# List all rules
mdlint rule
# View specific rule details
mdlint rule MD001
# Include valid/invalid examples
mdlint rule MD003 --show-examples
Rule compatibility matrix
The following table shows rule availability across mdlint and the
Ruby and
JavaScript markdownlint implementations. The rule behavior is mostly
consistent with that of the markdownlint projects (slight preference to the JavaScript implementation), but may differ
slightly over time as the project evolves.
| Rule(s) | mdlint | Ruby markdownlint | JS markdownlint | Notes |
|---|---|---|---|---|
| MD001 | ✓ | ✓ | ✓ | |
| MD002 | — | ✓ | — | Not implemented (use MD041) |
| MD003–MD005 | ✓ | ✓ | ✓ | |
| MD006 | — | ✓ | — | Not implemented (use MD007) |
| MD007 | ✓ | ✓ | ✓ | |
| MD008 | — | — | — | Not implemented |
| MD009–MD014 | ✓ | ✓ | ✓ | |
| MD015–MD017 | — | — | — | Not implemented |
| MD018–MD041 | ✓ | ✓ | ✓ | |
| MD042–MD045 | ✓ | — | ✓ | |
| MD046–MD047 | ✓ | ✓ | ✓ | |
| MD048–MD056 | ✓ | — | ✓ | |
| MD057 | — | — | — | Not implemented |
| MD058–MD060 | ✓ | — | ✓ |
Configuration
Configuration file
Create .mdlint.toml in your project root:
# Select specific rules to run (default: all rules)
select = ["MD001", "MD003", "MD041"]
# Ignore specific rules (subtracted from select)
ignore = ["MD041"]
# Rule-specific configuration
[rules.MD041]
level = 2 # Expect first heading to be h2
[rules.MD003]
style = "atx" # atx | atx_closed | setext | setext_with_atx | consistent
[rules.MD013]
line_length = 120
code_blocks = false
Or add to pyproject.toml:
[tool.mdlint]
ignore = ["MD041"]
[tool.mdlint.rules.MD003]
style = "atx"
Rule selection
The select and ignore options work together:
selectestablishes the baseline set of rules (defaults to all rules if omitted)ignoresubtracts from the select set
Examples:
# Run all rules except MD041
ignore = ["MD041"]
# Run only MD001 and MD003
select = ["MD001", "MD003"]
# Run MD001, MD003-MD005, but skip MD004
select = ["MD001", "MD003", "MD004", "MD005"]
ignore = ["MD004"] # Alternatively, omit from select list
Command-line options
# Use a specific config file
mdlint check --config path/to/config.toml
# Inline configuration
mdlint check --config "MD003.style='atx'"
# Select specific rules (replaces config select list)
mdlint check --select MD001 --select MD003
# Ignore specific rules (replaces config ignore list)
mdlint check --ignore MD002
# Add to existing select/ignore lists
mdlint check --extend-select MD004 --extend-ignore MD005
# Disable .gitignore and .ignore patterns
mdlint check --no-ignore
# Verbose output (show files being processed)
mdlint check --verbose
Exit codes
| Code | Meaning |
|---|---|
| 0 | No violations found |
| 1 | Violations found |
| 2 | Error occurred (file not found, invalid config, etc.) |
License
MIT
Metadata
Release files for mdlint 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mdlint-0.3.0.tar.gz | 81.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mdlint-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 208.8 kB
Release files / mdlint-0.3.0.tar.gz
| Download URL | mdlint-0.3.0.tar.gz |
|---|---|
| Size | 81.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a77e73f5a5e286193fd49c1c536d196a30d4313f07090f0c1e63224c9145c05b
|
|
BLAKE2b-256 checksum How to use checksums |
3e8aecbbdba71b390e2289619dfff8286ece8a558f7df87d8f9915901affe3e3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 7, 2026.
Transparency logRelease files / mdlint-0.3.0-py3-none-any.whl
| Download URL | mdlint-0.3.0-py3-none-any.whl |
|---|---|
| Size | 127.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c1ffaa5f332568a56da409bb04555e7d8ecb8bea221b14686f17ad7d3f6943b1
|
|
BLAKE2b-256 checksum How to use checksums |
b8df1130d3d89b41bf86baed898514f0bf023d20e63c135a16f2aa2c663cc21f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 7, 2026.
Transparency log