Skip to main content
RealityLint — README drift detector

RealityLint

Your README says it works. RealityLint checks if it actually does.

Static, deterministic README-vs-repository verification — without executing README commands, without an LLM, and without sending your code anywhere.

by @voonterr

English · Русский

CI Python 3.10+ License: MIT GitHub stars

local-first · no API key · no LLM · CI-ready · safe static analysis


The problem

README files drift.

A command gets renamed. A file moves. .env.example disappears. The project switches from Yarn to npm. AI-generated documentation confidently describes a script that never existed.

Most Markdown linters can tell you whether the document is formatted correctly. RealityLint asks a different question:

Do the locally verifiable claims in this README still match the repository?

It stays deliberately conservative: if a claim cannot be proven from local repository evidence, RealityLint skips it instead of guessing.

30-second demo

RealityLint demo

realitylint examples/broken-project --fail-on never
RealityLint v0.1.3 — by @voonterr
RealityLint score: 34/100

✗ README.md:3 ERROR   RL002 Documented local link target "docs/setup.md" does not exist.
! README.md:6 WARNING RL004 README uses yarn, but the repository has only an npm lockfile.
✗ README.md:7 ERROR   RL001 Documented package script "dev" is not defined in package.json.
✗ README.md:8 ERROR   RL003 Documented environment template ".env.example" does not exist.
✗ README.md:9 ERROR   RL005 Documented Python entry file "scripts/start.py" does not exist.

4 error(s), 1 warning(s), 0 notice(s).

Why RealityLint?

RealityLint
Deterministic Same repository → same result. No model randomness.
Safe by design Parses commands from docs but never executes them.
Private Your repository never leaves the machine.
CI-friendly Text, JSON, Markdown and SARIF output.
Low false-positive bias Ambiguous claims are skipped instead of guessed.
Monorepo-aware Understands common working-directory forms such as cd frontend && ....

What it checks

Rule Verification
RL000 Repository/README scan preconditions are safe and readable
RL001 npm/pnpm/yarn/bun package scripts exist in the relevant package.json
RL002 Relative Markdown links and images point to real local paths
RL003 Documented .env.example / .env.sample files exist
RL004 Package-manager commands agree with the detected lockfile family
RL005 Python entry-file commands point to real files
RL006 Documented Make targets exist in GNUmakefile/makefile/Makefile
RL007 Pinned self-install versions agree with [project].version
RL008 A claimed common license has a real LICENSE/COPYING file
RL009 Obvious inline repository paths still exist (notice)
RL010 Malformed/unreadable package metadata is reported instead of crashing

RealityLint also understands common cd subdir && ... flows, npm --prefix, yarn --cwd, pnpm --dir / pnpm -C, bun --cwd, make -C, nested README link bases, Windows-style path separators/prompts, backtick/tilde shell fences and inline shell commands.

Quick start

Requires Python 3.10+.

git clone https://github.com/voonterr/realitylint.git
cd realitylint
python -m pip install -e .
realitylint .

Or run it from the source checkout without installing the console script:

python -m realitylint /path/to/repository

Try the intentionally broken fixture:

realitylint examples/broken-project --fail-on never

GitHub Actions

Add this to .github/workflows/realitylint.yml in another repository:

name: README reality check
on: [pull_request]

permissions:
  contents: read

jobs:
  realitylint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: voonterr/realitylint@v1
        with:
          fail-on: error

The action emits inline annotations and a Markdown job summary.

Note: voonterr/realitylint@v1 becomes usable after the first v1 tag is published. See PUBLISH.md for the release checklist.

Output formats

realitylint . --format text
realitylint . --format json
realitylint . --format markdown
realitylint . --format sarif

CI failure policy:

realitylint . --fail-on error
realitylint . --fail-on warning
realitylint . --fail-on never

Machine-readable formats keep stdout clean — the by @voonterr banner does not corrupt JSON or SARIF output.

Security model

RealityLint is intentionally a static checker, not a sandbox.

  • README commands are parsed, never executed.
  • --readme cannot escape the repository root.
  • Symlink/path resolution is contained before files are read.
  • README and metadata files have size limits to reduce memory/regex abuse.
  • GitHub Action inputs are passed through environment variables instead of direct shell interpolation.
  • GitHub annotations escape workflow-command control characters.
  • Third-party Actions used by this repository are pinned to immutable commit SHAs.
  • No network access is required for the scanner itself.

Found a security issue? Please read SECURITY.md instead of opening a public exploit report.

Project philosophy

  1. Evidence over vibes. Every finding should point to repository evidence.
  2. No arbitrary execution. Documentation commands are parsed, never run.
  3. Prefer silence to a false accusation. Ambiguous syntax is skipped.
  4. Local-first. Source code and docs stay on the user's machine.
  5. Small rules, easy contributions. Ecosystem checks should remain isolated and testable.

Roadmap

Near-term priorities:

  • Go: go run, module path and toolchain claims
  • Rust: cargo run --bin, features and MSRV claims
  • Docker Compose service/port verification
  • .env variable drift: code ↔ template ↔ docs
  • pre-commit hook
  • ignore directives for intentional examples
  • CLI flag verification from generated --help snapshots

See the detailed ROADMAP.md.

Contributing

Bug reports, rule ideas and pull requests are welcome.

python -m unittest discover -s tests -v

Start with CONTRIBUTING.md. New contributors can also open a rule request using the repository issue template.

Status

RealityLint is currently alpha software. Its checks are intentionally narrow and deterministic. It will not understand every shell expression or every documentation style — and it should not pretend to.

Author

Created and maintained by @voonterr.

If RealityLint saves you from a broken README, consider ⭐ starring the repository — it helps other developers discover the project.

License

MIT License. Copyright © 2026 voonterr. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

realitylint-0.1.3.tar.gz (24.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

realitylint-0.1.3-py3-none-any.whl (17.1 kB view details)

Uploaded Python 3

File details

Details for the file realitylint-0.1.3.tar.gz.

File metadata

  • Download URL: realitylint-0.1.3.tar.gz
  • Upload date:
  • Size: 24.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for realitylint-0.1.3.tar.gz
Algorithm Hash digest
SHA256 b4710c0a900e562fc24b660f0fccb24002fe279309c35366c259475ebb831f2b
MD5 5b7d2378695f5b2111540fae30fd2606
BLAKE2b-256 0282167eb301df1268e1e18a131042efd13ae978e7a114283a538cee27d6fc92

See more details on using hashes here.

Provenance

The following attestation bundles were made for realitylint-0.1.3.tar.gz:

Publisher: publish-pypi.yml on voonterr/realitylint

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file realitylint-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: realitylint-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 17.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for realitylint-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 b55af560a75d386a0bf56d9e32625844ca98c593a3c3d80f19095fb285865b2a
MD5 361d2150013735a18137cc02e5139324
BLAKE2b-256 3f735c1b12c4dc14f00a881e237150c90b29990b9778a43ab770565eb07520a8

See more details on using hashes here.

Provenance

The following attestation bundles were made for realitylint-0.1.3-py3-none-any.whl:

Publisher: publish-pypi.yml on voonterr/realitylint

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page