prose-guard
Order of operations
Run the linter first. Do not read files hunting for violations by hand, that is what the script is for.
python <skill>/scripts/prose_lint.py <paths...>
With no paths it lints every git-tracked .md file in the repo. Output is one finding per line as path:line:col [rule] message.
Then fix what it found, and re-run until clean.
Flags worth knowing
| Flag | Effect |
|---|---|
--fail-on medium |
Treat medium findings as failures too. Use on docs meant for other people. |
--fix |
Rewrites only the unambiguous em dash cases, then reports the rest. Always re-read the touched lines afterwards. |
--json |
Machine-readable, for wiring into a hook or CI. |
--stats |
Counts by rule instead of per-line findings. Use on a large first pass. |
Fixing
The rules themselves live in references/rules.md. Read that file when you need the reasoning or the rewrite patterns, not before.
Two rules need judgment rather than a mechanical swap:
- Em dashes. The replacement depends on the clause. A parenthetical takes commas or parentheses. A pivot takes a period and a new sentence. A list intro takes a colon. Do not blanket-replace with commas.
- Medium-severity words.
robust,curated,comprehensive,state of the artand similar are legitimate in technical writing. Keep them where they carry meaning, cut them where they are decoration. Full list and the replacement table are in references/tells.md.
Writing new prose
When you are producing the text rather than reviewing it, apply the hard rules as you write and run the linter once at the end. The four that catch most output:
- No em dashes anywhere.
- Delete the opener. Start on the claim.
- One hedge per sentence, or none.
- If a bullet is over forty words, it is a paragraph.
Scope
Skip files the user has said are stored verbatim, vendored third-party text, and generated output. If a file is exempt for good, add <!-- prose-lint: off --> at the top rather than remembering to pass --exclude every time.