Vale is a linter for prose
Vale is a linter for prose
A command-line tool that brings code-like linting to your writing. Enforce a consistent editorial style across every doc, in any format—entirely offline.
bash — vale
$ vale sync
SUCCESS Synced 2 package(s) to 'styles'.
$ vale docs/
docs/configure.md
3:7 suggestion Consider using 'use' instead of 'utilize'. Microsoft.Wordiness
3:44 suggestion 'are loaded' looks like passive voice. Microsoft.Passive
9:12 error Use 'Vale CLI' instead of 'Vale cli'. Docs.Terms
docs/install.md
3:40 warning Use 'select' instead of the input-specific verb 'Click'. Microsoft.UIVerbs
4:28 error Did you really mean 'existant'? Vale.Spelling
✖ 2 errors, 1 warning and 2 suggestions in 2 files.
Setting up with an agent? Open in Claude Open in ChatGPT Agent skills
Thanks to Claude for Open Source.
Sponsor spotlights
These companies support Vale's future — and put it to work in their own products today.
Mintlify Ships Vale as a built-in CI check. Read the story
Promptless Runs Vale on every doc its agents write. Read the story
Read their configs
Every team here publishes something you can open — the `.vale.ini` they run, or the page they wrote about running it.
-
Writeup The EKS User Guide walks contributors through installing Vale for live style feedback. docs.aws.amazon.com Cloud & infrastructure
-
Repository Runs a packaged PowerShell-Docs style in their Documentarian toolkit. microsoft/Documentarian github.com
-
Discord Public config Vale's built-in rules across the public API documentation. .vale.ini discord/discord-api-docs -
Writeup A required check in GitLab's documentation testing pipeline. docs.gitlab.com Developer tools
-
Writeup Powers the prose linting rules in the Grafana Writers' Toolkit. grafana.com Data & observability
- NVIDIA Writeup All NeMo Agent Toolkit documentation is checked with Vale before it merges. docs.nvidia.com Developer tools
-
Public config Enforces style standards across the Docker product docs. .vale.ini docker/docs
-
Writeup Maintains "Vale at Red Hat", a public style package and onboarding guide. redhat-documentation.github.io Open source
-
Writeup Publishes datadog-vale and shifted docs quality left with it. datadoghq.com Data & observability
- Markdown
- AsciiDoc
- reStructuredText
- MDX
- MyST
- Quarto
- Typst
- HTML
- XML
- DITA
- Org
- QDoc How scopes work
- Go
- Rust
- Python
- Ruby
- C++
- C
- JavaScript
- TypeScript
- TSX
- Java
- Haskell
- Julia
- Lua
- PHP
- R
- QML
- Protobuf
- YAML
- CSS Inside the grammar
Why Vale
Most tools see text. Vale sees a document.
A heading, a code block, a comment, and a link URL are not the same thing—and a rule that can't tell them apart is a rule you end up switching off.
Markup-aware
Parses your markup instead of guessing at it
Twelve formats, each through a real parser rather than a pattern. Rules can target headings, lists, or table cells—and code spans, URLs, and fenced blocks are skipped before a rule ever runs.
Installation.md
Markdown parsed before prose rules run
heading paragraph blockquote list link ignored code ignored footnote ignored
#Installation
You can \\*utilize\\* Vale to lint \prose\—it ignores syntax like \`code\` and URLs.
\>A blockquote can still contain very unique product guidance.
\-Install the extension before the end result ships.
Vale is availible for macOS, Windows, and Linux.
\`\`\`js
const message = "This code utilizes a URL";
\`\`\`
\[^install\]: https://example.com/docs/utilize
Checked
headings, prose, quotes, lists
Skipped
syntax, links, code, footnotes
suggestion Consider replacing 'utilize', 'very unique', and 'end result'.
error Did you really mean 'availible'?
Code-aware
Your comments are documentation too
Vale lifts comments out of nineteen languages with tree-sitter grammars, so it knows where a comment ends and a marker inside a string literal stays code. The Markdown inside a doc comment is linted as though it were its own file.
person.rs
comments extracted with tree-sitter
line comment doc comment markdown string ignored code ignored
/// Creates a person with the given name.
///
/// \# Examples
///
/// \`\`\`
/// use doc::Person;
/// let person = Person::new("name");
/// \`\`\`
pub fn new(name: &str) -> Person {
// Names can utilize any script.
let raw = "// not a comment and not prose";
}
Checked
line comments, doc comments, Markdown prose
Skipped
syntax, identifiers, strings, fenced code
suggestion Consider using 'use' instead of 'utilize'.
Extensible
Rules that read grammar, not just strings
Part-of-speech patterns, cross-file relationships, readability formulas, and Tengo scripts sit alongside the token lists—twelve extension points in all. Each is a few lines of YAML in a folder you can hand around as a package.
sequence Matches grammar, not characters
extends: sequence
message: "Use 'meetup' instead of 'meet up'."
level: error
tokens:
- upos: NOUN
pattern: meet
- pattern: upOur next meet up is on Tuesday.
Let's meet up on Tuesday.
error Use 'meetup' instead of 'meet up'.
\# One alert, not two: 'meet' is a noun in the first sentence and a verb in the second.
conditional One pattern requires another
extends: conditional
message: "'%s' has no definition."
level: error
scope: text
first: '\b([A-Z]{3,5})\b'
second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)'
exceptions:
- APIThe HTTP endpoint requires an API key.
error 'HTTP' has no definition.
\# An acronym is allowed only once its expansion appears somewhere in the file.
consistency The file has a memory
extends: consistency
message: "Inconsistent spelling of '%s'."
level: error
either:
advisor: adviserAsk your advisor about it.
Then ask a different adviser.
error Inconsistent spelling of 'adviser'.
\# Neither spelling is wrong. Using both in one file is.
metric Arithmetic over the whole file
extends: metric
message: "Grade level (%s) is above 8."
level: warning
formula: |
(0.39 * (words / sentences)) +
(11.8 * (syllables / words)) - 15.59
condition: "> 8"Notwithstanding the aforementioned considerations regarding deployment, the implementation necessitates a comprehensive understanding of the underlying architecture and its associated operational characteristics, which must be evaluated in their entirety prior to the commencement of any migration activity undertaken by the platform engineering team.
warning Grade level (31.41) is above 8.
\# Counted, not matched—words, sentences, and syllables across the document.
script Drop down to real code
extends: script
message: "This paragraph runs long—consider splitting it."
level: suggestion
scope: raw
script: |
text := import("text")
matches := []
for line in text.split(scope, "\n") {
if len(text.split(line, " ")) > 40 {
i := text.index(scope, line)
matches = append(matches, {begin: i, end: i + len(line)})
}
}Notwithstanding the aforementioned considerations regarding deployment, the implementation necessitates a comprehensive understanding of the underlying architecture and its associated operational characteristics, which must be evaluated in their entirety prior to the commencement of any migration activity undertaken by the platform engineering team.
suggestion This paragraph runs long—consider splitting it.
\# Tengo, compiled once when the rule loads and cloned per block.
Previous slide Next slide
Fast
One binary, nothing to install alongside it
Written in Go, with no runtime and files linted in parallel. GitLab runs 82 rules across all 2,827 pages of its documentation in under twenty seconds.
2,827 pages of Markdown
82 rules applied
<20s start to finish
#### Private by design
Nothing leaves your machine. No account, no upload, and no training on your writing.
#### Runs everywhere
macOS, Windows, and Linux. MIT-licensed and maintained in the open.
#### Style guides included
Microsoft, Google, Red Hat and thirteen more, each installed with one command.
Distribution
Where Vale is downloaded
Also ships on WI WinGet v3.17.1 Snap Store v3.17.1LI Linux & BSD 17 repositories
Sources: GitHub, Docker Hub, PyPI, conda-forge, Homebrew, Chocolatey, winstall, Snapcraft, and Repology · 59 contributors · updated 2026-07-24
One tool, every app
More than just a command-line interface.
Vale runs where you already write—in your editor, in your notes app, and in CI before anything merges.
Apps
Wherever the prose gets written, with diagnostics as you type.
Automation
The same run, before anything merges.
Documentation platforms
Hosted docs that run Vale for you.
Learn more about our integrations →
