markdownlint: Lint Markdown Docs in CI
markdownlint checks Markdown files against MDxxx style rules and exits 1 when any file violates an enabled rule.
markdownlint keeps docs consistent (heading levels, list style, line length). In CI you run markdownlint-cli over the docs and gate on the exit code.
What it does
markdownlint (the markdownlint-cli binary) takes file globs, loads its config, and reports MDxxx violations with the rule name. It exits 1 when violations are found, 0 when clean. --fix corrects the rules that support automatic fixing.
Common usage
npx markdownlint "**/*.md"
# autofix what can be fixed
npx markdownlint --fix "docs/**/*.md"
# explicit config and ignore
npx markdownlint -c .markdownlint.json --ignore node_modules "**/*.md"Flags
| Flag | What it does |
|---|---|
| "<glob>" | Markdown files to lint |
| --fix | Apply automatic fixes in place |
| -c, --config <file> | Use a specific config file |
| --ignore <path> | Skip a file or glob (repeatable) |
| --ignore-path <file> | Read ignores from a file (.markdownlintignore) |
| -o, --output <file> | Write results to a file |
In CI
There are two CLIs: markdownlint-cli (command markdownlint) and markdownlint-cli2 (markdownlint-cli2, config-driven, faster). Pick one and pin it; their config discovery differs. Run --fix in a separate commit job, not the gate.
Common errors in CI
"MD013/line-length Line length" is the most frequent failure; raise or disable MD013 for prose. "MD040/fenced-code-language Fenced code blocks should have a language specified" flags ``` blocks with no language. "MD041/first-line-heading" fires when a file does not start with a top-level heading.