A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the
markdownlintlibrary
As a global CLI:
npm install markdownlint-cli2 --globalAs a development dependency of the current Node.js package:
npm install markdownlint-cli2 --save-devAs a Docker container image:
docker pull davidanson/markdownlint-cli2As a global CLI with Homebrew:
brew install markdownlint-cli2As a GitHub Action via
markdownlint-cli2-action:
- name: markdownlint-cli2-action
  uses: DavidAnson/markdownlint-cli2-action@v9- markdownlintis a library for linting Markdown/ CommonMark files on Node.js using the markdown-it parser.
- markdownlint-cliis a traditional command-line interface for- markdownlint.
- markdownlint-cli2is a slightly unconventional command-line interface for- markdownlint.
- markdownlint-cli2is configuration-based and prioritizes speed and simplicity.
- markdownlint-cli2supports all the features of- markdownlint-cli(sometimes a little differently).
- vscode-markdownlintis a- markdownlintextension for the Visual Studio Code editor.
- markdownlint-cli2is designed to work well in conjunction with- vscode-markdownlint.
- More about the motivation for markdownlint-cli2.
markdownlint-cli2 vX.Y.Z (markdownlint vX.Y.Z)
https://github.com/DavidAnson/markdownlint-cli2
Syntax: markdownlint-cli2 glob0 [glob1] [...] [globN] [--config file] [--fix] [--help]
Glob expressions (from the globby library):
- * matches any number of characters, but not /
- ? matches a single character, but not /
- ** matches any number of characters, including /
- {} allows for a comma-separated list of "or" expressions
- ! or # at the beginning of a pattern negate the match
- : at the beginning identifies a literal file path
- - as a glob represents standard input (stdin)
Dot-only glob:
- The command "markdownlint-cli2 ." would lint every file in the current directory tree which is probably not intended
- Instead, it is mapped to "markdownlint-cli2 *.{md,markdown}" which lints all Markdown files in the current directory
- To lint every file in the current directory tree, the command "markdownlint-cli2 **" can be used instead
Optional parameters:
- --config    specifies the path to a configuration file to define the base configuration
- --fix       updates files to resolve fixable issues (can be overridden in configuration)
- --help      writes this message to the console and exits without doing anything else
- --no-globs  ignores the "globs" property if present in the top-level options object
Configuration via:
- .markdownlint-cli2.jsonc
- .markdownlint-cli2.yaml
- .markdownlint-cli2.cjs or .markdownlint-cli2.mjs
- .markdownlint.jsonc or .markdownlint.json
- .markdownlint.yaml or .markdownlint.yml
- .markdownlint.cjs or .markdownlint.mjs
- package.json
Cross-platform compatibility:
- UNIX and Windows shells expand globs according to different rules; quoting arguments is recommended
- Some Windows shells don't handle single-quoted (') arguments well; double-quote (") is recommended
- Shells that expand globs do not support negated patterns (!node_modules); quoting is required here
- Some UNIX shells parse exclamation (!) in double-quotes; hashtag (#) is recommended in these cases
- The path separator is forward slash (/) on all platforms; backslash (\) is automatically converted
- On any platform, passing the parameter "--" causes all remaining parameters to be treated literally
The most compatible syntax for cross-platform support:
$ markdownlint-cli2 "**/*.md" "#node_modules"
For scenarios where it is preferable to specify glob expressions in a
configuration file, the globs property of .markdownlint-cli2.jsonc, .yaml,
.cjs, or .mjs may be used instead of (or in addition to) passing
glob0 ... globN on the command-line.
As shown above, a typical command-line for markdownlint-cli2 looks something
like:
markdownlint-cli2 "**/*.md" "#node_modules"Because sharing the same configuration between "normal" and "fix" modes is
common, the --fix argument can be used to default the fix property (see
below) to true (though it can still be overridden by a configuration file):
markdownlint-cli2 --fix "**/*.md" "#node_modules"In cases where it is not convenient to store a configuration file in the root
of a project, the --config argument can be used to provide a path to any
supported configuration file (except package.json):
markdownlint-cli2 --config "config/.markdownlint-cli2.jsonc" "**/*.md" "#node_modules"The configuration file name must be (or end with) one of the supported names
above. For example, .markdownlint.json or example.markdownlint-cli2.jsonc.
The specified configuration file will be loaded, parsed, and applied as a base
configuration for the current directory - which will then be handled normally.
A container image davidanson/markdownlint-cli2
can also be used (e.g., as part of a CI pipeline):
docker run -v $PWD:/workdir davidanson/markdownlint-cli2:v0.15.0 "**/*.md" "#node_modules"Notes:
- As when using the command line, glob patterns are passed as arguments.
- This image is built on the official Node.js Docker image.
Per security best practices, the default user noderuns with restricted permissions. If it is necessary to run asroot, pass the-u rootoption when invokingdocker.
- By default, markdownlint-cli2will execute within the/workdirdirectory inside the container. So, as shown above, bind mount the project's directory there.- 
A custom working directory can be specified with Docker's -wflag:docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:v0.15.0 "**/*.md" "#node_modules" 
 
- 
For convenience, the container image
davidanson/markdownlint-cli2-rules
includes the latest versions of custom rules published to npm with the tag
markdownlint-rule. These rules are installed globally
onto the base image davidanson/markdownlint-cli2.
Note: This container image exists for convenience and is not an endorsement of the rules within.
- 0: Linting was successful and there were no errors
- 1: Linting was successful and there were errors
- 2: Linting was not completed due to a runtime issue
- See the Rules / Aliases and
Tags sections of the markdownlintdocumentation.
- Globbing is performed by the globby library; refer to that documentation for more information and examples.
- See the Configuration section of the
markdownlintdocumentation for information about the inline comment syntax for enabling and disabling rules with HTML comments.
- In general, glob expressions should match files under the current directory;
the configuration for that directory will apply to the entire tree.
- When glob expressions match files not under the current directory, configuration for the current directory is applied to the closest common parent directory.
 
- Paths beginning with ~are resolved relative to the user's home directory (typically$HOMEon UNIX and%USERPROFILE%on Windows)
- There are two kinds of configuration file (both detailed below):
- Configuration files like .markdownlint-cli2.*allow complete control ofmarkdownlint-cli2behavior and are also used byvscode-markdownlint.- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
- .markdownlint-cli2.jsonc
- .markdownlint-cli2.yaml
- .markdownlint-cli2.cjs
- .markdownlint-cli2.mjs
- package.json(only supported in the current directory)
 
 
- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
- Configuration files like .markdownlint.*allow control over only themarkdownlintconfigobject and tend to be supported more broadly (such as bymarkdownlint-cli).- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
- .markdownlint.jsonc
- .markdownlint.json
- .markdownlint.yaml
- .markdownlint.yml
- .markdownlint.cjs
- .markdownlint.mjs
 
 
- If multiple of these files are present in the same directory, only one is
used according to the following precedence:
 
- Configuration files like 
- The VS Code extension includes a JSON Schema definition for the
JSON(C)configuration files described below. This adds auto-complete and can make it easier to define proper structure.
- See markdownlint-cli2-config-schema.json for that schema and ValidatingConfiguration.md for ways to use it to validate configuration files.
- The format of this file is a JSONC object similar to the
markdownlintoptionsobject.
- Valid properties are:
- config:- markdownlint- configobject to configure rules for this part of the directory tree- If a .markdownlint.{jsonc,json,yaml,yml,js}file (see below) is present in the same directory, it overrides the value of this property
- If the configobject contains anextendsproperty, it will be resolved the same as.markdownlint.{jsonc,json,yaml,yml,js}(see below)
 
- If a 
- customRules:- Arrayof- Strings (or- Arrays of- Strings) of module names/paths of custom rules to load and use when linting- Relative paths are resolved based on the location of the JSONCfile
- Search markdownlint-ruleon npm
 
- Relative paths are resolved based on the location of the 
- fix:- Booleanvalue to enable fixing of linting errors reported by rules that emit fix information- Fixes are made directly to the relevant file(s); no backup is created
 
- frontMatter:- Stringdefining the- RegExpused to match and ignore any front matter at the beginning of a document- The Stringis passed as thepatternparameter to theRegExpconstructor
- For example: (^---\s*$[^]*?^---\s*$)(\r\n|\r|\n|$)
 
- The 
- gitignore:- Booleanor- Stringvalue to automatically ignore files referenced by- .gitignore(or similar) when linting- When the value trueis specified, all.gitignorefiles in the tree are imported (defaultgitbehavior)
- When a Stringvalue is specified, that glob pattern is used to identify the set of ignore files to import- The value **/.gitignorecorresponds to theBooleanvaluetrue
- The value .gitignoreimports only the file in the root of the tree; this is usually equivalent and can be much faster for large trees
 
- The value 
- This top-level setting is valid only in the directory from which
markdownlint-cli2is run
 
- When the value 
- globs:- Arrayof- Strings defining glob expressions to append to the command-line arguments- This setting can be used instead of (or in addition to) passing globs on the command-line and offers identical performance
- This setting is ignored when the --no-globsparameter is passed on the command-line
- This top-level setting is valid only in the directory from which
markdownlint-cli2is run
 
- ignores:- Arrayof- Strings defining glob expressions to ignore when linting- This setting has the best performance when applied to the directory from
which markdownlint-cli2is run- In this case, glob expressions are negated (by adding a leading !) and appended to the command-line arguments before file enumeration
- The setting is not inherited by nested configuration files in this case
 
- In this case, glob expressions are negated (by adding a leading 
- When this setting is applied in subdirectories, ignoring of files is done
after file enumeration, so large directories can negatively impact
performance
- Nested configuration files inherit and reapply the setting to the contents of nested directories in this case
 
 
- This setting has the best performance when applied to the directory from
which 
- markdownItPlugins:- Arrayof- Arrays, each of which has a- Stringnaming a markdown-it plugin followed by parameters- Plugins can be used to add support for additional Markdown syntax
- Relative paths are resolved based on the location of the JSONCfile
- For example: [ [ "plugin-name", param_0, param_1, ... ], ... ]
- Search markdown-it-pluginson npm
 
- modulePaths:- Arrayof- Strings providing additional paths to use when resolving module references (e.g., alternate locations for- node_modules)
- noBanner:- Booleanvalue to disable the display of the banner message and version numbers on- stdout- This top-level setting is valid only in the directory from which
markdownlint-cli2is run
 
- This top-level setting is valid only in the directory from which
- noInlineConfig:- Booleanvalue to disable the support of HTML comments within Markdown content- For example: <!-- markdownlint-disable some-rule -->
 
- For example: 
- noProgress:- Booleanvalue to disable the display of progress on- stdout- This top-level setting is valid only in the directory from which
markdownlint-cli2is run
 
- This top-level setting is valid only in the directory from which
- outputFormatters:- Arrayof- Arrays, each of which has a- Stringnaming an output formatter followed by parameters- Formatters can be used to customize the tool's output for different scenarios
- Relative paths are resolved based on the location of the JSONCfile
- For example: [ [ "formatter-name", param_0, param_1, ... ], ... ]
- This top-level setting is valid only in the directory from which
markdownlint-cli2is run
- Search markdownlint-cli2-formatteron npm
 
- showFound:- Booleanvalue to display the list of found files on- stdout- This top-level setting is valid only in the directory from which
markdownlint-cli2is run and only whennoProgresshas not been set
 
- This top-level setting is valid only in the directory from which
 
- When referencing a module via the customRules,markdownItPlugins, oroutputFormattersproperties, eachStringidentifier is passed to Node'srequirefunction then (if that failed) itsimportexpression- Importing a locally-installed module using a bare specifier (ex:
package-name) or using a directory name (ex:./package-dir) will not work untilimport.meta.resolveis available
 
- Importing a locally-installed module using a bare specifier (ex:
- Settings in this file apply to the directory it is in and all subdirectories.
- Settings merge with those applied by any versions of this file in a parent directory (up to the current directory).
- For example: .markdownlint-cli2.jsoncwith all properties set
- The format of this file is a YAML object with the structure described
above for .markdownlint-cli2.jsonc.
- Other details are the same as for .markdownlint-cli2.jsoncdescribed above.
- For example: .markdownlint-cli2.yamlwith all properties set
- The format of this file is a CommonJS module (.cjs) or ECMAScript module (.mjs) that exports the object described above for.markdownlint-cli2.jsonc(directly or from aPromise).
- Instead of passing a Stringto identify the module name/path to load forcustomRules,markdownItPlugins, andoutputFormatters, the correspondingObjectorFunctioncan be provided directly.
- Other details are the same as for .markdownlint-cli2.jsoncdescribed above.
- For example: .markdownlint-cli2.cjsor.markdownlint-cli2.mjs
- The format of this file is a standard npm package.jsonfile including amarkdownlint-cli2property at the root and a value corresponding to the object described above for.markdownlint-cli2.jsonc.
- package.jsonis only supported in the current directory.
- package.jsonis not supported by the- --configargument.
- For example: package-json-sample
- The format of this file is a JSONC or JSON object matching
the markdownlintconfigobject.
- Settings in this file apply to the directory it is in and all subdirectories
- Settings override those applied by any versions of this file in a parent directory (up to the current directory).
- To merge the settings of these files or share configuration, use the extendsproperty (documented in the link above).
- Both file types support comments in JSON.
- For example: .markdownlint.jsonc
- The format of this file is a YAML object representing the
markdownlintconfigobject.
- Other details are the same as for jsonc/jsonfiles described above.
- For example: .markdownlint.yaml
- The format of this file is a CommonJS module (.cjs) or ECMAScript module (.mjs) that exports themarkdownlintconfigobject (directly or from aPromise).
- Other details are the same as for jsonc/jsonfiles described above.
- For example: .markdownlint.cjsor.markdownlint.mjs
- The glob implementation and handling of pattern matching is slightly different.
- Configuration files are supported in every directory (vs. only one at the root).
- The INIconfig format,.markdownlintrc, and.markdownlintignoreare not supported.
- .markdownlintignoreis not supported.
To run markdownlint-cli2 as part of a pre-commit workflow, add a
reference to the repos list in that project's .pre-commit-config.yaml like:
- repo: https://github.com/DavidAnson/markdownlint-cli2
  rev: v0.15.0
  hooks:
  - id: markdownlint-cli2Depending on the environment that workflow runs in, it may be necessary to override the version of Node.js used by pre-commit.
See CHANGELOG.md.