readme-lies
Your README is lying. Your agent believes it.
11 real doc bugs found in httpx, pydantic, uv & typer · 83% precision on repos it had never seen
You clone a repo. The README says:
npm run dev
There is no dev script. There hasn't been for eight months. Someone renamed it to start and never touched the docs.
You shrug and go look at package.json. Your coding agent doesn't shrug. It runs the command, reads the error, guesses, tries three variations, and burns ten minutes of your tokens, because the README said so.
Docs don't rot loudly. They rot one renamed heading at a time. readme-lies checks every claim your docs make against the code, on every push.
What it catches
$ readme-lies
README.md:42: `npm run dev` — no "dev" script in package.json
README.md:77: […](docs/setup.md) — file does not exist
docs/api.md:12: […](#client-instances) — no heading with that anchor
docs/api.md:30: `createClient()` — `createClient` is not in the code (renamed or removed?)
4 lie(s) found.
| Your docs say… | readme-lies checks… |
|---|---|
npm run build · pnpm run test · make deploy · just lint |
that script / target / recipe actually exists |
[see setup](docs/setup.md) |
that the file is still there |
[config](#configuration) |
that the heading still exists: GitHub, VitePress, Docusaurus and mkdocs rules |
`src/server/auth.ts` |
that the path is real |
`createClient()` |
that the function wasn't renamed away. Only flagged if it used to exist, so useState() never trips it |
mytool --verbose |
that your CLI still has that flag |
It already found real bugs
I pointed it at 27 popular repositories and checked every finding by hand. These are live on main as I write this:
| Repo | Lies | Example |
|---|---|---|
| encode/httpx | 7 | links to #client-instances, #routing, #http-proxying: all headings that got renamed |
| fastapi/typer | 2 | the root README links tutorial/install.md, which lives in docs/, so it's a 404 on GitHub |
| astral-sh/uv | 1 | init.md#unpackaged-applications: no such section |
| pydantic/pydantic | 1 | #customise-settings-sources on a page that's now a stub |
On 12 repos it had never seen during development, 10 of its 12 findings were real (83%). The other two taught it something, and every false alarm it has ever raised is now a regression test.
Add it to CI (30 seconds)
# .github/workflows/docs.yml
on: [push, pull_request]
jobs:
readme-lies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: sandeepsirodia/readme-lies@main
Lies show up as red annotations right on the PR diff, the moment someone renames the thing the docs point to.
Or just run it:
uvx --from git+https://github.com/sandeepsirodia/readme-lies readme-lies
Built to not cry wolf
A linter that's wrong twice gets uninstalled. So every rule stays quiet unless it's sure:
npm run buildinside a tutorial usually means the reader's project, not yours, so scripts are only checked in root docs and contributor guides. The same goes for anything afternpm init,npx create-…ormkdir.yarn huskyruns a binary, not a script. It's skipped.- Gitignored files (generated API docs) are skipped.
- Docs-site routes like
/guide/and mkdocstrings pages are skipped. - Setext headings,
_emphasis_in headings, CJK anchors, percent-encoding and{#custom-ids}: handled.
Still wrong? Put <!-- readme-lies-ignore --> on the line above and it'll look away.
Usage & development
readme-lies [paths…] [--root DIR] [--format text|github]
Defaults to README.md plus docs/**/*.md. Exits 1 when it finds a lie, so it drops into any CI or pre-commit hook. One Python file, zero dependencies, no LLM, no network.
python -m unittest discover -s tests -v
Tests map to SPEC.md. TestNoFalsePositives holds one regression test per false alarm ever seen in the wild. And yes: this README is checked by readme-lies on every push.
Prior art, and what's new here
- lychee checks URLs (readme-lies deliberately doesn't).
- markdown-link-check and remark-validate-links check local links and headings. If that's all you need, they're mature choices.
readme-lies goes past links, to the claims docs make about the code:
- package scripts and make/just targets
- file paths in inline code
- functions that were renamed away (via git history)
- your CLI's own flags
It also handles the anchor rules of docs sites (VitePress, Docusaurus, mkdocs), not just GitHub's.
MIT © Sandeep Sirodia · Found a lie in your own README? A ⭐ is a nice way to say thanks.
Release files for readme-lies 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| readme_lies-0.1.0.tar.gz | 14.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| readme_lies-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.5 kB
Release files / readme_lies-0.1.0.tar.gz
| Download URL | readme_lies-0.1.0.tar.gz |
|---|---|
| Size | 14.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
73cee463e76b497aa4516db6a9731cd9423803bd3bb8c58e26c3be1df1d2da4a
|
|
BLAKE2b-256 checksum How to use checksums |
d347e4e6c171a84db2b6fd3562198e954be93b456ac66cd235e39f20a6b18a2b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency logRelease files / readme_lies-0.1.0-py3-none-any.whl
| Download URL | readme_lies-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a7fc6303b1b8b630223c11a685b5a53f8f497c46499d450342a1ba580c2b1527
|
|
BLAKE2b-256 checksum How to use checksums |
a1baad76a0c2872876382c5d67e00725b77203c588768d8c4023ffc66c7b9de5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency log