compat-check
Check whether a GitHub repo or PyPI package would install cleanly in this environment — before you actually install it.
$ compat-check https://github.com/pallets/flask
compat-check: https://github.com/pallets/flask
backend: uv
requirements checked: blinker>=1.9.0, click>=8.1.3, itsdangerous>=2.2.0, jinja2>=3.1.2, markupsafe>=2.1.1, werkzeug>=3.1.0
OK — 6 package(s) would install cleanly:
+ blinker==1.9.0
+ click==8.5.0
...
$ compat-check some-package-with-a-real-conflict
PROBLEMS FOUND — 1 package(s) cannot be resolved:
[numpy]
× No solution found when resolving dependencies:
╰─▶ Because you require numpy>=2.0 and numpy<1.20, we can conclude that your
requirements are unsatisfiable.
Why this instead of uv/pip themselves
uv and pip already resolve dependencies — that's not the gap. Two things
are:
- You still have to actually run the install (or a dry-run) yourself,
reading whatever error comes back.
compat-checkdoes that in a throwaway venv and hands you a plain-language pass/fail, without touching your real environment. - Both resolvers are fail-fast: a single dry-run call reports only the
first unsatisfiable requirement. If two unrelated packages in the same
requirements.txtare both broken, one hides behind the other.compat-checkdrops each failure and retries until every one surfaces.
It does not try to out-resolve uv/pip — it wraps them (preferring
uv when available, falling back to the standard-library venv + pip
when it isn't) and reports what actually happened, not a static prediction
from metadata.
What it checks
- Whether every requirement resolves at all (missing versions, yanked releases, platform/ABI mismatches — reported with the resolver's own explanation)
- Whether requirements in the same source conflict with each other
What it deliberately does not check (yet)
- BLAS/LAPACK backend compatibility — this is a post-install diagnostic
(
numpy.show_config()), not something knowable before installing - GPU/CUDA driver compatibility beyond what the resolver itself reports — PyTorch-style packages that ship on a separate index aren't covered
setup.py-only packages with nopyproject.toml/requirements.txt/setup.cfg(would require unsafe code execution to parse reliably)
Install
Not yet published to PyPI — install directly from the repo:
uv tool install git+https://github.com/jahyunlee00299/compat-check
(or pipx install git+https://github.com/jahyunlee00299/compat-check, or clone and
pip install . into a venv)
Usage
compat-check <github-url-or-pypi-package-name> [--python 3.11] [--no-cache] [--tree]
Exit codes: 0 clean, 1 conflicts found, 2 source could not be resolved
at all (bad URL, nonexistent package), 3 invalid parameter (checked before
any network call, so a typo costs nothing).
--python and the pip fallback
--python is honoured only by the uv backend. The pip fallback builds its
venv with the standard-library venv module, which can only clone the
interpreter compat-check is itself running on — it cannot fetch another
version. Rather than accept the flag and quietly ignore it, the report states
the version actually probed:
$ compat-check requests --python 3.9 # on a machine without uv
compat-check: requests
backend: pip
python: 3.13 (requested 3.9 — NOT honoured)
with the reason on stderr. The cache is keyed on the version that was really
used, so two requests that run the identical probe share one cache entry
instead of being stored under two versions, only one of which was measured.
Install uv to target other Python versions for real.
--tree shows the full dependency tree (requires uv — no pip-backend
equivalent exists):
$ compat-check https://github.com/pallets/flask --tree
...
https://github.com/pallets/flask
├── blinker v1.9.0
├── click v8.5.0
├── itsdangerous v2.2.0
├── jinja2 v3.1.6
│ └── markupsafe v3.0.3
├── markupsafe v3.0.3
└── werkzeug v3.1.8
└── markupsafe v3.0.3
Results are cached locally (~/.cache/compat_check/, 7-day TTL) since a
dry-run against the same environment and requirements won't change
minute-to-minute. Use --no-cache to force a fresh probe. The cache holds the
500 most recent entries (oldest evicted first) and is invalidated automatically
when compat-check's own version changes, so a resolver change never serves an
answer computed by an older build.
How it works
- Fetch the requirement list — from
pyproject.toml,requirements.txt, orsetup.cfgon the GitHub repo, or from PyPI's JSON API for a bare package name. - Create a disposable virtual environment.
- Run
pip install --dry-run(oruv pip install --dry-run) against it — this resolves and would-download, but never actually installs anything or runs arbitrary setup code from the target package. - Report the result, retrying with failing packages dropped one at a time so every conflict in a multi-package source gets surfaced, not just the first one the resolver hits.
License
MIT
Release files for compat-check 0.2.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 | |
|---|---|---|---|
| compat_check-0.2.0.tar.gz | 25.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| compat_check-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.3 kB
Release files / compat_check-0.2.0.tar.gz
| Download URL | compat_check-0.2.0.tar.gz |
|---|---|
| Size | 25.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f4f258f631ed948354599aeafe76f985b783abcca7d9278f5c4e452469856011
|
|
BLAKE2b-256 checksum How to use checksums |
95d24cdef7564494537d32da30d7c956826df24af3fe3baa0224a4e7364ee3b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / compat_check-0.2.0-py3-none-any.whl
| Download URL | compat_check-0.2.0-py3-none-any.whl |
|---|---|
| Size | 20.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3ed28d91f7d3328dfd6d6cb02e88a802ee36c1132f376456aa94e8f5a890717c
|
|
BLAKE2b-256 checksum How to use checksums |
3d196dfa6ecb98c8f977dd75b5818129cc165c49cbef52bdc6193a4ca0c849a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|