这次我们来看一个开源项目:Vale,一个面向散文和自然语言文本的 Linter。
如果你写过技术文档、API 说明、博客文章,或者维护过一个团队的 Wiki,大概率遇到过这个问题:Markdown 文件写得很快,但风格不统一。有时候是 "login" 和 "log in" 混用,有时候是 "Click" 和 "Click on" 同时出现,人工 review 一遍遍改,既累又容易漏。Vale 解决的正是这个问题。它不是代码 Linter,而是把代码静态检查的思路搬到文字里,用规则去检查措辞、术语、语气、标点、书面表达的一致性。
这个项目来自 GitHub 上的 errata-ai 仓库,主程序用 Go 编写,安装后是一个独立命令行工具。它最有价值的地方是:完全本地运行、不需要 GPU、不依赖云服务、配置和规则都是文件、可以接进 CI/CD,也可以接进 VS Code。换句话说,它是一个可以长期沉淀进团队协作流程的文本质量基础设施。
这篇文章会先给你完整的核心能力速览,然后讲清楚 Vale 适合和不适合做什么,再带你完成本地安装、.vale.ini配置、样式加载、命令行检查、自定义规则编写,以及接入 Git 提交钩子和 CI 的通用方法。看完你可以直接把它用到自己的文档项目里,不用再靠肉眼逐字对齐。
1. Vale 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目类型 | 面向自然语言的 Linter,也可称为 Prose Linter、Style Linter |
| 开源情况 | 开源项目,主仓库在 GitHub 的 errata-ai/vale |
| 开发语言 | Go,发布为单个可执行文件 |
| 是否依赖 GPU / 云服务 | 不依赖,纯本地运行 |
| 支持平台 | 支持 macOS、Linux、Windows,常见发行渠道均有覆盖 |
| 安装方式 | Homebrew、Chocolatey、Scoop、下载 release 二进制、go install、Docker 镜像 |
| 输入格式 | Markdown、reStructuredText、AsciiDoc、HTML、XML、LaTeX、纯文本等常见文档格式 |
| 检查能力 | 拼写习惯、术语一致性、风格偏好、句式提示、过时用语检测、标点和格式提示 |
| 规则的扩展方式 | 基于 YAML 的自定义规则,支持 existence、substitution、sequence、occurrence 等多类规则模板 |
| 样式包 | 可加载社区和商业样式包,如 Vale 自带规则、Microsoft 风格、Google 文档风格等,也可自建 |
| 输出格式 | 终端可读文本,以及 JSON / 行输出等结构化形式,便于工具集成 |
| 批量任务 | 支持直接扫描目录、递归处理多个文件,适合在整个文档仓库上执行 |
| 接口与集成 | 支持配置文件驱动的服务模式、VS Code 插件,支持 pre-commit、GitHub Actions 等 CI 场景 |
| 适合场景 | 技术文档团队、知识库维护者、博客作者、API 文档系统、文档 CI 流水线 |
从这张表可以快速得出判断:Vale 的入门成本非常低,不需要显卡,不需要模型文件,也不强制你改掉现有写作流程。你只需要把二进制下载下来,写一个配置文件,再放上规则,它就能开始工作。
2. 适用场景与使用边界
Vale 最适合的场景是成规模的文档输入输出。当你的文档数量从几十篇涨到几百篇,或者团队里有多个成员同时维护同一套文档时,人工无法保证每一次用词都一致。这时候由 Vale 在提交前或 CI 中跑一遍,把低级的风格问题直接拦住,能让 Review 的人专注在内容本身。
常见落地场景包括:
- 团队知识库的 Markdown 文件统一检查。
- API 文档中的术语表强制匹配,降低用户理解偏差。
- 博客或产品文案的发布前检查。
- 与 Git 提交钩子、pre-commit、CI 流水线结合,不合格的文档不允许合并。
- 对历史文档批量扫描,发现一批过时用语或不一致表达。
从边界上看,Vale 不是内容生成器,也不是语义编辑器。它不会帮你判断一个句子是否逻辑通顺,不会做深层语法理解,更不会替你改写段落。它更像一个"基于规则的模式匹配器"加"轻量自然语言分析器"。规则写得好,检查效果就精准;规则没覆盖到,它就保持沉默。
另外要提一下部署边界:Vale 是本地命令行工具,所有规则和配置都以文件形式存在,因此适合放进 Git 仓库统一管理。你不需要启动常驻服务来做基础检查。如果你的诉求是"写一个带图形界面的校对平台"或"让 AI 自动改写整篇文字",Vale 不是那个答案。它是流程里的一环,不是完整的编辑系统。
3. 本地部署环境准备
Vale 对环境的要求非常宽松。操作系统层面,常规的 macOS、Linux、Windows 都有对应的安装方式。因为它是 Go 编出来的一个小体积二进制,基本不需要额外的运行时依赖,也不需要安装 Python 或 Node。你唯一要保证的,是终端能正常执行下载下来的可执行文件。
在正式开始前,建议确认四件事:
- 操作系统是什么版本。这个不卡 Vale 的版本,但会影响你使用包管理器还是手动下载二进制。
- 是否安装了 Homebrew、Chocolatey 或 Scoop。有包管理器安装会省事一些。
- 文档项目的目录结构。Vale 默认会在项目目录里找配置文件,建议先把目录规划好。
- 准备一个测试文件,比如
test.md,里面放几句话,方便后面验证效果。
如果你打算用 Docker 跑 Vale,不用关心系统环境;如果你打算本地二进制安装,只需要保证解压后有执行权限。对于 Windows 用户,我建议优先用 Chocolatey 或 Scoop 安装,这样可以自动把可执行文件放到 PATH 里,省去手动配置环境变量的步骤。
磁盘占用方面,Vale 本身是一个普通 CLI 工具,单个二进制文件往往只有几十 MB 量级,具体大小以 release 页面为准。它不像 AI 模型那样要占用几十 GB,普通开发机跑起来毫无压力。
4. 安装部署与启动方式
Vale 的安装路径比较多,我按使用场景给出常见的几种方式。你可以根据自己机器的软件管理习惯选一种。
4.1 macOS 通过 Homebrew
brew install vale装完后确认版本:
vale --version如果能在终端看到版本号,说明安装成功。这一步同时也是验证 PATH 是否配置正确的最直接方式。
4.2 Windows 通过 Chocolatey 或 Scoop
Chocolatey:
choco install valeScoop:
scoop install vale如果你的 Windows 机器没有这些包管理器,也可以直接从 Vale 的 GitHub release 页面下载对应平台的压缩包,解压后把vale.exe放到一个固定目录,再加入 PATH。Windows 下安装完成后,同样用vale --version验证。
4.3 Linux 下载二进制
# 先到 release 页面找到 linux 对应的下载地址 # 这里是一个通用思路,实际地址需要按版本替换 wget https://github.com/errata-ai/vale/releases/download/<version>/vale_<version>_Linux_64-bit.tar.gz tar -xzf vale_<version>_Linux_64-bit.tar.gz sudo mv vale /usr/local/bin/ vale --version这种手动安装方式的好处是干净、不引入额外依赖。缺点是每次升级都要自己重新下载。如果项目里有统一的自动化脚本,可以把这步写成固定任务。
4.4 Go 安装
如果你本机已经有 Go 环境,也可以用:
go install github.com/errata-ai/vale/v2/cmd/vale@latest安装后,Vale 会放到$GOPATH/bin或$HOME/go/bin,需要确保这个目录在 PATH 里。
4.5 Docker 方式
# 进入文档所在目录执行 docker run --rm \ -v "$(pwd)":/workspace \ -w /workspace \ erf/vale vale .使用 Docker 的好处是可以固定版本,避免不同机器上 Vale 版本不一致导致检查结果不同。缺点是容器内需要挂载目录,初次使用要理解 volume 参数的含义。
4.6 启动与查看帮助
Vale 不是一个常驻服务,它的"启动"就是执行一次命令行检查。建议先看帮助信息:
vale --help常见参数包括:
vale --config=.vale.ini --minAlertLevel=warning --output=JSON .其中--config指定配置文件;--minAlertLevel控制最低告警级别;--output控制输出格式;最后的.表示检查当前目录下的所有文件。这些参数在不同版本里可能略有差异,以vale --help输出为准。
5. Vale 的配置文件与样式加载
Vale 的核心是配置文件。它默认使用.vale.ini,放在项目根目录。这个文件用 INI 格式编写,决定了三个关键问题:去哪找规则、规则按什么级别生效、哪些文件适用哪些规则。
5.1 最小配置
# .vale.ini StylesPath = styles MinAlertLevel = warning [*.md] BasedOnStyles = Vale先解释一下:
StylesPath指向样式目录。Vale 的规则文件放在这个目录下。MinAlertLevel表示最低显示级别,可选suggestion、warning、error。设置成warning可以过滤掉过于细碎的建议。[*.md]是一个格式匹配段,表示对 Markdown 文件生效。BasedOnStyles决定要应用哪一组规则目录。这里引用的是Vale这个内置样式。
没有配置文件时,Vale 无法判断该用什么规则,所以写文档项目时,.vale.ini要随仓库一起提交。
5.2 引入更多样式包
Vale 支持通过Packages声明需要同步的样式包。比如:
StylesPath = styles MinAlertLevel = warning Packages = Microsoft, Google [*.md] BasedOnStyles = Vale, Microsoft, Google这里Packages表示去样式市场拉取Microsoft和Google这两个公开样式包,BasedOnStyles表示在扫描 Markdown 时同时启用这几组规则。不同样式包之间可能对同一个词给出不同建议,这时你可以通过级别设置和自定义覆盖来平衡。实际生产项目中,我更倾向于先启用一组样式,跑完看输出,再按团队需要加第二组,不要一上来就同时启用很多。
5.3 Vocab 词汇表
Vale 还有一个很实用的机制叫Vocab,用来指定专有名词或允许出现的词汇。比如 API 名字、产品名、团队内部术语,这些词既不想被拼写规则报错,又想在术语检查里保持统一,就可以放进词汇表。
Vocab = Docs [*.md] BasedOnStyles = Vale然后在styles/Vocab/Docs/accept.txt里写上允许的词:
AIGC RAG ComfyUI在styles/Vocab/Docs/reject.txt里写不推荐出现的词。这样写文档的时候,产品名就不会被误报成拼写错误,同时你也能集中管理团队内部的"禁用词"。
5.4 格式匹配与作用范围
配置文件里的[...]段就是格式匹配规则。你可以为不同格式使用不同规则:
[*.md] BasedOnStyles = Vale [*.adoc] BasedOnStyles = Vale, Microsoft [*.html] BasedOnStyles = Vale也可以对特定文件覆盖配置。这个机制让 Vale 在混合文档仓库里非常灵活。比如README.md要求更严格,其他开发笔记放宽,都能通过不同段实现。
从使用习惯来说,配置文件是 Vale 真正需要沉淀的东西。安装二进制只是第一步,规则、词汇表、格式匹配方案才是最花时间的地方。建议团队把.vale.ini和styles目录都提交进 Git,让所有人用同一套检查标准。
6. 功能测试与效果验证
环境配好后,先别急着写复杂规则。我们用一个最简案例验证 Vale 是否真的在检查文本。
6.1 准备测试文件
创建test.md:
# Vale Test This is a sample text. It contains some words. The user should click on the button.这个文本里至少有两点值得注意:should属于文档风格里常见的弱表达;click on在很多技术写作规范里也被建议改成click。如果样式包里有对应规则,Vale 会提示。
6.2 执行检查
在test.md所在目录执行:
vale test.md终端会输出类似下面的内容:
test.md 2:1 warning Consider removing 'Vale' Vale.Spelling warning并且最终会有一行总结,类似:
✓ 0 errors, 0 warnings and 0 suggestions in 1 file.不同版本的 Vale 输出格式会有差异,这里只是一个示意。关键是判断标准:只要命令能正常执行,并且文件路径、行号、规则名出现在输出里,就说明 Vale 的检查链路已经通了。
6.3 测试不命中规则的情况
再创建一个没有问题的文件:
# Clean Test This document contains no obvious style issues.跑vale clean_test.md,如果终端显示零告警,说明 Vale 的规则过滤是有效的。这个正反例验证过程很有用,它能让你快速辨别"规则没生效"和"当前文本本来就合规"这两种情况。
6.4 验证告警级别
如果想看更多提示,可以在命令中加参数:
vale --minAlertLevel=suggestion test.md这样会把suggestion级别的建议也显示出来。第一次使用 Vale 时,我建议用suggestion级别看完整输出,了解规则覆盖面;真正接入 CI 时再考虑用warning或error,避免被大量建议刷屏。
6.5 输出结构化结果
如果你想把 Vale 接入自己的脚本,可以使用 JSON 输出:
vale --output=JSON test.md输出会是一段结构化 JSON,包含文件路径、行号、消息内容、严重级别等信息。在你的工具链里解析起来会方便很多。结构化输出是 Vale 的一个重要接口能力,文本终端汇报只是它的表面形态。
7. 与 VS Code、Git、CI 集成
Vale 最常见的生产用法不是手动敲命令,而是接入到编辑器、Git 钩子和 CI 流水线里。这样文档在生成前就被检查了。
7.1 VS Code 插件
VS Code 扩展市场里可以搜索 Vale 相关插件,安装后打开一个 Markdown 文件,插件会调用本地 Vale 并在编辑器里标出问题。它的好处是即时反馈:写一句,看到一句,不需要切到终端。插件的本质还是调用本机的 Vale 二进制,所以本地必须已经安装好 Vale,并且项目里要有.vale.ini。如果插件提示找不到 Vale,先检查 PATH 和配置路径。
7.2 pre-commit 集成
如果你用 pre-commit 管理 Git 钩子,可以在.pre-commit-config.yaml里加一个 Vale 的 hook。社区有对应的 Vale hook 仓库,通用配置大概是:
repos: - repo: https://github.com/errata-ai/vale rev: <版本号> hooks: - id: vale args: ["--minAlertLevel=error"]上面的确切rev和仓库地址需要以 pre-commit 社区当前配置为准。接入后,每次git commit前,Vale 只会检查暂存区里的文档文件,不合格就直接拦截提交。这种模式很适合强制团队统一写作风格。
7.3 GitHub Actions 集成
如果是 GitHub 仓库,可以在.github/workflows/docs.yml里加一个文档检查任务。常规逻辑是:安装 Vale、同步规则、对变更文档执行检查、有问题就失败。伪配置如下:
name: Vale Doc Check on: pull_request: jobs: vale: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Vale run: | # 从 release 下载对应版本 # 这里用通用命令模板,实际版本号按仓库 release 替换 wget -q https://github.com/errata-ai/vale/releases/download/<version>/vale_<version>_Linux_64-bit.tar.gz tar -xzf vale_*.tar.gz sudo mv vale /usr/local/bin/ - name: Run Vale run: vale . --minAlertLevel=warning社区也有专门的 Vale action,使用起来更简洁。如果你不想维护下载脚本,可以优先搜 action。这里给的是一个不依赖第三方仓库也能跑通的模板思路。
8. 自定义规则与样式包开发
Vale 的规则文件放在样式目录下,每个规则是一个 YAML 文件。这是它最强大的地方:你可以把团队吐槽过无数次的"不要用 click on"变成一条自动规则。
8.1 规则文件基本结构
extends: substitution message: "Use '%s' instead of '%s'." level: warning ignorecase: true swap: "click on": "click" "log in": "sign in"解释一下这个规则:
extends声明规则类型,常用有existence、substitution、sequence、occurrence等。message是触发后展示给用户的提示,%s是占位符。level是严重级别。ignorecase表示忽略大小写。swap是替换型规则特有的字段,定义哪些词会被检查。
这个规则放到styles/MyDocs/Substitutions.yml后,在.vale.ini的对应格式段里启用MyDocs样式:
[*.md] BasedOnStyles = Vale, MyDocs然后重新执行vale test.md,你就能看到click on被提示了。
8.2 常用规则类型
再举几个常见规则类型的例子,方便你判断怎么写。
existence用于检查某个词或模式是否出现:
extends: existence message: "Do not use '%s'." level: error ignorecase: true tokens: - should - may besequence用于检查多个词之间的顺序关系:
extends: sequence message: "Use 'first' before 'second'." level: warning ignorecase: true sequence: - scope: sentence tokens: - "first" - "second"occurrence用于限制某个词在范围内出现的最多次数:
extends: occurrence message: "Avoid multiple uses of '%s'." level: warning scope: sentence max: 1 tokens: - very这些类型乍看不多,但组合起来已经能覆盖大部分文档风格检查需求。更重要的是,规则以文件形式存在,团队里谁都能 review 和修改,不需要写一整个插件。
8.3 规则调试建议
新建规则后,用一个小文件做正反测试:
# 应触发规则 echo "You should click on the button." > test_bad.md vale test_bad.md # 不应触发规则 echo "Click the button." > test_good.md vale test_good.md如果正例不提示、反例提示,说明规则可用;如果两者都不提示,先检查规则文件名是否被加载、格式段是否匹配、规则里的scope是否正确。规则调试是 Vale 使用里最需要耐心的一环,但也是收益最大的一环。
9. 资源占用与性能观察
Vale 是用 Go 写的命令行工具,和跑大模型或者启动 WebUI 完全是两回事。它没有显存需求,没有 GPU 需求,也不占用常驻内存。你把它看成一个速度快、体积小的静态检查器就行。
在性能观察上,值得关注的是扫描耗时。对一个几十篇到几百篇 Markdown 文件的仓库,Vale 的扫描速度通常很快,但具体耗时受文件数量、样式规则复杂度、机器磁盘性能影响。想量化观察,可以用系统自带的时间统计:
# 在 Linux / macOS 下 time vale .如果扫描很慢,优先排查是不是单个超大文件拖累了整体,或者规则里使用了过多复杂的正则匹配。另一个有效的做法是只扫描变更文件,而不是每次都全量扫描。这样在 CI 中能显著缩短检查时间。
资源占用方面,不需要针对 Vale 做专门优化,除非你把它接到一个超大规模文档系统的后端,并且要频繁调用。即使那样,合理的做法也是把扫描任务做成异步队列,不要让 CLI 进程长期存活。
10. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
vale命令找不到 | 可执行文件不在 PATH | 使用which vale或where vale查看 | 把二进制所在目录加入 PATH,或重装 |
| 执行后提示找不到配置文件 | 当前目录没有.vale.ini | 运行ls -a查看隐藏文件 | 在项目根目录创建或指定--config |
| 所有文件都是零告警 | 规则未启用、格式段不匹配 | 检查[*.md]与文件扩展名是否匹配,确认BasedOnStyles正确 | 在配置里显式启用对应样式 |
| 规则写了但没生效 | 规则文件没放在StylesPath对应目录 | 检查规则文件路径、YAML 语法 | 修正路径,运行vale --debug看加载情况 |
| 中文文档被误报 | 默认规则基于英文风格 | 查看告警规则名 | 为中文文档配置独立格式段或词汇表 |
| 带 BOM 的文件出现奇怪提示 | 文件编码问题 | 用编辑器另存为 UTF-8 无 BOM | 统一文档编码 |
| CI 中检查失败 | 版本不一致或未安装 | 在 CI 日志里查看 Vale 版本 | 固定 Vale 版本,使用相同命令 |
| 输出结果很多,没法看 | 未设置告警级别 | 添加--minAlertLevel=warning | 生成 JSON 结果,交给脚本过滤 |
从排查规律来看,Vale 的问题通常出在配置加载阶段,而不是检查阶段。先确认配置文件和规则目录能被找到,再往下排查规则匹配,比盯着文本内容猜测要高效得多。
11. 最佳实践与使用建议
结合 Vale 的特性和日常使用经验,我建议按下面几个步骤推进,而不是一上来就追求最全规则集。
第一,先小范围试点。选一个文档子目录或一类文件,用默认规则跑一遍,确认 Vale 的告警符合你的预期。这个步骤能帮你熟悉输出格式和规则级别。
第二,固定配置文件。把.vale.ini、styles目录、Vocab词汇表全部提交进 Git,所有成员共用。不要在个人电脑上写一堆只在本地生效的规则。
第三,定期更新样式包。公开样式包会不断迭代,过老的规则可能不符合最新文档规范。建议在有版本控制的 CI 环境里升级测试,再推广到团队。
第四,把级别定高一点。如果只是想低调引入,先让 Vale 在 CI 中以warning或suggestion级别输出,不直接禁止合并;等团队接受后,再把关键规则调到error。强制不一定能带来配合,渐进式引入会更稳。
第五,为团队定制少量关键规则。公开样式覆盖的是通用规范,真正解决团队痛点是那几个反复出现的词和句式。用 YAML 把它们写进去,让规则替人盯这些细节。
12. 总结与下一步
Vale 是一个不用图形界面、不用 GPU、不用云服务就能跑起来的文档风格检查工具。它的核心能力在于把"写作风格约束"变成文件、变成规则、变成 CI 里的一环。把安装、配置、样式和集成做完之后,你的文档仓库就拥有了一道自动的文本质量检查关卡。
如果现在开始尝试,我建议第一件事是先安装 Vale 并跑通一个测试文件;第二件事是写一个替换型规则,把团队常用的违规词替换掉;第三件事是把它接进 Git 提交钩子或 CI,让检查自动发生。最容易踩的坑是配置文件路径和规则启用方式,遇到问题先往这两个方向排查。
后续可以继续扩展的方向:一类是维护团队自己的样式包,把术语表、禁用词、推荐句式沉淀成一个独立的规则库;另一类是把 Vale 的输出接到文档发布流程里,在生成 PDF 或 HTML 之前再跑一次终检。如果将来你的团队文档量继续增大,也可以考虑把 Vale 的 JSON 输出接入到一个简单的 dashboard,让文档质量问题变得可见、可追踪。