Skip to content

Blog

Documentation review in CI: a quality gate for docs

How to gate documentation in CI the way you gate code, and how Vale, markdownlint, lychee, and six other doc linters compare with EkLine on what each checks, what it misses, and how it is set up.

Cover Image for Documentation review in CI: a quality gate for docs
Published on
Read time
12 min

Your repository gates code on every pull request. A linter blocks the merge on a style violation, the test suite fails the build when behavior breaks, a scanner flags a vulnerable dependency. The documentation in that same repository usually ships with none of that. A broken link, a product name spelled three different ways, a heading that jumps from H2 to H4, or an API reference that no longer matches the code all move through review because no job is watching for them.

A prose linter in a CI job catches style nits, and that is worth having. A documentation quality gate does more. It also checks links, terminology, and structure, and the harder problem sits one step upstream: catching docs that no longer match the shipped code. Teams that start with a single-purpose linter tend to outgrow it once correctness, not just style, is what should break the build.

If you own the docs-as-code pipeline and decide what gates a pull request, here is how the common open-source doc linters and EkLine compare on what each tool checks and how it is set up, not on measured catch rates. EkLine makes one of the rows below, so read the table as a vendor's survey of its own category. There is no head-to-head accuracy benchmark here, and tool scope was checked in October 2026.

TL;DR

  • A documentation quality gate is a CI job that reviews a pull request and can fail the build or post inline comments, the same way a test suite or a code linter does.
  • Most open-source doc tools each cover one dimension: Vale checks prose style, markdownlint checks Markdown structure, lychee checks links, cspell checks spelling. Covering more means running several and maintaining several configs.
  • None of these tools, open-source or hosted, check whether the prose still matches the code it describes. That is a different job.
  • A tuned open-source linter is free, transparent, and good enough for a team with a settled style guide and someone to maintain the rules.
  • EkLine runs one CI gate across style, grammar, terminology, structure, and broken links, and reviews OpenAPI specs for quality. Checking docs against shipped code is the Docs Agent's drift workflow, which opens a pull request rather than failing the gate.

How a docs quality gate is wired into CI

A documentation gate works like any other CI check. It runs on each pull request, reviews the changed files, and reports what it finds. Two behaviors decide how strict it is: whether a finding fails the build, and whether findings land as inline comments on the pull request. EkLine's Docs Reviewer runs in the CI/CD pipeline and reviews every pull request across style, grammar, terminology, and structure, posting inline comments on the diff. It supports GitHub Actions, GitLab CI, and Bitbucket Pipelines.

The published GitHub Action quickstart wires it up with a single workflow file:

.github/workflows/ekline.ymlYAML
name: EkLine
on: [pull_request]
 
jobs:
  docs:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: ekline-io/ekline-github-action@v6
        with:
          content_dir: .
          ek_token: ${{ secrets.EK_TOKEN }}
          github_token: ${{ secrets.GITHUB_TOKEN }}
          reporter: github-pr-review

With that configuration, the github-pr-review reporter posts findings as review comments on the diff, and the workflow does not set fail_on_error. The action's fail_on_error input controls whether findings produce a failing exit code, and it defaults to false. So out of the box a finding shows up as a comment rather than blocking the merge. To make the build fail when the reviewer finds an error, set fail_on_error to true. A level input decides what counts as reportable at all, from informational notes up to errors. That gradient, comment-only to build-breaking, is what lets a team roll a gate out without blocking engineers on day one and tighten it once the signal is trusted.

What a documentation gate should check

Code review covers more than one concern, and so does a documentation review. Four categories catch most of what slips through a pull request, and a fifth is the one no linter solves.

  • Style. Active voice, sentence length, readability, and house conventions. This is what prose linters do, and it is where a style guide gets enforced automatically instead of in a reviewer's head.
  • Grammar. Spelling, punctuation, and syntax.
  • Terminology. One product name, one casing, one spelling across every contributor. This is the category that erodes quietly, because each author is locally consistent and the drift only shows across pages.
  • Structure and links. Heading hierarchy and link validity. A broken link is a defect that reaches the reader.
  • Match to the code. Whether the documented endpoint, flag, or default still exists in the shipped code. No linter in this comparison checks this, and it is worth being clear about why: a linter reads the document, not the system it describes.

The first four are what a CI gate can enforce on a pull request today. The fifth is a different job, and a fair comparison keeps it separate instead of implying a style checker covers it. For the background on what automated documentation review checks and how it fits a pipeline, that overview is a good starting point.

The tools, compared on scope and setup

These are the tools teams reach for when they wire documentation checks into CI. EkLine makes the last row; every other row is a separate third-party project, described from its own current project page. The comparison is on what each tool checks, what it leaves out, how it is run, and whether it fits a CI job. It is not a measurement of how many real issues each one catches.

ToolWhat it checksWhat it missesSetup modelRuns in CI
ValeProse and style, markup-aware, via YAML rules you write or adoptLink checking, Markdown structure, match to codeOpen-source (MIT), self-hosted CLIYes
lycheeBroken URLs and mail addresses in Markdown and HTMLProse, grammar, structure, terminology, match to codeOpen-source, self-hosted binary and GitHub ActionYes
markdownlintMarkdown structure and syntax: heading levels, list indentation, code-fence languageProse, grammar, links, match to codeOpen-source (MIT), self-hosted CLIYes
textlintNatural-language text, with rules added per need through pluginsLinks, structure, match to codeOpen-source (MIT), self-hosted CLIYes
proselintEnglish usage and clichés, via fixed heuristicsA configurable house style, links, structure, match to codeOpen-source (BSD-3), self-hosted CLIYes
write-goodHeuristic prose checks such as passive voice and weasel wordsLinks, structure, terminology, match to codeOpen-source (MIT), self-hosted CLIYes
alexInclusive-language word choiceEverything else, including links and match to codeOpen-source (MIT), self-hosted CLIYes
cspellSpelling in code and docsProse style, grammar, links, structure, match to codeOpen-source (MIT), self-hosted CLIYes
LanguageToolGrammar, spelling, punctuation, and some styleLinks, structure, match to codeHosted API, with an open-source self-hosted optionYes
Several linters paired, for example Vale plus markdownlint plus lycheeProse, structure, and links, each by its own toolMatch to code; one shared config and one place to tuneOpen-source, self-hosted, multiple configsYes
EkLineStyle, grammar, terminology, structure, broken links, and OpenAPI spec quality, in one reviewMatch to code is handled by a separate workflow, not this gateHosted, configured through one CI stepYes

Read down the "what it misses" column and the pattern is plain: each open-source tool covers one dimension well, none of them check documentation against the code, and getting broad coverage from them means running and maintaining more than one.

Where each option wins

Grouping by job makes the choice easier, because these tools are not really competing for the same slot.

If your only concern is Markdown structure, markdownlint is a light, direct fit. If you want to catch dead links and nothing else, lychee does that one job quickly. For spelling, cspell covers code and docs together, and for inclusive-language word choice, alex is purpose-built. For house prose style, Vale is the most capable of the group, provided you are ready to write and maintain the rules. LanguageTool leans toward grammar and punctuation and offers both a hosted API and a self-hosted build.

Once your answer is "more than one of those," the task shifts from picking a tool to assembling and maintaining a toolchain.

The case for staying with open-source linters

A tuned open-source linter in CI is free and auditable, and often good enough, and that case deserves to be made at full strength before anything replaces it. The rules are readable and the tool runs offline, so nothing leaves your pipeline.

Contentsquare's engineering team added Vale to CI "to surface errors to all contributors with every commit," found the full Google style package too noisy, enabled only the rules that fit, and ran it non-blocking, so neither errors nor warnings stopped the build. They advised teams to "resist rolling out every single rule." Scott Lowe, writing up his own setup, found that getting Vale going "isn't hard, but you do need to know where to put the files." For a team with a settled style guide and someone willing to own the configuration, stopping there is a sound decision.

The limit shows up along two lines. The first is coverage: because each tool owns one dimension, a gate that checks prose, structure, and links means Vale and markdownlint and lychee together, each with its own config file and its own place to tune. That is the configuration debt and the separate link checker that a pairing accumulates over time, and keeping the noise down across all of them is its own ongoing task, the kind of false-positive tuning that decides whether engineers trust the gate or route around it. The second is the category none of them reach: whether the docs still describe the code that shipped. When that is the failure you most want to catch, more prose rules do not help. That gap is the argument for treating documentation as one quality gate rather than a stack of single-purpose jobs.

A before and after diagram: on the left, three separate linters, Vale for prose, markdownlint for structure, and lychee for links, each with its own config and letting a renamed product slip through; on the right, one CI gate that checks style, grammar, terminology, structure, and links together and posts inline comments on the pull request (opens the full-size image in a new tab)
The same checks, consolidated from several single-purpose tools into one review.

Where EkLine fits, and where it does not

EkLine's Docs Reviewer is the hosted gate in the comparison. In CI it reviews a pull request for style, grammar, terminology, and structure, and posts inline comments on the diff, with the option to fail the build. Broken-link checking is built into the review as rule EK20001, on by default at severity Error, rather than a second tool bolted on. For API docs, EkLine can also review an OpenAPI spec for description completeness, security constraints, and structure such as unused components and broken references. That last check is about the quality of the spec itself, not about whether the prose matches running code.

In practice the before-and-after looks like this. Before, an engineer wires Vale for prose, markdownlint for structure, and lychee for links, each with a config file and a CI step, and a renamed product still slips through because terminology is not enforced consistently across contributors. After, one CI step reviews the same pull request across style, grammar, terminology, structure, and links, and leaves its findings inline where the author is already looking.

Be clear about the boundary. The Reviewer does not check whether the documentation matches the shipped code, and it should not be sold as if it did. That job belongs to the Docs Agent, whose drift workflow flags pull requests with documentation impact and can open a pull request with the fix for a person to review. That is upstream of the gate and produces a pull request, not a pass or fail check inside it. And where you need only one dimension, a lighter tool wins: if Markdown structure is your whole concern, markdownlint alone is less to run, and if a fully self-hosted, offline toolchain is a hard requirement, the open-source pairing is the better fit.

A recommendation by situation

  • One concern, settled. Pick the single tool for it: markdownlint for structure, lychee for links, cspell for spelling, Vale for a maintained house style.
  • Several concerns, a maintainer on hand. Pair the open-source tools and accept the configuration cost. For many teams this is a reasonable, transparent place to land, and it brings docs into the same pipeline discipline as code.
  • One gate across style, grammar, terminology, structure, and links, without stitching configs. This is where a hosted reviewer such as EkLine earns its place.
  • Docs that match the shipped code. No CI linter does this. Treat it as a separate workflow that opens a pull request, not as something you can add to the gate.

Count the dimensions you need to gate, including whether correctness as well as style belongs on that list. One prose linter fits a single dimension and falls short across several.

To see what the gate flags on your own pull requests, read the Docs Reviewer documentation and add it to your pipeline.

FAQ

A documentation quality gate is a CI job that reviews each pull request and can fail the build or post inline comments, the same way a test suite or a code linter does. A useful gate checks style, grammar, terminology, structure, and links.

It depends on how many dimensions you need to gate. For one concern, pick the single tool for it: markdownlint for Markdown structure, lychee for links, cspell for spelling, alex for inclusive language, or Vale for a maintained house style. For several concerns, either pair the open-source tools and maintain their configs, or use a hosted reviewer such as EkLine that covers style, grammar, terminology, structure, and links in one CI step.

No. None of the tools compared here check whether the prose still matches the shipped code, including EkLine's Docs Reviewer. A linter reads the document, not the system it describes. EkLine handles that job with the Docs Agent, which flags pull requests with documentation impact and can open a pull request with the fix for a person to review.

No. With the published quickstart, the github-pr-review reporter posts findings as review comments, and the fail_on_error input defaults to false. Set fail_on_error to true to fail the build when the reviewer finds an error.


Sources


Read more about

Cover Image for The right llms.txt plugin for each docs framework, and which to skip
Blog

The right llms.txt plugin for each docs framework, and which to skip

·14 min read

One llms.txt pick each for Docusaurus, MkDocs, Starlight, VitePress, Fumadocs, and Nextra, judged on GitHub stars, recent releases, llms.txt v2 accuracy, and extensibility, with the contenders we rejected and why.

Cover Image for Claude Code mods: what they are and when to build one
Blog

Claude Code mods: what they are and when to build one

·9 min read

Claude Code mods are small TypeScript or JavaScript plugins that draw panes, guard tool calls, and add commands inside Claude Code. What they are, why hooks were not enough, creative first mods, and when to skip one.

Cover Image for Gemini 4 Argon: What It Does and Where It Falls Short
Blog

Gemini 4 Argon: What It Does and Where It Falls Short

·15 min read

Google's Gemini 4 Argon leads its own benchmark table but trails on terminal agents and independent scoring, and you cannot call it yet. What it does, where it falls short, and which workloads to queue.

Cover Image for A2A Production Readiness: What It Takes Beyond Protocol Support
Blog

A2A Production Readiness: What It Takes Beyond Protocol Support

·12 min read

A2A standardizes agent communication. Production systems still need durable tasks, retry safety, authorization, recovery, and real interoperability tests.

Cover Image for OAuth for AI Agents: Why General-Purpose Agents Strain the Integration Model
Blog

OAuth for AI Agents: Why General-Purpose Agents Strain the Integration Model

·12 min read

General-purpose AI agents turn OAuth into a multi-identity, multi-provider state problem. Here is what integration platforms should change.

Cover Image for What Is WebMCP? When to Expose Browser Tools to AI Agents
Blog

What Is WebMCP? When to Expose Browser Tools to AI Agents

·12 min read

WebMCP lets a web app expose structured actions to browser agents. This guide compares it with browser automation and MCP servers.

See what EkLine finds in your docs.

Book a demo

15 minutes to set up. 15 insights of what agents read about you, and 15 days to improve. If you do not see the value, you walk away with 15 better pages.