driftfix
Dependabot bumps it. CI breaks. driftfix fixes the code.
Dependency bots open the upgrade PR, then leave you to fix whatever broke. driftfix finishes the job: it reads the failing tests, has Claude adapt your code to the new version, reruns your tests itself, and pushes the fix onto the same PR. If it can't get to green, it comments what it tried and commits nothing.
Dependabot PR (openai 0.28 → 1.x)
→ tests fail
→ Claude reads the failure + changelog, edits your code
→ driftfix reruns your tests
✅ green → fix committed to the PR, with an explanation
❌ red → comment only, nothing committed
See it on a real Dependabot PR: driftfix-playground#1.
Benchmark
Real breaking upgrades. Each case is a small app whose tests pass on the old version and fail on the new one. Most include a trap beyond renames: a silent behavior change, a security footgun, or a multi-file refactor.
| Package | Upgrade | Fixed | Cost | Diff |
|---|---|---|---|---|
| httpx | 0.27.2 → 0.28.1 | ✅ | $0.12 | 1 file changed, 4 insertions(+), 1 deletion(-) |
| numpy | 1.26.4 → 2.5.3 | ✅ | $0.14 | 1 file changed, 5 insertions(+), 5 deletions(-) |
| openai | 0.28.1 → 3.24.0 | ✅ | $0.29 | 1 file changed, 4 insertions(+), 3 deletions(-) |
| pydantic | 1.10.21 → 2.13.5 | ✅ | $0.20 | 1 file changed, 11 insertions(+), 11 deletions(-) |
| sqlalchemy | 1.4.54 → 2.1.3 | ✅ | $0.19 | 1 file changed, 7 insertions(+), 4 deletions(-) |
| pydantic (6-file app, shared base model) | 1.10.21 → 2.13.5 | ✅ | $0.51 | 4 files changed, 47 insertions(+), 29 deletions(-) |
pydantic (BaseSettings moved to new package) |
1.10.21 → 2.13.5 | ✅ | $0.22 | 2 files changed, 8 insertions(+), 5 deletions(-) |
| pandas | 1.5.3 → 2.3.3 | ✅ | $0.19 | 1 file changed, 5 insertions(+), 5 deletions(-) |
| django | 3.2.25 → 5.2.17 | ✅ | $0.20 | 1 file changed, 7 insertions(+), 8 deletions(-) |
| flask | 2.2.5 → 3.1.3 | ✅ | $0.22 | 1 file changed, 6 insertions(+), 12 deletions(-) |
| pillow | 9.5.0 → 12.3.0 | ✅ | $0.13 | 1 file changed, 3 insertions(+), 2 deletions(-) |
| pyyaml | 5.4.1 → 6.0.3 | ✅ | $0.18 | 1 file changed, 2 insertions(+), 2 deletions(-) |
12/12 fixed, $2.59 total ($0.12–$0.51 per fix).
Every fix was verified by rerunning the tests, and no test was edited.
Reproduce with python bench/run.py (needs an API key), or validate the cases
for free with python bench/run.py --check.
Found an upgrade it can't fix? That's the most useful contribution: see
CONTRIBUTING.md.
Real projects
The synthetic cases above are small. On real open-source projects broken by pydantic 1 → 2 (study, 39 candidates → 4 real breaks):
| Project | Tests broken | Result | Cost |
|---|---|---|---|
| internetarchive/fatcat-scholar | 15 of 115 | ✅ fixed, 11 files | $2.38 |
| antonagestam/phantom-types | 2 of 677 | ✅ fixed, one test assertion edit to review | $2.93 |
| epi2me-labs/ezcharts | 5 of 37 | ✅ fixed, including the model generator | ~$1 |
| bdd100k/bdd100k | 2 of 46 | ⚠️ tests pass, but via a workaround for a third-party library | $0.95 |
Real fixes cost $1–3, not $0.20, so set budget to at least 3 for real
codebases. Always read the diff: "tests pass" and "correct" aren't the same
thing. Details in the study's RESULTS.md.
Quick start: GitHub Action
-
Add
.github/workflows/driftfix.yml:name: driftfix on: pull_request permissions: { contents: write, pull-requests: write } jobs: fix: if: github.actor == 'dependabot[bot]' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: { ref: "${{ github.head_ref }}" } - uses: Gthejesraj/driftfix@v0 with: anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} setup: pip install -r requirements.txt # however you install deps test: pytest -q # however you run tests
-
Add
ANTHROPIC_API_KEYunder Settings → Secrets and variables → Dependabot. Workflows triggered by Dependabot can't read your normal Actions secrets.
That's it. The next Dependabot PR that breaks your tests gets a fix commit.
| Input | Default | |
|---|---|---|
anthropic-api-key |
required | |
setup |
pip install -r requirements.txt |
command that installs dependencies |
test |
pytest -q |
any command; exit code 0 = green |
package |
from Dependabot | set it for non-Dependabot PRs |
model |
claude-opus-5 |
|
budget |
5 |
max USD per run |
Quick start: CLI
pip install driftfix
export ANTHROPIC_API_KEY=sk-ant-...
# you upgraded a dependency and your tests fail:
driftfix fix --package openai --from 0.28 --to 1.40 --test "pytest -q"
Flags: --test, --model, --budget (USD, default 5), --max-turns
(default 50), --timeout (test timeout, seconds), --summary FILE (write the
markdown report), --repo PATH.
Exit codes: 0 fixed or nothing to fix, 1 not fixed, 2 dirty working tree.
Guardrails
- Your tests decide. driftfix reruns them after the agent finishes. The agent saying it's done doesn't count.
- No pinning back. A requirement that excludes the new version, or any
lock file edit, is rejected. Widening a requirement so the new version is
allowed (dropping an old
<2cap) is fine, and so is adding a package the upgrade split out (likepydantic-settings). - No deleting or skipping tests. The agent is told not to, and every test change shows up in the diff you review.
- Reviewable. It needs a clean git tree, so every change is a diff, and it never merges.
- Bounded. Spend cap per run, and the cost is printed in every report.
See SECURITY.md for the threat model. The short version: the agent can run commands inside the checkout, so run it in CI or a throwaway clone.
FAQ
What does it cost? $0.12–0.51 per fix in the benchmark, billed to your Anthropic API key. When tests already pass, Claude isn't called at all.
Does my code leave my machine? Yes. The relevant files and test output are sent to the Anthropic API.
Which languages? Python is what's benchmarked. The Action takes any
setup and test command, so npm projects should work, but that's untested.
Reports are welcome.
Renovate instead of Dependabot? Use the CLI or set the package input.
Native Renovate support is on the roadmap.
Why doesn't CI rerun after the fix commit? GitHub doesn't trigger
workflows from commits pushed with the default GITHUB_TOKEN. Pass a personal
access token or GitHub App token to actions/checkout if you want that.
Can it fix deprecations before they break? Yes. Make the test command
treat them as errors, e.g. pytest -q -W error::DeprecationWarning (some
libraries use their own warning class, like
-W error::starlette.exceptions.StarletteDeprecationWarning). On a real
31-file FastAPI app, this caught Starlette's httpx → httpx2 deprecation and
fixed it with a one-line dependency swap ($0.40).
Mocked tests? driftfix can only catch what your tests catch. A test that mocks the library can pass while the real call is broken.
Roadmap
- More benchmark cases (langchain, Django REST framework), larger real repos
- npm and Renovate support
- Provider mode: packages publish migration notes that driftfix reads
Contributing
Bug reports, failed-fix reports and benchmark cases are all welcome. See CONTRIBUTING.md and the Code of Conduct.
License
Metadata
Release files for driftfix 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| driftfix-0.2.1.tar.gz | 22.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| driftfix-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.4 kB
Release files / driftfix-0.2.1.tar.gz
| Download URL | driftfix-0.2.1.tar.gz |
|---|---|
| Size | 22.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b984c3a8461df21620cd4ab0d833079542fbf08935147c8285b876ea1ec321e2
|
|
BLAKE2b-256 checksum How to use checksums |
c1845cacb1038586a353ff2e60511e047ea3f02f32cfb2100860745113b76840
|
| 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 Oct 5, 2026.
Transparency logRelease files / driftfix-0.2.1-py3-none-any.whl
| Download URL | driftfix-0.2.1-py3-none-any.whl |
|---|---|
| Size | 9.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
21bb7c21e26f45d8e0e7217378c60757295800be3a1c2721ce425bf3d54069d1
|
|
BLAKE2b-256 checksum How to use checksums |
b9f3cc03a7de848d361a4069f83613d4390f731cb904477e865e19449f23f3a0
|
| 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 Oct 5, 2026.
Transparency log