Skip to content

Markdown Line Handling

Source: hooks/ways/documentation/markdown/markdown.md

Frontmatter
Field Value
description markdown authoring mechanics — line handling, hard wrapping versus flat prose, when a line break carries structure, tables and fences
vocabulary markdown wrap unwrap reflow flatten line length column paragraph prose hard wrap fill width flow text file authoring plaintext txt
files .md$
refire 0.15
scope agent, subagent

Write prose one line per paragraph. One line per list item, one line per table row, one line per blockquote line. Don't hard-wrap prose to a column.

This is a machine-ergonomics convention, not a style preference. Two concrete costs:

  • Hard wrapping breaks Edit. Exact-string replacement means old_string has to reproduce every interior line break perfectly. A one-sentence change inside a wrapped paragraph becomes a multi-line match to transcribe; flat, it's a single line. This is where edits miss and get retried, not merely where they get long.
  • Hard wrapping makes diffs non-semantic. Change three words and the rest of the paragraph reflows, so git diff shows five changed lines for one changed thought. Review cost starts scaling with wrap width instead of with the size of the change.

Neither cost is one-time. A flat file stays cheaper to edit for its whole life.

Line breaks that do carry structure

A line break is fine — required, even — where the break is the structure. Keep these on their own lines:

Construct Why it stays
List items The marker is line-initial syntax
Table rows Row boundary is the line boundary
Headings, thematic breaks Block-level, line-initial
Blockquote label lines (**Status:**, **Next:**) Reads as a field list; joining makes one run-on line
Deliberate hard breaks (two trailing spaces, or \) The break renders as <br> — joining silently deletes it
Parallel one-clause-per-line prose Authored rhythm, not wrapping

That last one is the judgment call. The test that separates it from hard wrapping: does the break land at a clause boundary, or mid-phrase? Wrapping breaks wherever the column runs out — mid-phrase, with line lengths all clustered just under the fill width. Authored breaks land where the thought turns, and their lengths vary freely.

Wide content is allowed to be wide

Tables, long links, deep code lines, and long fenced blocks may run past any comfortable reading width. Readers scroll; authors shouldn't reflow. Never "fix" a table by rewrapping its cells.

Other text formats are not markdown

The reasoning above depends on a renderer that reflows paragraphs. Where there is none, wrapping is the layout and should stay:

  • Plain .txt — no renderer, so the wrap is the presentation. Leave it alone; 72 columns there is correct, not drift.
  • Commit message bodies — keep the conventional 72-column wrap. Git tooling assumes it.
  • Code comments — follow the language's own line-length convention.

Repairing a wrapped file

ways author reflow <file> reports hard-wrapped paragraphs and exits non-zero when it finds any; --fix flattens them, backs the original up first, and prints the backup path.

It repairs the enclosing paragraph of each detection and leaves everything else byte-identical, so it won't flatten authored one-clause-per-line prose elsewhere in the file.

Before writing, it reparses the result and compares the document's structure against the original. If anything moved beyond the line breaks inside a paragraph, it refuses to write and says so — a construct it misread becomes a refusal rather than a corrupted file. Read the diff anyway: two things that check cannot see are a join that erased an authored line break, and non-CommonMark syntax like ::: directives.

See Also

  • mermaid(documentation) — the sibling convention-plus-tool pair, for diagrams
  • diataxis(documentation) — which mode a page is written in
  • standards(documentation) — how conventions like this one get established
  • knowledge/authoring(meta) — authoring the way files themselves