MD013 - Keep lines short for better readability¶
Aliases: line-length
What this rule does¶
Checks that lines don't exceed a maximum length to ensure your content is easy to read on all devices.
Why this matters¶
- Improves readability: Shorter lines are easier to scan and understand quickly
- Works everywhere: Content displays properly on mobile devices, terminals, and narrow windows
- Better for code reviews: Side-by-side comparisons work better with reasonable line lengths
- Accessibility: Screen readers and assistive technologies handle shorter lines more effectively
Examples¶
✅ Correct¶
This line is a reasonable length that's easy to read
and displays well on all devices.
Even with links, you can keep lines manageable by using
[reference-style links][1] instead of inline URLs.
[1]: https://example.com/very-long-url-that-would-make-the-line-too-long
❌ Incorrect¶
This is an extremely long line that goes on and on and makes it difficult to read the content, especially on mobile devices or when viewing files in split-screen editors or during code reviews where horizontal space is limited.
🔧 Fixed¶
This is a line that has been wrapped to stay within
the maximum length, making it much easier to read
and work with in various contexts.
Configuration¶
[MD013]
line-length = 100 # Maximum characters per line (default: 80)
code-blocks = false # Don't check code blocks (default: true)
code-spans = false # Don't flag lines whose only overflow is an unbreakable inline code span (default: true)
tables = false # Don't check tables (default: false)
headings = true # Check headings (default: true)
paragraphs = true # Check paragraph/regular text (default: true)
blockquotes = true # Check blockquote content (default: true)
strict = false # Disables exceptions for URLs, etc. (default: false)
stern = false # Like strict, but unwrappable single-token lines are still permitted (default: false)
ignore-link-urls = true # Ignore inline link/image URLs when measuring line length (default: true)
heading-line-length = 100 # Optional per-context limit for headings; falls back to line-length when unset
code-block-line-length = 120 # Optional per-context limit for code blocks; falls back to line-length when unset
reflow = false # Enable automatic text reflow/wrapping (default: false)
reflow-mode = "default" # Reflow mode: "default", "normalize", "sentence-per-line", or "semantic-line-breaks" (default: "default")
length-mode = "visual" # How to count line length: "visual", "chars", or "bytes" (default: "visual")
abbreviations = ["Assn", "Univ"] # Add custom abbreviations for sentence-per-line mode
require-sentence-capital = true # Require uppercase after periods for sentence detection (default: true)
atomic-spans = true # Treat code/emphasis spans as atomic units during reflow (default: true)
Configuration options explained¶
line-length: The maximum number of characters allowed per line (set to0to disable all line length checks)code-blocks: Whether to check line length in code blocks (default:true)code-spans: Whether to check lines whose length comes from an inline code span (default:true). Inline code spans (`like this`) cannot be wrapped, so reflow cannot shorten a line whose excess length is one. Whenfalse, a line is not reported if it would fit within the limit once its inline code spans are excluded - useful withreflowso an unbreakable code incantation does not fail an otherwise-clean filetables: Whether to check line length in tables (default:false)headings: Whether to check line length in headings (default:true)paragraphs: Whether to check line length in regular text/paragraphs (default:true). When false,line-lengthis still used for reflow but no warnings are reported. Blockquote content is treated as paragraph text, soparagraphs = falsealso skips blockquotesblockquotes: Whether to check line length in blockquote content (default:true). Set tofalseto skip blockquote lines specifically without disabling all paragraph checksstrict: When true, disables exceptions for URLs and other special content (default:false). Overridesstern.stern: Tighter than the default but laxer than strict. Disables the trailing-token forgiveness used in default mode (so a line is flagged even when only the final token spills past the limit), but keeps the "unwrappable line" exemption — lines that consist of a single non-whitespace token, optionally prefixed by#heading or>blockquote markers, are still permitted (default:false). Mirrors markdownlint'ssternoption.ignore-link-urls: Whether to forgive a line that exceeds the limit only because of the URL inside an inline[text](url)/(default:true; see Ignoring inline link URLs). Set tofalseto count those URLs toward the line length. Combined withstern, this flags a link line that has wrappable text around it while still exempting a line that is a single unbreakable token (a bare URL or a standalone link): stricter thansternabout links, but withoutstrictflagging genuinely unbreakable link lines. Has no effect understrict(which already disables all forgiveness). The former keysemantic-link-understandingis still accepted as an alias.heading-line-length: Per-context maximum length for heading lines. Unset (null) falls back toline-length;0means "no limit for headings". Mirrors markdownlint'sheading_line_lengthoption.code-block-line-length: Per-context maximum length for fenced or indented code-block lines. Unset (null) falls back toline-length;0means "no limit for code blocks". Mirrors markdownlint'scode_block_line_lengthoption.reflow: When true, enables automatic text reflow to wrap long lines intelligently (default:false)reflow-mode: Controls how text is reflowed whenreflowis true (default:"default", see Reflow Modes section below)length-mode: How to calculate line length (default:"visual"):"visual": Count visual display width (emoji = 2 columns, CJK = 2 columns). Recommended and default. Correctly handles international content and matches terminal display."chars": Count Unicode characters (emoji = 1, CJK = 1). Use only for backward compatibility."bytes": Count raw UTF-8 bytes (not recommended for Unicode text).abbreviations: Custom abbreviations for sentence-per-line mode (optional)- Periods are optional: both
"Dr"and"Dr."work the same - Added to built-in defaults:
Mr,Mrs,Ms,Dr,Prof,Sr,Jr,i.e,e.g,vs,fig,no,vol,ch,sec,al require-sentence-capital: Whether to require uppercase after periods for sentence boundary detection (default:true)- When
true, onlyword. Capitalis treated as a sentence boundary (fewer false positives) - When
false,word. lowercaseis also treated as a sentence boundary (more splitting) - Does not affect
!and?which are always treated as sentence boundaries atomic-spans: Whether to hold emphasis/strong/strikethrough and code spans atomic during reflow (default:true). Whentrue, these spans are treated as atomic units. Whenfalse, they can be wrapped word-by-word like normal text. Note that if an emphasis span contains a nested code span, the emphasis span is kept atomic to prevent formatting corruption.
Ignoring inline link URLs (non-strict mode)¶
In non-strict mode, this rule understands that inline links and images often contain
long URLs that the author cannot reasonably shorten. When a line exceeds the limit,
the rule checks whether replacing each [text](url) with just [text] (and
 with ![alt]) would bring the line within the limit. If so, the
warning is suppressed.
This applies to:
- Inline links:
[text](url)and[text](url "title") - Inline images:
 - Nested badge patterns:
[](link-url)
This does not apply to:
- Reference links (
[text][ref]) — these already have no inline URL - Autolinks (
<url>) — the URL itself is the visible content - Strict mode — all exceptions are disabled
ignore-link-urls = false: count inline link/image URLs toward the line length. Withstern, this flags a link line that has wrappable text around it, while a line that is a single unbreakable token (a bare URL or a standalone link) is still permitted by stern's unwrappable-line exemption.
Example¶
With line-length = 80:
<!-- No warning: text without URLs is only ~30 chars -->
See the [installation guide](https://example.com/docs/getting-started/installation/v2) for details.
<!-- Warning: text alone still exceeds 80 chars -->
This is already a very long sentence with lots of words that pushes past the limit even [without](https://example.com) the URL.
Automatic fixes¶
When reflow is set to true, this rule can automatically wrap long lines while preserving Markdown formatting:
- Intelligently breaks lines at appropriate points
- Preserves bold, italic, links, code spans, and other Markdown elements
- Reflows list items using the configured marker spacing and aligns continuation lines to the content column (see List reflow and marker spacing)
- Reflows blockquote paragraphs (including lazy continuation lines) while preserving input style
- Preserves hard line breaks (two trailing spaces)
- Does not wrap code blocks, tables, headings, or reference definitions
List reflow and marker spacing¶
When reflowing list items (including nested and blockquote-nested lists), rumdl
does not hard-code the spacing after a list marker. In the spacing-normalizing
modes (default and normalize) it derives the number of spaces after the
marker from the MD030 configuration — ul-single/ul-multi for
unordered lists, ol-single/ol-multi for ordered lists, and the
ol-align-column override — choosing the single- or multi-line value the same
way MD030 does. Continuation (wrapped) lines are then indented to the resulting
content column, so wrapped text aligns under the item's text exactly as
MD007's text-aligned style expects. With the default MD030 setting
(a single space) the output is unchanged.
The sentence-per-line and semantic-line-breaks modes only change where lines
break, so they preserve the marker spacing and indentation already in the
source. The MkDocs flavor keeps its own fixed 4-space structural indent.
Example (line-length = 50, MD030 ol-multi = 2):
# Before
1. This is a fairly long numbered item that wraps onto another line.
# After
1. This is a fairly long numbered item that wraps
onto another line.
Blockquote reflow style preservation¶
When reflowing blockquote paragraphs, rumdl preserves the source style:
- Explicit continuation input stays explicit (
>on wrapped lines) - Lazy continuation input stays lazy when safe
- Mixed explicit/lazy input uses deterministic style selection (explicit on ties)
- Lazy output is automatically upgraded to explicit for lines that would otherwise start a new block structure
Example (line-length = 60):
# Before
> This is a very long blockquote line that should be wrapped while preserving the source style and markdown structure.
# After
> This is a very long blockquote line that should be wrapped
> while preserving the source style and markdown structure.
Reflow Modes¶
The reflow-mode option controls how text is reformatted when reflow is true:
default mode¶
Standard text wrapping that breaks lines at word boundaries to fit within the configured line length.
normalize mode¶
Normalizes all paragraph text to consistently wrap at the configured line length, removing irregular line breaks.
This mode is useful for standardizing documents with inconsistent line wrapping.
sentence-per-line mode¶
Enforces one sentence per line, making diffs cleaner and easier to review, among other advantages. This mode:
- Detects sentence boundaries (periods, exclamation marks, question marks)
- Handles common abbreviations (e.g., i.e., Mr., Dr., Ph.D., Inc., etc.) without breaking sentences
- Preserves decimal numbers and ellipses
- Works with markdown formatting
Example transformation:
# Before
This is the first sentence. This is the second sentence. And this is the third.
# After
This is the first sentence.
This is the second sentence.
And this is the third.
This mode is particularly useful for:
- Technical documentation where each sentence often contains a single concept
- Documents maintained in version control where sentence-level diffs are clearer
- Collaborative writing where different authors work on different sentences
Safety exception: a sentence is kept on the previous line when placing it
on its own line would change the document's structure. Text that starts with a
list marker (-, *, +, 1.), blockquote marker (>), heading marker
(#), code fence, horizontal rule, reference definition ([label]:), or
block-level HTML tag becomes real block syntax at the start of a line, so
reflow never puts it there:
# Stays on one line (the dash clause would otherwise become a list item)
Google Calendar (Can't we get rid of this dependency? - I don't really see the need)
Structure always wins over strict one-sentence-per-line in these cases. The same guard applies to line wrapping in all reflow modes, where a wrapped line is instead broken one word earlier (or left slightly over the limit when no earlier break point exists).
semantic-line-breaks mode¶
Breaks lines at semantic boundaries using a cascading strategy. Unlike sentence-per-line (which always breaks at every sentence boundary only), this mode also splits long sentences at clause punctuation and break-words to keep lines within the configured line length.
Cascading priority:
| Priority | Split point | When applied |
|---|---|---|
| 1 | Sentence boundaries (. ! ?) |
Always |
| 2 | Clause punctuation (, ; : —) |
When line > line-length |
| 3 | Break-words (and, or, but, which, because, ...) |
When line still > line-length |
| 4 | Word wrap | Fallback |
Example transformation:
# Before
All human beings are born free and equal in dignity and rights. They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.
# After (with line-length = 80)
All human beings are born free and equal in dignity and rights.
They are endowed with reason and conscience
and should act towards one another in a spirit of brotherhood.
Break-words list: and, or, but, nor, yet, so, for, which, that, because, when, if, while, where, although, though, unless, since, after, before, until, as, once, whether, however, therefore, moreover, furthermore, nevertheless, whereas
With line-length = 0, only sentence boundaries are used (no cascading), behaving like sentence-per-line.
Sentence-per-line without line length warnings¶
If you want to use sentence-per-line mode for formatting but don't want warnings about long sentences, you can disable paragraph checking while keeping code blocks and tables checked:
[MD013]
line-length = 80
paragraphs = false # Don't warn about long paragraphs
code-blocks = true # Still check code blocks
tables = true # Still check tables
reflow = true
reflow-mode = "sentence-per-line"
This configuration is useful when:
- You want automatic sentence-per-line formatting without validation noise
- You care about line length in code blocks and tables but not in regular text
- You're using semantic line breaks where sentence length is determined by content, not arbitrary limits
Disabling all line length checks¶
If you want to completely disable all line length checking (for paragraphs, headings, code blocks, and tables), set line-length to 0:
[MD013]
line-length = 0 # Disable all line length checks
reflow = true
reflow-mode = "sentence-per-line"
When line-length is set to 0, no line length warnings will be reported for any content type. This is particularly useful for:
- Projects using semantic line breaks where lines break at logical boundaries regardless of length
- Sentence-per-line workflows where line length is not a concern
- Documentation where long lines (e.g., URLs, technical terms) are unavoidable and acceptable
Note: With line-length: 0 and reflow-mode: "sentence-per-line", rumdl will:
- Split multiple sentences that share a line into separate lines
- Join single sentences that span multiple lines into one line (since there's no length constraint)
- Provide consistent "one sentence = one line" formatting throughout your document
Example with automatic reflow¶
With this configuration, long lines will be automatically wrapped to fit within 80 characters while maintaining proper Markdown formatting.
Note: When reflow is false (default), automatic fixes are not available and you'll need to manually wrap long lines.