wouldcatch
Your tests pass. Would they catch a bug?
wouldcatch plants small bugs in the lines you just changed, runs your tests, and shows the ones nobody noticed.
pipx install git+https://github.com/Sahil-u07/wouldcatch
cd your-repo && wouldcatch
On Windows without pipx: py -m pip install git+https://github.com/Sahil-u07/wouldcatch, then run wouldcatch from PowerShell or Windows Terminal.
No config. No dependencies. Works on any git repo with pytest (or any test command).
Green tests can still miss bugs
You add a member discount and write two tests. Every line runs. Everything passes.
def discount(price, is_member):
if is_member and price >= 100:
return price - 10
return price
def test_member():
assert discount(200, True) == 190
def test_guest():
assert discount(50, False) == 50
$ wouldcatch
MISSED shop.py:2 `and` -> `or`
MISSED shop.py:2 `>=` -> `>`
MISSED shop.py:2 `100` -> `101`
4/7 caught. 3 bug(s) your tests would not notice.
Each MISSED line is a bug someone could ship and your suite would stay green:
>=becoming>means a member spending exactly 100 gets no discount. No test checks 100.andbecomingorgives every guest over 100 the discount. No test has a guest over 100.
Add assert discount(100, True) == 90 and assert discount(200, False) == 200, run it again, and you get 7/7 caught.
Coverage can't tell you this. It counts which lines ran, not whether a test would fail if they were wrong.
Why only the diff
Mutation testing is the honest way to grade a test suite, but running it on a whole project can take hours, so almost nobody does. wouldcatch only mutates the lines in your git diff. A normal change gives 5 to 30 mutants, so it finishes while you're still writing the commit message.
| Line coverage | Whole-project mutation testing | wouldcatch | |
|---|---|---|---|
| Tells you a test would fail on a bug | no | yes | yes |
| Time on a typical change | seconds | minutes to hours | seconds to a few minutes |
| Setup | plugin | config files | none |
| Output | a percentage | a report on everything | the exact lines to test |
How it works
- Reads
git diffto find the Python lines you changed. Test files are skipped. - Makes one small change at a time on those lines:
<to<=,==to!=,andtoor,+to-,TruetoFalse,100to101, a return value toNone, anifflipped. - Runs your tests after each change. Tests still green means that bug would have gotten through.
- Puts the file back byte for byte (CRLF included) after every run, even on Ctrl+C or a killed process.
Usage
wouldcatch # uncommitted changes, or the last commit if the tree is clean
wouldcatch --base main # everything on this branch since main
wouldcatch --cmd "pytest tests/unit -x -q" # run only the tests that matter
wouldcatch --json # machine-readable output for scripts and agents
wouldcatch --all # list caught mutants too
wouldcatch --max 100 # try more mutants (default 50)
Exit codes: 0 all caught, 1 something missed, 2 setup problem (not a git repo, tests already failing).
Skip a line on purpose:
RETRY_DELAY = 5 # wouldcatch: ignore
Use it everywhere
GitHub Actions, on every pull request:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- run: pip install git+https://github.com/Sahil-u07/wouldcatch pytest
- run: wouldcatch --base origin/${{ github.base_ref }}
pre-commit, before every commit (with wouldcatch installed in your project environment):
- repo: https://github.com/Sahil-u07/wouldcatch
rev: main
hooks:
- id: wouldcatch
AI coding agents. Agents are good at writing tests that pass and bad at writing tests that check anything. wouldcatch gives them a concrete target: make every MISSED line fail.
- Claude Code: copy
skills/wouldcatchinto.claude/skills/in your project. - Any other agent: add this to
AGENTS.md:
After changing Python code, run `wouldcatch --json`. For every mutant with
"status": "missed", add a test that fails for that change. Re-run until none are missed.
Never change the source code to make a mutant go away.
FAQ
Will it mess up my files? It edits one file at a time and restores it right after. If the process dies mid-run, the next run restores the file from .wouldcatch-backup.json before doing anything else.
My test suite is slow. Each mutant is one run of your test command. Point --cmd at the relevant tests and use -x so pytest stops at the first failure.
A mutant can't be caught, the code really doesn't care. That happens (a log interval, a cache size). Mark the line # wouldcatch: ignore.
JavaScript, TypeScript, Go? Python today. The git part is language-neutral; JS/TS is next. Join the discussion.
Contributing
New mutations are small, self-contained PRs. Start with a good first issue and see CONTRIBUTING.md.
If wouldcatch found a bug your tests missed, a star helps other people find it.
License
Metadata
Release files for wouldcatch 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 | Provenance | Actions |
|---|---|---|---|---|
| wouldcatch-0.1.0.tar.gz | 14.2 kB | With provenance | Details for wouldcatch-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| wouldcatch-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for wouldcatch-0.1.0-py3-none-any.whl |
Total release size: 25.2 kB
Release files / wouldcatch-0.1.0.tar.gz
| Download URL | wouldcatch-0.1.0.tar.gz |
|---|---|
| Size | 14.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
18e26e6f7b27fa270b8b386516ab55cbc6fb4cef9af607c542b4ff634c97e48c
|
|
BLAKE2b-256 checksum How to use checksums |
8f0ad464b8c88b2cb640bcc202978a5d62ce9e5f5fbffed12d63979e88de6e15
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 11, 2026.
Transparency logRelease files / wouldcatch-0.1.0-py3-none-any.whl
| Download URL | wouldcatch-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2cdfb3f9f6a9c44eeb20adbd3a008c7375fa825d3a4bfbc6e683aa44b2813341
|
|
BLAKE2b-256 checksum How to use checksums |
08fed66e5392ae0cd4deeb416ff14431abac63c62f34ee4a1389b682ccb10824
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 11, 2026.
Transparency logSecurity for wouldcatch 0.1.0
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.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for wouldcatch-0.1.0.tar.gz
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 Nov 11, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.