Skip to main content

AutoFixAI

CI PyPI Python License: MIT

Automatically detect, repair, validate and explain common Python bugs.

AutoFixAI reads a Python file, finds bugs, fixes them with surgical, position-exact edits, re-runs the program in an isolated process to prove the fix worked, and tells you why each change was made and how confident it is.

$ autofix samples/buggy_code.py
Issues detected: 3
  line 2    [literal-zero-division] Division by a literal zero always raises ZeroDivisionError
  line 3    [unused-variable] local variable 'unused' is assigned to but never used
  line 6    [undefined-name] undefined name 'calculte'

Before: FAIL - NameError: name 'calculte' is not defined (line 6)

Fixes applied: 3 (in 2 rounds)
  1. line 3  [unused-variable] Remove unused variable 'unused'                (confidence 0.95)
  2. line 6  [undefined-name]  Rename 'calculte' to 'calculate'              (confidence 0.94)
  3. line 2  [zero-division]   Replace the literal divisor 0 with parameter 'b' and guard against zero (confidence 0.75)

After:  PASS - runs without errors
Result: FIXED

Why it is different from a linter or a chatbot

Linter Chatbot AutoFixAI
Finds problems yes sometimes yes
Fixes them rarely yes, unverified yes
Proves the fix by running the program no no yes
Explains why, with a confidence score no loosely yes
Never rewrites code it did not need to touch n/a often does yes (exact-range edits)

Install

git clone https://github.com/KomaliG7/AutoFixAI.git
cd AutoFixAI
pip install -e ".[dev]"

Requires Python 3.10+. The only runtime dependency is pyflakes.

Usage

autofix my_script.py                 # analyse, repair, show a report and diff
autofix my_script.py --write         # apply the fixes (keeps my_script.py.orig)
autofix my_script.py -o fixed.py     # write the fixed code somewhere else
autofix my_script.py --json          # machine-readable report (for CI / IDE plugins)
autofix my_script.py --no-run        # static analysis only - never executes your code
autofix my_script.py --ignore unused-import
autofix calc.py --test-cmd "python check_calc.py"   # test-driven repair (see below)

Exit code: 0 = clean or fixed, 1 = something still needs a human, 2 = usage error.

As a library:

from autofixai import repair

report = repair(open("my_script.py").read())
print(report.success, report.fixed)
for fix in report.fixes:
    print(fix.rule, fix.description, fix.confidence, fix.reason)

What it fixes today

Rule Detects Repair
undefined-name typos (calculte) and missing stdlib imports (os.getcwd() with no import os) rename to the closest defined name (call-aware) / add the import
unused-variable local assigned but never read delete it - or keep the expression if it has side effects
unused-import imported but never used remove the import (or just that alias)
mutable-default def f(x=[]) x=None + if x is None: x = []
literal-zero-division / zero-division a / 0, or a runtime ZeroDivisionError use the intended parameter as divisor + zero guard
index-off-by-one range(len(xs) + 1), while i <= len(xs), xs[len(xs)] that raise IndexError shift the bound by one
key-error d["missing"] that raised KeyError d.get("missing")
str-concat "n=" + n / n + " items" that raised TypeError wrap the number in str()
is-literal x is "text", n is not 5 == / !=

Test-driven repair (for bugs that don't crash)

A wrong operator, an off-by-one or the wrong variable produces no traceback, so rule-based fixers have nothing to latch onto. With --test-cmd, AutoFixAI uses your tests as the specification and searches for a fix the way academic repair tools do (generate-and-validate):

  1. Localise - rank lines by suspiciousness with spectrum-based fault localisation (Ochiai).
  2. Mutate - generate small edits with generic operators: swap a comparison / arithmetic / bitwise operator, and/or, change a constant by one, ± 1 on an index or bound, swap call arguments, negate a condition, delete a statement, use a different local variable.
  3. Validate - accept the first single edit that makes your test command pass.
$ autofix calc.py --test-cmd "python check_calc.py" --write
  1. line 2  [mutation] Line 2: replace '-' with '+'  (confidence 0.50)
       why: Found by test-driven search after 3 candidates ... Tests are the only specification, so review it.

The command runs in the file's directory and the file is temporarily overwritten with candidates (always restored). Only run test commands you would run yourself.

Independent evaluation: QuixBugs

QuixBugs has 40 classic algorithms, each with a one-line bug and a test-suite. Full table: benchmark/QUIXBUGS_RESULTS.md.

Programs
Rule-based pipeline only (no --test-cmd) 0 / 40
Test-driven search: patch passes all tests ("plausible") 13 / 40
... of which identical to the reference fix 7
... of which different but equivalent on 400 held-out random inputs 4
... of which overfit (pass the tests, wrong on new inputs) 2
Correct repairs 11 / 40 (28%)

Why the held-out check matters: passing the tests is not the same as being right. Two of the 13 "successful" patches (depth_first_search, find_in_sorted) were lucky edits that break on inputs the tests never used. Reporting plausible patches as fixes is a well-known flaw in repair papers; this repo separates them.

Caveats, stated plainly: the operator set was designed by someone who knows QuixBugs-style bug categories, and the argument-swap operator was added after gcd failed without it, so 28% is best read as an optimistic estimate for this operator set. Only single-edit repairs are searched. Reproduce with python -m benchmark.run_quixbugs --root path/to/QuixBugs.

How it works

source ──► analyse (pyflakes + AST rules) ──► propose fixes ──► apply exact edits
   ▲                                                                   │
   └──────── re-run in sandbox, read the traceback  ◄───────────────────┘
                   (repeat until clean, stuck, or max rounds)
  1. Detect – scope-aware static analysis, plus a real run in a sandboxed subprocess.
  2. Propose – each Fixer returns Fix objects: exact TextEdits, a reason, a confidence.
  3. Apply – non-overlapping edits are applied by source position, never by string search, so strings, comments and formatting elsewhere are untouched. A fix that would produce invalid syntax is discarded.
  4. Validate – the program is re-executed (timeout, isolated mode, temp dir, CPU/memory caps on POSIX). Fixes can unlock one another, so this loops.
  5. Explain – every fix reports its rule, reason and confidence.

See docs/ARCHITECTURE.md for the design and the reasoning behind it.

Benchmark

python -m benchmark.run_benchmark runs 40 buggy programs and 11 already-correct controls. Every case has a hand-written reference solution; a repair only counts if the program runs, prints exactly what the reference prints, and no static issues remain. See benchmark/RESULTS.md for the current table.

Please read the numbers with the right expectations:

  • The corpus was written by the author, so it is a regression suite, not independent evidence. Scoring 100% on bug classes the tool was built for is expected. Six UNSUP- cases (syntax errors, logic bugs, None attributes, infinite loops, missing recursion base case) are included on purpose and are not fixed.
  • The "no fixers" baseline solves 0 cases, so the harness does measure repair, not luck.
  • Independent evaluation on public datasets (e.g. QuixBugs, BugsInPy) is on the roadmap and will produce much lower, more honest numbers.

Honest limitations

  • Not every bug can be fixed automatically; unresolved problems are reported, never hidden.
  • Confidence scores are heuristic rules, not calibrated probabilities (yet - see roadmap).
  • A "fix" makes the program run; only you know if it does what you intended. Review the diff.
  • The sandbox limits accidents, not attackers. Do not run AutoFixAI on untrusted code. Use --no-run if you only want static analysis.
  • Syntax errors are reported but not yet repaired.
  • Test-driven repair returns plausible patches: the first edit that passes your tests. If your tests are weak, the patch can be wrong. Read the diff.

Roadmap

  • Syntax-error repair (missing colons, unbalanced brackets)
  • Runtime fixers for IndexError, KeyError, TypeError (string concatenation)
  • More runtime fixers: AttributeError, UnboundLocalError, argument-count TypeError
  • Author-written regression benchmark with published results
  • Independent evaluation on QuixBugs with held-out overfitting checks
  • Evaluate on BugsInPy (real-world bugs) - expect much lower numbers
  • Multi-edit and statement-insertion repair (e.g. missing visited.add(node))
  • Coverage-based localisation inside --test-cmd
  • Optional LLM fallback whose every patch must pass the same sandbox validation
  • Calibrated confidence scores
  • Pre-commit hook and VS Code extension
  • Publish to PyPI

Contributions are welcome - see CONTRIBUTING.md and the open issues labelled good first issue. If you use AutoFixAI in research, see CITATION.cff.

Project history

AutoFixAI began as a prototype (detect → analyse → fix → validate → explain). Version 0.2 is a ground-up rewrite that keeps the same pipeline idea but replaces string replacement with exact AST-position edits, in-process exec with a sandboxed subprocess, and hard-coded fixes with general rules, and adds a CLI, a JSON report, and a test suite.

License

MIT - see LICENSE.

Author: Komali (@KomaliG7)

Metadata

Release files for autofixai 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for autofixai 0.4.0
File Size Uploaded Provenance
autofixai-0.4.0.tar.gz 39.7 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for autofixai 0.4.0
File Interpreter ABI Platform
autofixai-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 76.0 kB

Release files / autofixai-0.4.0.tar.gz

Download URL autofixai-0.4.0.tar.gz
Size 39.7 kB
Tags Source
SHA-256 checksum
How to use checksums
8c7f8635bc5ba318f95be93532c835dad150db433d5bbcac698ff82fc5a9a420
BLAKE2b-256 checksum
How to use checksums
52df5db815dc050af3c0a434252d4b4dc03c3863a00d46db3099f566874c316a
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 1, 2026.

Transparency log

Release files / autofixai-0.4.0-py3-none-any.whl

Download URL autofixai-0.4.0-py3-none-any.whl
Size 36.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9857541fc1e6a8dc2ade3580ffc0683b21f8efc333d71cfdc7bf21e958e085c3
BLAKE2b-256 checksum
How to use checksums
00ff5f8cb47a0fe2881278a9bf746703bb626e095aa66798d92e6a914add8faf
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 1, 2026.

Transparency log

Security for autofixai 0.4.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

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for autofixai-0.4.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 Oct 1, 2026.

Transparency log

A 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.

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page