Comparison with Obsidian Linter¶
This page maps every Obsidian Linter rule to its rumdl counterpart, so that a vault owner can judge a migration before starting it, and so that a rule request for something rumdl lacks arrives pre-triaged.
Last verified: August 2026 against Obsidian Linter's generated rule documentation. Obsidian Linter changes over time; if a row is out of date, please open an issue.
Quick Summary¶
rumdl and Obsidian Linter are different kinds of tool that overlap on formatting:
- rumdl is a file linter and formatter. It runs as a CLI, in pre-commit, as an LSP server, in VS Code, and inside Obsidian through the obsidian-rumdl plugin, which runs the same rule engine on the notes in a vault. Its rules read only files on disk (the file, and the workspace for cross-file rules), so a run is reproducible in CI.
- Obsidian Linter is an editor plugin. Besides formatting rules it has rules that run when text is pasted, rules that read the file system (creation and modification times, the file name), and user-defined regex replacements and shell commands.
Of Obsidian Linter's 65 rules, 16 have a rumdl equivalent, 12 overlap partially (same idea, different contract), 28 have no rumdl counterpart, and 9 are out of scope by construction: the 8 paste rules and YAML timestamp. A file linter has no paste event, and a formatter that writes the current time into the file on every run cannot be idempotent, so those rows are not gaps that a rule request could close.
Of the 28 without a counterpart, 12 concern the front matter (11 write or rewrite YAML values, Compact YAML removes blank lines inside it), 3 handle spacing around CJK and fullwidth characters, and the remaining 13 are one-off transforms.
How the Two Tools Differ¶
| Aspect | rumdl | Obsidian Linter |
|---|---|---|
| Where it runs | CLI, pre-commit, LSP, VS Code, Obsidian plugin, WebAssembly | Obsidian only |
| Input | The file, plus the workspace for cross-file rules | The open note, the clipboard, the file system |
| Rules | 82 built in, opt-in ones enabled in config | 65 built in, plus custom regex replacements and commands |
| Obsidian syntax | flavor = "obsidian": callouts, wikilinks, %% comments, tags |
Native |
| Configuration | .rumdl.toml (also JSON, YAML, pyproject.toml) |
Plugin settings UI |
| Fix mode | rumdl fmt, rumdl check --fix, editor code actions |
Lint on save or on command |
Rule Mapping¶
Legend: Yes means an equivalent rule exists and every explicit option maps (a difference in how a consistent style is inferred is noted on the row, not demoted), Partial means the rules
overlap but an option or direction has no counterpart, None means rumdl has no such rule, and Out of scope means a file linter cannot do it. Where an Obsidian Linter option has a rumdl option,
the Notes column names it.
YAML Rules (14)¶
| Obsidian Linter | rumdl | Notes |
|---|---|---|
| Add blank line after YAML | Yes MD071 | Both leave a file that is only front matter alone |
| YAML key sort | Partial MD072 (opt-in) | "YAML key priority sort order" is key-order. "YAML sort order for other keys" has no equivalent: rumdl always sorts unlisted keys ascending. rumdl skips the fix when the front matter contains a comment line |
| Dedupe YAML array values | None | |
| Escape YAML special characters | None | |
| Force YAML escape | None | |
| Format tags in YAML | None | |
| Format YAML array | None | |
| Insert YAML attributes | None | Content generation |
| Move tags to YAML | None | Content generation |
| Remove YAML keys | None | |
| Sort YAML array values | None | |
| YAML timestamp | Out of scope | Needs the file's creation and modification times. A formatter that rewrites a date on every run is also the opposite of idempotent |
| YAML title | None | Writes the file name into title. rumdl knows the file name (MD041 derives a heading from it) but no rule writes front matter values |
| YAML title alias | None | Adds the file name to aliases. See YAML title |
The general settings "Default escape character" and "YAML aliases section style" configure YAML value formatting and have no rumdl equivalent.
Heading Rules (5)¶
| Obsidian Linter | rumdl | Notes |
|---|---|---|
| Capitalize headings | Yes MD063 (opt-in) | "Style" Title Case / ALL CAPS / First letter is style title-case / all-caps / sentence-case. "Ignore cased words" is preserve-cased-words, "Ignore words" is ignore-words, "Lowercase words" is lowercase-words (rumdl ships its own default list) |
| Header increment | Partial MD001 | "Start header increment at heading level 2" has no MD001 option. The nearest is MD041 with level = 2, which checks the first heading only |
| Headings start line | Yes MD023 | MD023 leaves an indented level-1 heading alone when its first word starts with a lowercase letter or a digit (# tag, # 123), reading it as a hashtag or issue reference rather than a heading |
| Remove trailing punctuation in heading | Partial MD026 | Same punctuation concept. Obsidian Linter's default set also contains the fullwidth 。,;:!; rumdl's default is the ASCII .,;:!, and the starter configuration below adds the fullwidth forms. Both leave a trailing HTML entity such as & alone |
| File name heading | Partial MD041 | Inserts the file name as the H1. MD041 reports a missing H1; with fix = true it promotes a title-like first line (at most 80 characters, no sentence-ending punctuation, followed by a blank line or the end of the file) to a heading, or, when the file holds only directive blocks, inserts one derived from the file name (kebab-case and underscores become Title Case). A file that opens with a body paragraph is reported but left unchanged |
Footnote Rules (3)¶
| Obsidian Linter | rumdl | Notes |
|---|---|---|
| Footnote after punctuation | None | Lorem[^1]. is clean to rumdl |
| Move footnotes to the bottom | Partial MD067 | MD067 reports definitions that are out of reference order, without a fix, and does not move them to the end of the file |
| Re-index footnotes | None | MD067 checks definition order and never renames an identifier |
Content Rules (16)¶
| Obsidian Linter | rumdl | Notes |
|---|---|---|
| Emphasis style | Yes MD049 | style consistent / asterisk / underscore. See the note on consistent below |
| Strong style | Yes MD050 | style consistent / asterisk / underscore. See the note on consistent below |
| Unordered list style | Yes MD004 | style consistent / dash / asterisk / plus. See the note on consistent below |
| Ordered list style | Partial MD029 | "Number style" ascending is style = "ordered", lazy is style = "one". "Preserve starting number" has no option (rumdl honors the start number under ordered). "Ordered list marker end style" has no equivalent: rumdl accepts . and ) and never converts between them |
| No bare URLs | Yes MD034 | Both wrap the URL in angle brackets |
| Remove consecutive list markers | Yes MD069 | |
| Remove multiple spaces | Partial MD064 | rumdl skips runs that are a multiple of 4 spaces, spaces after a task checkbox, and the item lines of column-aligned lists of two or more items. See the differences below |
| Default language for code fences | Partial MD040 | rumdl's fix always inserts text; "Programming language" has no equivalent |
| Blockquote style | Partial MD027 | MD027 removes extra spaces after > but does not add a missing one. The "no space" style has no equivalent |
| Quote style | Partial MD088 (opt-in) | Only the smart-to-straight direction (normalize-quotes = true). Obsidian Linter's default direction is also straight quotes, so the defaults agree; its smart-quote styles have no rumdl equivalent |
| Auto-correct common misspellings | None | MD044 (proper names) and MD061 (forbidden terms, no fix) are the nearest, but neither is a dictionary |
| Convert bullet list markers | None | • and § are not recognized as list markers |
| Proper ellipsis | None | MD088 normalizes quotes and dashes toward ASCII and does not touch ellipses |
| Remove empty list markers | None | A - on its own line is clean to rumdl |
| Remove hyphenated line breaks | None | |
| Line break between lines with content | None | Inserts trailing double spaces or <br>. MD009 only tolerates a br-spaces run; nothing inserts one |
Spacing Rules (19)¶
| Obsidian Linter | rumdl | Notes |
|---|---|---|
| Consecutive blank lines | Yes MD012 | |
| Empty line around code fences | Yes MD031 | |
| Empty line around horizontal rules | Yes MD065 | |
| Empty line around tables | Yes MD058 | |
| Heading blank lines | Yes MD022 and MD071 | "Bottom" off is lines-below = 0. "Empty line between YAML and header" is MD071 |
| Line break at document end | Yes MD047 | |
| Remove empty lines between list markers | Yes MD076 | style = "tight" |
| Remove link spacing | Partial MD039 | Both trim inline link text ([ text ](url)) and neither touches reference-style links ([ text ][id]). rumdl also trims image alt text and leaves wikilinks ([[page\| text ]]) alone, because a wikilink has no destination to rewrite the text against; Obsidian Linter trims wikilinks and leaves images alone |
| Space after list markers | Partial MD030 | Marker spacing only (ul-single, ol-single, ul-multi, ol-multi). Obsidian Linter also normalizes the space after a [x] checkbox, which MD030 ignores and MD064 exempts |
| Trailing spaces | Yes MD009 | Obsidian Linter strips hard line breaks along with other trailing spaces by default; br-spaces = 0 does the same. Its "Two Space Linebreak" option, which keeps 2-space hard line breaks, is rumdl's default. Both skip code blocks |
| Convert spaces to tabs | None | The opposite of MD010. See "Tabs versus spaces" below |
| Compact YAML | None | MD012 ignores blank lines inside front matter |
| Empty line around blockquotes | None | MD028 is about blank lines inside a blockquote |
| Empty line around math blocks | None | |
| Move math block indicators to their own line | None | |
| Paragraph blank lines | None | Puts every line of prose in its own paragraph |
| Remove space around characters | None | Fullwidth forms and CJK punctuation |
| Remove space before or after characters | None | |
| Space between Chinese Japanese or Korean and English or numbers | None |
Paste Rules (8) and Custom Rules¶
The eight paste rules (blockquote indentation on paste, double checklist and list marker prevention, proper ellipsis on paste, remove hyphens on paste, remove leading or trailing whitespace on paste, remove leftover footnotes from a quote on paste, remove multiple blank lines on paste) transform the clipboard contents at paste time. There is no paste event in a CLI, a pre-commit hook or a language server, so they are out of scope.
"Custom regex replacement" and "Custom commands" are None: rumdl has no user-defined rules.
Starter Configuration¶
This .rumdl.toml enables the Obsidian flavor and the opt-in rules that have an Obsidian Linter counterpart, and sets the options whose rumdl default differs from Obsidian Linter's. Drop the sections
for rules you did not use in Obsidian Linter.
[global]
flavor = "obsidian"
# Opt-in rules with an Obsidian Linter counterpart:
# MD063 Capitalize headings, MD072 YAML key sort, MD088 Quote style
extend-enable = ["MD063", "MD072", "MD088"]
# Capitalize headings
[MD063]
style = "title-case"
preserve-cased-words = true
ignore-words = ["macOS", "iOS", "iPhone", "iPad", "JavaScript", "TypeScript", "AppleScript", "I"]
# YAML key sort: list the keys from "YAML key priority sort order"
[MD072]
key-order = ["title", "aliases", "tags"]
# Quote style (straight quotes, Obsidian Linter's default direction)
[MD088]
normalize-quotes = true
# Remove trailing punctuation in heading: add the fullwidth forms
[MD026]
punctuation = ".,;:!。,;:!"
# Remove empty lines between list markers
[MD076]
style = "tight"
# Trailing spaces: strip hard line breaks too, Obsidian Linter's default.
# Drop this section to keep 2-space hard line breaks ("Two Space Linebreak").
[MD009]
br-spaces = 0
Rules that are on by default in rumdl and have a direct counterpart (MD012, MD022, MD023, MD031, MD034, MD047, MD058, MD065, MD069, MD071, MD004, MD049, MD050) need no configuration; the differences noted on their rows are fixed behavior, not options. To keep a behavior Obsidian Linter never touched, disable the rule:
Known Behavioral Differences¶
consistentfollows the majority, not the first occurrence. Obsidian Linter'sconsistentstyle for emphasis, strong and unordered lists takes the first marker in the file as the standard. rumdl's MD004, MD049 and MD050 take the most prevalent marker, with a fixed tie-break (dash for lists, asterisk for emphasis). A file whose first list uses*and whose other lists use-converges to-under rumdl and to*under Obsidian Linter.- MD064 leaves some space runs alone on purpose. A run of 4, 8 or 12 spaces reads as a replaced tab and is skipped so that MD064 does not undo MD010 at its default width, spaces after a task checkbox are skipped, and the item lines of a list of at least two items that are all column-aligned are skipped. Obsidian Linter's "Remove multiple spaces" collapses all of these. See MD064 for the full exception list.
- MD027 only removes spaces.
> textbecomes> text, but>textis not given a space. Obsidian Linter's "Blockquote style" adds it. - MD039 leaves wikilinks alone.
[[Page| alias ]]keeps its spaces under rumdl because the pipe text of a wikilink has no destination it could be normalized against. Obsidian Linter trims it. - MD088 only goes toward ASCII. It replaces smart quotes with straight ones and, with
normalize-dashes = true, dashes with hyphens. Obsidian Linter can also convert straight quotes to smart quotes; rumdl cannot. - MD040 inserts
text. Obsidian Linter's "Default language for code fences" inserts the language you configure. rumdl's fix insertstext(except under themdgflavor, where a Doc String's label is its media type and is left to the author), and the MD040 options normalize labels that are already present rather than choose a default. - MD001 has no "start at level 2". rumdl checks that heading levels increment by one; it has no option to shift every heading so the document starts at H2.
- MD029 never changes the marker delimiter.
1)and1.are both accepted and neither is converted to the other. - MD072 sorts every unlisted key ascending. There is no "None" or "Descending" mode for keys outside
key-order, and the fix is skipped when the front matter contains a comment line, which a reorder could leave next to the wrong key. An inline comment after a value moves with its line. - MD026's default punctuation set is ASCII. Add the fullwidth forms through
punctuationas in the starter configuration if your headings use them.
Tabs Versus Spaces¶
Obsidian Linter's "Convert spaces to tabs" turns leading spaces into tabs. rumdl's MD010 enforces the opposite convention and replaces tabs with spaces.
MD010 already leaves tabs inside code blocks alone by default (code-blocks = false). To keep tabs everywhere, disable the rule with disable = ["MD010"]. Nothing in rumdl converts spaces to tabs.
Such a rule would be a new opt-in rule and a product decision, not a compatibility fix, because it reverses a rule that every other rumdl user relies on.
Candidate Rules¶
These are the rows above that a file linter could legitimately own. They are listed so that a request for one arrives with the mapping already done; they are not commitments.
- Empty list markers (a
-or1.with nothing after it) - Blank lines around blockquotes
- Blank lines around math blocks
- Footnote reference placement after punctuation
- Footnote re-indexing (
[^3]becomes[^1]when it is the first reference) - Moving footnote definitions to the end of the document
- Front matter
titleandaliasesderived from the file name
YAML value formatting (array style, deduplication, escaping, tag formatting) and the CJK spacing rules are further from what rumdl does today and would need a design of their own.
See Also¶
- Obsidian Flavor - the syntax the
obsidianflavor recognizes and how rules adapt to it - obsidian-rumdl - the Obsidian plugin that runs rumdl inside a vault
- Comparison with markdownlint - for users coming from markdownlint
- Comparison with mdformat - for users coming from mdformat
- Rules Reference - the complete list of rumdl's 82 rules
- Obsidian Linter documentation - the rule reference this page was verified against