Vale
The prose linter — a syntax-aware, configurable style enforcer for Markdown, reStructuredText, AsciiDoc, and plain text. Wraps a YAML config + a folder of rule definitions around a Go binary. Catches the recurring phrase fingerprints, banned clichés, and voice drift that ${'`'}post-system.md${'`'} already names. Pre-commit hook material; zero spend, runs locally.
Vale is the editorial discipline of the post-system bar made executable. Rules live in a folder; the CLI walks Markdown and flags every line that breaks them. This page is the orient-and-set-up-the-style surface — official docs at vale.sh own the rule grammar.
What it is
A syntax-aware command-line linter for natural-language prose, written in Go. MIT licensed; brew install vale or go install github.com/errata-ai/vale/v3. Rules are YAML files declaring one of a handful of checks — existence (forbidden phrases), substitution (preferred wording), occurrence (frequency caps), repetition (banned repeats), conditional (compound rules). Rules collect into a style (a folder); a project's .vale.ini selects which styles run against which files.
The pitch: editorial rules that today live as English in post-system.md ("retire 'and that's the whole point' for three posts," "no template fingerprints," "≤ one disclaimer loop") become enforceable as code. Pre-commit, pre-merge, or in CI — your call. The discipline survives without you remembering it.
When to use it
Reach for it when:
- You have recurring phrase fingerprints you want to catch before they ship — Build Daily already names these in
post-system.md. - You're shipping a publication with a voice bar and want the bar enforced consistently across drafts.
- You want PR-time feedback rather than a post-mortem after a bad post ships.
- You'd benefit from a personal style memory — every correction you make becomes a rule you never have to make again.
Skip it when:
- The corpus is one-off, low-volume, or doesn't have a consistent voice yet.
- The voice rules are still being discovered — Vale rewards a fairly settled bar.
- All editorial happens through a human reviewer who already catches what Vale would.
At a glance
Core concepts
- Check — a rule kind.
existenceforbids phrases;substitutionswaps for preferred wording;occurrencecaps frequency;repetitioncatches accidental repeats;conditionaldoes compound logic. - Rule — a single YAML file declaring one check, plus the trigger phrases/regex + a severity (
suggestion/warning/error). - Style — a folder of rules; multiple styles can run together. Errata AI ships several (
Microsoft,Google,proselint,write-good,alex); custom styles live instyles/<YourStyle>/. .vale.ini— project config. Selects styles, scopes them to file types, sets paths.
Distribution
- CLI —
vale .walks the project, prints findings. - VS Code / editor extensions — surfaces findings inline as you write.
- GitHub Action — runs on PR; can fail the build on
error-severity hits or just comment. - Pre-commit hook —
pre-commitintegration; runs against staged changes.
How to integrate
Default integration order for a Build Daily-style publication:
- Install + config.
brew install vale; commit.vale.iniselecting starter styles (MicrosoftorGoogleas the base, your custom style on top). - Mine
post-system.mdfor rules. Each banned phrase, fingerprint, and "retire for N posts" rule becomes one Vale YAML rule understyles/BuildDaily/. - Severity ramp. Start every rule at
suggestionfor a week — surface, don't block. Promote towarningonce the noise is tolerable. Promote toerroronly for rules you'd reject a PR over. - Wire to CI. GitHub Action runs Vale on every PR to
beta; posts inline comments at the flagged lines. - Editor extension on the writing machine. Findings show up while drafting, not just at PR time.
- Feedback loop. When a reviewer catches something Vale missed, write the rule. The custom style grows with the bar.
In the GL stack
builddaily.io
- Encode
post-system.mdas a Vale style. "Retire 'and that's the whole point' for three posts," "no template fingerprints," "≤ one disclaimer loop" — each rule one YAML file underweb/.vale/styles/BuildDaily/. - CI gate on draft PRs. Vale runs against
web/content/posts/**/*.mdandweb/content/logs/**/*.mdon every PR targetingbeta; anerror-severity hit fails the check. - Personal style accretion. Every correction you make on a draft becomes a Vale rule. Over time, the style file is a machine-readable record of your editorial preferences.
paiddaily.io
- Trading Almanac voice enforcement. Same shape, different vocabulary. Catches the financial-marketing clichés ("market-beating", "high-conviction", "edge") that don't fit the publication's voice.
- Morning Brief consistency. The brief has a fixed shape — Vale rules can enforce section presence, banned hedge phrases, ticker-symbol formatting.
sagedaily.io
- Sage voice guardrails. The "Oracle voice" notes in the DSPy Signatures (playful, loving, slightly mystical, ≤ 150 words, no "you will" predictions) translate into Vale rules — catch a reading that ships with "you will" before it goes out.
- Astrology-jargon caps.
occurrencerules cap how often Vedic/tarot jargon stacks in a single reading.
Gotchas
- Severity ramp matters. Starting every rule at
errorfloods PRs with noise and trains everyone to ignore it. Default tosuggestion; promote one rule at a time. - False positives compound. A rule that's right 80% of the time is wrong 1 in 5 hits — the wrong hits erode trust. Tighter is better; add an exception list if needed.
- Vale knows nothing about content collections. It lints text; it doesn't validate frontmatter schemas (Astro/Hugo do that). Don't try to make Vale do schema work.
- Code blocks are skipped by default. Good for prose-only checks; surprising the first time you wonder why a check didn't fire inside a fenced block.
Risks
- Discipline tax. Vale only earns its keep if the style file is maintained. Stale rules misfire; missing rules let regressions through. Budget ~5 minutes per rule corrected.
- Voice drift toward the mean. Aggressive auto-flagging can pressure writing toward the lowest-common-denominator phrasing. Mitigate by keeping most rules at
suggestionand reservingerrorfor true house-style violations.
Related
- DSPy — pairs with Vale on the writer side. DSPy compiles the draft; Vale checks it against the editorial bar before merge.
