← Back to DevBytes

Markdownlint: Complete Configuration Guide

What is Markdownlint?

markdownlint is a linter for Markdown files that enforces specific formatting and syntax rules. It checks your Markdown content against a set of predefined rules, each identified by a unique code like MD001 or MD041. The tool is available as a Node.js library (markdownlint), a command-line interface (markdownlint-cli), and a faster alternative CLI (markdownlint-cli2). Editor integrations such as the VS Code extension make it possible to see violations directly in your workspace. The goal is not to impose a single “correct” style, but to help teams maintain consistency, avoid broken syntax, and keep documentation clean and readable.

Why Markdown Linting Matters

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

Markdown is often used for technical documentation, README files, wikis, and blog posts. Without a linter, small inconsistencies can creep in — double‑spacing after headings, mixed bullet styles, broken links, or raw HTML that could break rendering in some contexts. A linter brings several benefits:

Getting Started with Markdownlint

The quickest way to get started is with markdownlint-cli. You can install it globally or as a dev dependency in a Node.js project.

# Install globally
npm install -g markdownlint-cli

# Or add to a project
npm install --save-dev markdownlint-cli

Using markdownlint-cli

Lint all Markdown files in the current directory recursively:

markdownlint '**/*.md'

Lint a single file and see the output:

markdownlint README.md

If there are violations, the CLI prints file, line, rule code, and a description. For example:

README.md:3:1 MD002 First header should be a h1 header
README.md:10 MD009 Trailing spaces
README.md:15:1 MD032 Lists should be surrounded by blank lines

You can also use the --config flag to point to a configuration file:

markdownlint -c .markdownlint.json 'docs/**/*.md'

Using markdownlint as a Library

For custom tooling, you can use the markdownlint package directly. It provides synchronous and asynchronous APIs.

const markdownlint = require('markdownlint');

const options = {
  files: ['README.md'],
  config: {
    default: true,
    MD013: false, // disable line length rule
  },
};

markdownlint(options, (err, result) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(JSON.stringify(result, null, 2));
});

The result object contains arrays of violations per file, making it easy to integrate with build scripts or reporting tools.

Configuration Files

Configuration tells markdownlint which rules to enable/disable and how to tune them. The configuration file can be in JSON, YAML, or even placed inside package.json under a markdownlint key. By default the CLI looks for .markdownlint.json, .markdownlint.yaml, .markdownlint.yml, or .markdownlintrc (in that order). You can also specify a custom path with -c.

Example .markdownlint.json

{
  "default": true,
  "MD001": false,
  "MD013": {
    "line_length": 120,
    "heading_line_length": 80,
    "code_block_line_length": 120
  },
  "MD024": {
    "siblings_only": true
  },
  "MD033": false,
  "MD041": false
}

Explanation: "default": true enables all rules except those explicitly disabled. MD001 (heading‑increment) is turned off entirely. MD013 (line‑length) is customized to allow up to 120 characters, with separate limits for headings and code blocks. MD024 (duplicate headings) is set to only flag duplicates at the same level as siblings. MD033 (inline HTML) and MD041 (first line heading) are disabled.

Using YAML Configuration

# .markdownlint.yaml
default: true
MD001: false
MD013:
  line_length: 120
  heading_line_length: 80
  code_block_line_length: 120
MD024:
  siblings_only: true
MD033: false
MD041: false

YAML is often preferred for its readability and ability to include comments.

Disabling Rules Inline

Sometimes you need to suppress a rule for a specific section. Use HTML comments with markdownlint-disable:

Text that triggers a rule...

This paragraph has trailing spaces and raw html without complaint.

Normal linting resumes.

You can also disable all rules temporarily with <!-- markdownlint-disable --> and re-enable with <!-- markdownlint-enable -->. This is useful for auto‑generated content or edge cases.

Common Rules and Customization

Here are some of the most frequently encountered rules and how to configure them.

Configuring Rule Options

Many rules accept an object with parameters. Here is an example that tunes several rules:

{
  "MD007": { "indent": 4 },
  "MD013": {
    "line_length": 100,
    "code_block_line_length": 100,
    "tables": false
  },
  "MD022": { "lines_above": 2, "lines_below": 1 },
  "MD026": { "punctuation": ".,;:!?" },
  "MD030": { "ol_single": 2, "ol_multi": 1, "ul_single": 2, "ul_multi": 1 },
  "MD035": { "style": "---" }
}

Always consult the official rule documentation for the exact parameter names and defaults.

Integrating with Editors and CI/CD

Real‑time feedback while writing is invaluable. The VS Code extension (davidanson.vscode-markdownlint) uses the same engine and configuration. After installing the extension, create a .markdownlint.json in your workspace root. The extension will pick it up automatically and underline violations in the editor.

For CI/CD pipelines, add a lint step to your build script:

# In package.json scripts
"scripts": {
  "lint:markdown": "markdownlint '**/*.md' -c .markdownlint.json"
}

Then run it as part of your pipeline:

npm run lint:markdown

Most CI services (GitHub Actions, GitLab CI, Jenkins) will treat a non‑zero exit code as a failure, blocking the merge.

Setting Up a Pre-commit Hook

To prevent un‑linted files from being committed, use lint-staged together with husky:

// package.json (or .lintstagedrc.json)
{
  "lint-staged": {
    "*.md": [
      "markdownlint -c .markdownlint.json"
    ]
  }
}

Then register a pre‑commit hook with husky:

npx husky add .husky/pre-commit "npx lint-staged"

Now every commit will automatically lint staged Markdown files and abort if violations are found.

Best Practices

Conclusion

markdownlint turns Markdown style guidelines into an automated, enforceable system. With a single configuration file you can define exactly how headings, lists, whitespace, and other elements should behave. The tool fits naturally into local editors, pre‑commit hooks, and CI/CD pipelines, giving you a consistent documentation experience across your entire team. Start with the default rules, tune the ones that conflict with your existing style, and commit the configuration file – you’ll immediately see cleaner, more maintainable Markdown across your project.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles