Carles Andres' avatarHomeBlogReference
Back to reference

Validate your Markdown files with markdownlint

This is a reference article.
Reference articles are written with the help of AI agents, after we have managed to solve a problem.

TL;DR

  • Use markdownlint-cli2 to lint Markdown from the CLI.
  • Put global rules in a root .markdownlint.json.
  • For folder-specific exceptions, add a nested .markdownlint.json that extends the root config.

Why lint Markdown

Linting Markdown helps teams agree on a baseline style without micromanaging every doc. It also surfaces structural issues (like missing top-level headings) in the editor, so fixes happen while you write instead of during reviews.

The markdownlint tool

markdownlint is the rule engine and markdownlint-cli2 is the config-driven CLI that runs it. There are many rules (for example MD013 and MD041), and the goal is to set a sensible baseline, then tune only what does not fit your content.

Useful references:

Install and run in a project:

If you use Neovim, you can install a markdownlint binary via Mason so your editor tooling can run the linter locally. Pick the package that matches your setup (for example, markdownlint or markdownlint-cli2), then wire it into your linting plugin.

Global rules and folder-specific overrides

Start with global rules in a root .markdownlint.json so the whole repository has a consistent baseline:

For folder-specific behaviour, add a nested config file and extends the root config. This is the reliable approach when a rule should only be relaxed in one area:

In this example, command docs can skip MD041 (first line should be a top-level heading), while the rest of the project keeps stricter defaults.

Example layout for folder-specific rules with nested .markdownlint.json files:

The nested config inherits the root rules via extends (see the example snippet above), then overrides just the rules that don't apply to that folder.

Note: overrides is not a valid key in .markdownlint.json. If you need top-level CLI options such as globs, ignores, or gitignore, use a .markdownlint-cli2.* config instead.