Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/remarkjs/remark/llms.txt

Use this file to discover all available pages before exploring further.

Inconsistent markdown is a common source of friction in collaborative projects. Authors mix emphasis markers (* vs _), ordered list styles (. vs )), and may omit final newlines — issues that are invisible when rendered but create noisy diffs and make automated processing less predictable. remark-lint is a remark plugin that reports these inconsistencies as structured warnings attached to the virtual file, letting you enforce a consistent style programmatically or from the command line.

How remark-lint works

remark-lint is not a standalone tool — it is a collection of individual rule plugins that plug into the remark pipeline. Each rule checks one aspect of markdown style and attaches warning messages to the vfile when it finds a violation. After processing, you pass the file through vfile-reporter to produce human-readable output. Rather than installing individual rules one by one, it is practical to start with a preset: a curated bundle of rules with opinionated defaults.

Lint presets

Three official presets cover the most common needs:
PresetPurpose
remark-preset-lint-consistentEnforces internal consistency — e.g., the emphasis marker you use first becomes the required marker for the rest of the document
remark-preset-lint-recommendedA small set of rules representing broadly agreed best practices
remark-preset-lint-markdown-style-guideA thorough style guide with opinions about every aspect of markdown formatting
You can use multiple presets together. They compose cleanly because each rule only fires when it detects a real violation.

Linting programmatically

Install the presets and the reporter:
npm install remark remark-preset-lint-consistent remark-preset-lint-recommended vfile-reporter
Then run the linter in a script:
import {remark} from 'remark'
import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
import {reporter} from 'vfile-reporter'

const file = await remark()
  .use(remarkPresetLintConsistent)
  .use(remarkPresetLintRecommended)
  .process('1) Hello, _Jupiter_ and *Neptune*!')

console.error(reporter(file))
This produces the following output:
1:2           warning Unexpected ordered list marker `)`, expected `.`                                     ordered-list-marker-style remark-lint
1:25-1:34     warning Unexpected emphasis marker `*`, expected `_`                                         emphasis-marker           remark-lint
  [cause]:
    1:11-1:20 info    Emphasis marker style `'_'` first defined for `'consistent'` here                    emphasis-marker           remark-lint
1:35          warning Unexpected missing final newline character, expected line feed (`\n`) at end of file final-newline             remark-lint

⚠ 3 warnings
Three issues are caught: the ) list marker should be ., the * emphasis marker should be _ (to match the _ used earlier in the same document — remark-preset-lint-consistent records where the first style was established and reports it as a [cause]), and the file is missing a trailing newline.

Linting files with remark-cli

For checking markdown files in a project, remark-cli is the right tool. It accepts glob patterns, loads configuration from your project, and exits with a non-zero code when issues are found — making it suitable for CI pipelines.
1
Install the CLI and presets
2
npm install --save-dev remark-cli remark-preset-lint-consistent remark-preset-lint-recommended
3
Run the linter from the command line
4
Check all markdown files in the current directory:
5
remark --use remark-preset-lint-consistent --use remark-preset-lint-recommended .
6
Add an npm script
7
For convenience, add a script to your package.json:
8
{
  "scripts": {
    "lint:md": "remark . --frail"
  }
}
9
Then run it with:
10
npm run lint:md
11
Configure remark in package.json
12
Rather than passing plugins as CLI flags every time, add a remarkConfig field to your package.json to keep the configuration in one place:
13
{
  "remarkConfig": {
    "plugins": [
      "remark-preset-lint-consistent",
      "remark-preset-lint-recommended"
    ]
  }
}
14
With this in place, running remark . or npm run lint:md automatically picks up the configuration.
Pass the --frail flag to remark-cli so that the process exits with code 1 when any warnings are reported. Without --frail, warnings are printed but the exit code remains 0, which means CI checks will pass even when lint violations exist.

Configuration files

For larger projects, or when you need comments in your configuration, you can store remark configuration in a separate file instead of package.json. remark-cli searches upward from each processed file and supports several formats. Here is the equivalent JavaScript configuration in .remarkrc.js:
import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'

const remarkConfig = {
  plugins: [
    remarkPresetLintConsistent,
    remarkPresetLintRecommended
  ]
}

export default remarkConfig
Or in YAML as .remarkrc.yml:
plugins:
  - remark-preset-lint-consistent
  - remark-preset-lint-recommended
The supported configuration file formats in order of precedence are: .remarkrc, .remarkrc.cjs, .remarkrc.json, .remarkrc.js, .remarkrc.mjs, .remarkrc.yaml, .remarkrc.yml, and the remarkConfig field in package.json.

Formatting markdown automatically

remark-lint reports issues, but remark can also fix many style inconsistencies automatically by re-serializing the file through remark-stringify. Add --output to the CLI command to rewrite files in place:
remark . --output
This is useful for initial adoption of a style guide — you can auto-format all existing files in one pass, then enforce the rules going forward with the linter in CI.

Next steps

Creating Plugins

Write custom lint rules or transformations as remark plugins.

Security

Understand the security implications of processing untrusted markdown.

Build docs developers (and LLMs) love