A wheel either fits your Python or leaves a hole.
Every wheel filename carries three tags. wheelripe checks all three against the Python and platform you are moving to, the same way pip does, for every file of every release on the index — without installing anything.
Ask before you bump.
# one-off, no install
uvx --from git+https://github.com/Blackman99/wheelripe wheelripe
# reads uv.lock, pylock.toml, poetry.lock, Pipfile.lock,
# requirements*.txt or pyproject.toml — whichever it finds
wheelripe --python 3.15
wheelripe uv.lock --python 3.15t --platform linux-aarch64,macos-arm64
- Reads the pins. Exact versions from your lockfile, or the newest release your specifier allows.
- Reads the files. One index request per package: every wheel of every release, its tags and
requires-python. - Says what to do. Ready, bump to the first release that has the wheel, or blocked upstream with a link to the repo.
Reading the holes
- READY a wheel installs (version-specific, abi3/abi3t or pure Python)
- BUMP your pin has no wheel; a newer release does — wheelripe names it
- BLOCKED no release has a wheel yet: you wait on upstream (or build it yourself)
- EXCLUDED
requires-pythonrules your Python out - BUILD sdist only for every Python — fine if it is pure Python
Exit code 1 when anything needs a bump or is blocked (--fail-on blocked to only fail on upstream blockers). Glibc and macOS floors are yours to set: --glibc 2.28, --macos 13. If a package only ships wheels for a newer glibc than your floor, wheelripe says so.
In CI, and for your coding agent
# .github/workflows/py315.yml — weekly: are we ripe yet?
on: {schedule: [{cron: "0 6 * * 1"}], workflow_dispatch: {}}
jobs:
ripe:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: Blackman99/wheelripe@v0.1.0
with: {python-version: "3.15", fail-on: blocked}
# MCP (Claude Code, Cursor, Codex …) — read-only
{"mcpServers": {"wheelripe": {
"command": "uvx",
"args": ["--from", "git+https://github.com/Blackman99/wheelripe",
"wheelripe", "mcp"]}}}
# tools: check_python_upgrade, explain_wheel
The Action writes a table to the job summary, annotates each blocker and exposes ripe, blocked and bump outputs — so a scheduled job can tell you the week your last blocker clears.
It agrees with pip, or CI goes red.
On every push, CI asks pip itself — --only-binary=:all: with an explicit Python, ABI and platform — about 26 real packages on 7 platforms against the live PyPI, for both 3.15 and 3.15t, and fails on any disagreement (182/182 today). Then it installs on real CPython 3.15 and 3.15t interpreters and checks the predictions again.
The cheese at the top is real too: those are wheelripe's verdicts for a mid-2025 lockfile, fetched from PyPI on build day.