markdown-style
The Markdown authoring and review skill. Owns two layers of rules and the procedure for applying them:
- Syntax canon - what valid, portable Markdown looks like. Full canon:
references/syntax-canon.md.
- Style overlay - opinionated rules a reviewer enforces on top of valid syntax. Full overlay:
references/style-overlay.md.
The question this skill answers is 'is this doc well-formed?' - not 'does this doc belong here?' Style review never decides whether a doc should exist; it assumes the doc earned its place and asks whether the prose structure and Markdown are clean.
How to run a review
Two passes, syntax before style. The reviewer reads a syntax violation differently from a style violation, so do not interleave them.
Pass 1 - syntax (must-fix)
Run markdownlint first when it is available - the mechanical checks (heading style, list markers, blank lines around blocks, fence style) are its job, and each hit maps onto a canon rule; then walk the file top to bottom for what a linter cannot see. Syntax violations are bugs (invalid or non-portable Markdown: setext where ATX is expected, unfenced code block, missing blank line around a block element, ) instead of . in an ordered list, missing space after #), not judgment calls - fix them directly in one Edit pass. No approval gate; the diff is self-explaining and each fix cites its rule by short name (e.g. syntax/headings/atx-space-after).
Pass 2 - style (should-fix)
Re-walk for style-overlay violations. These are opinionated. Apply the clear wins directly - fenced blocks with a language tag, single H1 as the title, informative link text (never 'here'), no trailing whitespace, product-name capitalization. Batch the genuine judgment calls - [TOC] on a borderline-length doc, table-vs-list, reference-vs-inline links, heading-uniqueness prefixes - into one short list, each with a recommendation, and move. Do not gate each finding on a reply.
Defer to the project on any conflict with a local convention (e.g. a repo standardized on _underscore_ emphasis) - note the conflict, defer, move on. No audit markers or [reviewed] stamps in the file; the diff is the audit trail.
The two layers - quick reference
Detailed rules with examples live in references/. These summaries cover the violations that account for most findings.
Syntax (must-fix)
| Construct |
Rule |
| Headings |
ATX (#-######), space after #, blank lines before and after. |
| Paragraphs |
Separated by a blank line. Do not indent. |
| Line breaks |
Trailing-two-spaces is controversial (invisible). Prefer a paragraph break. |
| Emphasis |
**bold**, *italic*, ***both***. Asterisks mid-word (underscores break). |
| Blockquotes |
> prefix; > on the blank line between paragraphs; nest with >>. |
| Ordered lists |
1. 2. 3. (period, not )). Start at 1. Numbering can be lazy. |
| Unordered lists |
Choose one of - / * / +; do not mix within a list. |
| Nested list content |
Indent 4 spaces (1 tab). Code inside a list item indents 8 spaces (2 tabs). |
| Inline code |
Single backticks. Double backticks if the code contains a backtick. |
| Code blocks |
Fenced with a language tag. Indented blocks are valid but discouraged. |
| Horizontal rule |
Three or more --- / *** / ___ alone on a line with blank lines around. |
| Links |
[text](url). Autolink with <https://...>. Reference links resolve elsewhere. |
| Images |
. Always include alt text. |
| Inline HTML |
Allowed. Separate block-level HTML with blank lines. Do not indent the tags. |
Full canon with examples and known-broken edge cases: references/syntax-canon.md.
Style (should-fix)
| Concern |
Rule |
| H1 |
Exactly one H1, used as the document title (match or nearly match the filename). Rest start at H2. |
| Heading style |
ATX only. No setext underlines. |
| Heading uniqueness |
Avoid bare repeated subheadings ('Summary', 'Example') under multiple parents. Prefix them. |
| Document skeleton |
Title -> optional owner -> 1-3 sentence intro -> [TOC] -> ## Topic sections -> ## See also. |
| Table of contents |
[TOC] for any doc that would not fit on one screen. Between intro and first H2. |
| Line length |
80 chars. Exceptions: links, tables, headings, code blocks. Prose around a long link still wraps. |
| Trailing whitespace |
None. Prefer a paragraph break to the two-space line-break trick. |
| Lists |
Lazy numbering (1. repeated) for long lists; full numbering for short stable ones. Prefer lists to tables for one-dimensional data. |
| Code fencing |
Always fenced, never indented. Always declare a language (text if none). Escape wrapped shell newlines with \. |
| Links |
Repo-absolute paths (/path/to/page.md) over https://... for in-repo links. Avoid ../ traversal. |
| Link text |
Informative. Never 'here', 'link', or a raw URL. |
| Reference links |
Use in tables, when the URL hurts readability, or when a target repeats. Define just before the next heading. |
| Tables |
Only for scannable two-dimensional data. No prose cells (cells cannot wrap). |
| Images |
Sparingly. Always alt text. |
| Capitalization |
Preserve product / tool / binary capitalization (Markdown, not markdown; npm, iOS). |
Full overlay with rationales: references/style-overlay.md.
What this skill does NOT cover
Markdown form only - heading style, list indentation, code-fence language tags, link syntax, line length, and the rest of the two rule sets above. It does not cover:
- Whether a doc should exist, or where it belongs - that is a content / architecture decision, not a form review. Style review assumes the doc earned its place.
- Prose-level enforcement - terminology consistency, inclusive-language substitutions, banned phrases, voice / tense / mood. Reach for Vale (a prose linter that runs configurable style packs over Markdown). It composes with this skill: this skill fixes the Markdown form, Vale enforces prose terminology.
- Spelling and grammar - use
codespell / hunspell / LanguageTool in addition, not instead.
- AsciiDoc / reStructuredText / org-mode / MDX - Markdown only; other markup has its own canonical rules (e.g.
asciidoctor --safe-mode).
Hard limits
- Never invent rules. Every finding cites a rule from
references/syntax-canon.md or references/style-overlay.md.
Examples
Attribution
The two layers are distilled from publicly available style references - load-bearing rules only, not verbatim reproduction:
When the user needs the original text, link out - do not paste long excerpts.
1---2name: markdown-style3description: Markdown authoring and review skill - the two-layer rule set (syntax canon = valid, portable Markdown from the Markdown Guide; style overlay = opinionated house form from Google's style guide) plus the review procedure. Load when authoring or restructuring any .md (README, ADR, runbook, how-to, design doc) or on an explicit 'lint / style-check / fix this markdown', 'ATX vs setext', 'should I use a TOC?', or 'fix the headings / list indentation' ask. Markdown form only - not prose clarity (that is Vale) or spelling (codespell / hunspell).4---56# markdown-style78The Markdown authoring and review skill. Owns two layers of rules and the procedure for applying them:9101. **Syntax canon** - what valid, portable Markdown looks like. Full canon: `references/syntax-canon.md`.112. **Style overlay** - opinionated rules a reviewer enforces on top of valid syntax. Full overlay: `references/style-overlay.md`.1213The question this skill answers is **'is this doc well-formed?'** - not 'does this doc belong here?' Style review never decides whether a doc should exist; it assumes the doc earned its place and asks whether the prose structure and Markdown are clean.1415## How to run a review1617Two passes, syntax before style. The reviewer reads a syntax violation differently from a style violation, so do not interleave them.1819### Pass 1 - syntax (must-fix)2021Run `markdownlint` first when it is available - the mechanical checks (heading style, list markers, blank lines around blocks, fence style) are its job, and each hit maps onto a canon rule; then walk the file top to bottom for what a linter cannot see. Syntax violations are bugs (invalid or non-portable Markdown: setext where ATX is expected, unfenced code block, missing blank line around a block element, `)` instead of `.` in an ordered list, missing space after `#`), not judgment calls - **fix them directly in one Edit pass**. No approval gate; the diff is self-explaining and each fix cites its rule by short name (e.g. `syntax/headings/atx-space-after`).2223### Pass 2 - style (should-fix)2425Re-walk for style-overlay violations. These are opinionated. **Apply the clear wins directly** - fenced blocks with a language tag, single H1 as the title, informative link text (never 'here'), no trailing whitespace, product-name capitalization. **Batch the genuine judgment calls** - `[TOC]` on a borderline-length doc, table-vs-list, reference-vs-inline links, heading-uniqueness prefixes - into one short list, each with a recommendation, and move. Do not gate each finding on a reply.2627Defer to the project on any conflict with a local convention (e.g. a repo standardized on `_underscore_` emphasis) - note the conflict, defer, move on. No audit markers or `[reviewed]` stamps in the file; the diff is the audit trail.2829## The two layers - quick reference3031Detailed rules with examples live in `references/`. These summaries cover the violations that account for most findings.3233### Syntax (must-fix)3435| Construct | Rule |36|---------------------|---------------------------------------------------------------------------------|37| Headings | ATX (`#`-`######`), space after `#`, blank lines before and after. |38| Paragraphs | Separated by a blank line. Do not indent. |39| Line breaks | Trailing-two-spaces is controversial (invisible). Prefer a paragraph break. |40| Emphasis | `**bold**`, `*italic*`, `***both***`. Asterisks mid-word (underscores break). |41| Blockquotes | `>` prefix; `>` on the blank line between paragraphs; nest with `>>`. |42| Ordered lists | `1.` `2.` `3.` (period, not `)`). Start at 1. Numbering can be lazy. |43| Unordered lists | Choose one of `-` / `*` / `+`; do not mix within a list. |44| Nested list content | Indent 4 spaces (1 tab). Code inside a list item indents 8 spaces (2 tabs). |45| Inline code | Single backticks. Double backticks if the code contains a backtick. |46| Code blocks | Fenced with a language tag. Indented blocks are valid but discouraged. |47| Horizontal rule | Three or more `---` / `***` / `___` alone on a line with blank lines around. |48| Links | `[text](url)`. Autolink with `<https://...>`. Reference links resolve elsewhere.|49| Images | ``. Always include alt text. |50| Inline HTML | Allowed. Separate block-level HTML with blank lines. Do not indent the tags. |5152Full canon with examples and known-broken edge cases: `references/syntax-canon.md`.5354### Style (should-fix)5556| Concern | Rule |57|-----------------------|-----------------------------------------------------------------------------------------------|58| H1 | Exactly one H1, used as the document title (match or nearly match the filename). Rest start at H2. |59| Heading style | ATX only. No setext underlines. |60| Heading uniqueness | Avoid bare repeated subheadings ('Summary', 'Example') under multiple parents. Prefix them. |61| Document skeleton | Title -> optional owner -> 1-3 sentence intro -> `[TOC]` -> `## Topic` sections -> `## See also`. |62| Table of contents | `[TOC]` for any doc that would not fit on one screen. Between intro and first H2. |63| Line length | 80 chars. Exceptions: links, tables, headings, code blocks. Prose around a long link still wraps. |64| Trailing whitespace | None. Prefer a paragraph break to the two-space line-break trick. |65| Lists | Lazy numbering (`1.` repeated) for long lists; full numbering for short stable ones. Prefer lists to tables for one-dimensional data. |66| Code fencing | Always fenced, never indented. Always declare a language (`text` if none). Escape wrapped shell newlines with `\`. |67| Links | Repo-absolute paths (`/path/to/page.md`) over `https://...` for in-repo links. Avoid `../` traversal. |68| Link text | Informative. Never 'here', 'link', or a raw URL. |69| Reference links | Use in tables, when the URL hurts readability, or when a target repeats. Define just before the next heading. |70| Tables | Only for scannable two-dimensional data. No prose cells (cells cannot wrap). |71| Images | Sparingly. Always alt text. |72| Capitalization | Preserve product / tool / binary capitalization (`Markdown`, not `markdown`; `npm`, `iOS`). |7374Full overlay with rationales: `references/style-overlay.md`.7576## What this skill does NOT cover7778Markdown **form** only - heading style, list indentation, code-fence language tags, link syntax, line length, and the rest of the two rule sets above. It does not cover:7980- **Whether a doc should exist, or where it belongs** - that is a content / architecture decision, not a form review. Style review assumes the doc earned its place.81- **Prose-level enforcement** - terminology consistency, inclusive-language substitutions, banned phrases, voice / tense / mood. Reach for [Vale](https://vale.sh) (a prose linter that runs configurable style packs over Markdown). It composes with this skill: this skill fixes the Markdown form, Vale enforces prose terminology.82- **Spelling and grammar** - use `codespell` / `hunspell` / `LanguageTool` in addition, not instead.83- **AsciiDoc / reStructuredText / org-mode / MDX** - Markdown only; other markup has its own canonical rules (e.g. `asciidoctor --safe-mode`).8485## Hard limits8687- Never invent rules. Every finding cites a rule from `references/syntax-canon.md` or `references/style-overlay.md`.8889## Examples9091<example>92<user_query>Is `===` under a heading line valid Markdown?</user_query>93<response>94Yes - that is setext-style H1, valid Markdown. But the style overlay (and Google's guide) prefer ATX (`# Heading`): setext is annoying to maintain, cannot express H3 or below, and obscures the level when scanning. Recommendation: replace `===` with a single `#` - a syntax-equivalent rewrite. Point me at the file and I will apply it.95</response>96</example>9798<example>99<user_query>Lint this README - the formatting is messy.</user_query>100<response>101Running the two-pass review. Pass 1 fixes syntax bugs (fences, blank lines, ATX headings, list markers) directly. Pass 2 applies the clear style wins and flags any judgment calls (TOC, table-vs-list) as a short list. Send the path.102</response>103</example>104105## Attribution106107The two layers are distilled from publicly available style references - load-bearing rules only, not verbatim reproduction:108109- **Syntax canon** - the Markdown Guide basic-syntax reference (<https://www.markdownguide.org/basic-syntax/>), CC BY-SA 4.0.110- **Style overlay** - Google's developer-documentation Markdown style guide (<https://google.github.io/styleguide/docguide/style.html>), from `google/styleguide`, Apache License 2.0.111112When the user needs the original text, link out - do not paste long excerpts.