README врёт: как я сделал open‑source линтер, который сверяет документацию с реальным репозиторием
README редко ломается в один момент. Обычно документация постепенно перестаёт соответствовать проекту: переименовали команду, перенесли файл, удалили .env.example, поменяли package manager или Docker service, а инструкция осталась прежней.
В итоге новый пользователь копирует команду из README и получает ошибку, а разработчик узнаёт об устаревшей документации только после issue, сообщения коллеги или неудачного запуска CI. При этом сам Markdown может быть совершенно правильным — проблема в том, что описанные в нём факты больше не соответствуют реальному проекту.
Мне стало интересно, какую часть таких ошибок можно находить автоматически, не выполняя команды из документации и не отправляя исходный код во внешние сервисы. Так появился RealityLint — open‑source CLI, который статически сверяет проверяемые утверждения из документации с фактическим состоянием репозитория.
Например, README предлагает выполнить npm run dev, но в реальном package.json остался только скрипт start. Или инструкция говорит скопировать .env.example, хотя этот файл уже удалён. То же самое происходит с Python entry‑файлами, Make targets, относительными ссылками, версиями и package manager.
Главный принцип RealityLint простой: если утверждение можно доказать по локальным данным репозитория — проверяем. Если надёжного доказательства нет — не угадываем. Поэтому инструмент не пытается «понять весь README», а работает только с конкретными фактами, которые можно проверить детерминированно.
В версии RealityLint v0.5.0 — Project Truth проект заметно вырос. Теперь можно проверять не только основной README, но и документацию проекта целиком:
realitylint . --all-docs
Поддерживаются README*.md, документы внутри docs/, CONTRIBUTING.md и собственные glob‑шаблоны.
Сейчас RealityLint содержит правила RL000–RL022. Инструмент умеет проверять npm/yarn/pnpm/bun scripts, относительные ссылки и локальные пути, .env.example и .env.sample, соответствие package manager lock‑файлам, Python entry files, Make targets, версии проекта и заявления о лицензии.
В v0.5 появились и более серьёзные проверки. Например, RealityLint умеет анализировать Docker Compose. Если документация говорит:
docker compose up api
а в compose.yml существует только service web, инструмент сообщит о расхождении. Также проверяются env_file, profiles и документированные localhost‑порты. README может предлагать открыть localhost:9999, хотя Compose уже публикует 8080 — это тоже можно обнаружить статически, не запуская контейнеры.
Ещё одно направление — переменные окружения. Допустим, приложение использует:
os.getenv("DATABASE_URL")
README говорит настроить DATABASE_URL, но в .env.example этой переменной больше нет. RealityLint может сопоставлять явные упоминания переменных в документации, env templates и распространённые способы обращения к ним в исходном коде.
Добавилась поддержка Go и Rust. Для Go можно проверять локальные go run targets и сравнивать заявленную в документации версию с go.mod. Для Rust/Cargo проверяются manifest, binaries, features и MSRV.
При этом одно из основных ограничений проекта осталось неизменным: RealityLint никогда не выполняет команды, найденные в документации. README рассматривается как недоверенный ввод. Инструмент работает локально, не требует API‑ключа, не отправляет исходный код наружу и не использует LLM как источник истины. Если утверждение нельзя проверить достаточно надёжно, оно пропускается.
Для старых проектов появился baseline‑режим. Если RealityLint впервые подключается к большому репозиторию и сразу находит накопившиеся проблемы, необязательно исправлять всё перед включением CI. Можно сохранить текущее состояние:
realitylint . --all-docs --write-baseline
а затем отслеживать уже новые расхождения:
realitylint . --all-docs
Также появились .realitylint.toml, настройка severity отдельных правил, отключение ненужных проверок, inline ignore directives для намеренно неправильных примеров, pre‑commit integration и JUnit XML. Помимо этого поддерживаются text, JSON, Markdown и SARIF.
Установить RealityLint можно из PyPI:
pip install realitylint
Обычная проверка текущего проекта:
realitylint .
Проверка нескольких документов:
realitylint . --all-docs
Для CI можно указать порог:
realitylint . --fail-on error
RealityLint также доступен как GitHub Action:
- uses: voonterr/realitylint@v1 with: fail-on: error
Смысл такого сценария в том, чтобы замечать устаревшую документацию в том же pull request, который её случайно сломал. README обычно не портят специально — он становится неправильным побочным эффектом обычного изменения кода, структуры каталогов или конфигурации.
На момент публикации актуальная версия — 0.5.0. Проект находится в Beta, поддерживает Python 3.10+, тестируется на Windows, Linux и macOS, содержит 91 автоматический тест, опубликован в PyPI и доступен как GitHub Action.
Для меня основная идея RealityLint в итоге оказалась довольно простой: документация — это тоже часть интерфейса проекта. Если код проверяется тестами, metadata — валидаторами, а конфигурация — линтерами, то хотя бы часть конкретных утверждений README тоже можно проверять автоматически.
Не весь естественный язык и не любое предложение. Но утверждения вроде «этот файл существует», «эта команда определена», «этот Docker service есть в Compose», “эта переменная присутствует в env template” или «этот Cargo feature существует» вполне можно сверять с реальностью.
Исходный код: https://github.com/voonterr/realitylint
PyPI: https://pypi.org/project/realitylint/
Проект открыт для issues и pull requests. Особенно интересно мнение тех, кто поддерживает open‑source или большие внутренние репозитории: какие виды устаревания документации встречаются у вас чаще всего и что из этого стоило бы проверять автоматически?

