Skip to content

Migrating from markdownlint

crackdown ships a built-in migration tool that reads your .markdownlintrc and generates a ready-to-use crackdown.config.ts with all supported rules pre-wired.

Automatic migration

Terminal window
crackdown migrate .markdownlintrc

This command:

  1. Reads your existing config file.
  2. Maps each enabled rule to its crackdown equivalent.
  3. Writes crackdown.config.ts alongside the config file.
  4. Prints a report with ✓ supported and ✗ unsupported rules.

Rule mapping reference

18 markdownlint rules are supported. crackdown migrate maps all of them automatically.

markdownlint ruleStatuscrackdown equivalentPackage
MD001 (heading-increment)md001Rule@crackdown/compat-markdownlint
MD005 (list-indent)md005Rule@crackdown/compat-markdownlint
MD007 (unordered-list-indent)md007Rule (configurable indent, default 2)@crackdown/compat-markdownlint
MD009 (trailing-spaces)md009Rule + md009Fixer@crackdown/core
MD010 (no-hard-tabs)md010Rule + md010Fixer@crackdown/core
MD012 (multiple-blank-lines)md012Rule + md012Fixer@crackdown/compat-markdownlint
MD013 (line-length)md013Rule (configurable lineLength, default 80)@crackdown/compat-markdownlint
MD022 (blanks-around-headings)md022Rule@crackdown/compat-markdownlint
MD024 (no-duplicate-headings)md024Rule@crackdown/compat-markdownlint
MD025 (single-top-level-heading)md025Rule@crackdown/compat-markdownlint
MD026 (trailing-punctuation)md026Rule@crackdown/compat-markdownlint
MD031 (blanks-around-fences)md031Rule@crackdown/compat-markdownlint
MD032 (blanks-around-lists)md032Rule@crackdown/compat-markdownlint
MD033 (no-inline-html)md033Rule@crackdown/compat-markdownlint
MD034 (no-bare-urls)md034Rule@crackdown/compat-markdownlint
MD040 (fenced-code-language)md040Rule@crackdown/compat-markdownlint
MD041 (first-line-heading)md041Rule@crackdown/compat-markdownlint
MD047 (single-trailing-newline)md047Rule + md047Fixer@crackdown/compat-markdownlint
MD003 (heading-style)❌ Not yet implemented
MD036 (no-emphasis-as-heading)❌ Not yet implemented

Manual migration

If you prefer to set up manually:

Terminal window
pnpm add -D @crackdown/core @crackdown/cli @crackdown/compat-markdownlint

Create crackdown.config.ts:

import {
md001Rule,
md012Rule, md012Fixer,
md013Rule,
md022Rule,
md024Rule,
md025Rule,
md031Rule,
md040Rule,
md041Rule,
md047Rule, md047Fixer,
} from '@crackdown/compat-markdownlint'
import { md009Rule, md009Fixer, md010Rule, md010Fixer } from '@crackdown/core'
import type { MarkyConfig } from '@crackdown/core'
const config: MarkyConfig = {
plugins: [
md001Rule, // heading levels increment by 1
md009Rule, // no trailing spaces
md010Rule, // no hard tabs
md012Rule, // no multiple consecutive blank lines
md013Rule, // line length ≤ 80
md022Rule, // blank lines around headings
md024Rule, // no duplicate heading text
md025Rule, // single top-level heading
md031Rule, // blank lines around fenced code blocks
md040Rule, // fenced code blocks have a language
md041Rule, // first line must be a heading
md047Rule, // file ends with a newline
],
fixers: [
md009Fixer, // strip trailing spaces
md010Fixer, // replace tabs with spaces
md012Fixer, // collapse multiple blank lines
// (c) => md010Fixer(c, { tabSize: 2 }), // custom tab size
md047Fixer, // append trailing newline
],
}
export default config

Configuring line length (MD013)

The default line length is 80 characters. Use the [rule, options] tuple to configure it:

import { md013Rule } from '@crackdown/compat-markdownlint'
const config: MarkyConfig = {
plugins: [
[md013Rule, { lineLength: 120 }],
],
}

Configuring rule severity

Use config.rules to override severity per rule ID:

const config: MarkyConfig = {
plugins: [md013Rule],
rules: {
'remark-lint:maximum-line-length': 'error', // upgrade to error
'crackdown:no-trailing-spaces': 'off', // disable entirely
},
}

Rule IDs follow the pattern <source>:<rule-name> as shown in crackdown lint output.

Loading .markdownlintrc at runtime

You can also load an existing .markdownlintrc programmatically:

import { loadMarkdownlintConfig } from '@crackdown/compat-markdownlint'
import { lint } from '@crackdown/core'
const config = await loadMarkdownlintConfig(process.cwd())
const results = await lint(['README.md'], config)

This is useful for tools that wrap crackdown and want to respect an existing markdownlint config.