Skip to main content

readme-lies

Your README is lying. Your agent believes it.

CI Zero dependencies No LLM MIT

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

readme-lies on encode/httpx: 7 links to headings that no longer exist

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 build inside 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 after npm init, npx create-… or mkdir.
  • yarn husky runs 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

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)

Source distribution for readme-lies 0.1.0
File Size Uploaded
readme_lies-0.1.0.tar.gz 14.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for readme-lies 0.1.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page