Deterministic runtime compatibility analyzer
The static analyzer for runtime compatibility.
Predict why a repository will fail on your machine before you run it.
repofail answers one question: Will this repository actually run here?
It inspects both the repo and your machine — then reports deterministic incompatibilities before you install anything.
Why · Example · Works on · Install · Usage · Rules · CI · Contracts · FAQ
pip install repofail
cd /path/to/any/repo
repofailYou get a compatibility score and a list of deterministic blockers (Node version, Python range, CUDA, lock file, spec drift, etc.). No install of the repo’s dependencies. No cloud. No AI.
Most tools install dependencies.
Few tools tell you:
- Your Node version violates
engines.node. - Docker targets the wrong architecture.
- CUDA is hard-coded with no fallback.
- CI and local Python versions drifted.
repofail inspects both the repository and your machine — then reports deterministic incompatibilities before install or runtime.
repofail works on:
- Python projects
- Node projects
- Dockerized repos
- ML repositories
- Monorepos
Run it against any local clone.
Deterministic spec violation detected — engines.node requires 22.x, host is 20.x.
| Scenario | Without repofail | With repofail |
|---|---|---|
| Node engine mismatch | Clone → npm install → EBADENGINE → search, fix, retry |
repofail . → "Node 22.x required, host is 20.x" + suggested fix in <1s |
| CUDA on laptop | Clone → pip install → run → RuntimeError: CUDA unavailable |
repofail . → "Hard-coded CUDA path, host has no GPU" before you run |
| Spec drift (Python) | CI passes, local fails; pyproject says 3.11, Docker uses 3.9 | repofail . → "Spec drift — 3 distinct Python targets" + where they differ |
Try the demos: node engine, spec drift, CUDA hardcoded.
From PyPI (recommended)
pip install repofailOne-liner (curl)
curl -sSL https://raw.githubusercontent.com/jayvenn21/repofail/main/install.sh | bashpipx (isolated CLI)
pipx install repofailHomebrew (formula: jayvenn21/homebrew-tap)
brew tap jayvenn21/tap
brew install jayvenn21/tap/repofailFrom source (development)
git clone https://github.com/jayvenn21/repofail.git
cd repofail
pip install -e .# Scan
repofail # Scan current dir
repofail -p /path/to/repo # Scan specific repo
repofail -j # JSON output (machine-readable)
repofail -m # Markdown output
repofail -v # Verbose: rule IDs and low-confidence hints
repofail --ci # CI mode: exit 1 if HIGH rules fire
repofail --fail-on MEDIUM # CI: fail on MEDIUM or higher (default: HIGH)
repofail -r # Save failure report when rules fire (opt-in telemetry)
# Rules
repofail -e list # List all rules
repofail -e spec_drift # Explain a rule
# Contracts
repofail gen . # Generate env contract to stdout
repofail gen . -o contract.json
repofail check contract.json
# Fleet
repofail a /path # Audit: scan all repos in directory
repofail a /path -j # Audit with JSON output
repofail sim . -H host.json # Simulate: would this work on target host?
repofail s # Stats: local failure counts (from -r reports)
repofail s -j # Stats with JSON output- 0 — No deterministic violations (or scan completed successfully)
- 1 — Violations detected (with
--ci) or target host has issues (withsim) - 2 — Invalid usage / bad input (e.g. not a directory, contract violation)
Option A — Reusable action (comment on PR + fail CI)
name: repofail
on:
pull_request:
branches: [main, master]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jayvenn21/repofail/.github/actions/repofail@main
with:
path: .
fail_on: HIGH
comment: 'true'
upload_artifact: 'true'
pr_number: ${{ github.event.pull_request.number }}The action installs repofail, runs a compatibility check, comments the Markdown report on the PR, uploads the JSON artifact, and fails the job if violations meet the threshold.
Option B — Inline (no comment)
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install repofail
- run: repofail --ciExits 1 if HIGH rules fire. Use --fail-on MEDIUM to be stricter.
Option C — Lock + verify (enforcement)
Pin the runtime once, then fail CI on drift:
repofail lock # generates repofail.lock.json (python, node, arch, os, cuda, docker_base)
repofail verify # exit 1 if host doesn't match lockCommit repofail.lock.json. In CI, run repofail verify so builds only pass on the locked environment.
Fleet compliance
Scan many repos and get violations, most common drift, and risk clusters:
repofail fleet scan ~/org --policy org.policy.yamlPolicy YAML (optional): fail_on: HIGH, max_repos: 500, max_depth: 4. With fail_on: HIGH, exit code is 1 if any repo has a HIGH finding.
repofail gen . -o contract.json
repofail check contract.jsonVersioned runtime expectations. Teams share contracts. CI checks drift. Generated contracts report the installed repofail version (from PyPI/Homebrew) so tooling stays traceable.
| Tool | Reads Repo | Inspects Host | Predicts Failure | CI Enforceable |
|---|---|---|---|---|
| pip | ✅ | ❌ | ❌ | ❌ |
| Docker | ✅ | ❌ | ❌ | ❌ |
| repofail | ✅ | ✅ | ✅ | ✅ |
Deterministic rule coverage — repofail includes checks across:
- Spec violations — version ranges, engines.node, requires-python
- Architecture mismatches — Apple Silicon vs amd64 Docker
- Hardware constraints — CUDA requirements, GPU memory
- Toolchain gaps — missing compilers, Rust, node-gyp
- Runtime drift — CI vs Docker vs local inconsistencies
- Environment shape — multi-service RAM pressure, port collisions
See all rules: repofail -e list · Explain one: repofail -e <rule_id>
Rule reference
| Rule | Severity | When |
|---|---|---|
| Torch CUDA mismatch | HIGH | Hard-coded CUDA, host has no GPU |
| Python version violation | HIGH | Host outside requires-python range |
| Spec drift | HIGH | pyproject vs Docker vs CI — inconsistent Python |
| Node engine mismatch | HIGH | package.json engines.node vs host |
| Lock file missing | HIGH | package.json has deps, no lock file |
| Apple Silicon wheel mismatch | MEDIUM/HIGH | arm64 + x86-only packages or Docker amd64 |
| … | repofail -e list |
Scoring model
Compatibility Score = 100 − Σ(weight × confidence × determinism)
| Severity | Weight | Determinism |
|---|---|---|
| HIGH | 45 | 1.0 for spec violations |
| MEDIUM | 20 | 0.8–1.0 |
| LOW | 7 | 0.5–1.0 |
| INFO | 5 | structural only |
Determinism scale: 1.0 = guaranteed failure · 0.75 = high likelihood · 0.6 = probabilistic (spec drift) · 0.5 = structural risk
Score floors at 10%. When score ≤15% with HIGH rules: "— fatal deterministic violations present".
repofail/
cli.py
engine.py
scanner/ # Repo + host inspection
rules/ # Deterministic rule implementations
fleet.py # Audit, simulate
Extensible via .repofail/rules.yaml.
Does repofail install or run my project?
No. It only reads configs and (optionally) inspects Python/JS for patterns. No pip install, no npm install, no execution.
Does it need the internet?
No. It runs fully offline. Host inspection uses local subprocesses (e.g. node --version).
Why “deterministic”?
Same repo + same host → same result. No ML, no heuristics that change between runs. Rules are based on config and code.
Can I add my own rules?
Yes. Put a .repofail/rules.yaml (or repofail-rules.yaml) in the repo and define conditions on repo.* and host.*. See repofail -e list for built-in rule IDs.
What if my repo is clean?
You get a high score (e.g. 96–100%) and “No deterministic blockers detected.” repofail does not invent problems.
- You need dependency resolution — use pip, npm, poetry, etc. repofail does not install or resolve.
- You need security scanning — use Dependabot, Snyk, or similar. repofail is compatibility-only.
- You want “AI suggested fixes” — repofail gives deterministic, rule-based suggestions only.
- You run only in one environment — if every dev and CI use the same OS/runtime, the value is smaller (still useful for drift and contracts).
pip install -e ".[dev]"
pytest tests/ -vQuick checks: bash -n install.sh (syntax). The GitHub Action runs on every PR in this repo (see .github/workflows/repofail.yml); to test the reusable action, use it in another repo’s workflow on a PR.
MIT — see LICENSE.

