Self-healing Python โ catches runtime errors, fixes code & dependencies via LLM + MCP
Project description
๐ง pfix
Self-healing Python โ catches runtime errors and fixes source code + dependencies via LLM + MCP.
๐ก New in 0.1.5: Zero-configuration mode! Just
import pfixwithPFIX_AUTO_APPLY=truein.envand any exception triggers automatic repair.
Features
- Zero-config mode โ
import pfix+.env= auto-healing for entire project @pfixdecorator โ wrap any function; errors trigger automatic repair- Fast dep fix โ
ModuleNotFoundErrorโ instantpip/uv install(no LLM call) - pipreqs scanning โ project-wide import analysis for missing dependencies
- LLM code repair โ sends error context to LLM (OpenRouter/LiteLLM) for intelligent fixes
- pip + uv โ auto-detects
uvfor faster installs, falls back topip - MCP server โ
@mcp.tool()via FastMCP for IDE integration (Claude Code, Cursor, VS Code) - Git auto-commit โ optional auto-commit of fixes with configurable prefix
- Auto-restart โ
os.execvprocess restart after fix applied - Interactive diff โ unified diff with confirmation before applying
- Backup system โ timestamped backups in
.pfix_backups/(can be disabled) - Async support โ
@apfixfor async functions
Installation
pip install pfix
# With MCP server support
pip install pfix[mcp]
# With git auto-commit
pip install pfix[git]
# Everything
pip install pfix[all]
Quick Start (3 Ways)
Option 1: Zero Configuration (Recommended)
Just import pfix with PFIX_AUTO_APPLY=true in your .env:
# .env
OPENROUTER_API_KEY=sk-or-v1-...
PFIX_AUTO_APPLY=true
# your_script.py
import pfix # Auto-activates global exception hook
def buggy_function(x):
return 1 / x # Division by zero? Auto-fixed!
buggy_function(0) # pfix catches, analyzes, fixes, and retries
What happens:
- Exception is caught by global hook
- LLM analyzes the error context
- Fix is applied to source file
- Process restarts (if
PFIX_AUTO_RESTART=true)
Option 2: Explicit Session Control
Use pfix_session for fine-grained control:
from pfix import configure, pfix_session
configure(auto_apply=True, dry_run=False)
def process_data(data):
return data[0] / data[1] # Might fail
with pfix_session(__file__, auto_apply=True):
result = process_data([1, 0]) # Auto-fixed on error
print(f"Result: {result}")
Option 3: Decorator (Per-Function)
Use @pfix for function-level control:
from pfix import pfix
@pfix(retries=3, hint="Processes CSV files")
def analyze_csv(path):
import pandas as pd # Auto-installed if missing
df = pd.read_csv(path)
return df.groupby("category").sum()
@pfix(deps=["requests", "python-dateutil"])
def fetch_events(url: str):
import requests
from dateutil.parser import parse
return [parse(e["ts"]) for e in requests.get(url).json()["events"]]
Usage Patterns
Pattern A: Development Mode (Interactive)
from pfix import configure
# Ask before applying fixes
configure(auto_apply=False)
import pfix # Hook installed
def risky_operation():
return undefined_variable # NameError
risky_operation() # Shows diff, asks for confirmation
Pattern B: CI/CD Mode (Non-Interactive)
from pfix import configure
# Auto-apply everything, dry run for safety
configure(auto_apply=True, dry_run=True, create_backups=False)
import pfix
Pattern C: Library Mode (Specific Functions)
from pfix import pfix, pfix_session
# Only protect specific functions
@pfix(auto_apply=True)
def unstable_api_call():
...
# Or specific code blocks
with pfix_session(__file__):
untrusted_code()
Library Behavior
How It Works
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Your Code โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ Zero Config โ or โ Session Block โ or โ @pfix Decor โ โ
โ โ import pfix โ โ with pfix_sessionโ โ @pfix โ โ
โ โโโโโโโโโโฌโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโ โโโโโโโโฌโโโโโ โ
โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Exception Occurs โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ 1. ModuleNotFoundError? โ โ โ
โ โ โ โ pip/uv install โ retry โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ โ
โ โ โผ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ 2. Build ErrorContext โ โ โ
โ โ โ - Traceback โ โ โ
โ โ โ - Source code โ โ โ
โ โ โ - Local variables โ โ โ
โ โ โ - File imports โ โ โ
โ โ โ - pipreqs scan โ โ โ
โ โ โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ โ
โ โ โผ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ 3. LLM Analysis (LiteLLM โ OpenRouter) โ โ โ
โ โ โ - Diagnosis โ โ โ
โ โ โ - Fix proposal โ โ โ
โ โ โ - Confidence score โ โ โ
โ โ โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ โ
โ โ โผ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ 4. Apply Fix (if confidence > 0.1) โ โ โ
โ โ โ - Show diff (or auto-apply) โ โ โ
โ โ โ - Create backup (if create_backups=True) โ โ โ
โ โ โ - Write fixed code โ โ โ
โ โ โ - Git commit (if git_auto_commit=True) โ โ โ
โ โ โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ โ
โ โ โผ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ 5. Recovery โ โ โ
โ โ โ - Reload module โ retry โ โ โ
โ โ โ - or os.execv restart โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Error Types & Fixes
| Error Type | Auto-Fix Strategy | Example Fix |
|---|---|---|
ModuleNotFoundError |
pip/uv install | pip install requests |
NameError |
Add import | import os at top |
TypeError |
Type conversion | str(age) instead of age |
AttributeError |
Fix attribute access | obj.get() instead of obj.attr |
ZeroDivisionError |
Add guard clause | if x == 0: return 0 |
IndexError |
Bounds checking | if i < len(list): |
KeyError |
Safe dict access | dict.get(key, default) |
ValueError |
Input validation | Try/except or validation |
FileNotFoundError |
Check path existence | if os.path.exists(): |
Confidence Thresholds
- > 90%: High confidence fixes (type conversions, simple guards)
- 50-90%: Medium confidence (logic changes, API adjustments)
- 10-50%: Low confidence (complex refactorings)
- < 10%: Skipped (manual review recommended)
CLI
pfix run script.py # Run with global exception hook
pfix run script.py --auto # Auto-apply fixes
pfix run script.py --restart # Restart process after fix
pfix check # Show config status
pfix deps scan # Scan for missing deps (pipreqs)
pfix deps install # Install all missing deps
pfix deps generate # Generate requirements.txt
pfix server # Start MCP server (stdio)
pfix server --http 3001 # Start MCP server (HTTP)
MCP Integration
pfix exposes tools via FastMCP for IDE integration:
| Tool | Description |
|---|---|
pfix_analyze |
Analyze error โ diagnosis + fix proposal |
pfix_fix |
Analyze + apply fix (with backup) |
pfix_deps_scan |
Scan for missing deps |
pfix_deps_install |
Install a package |
pfix_deps_generate |
Generate requirements.txt |
pfix_edit_file |
Write file content |
Claude Code / VS Code setup
Add to your MCP config (.claude/mcp.json or VS Code settings):
{
"mcpServers": {
"pfix": {
"command": "python",
"args": ["-m", "pfix.mcp_server"]
}
}
}
Configuration
.env
| Variable | Default | Description |
|---|---|---|
OPENROUTER_API_KEY |
โ | Required โ OpenRouter API key |
PFIX_MODEL |
openrouter/anthropic/claude-sonnet-4 |
LLM model to use |
PFIX_AUTO_APPLY |
false |
Auto-apply fixes without confirmation |
PFIX_AUTO_INSTALL_DEPS |
true |
Auto-install missing dependencies |
PFIX_AUTO_RESTART |
false |
Restart process after fix applied |
PFIX_MAX_RETRIES |
3 |
Max fix attempts per error |
PFIX_DRY_RUN |
false |
Show proposed fixes without applying |
PFIX_CREATE_BACKUPS |
true |
Create .pfix_backups/ before fixing |
PFIX_PKG_MANAGER |
auto | pip or uv (auto-detected) |
PFIX_GIT_COMMIT |
false |
Auto-commit fixes to git |
PFIX_GIT_PREFIX |
pfix: |
Git commit message prefix |
PFIX_MCP_ENABLED |
false |
Enable MCP server |
PFIX_MCP_TRANSPORT |
stdio |
stdio or http |
PFIX_ENABLED |
true |
Master switch to disable pfix |
pyproject.toml
[tool.pfix]
model = "openrouter/anthropic/claude-sonnet-4"
auto_apply = true
auto_install_deps = true
max_retries = 3
create_backups = false
git_auto_commit = true
git_prefix = "fix: "
Programmatic
from pfix import configure
configure(
auto_apply=True,
dry_run=False,
pkg_manager="uv",
create_backups=False,
git_auto_commit=True,
max_retries=5,
)
Advanced Usage
Custom Error Handlers
from pfix import pfix
def log_error(exc):
with open("errors.log", "a") as f:
f.write(f"{type(exc).__name__}: {exc}\n")
@pfix(on_error=log_error, retries=3)
def risky_operation():
...
Async Support
from pfix import apfix
@apfix(auto_apply=True)
async def fetch_data(url):
import aiohttp
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
Session with Custom Config
from pfix import pfix_session, get_config
config = get_config()
config.llm_model = "openrouter/anthropic/claude-opus-4"
config.llm_temperature = 0.1
with pfix_session(__file__, auto_apply=True, restart=True):
main()
Examples
See examples/ directory for working examples:
demo_auto.pyโ Zero-config auto-healingdemo.pyโ Explicit session controlREADME.mdโ Examples documentation
Best Practices
- Start with
PFIX_AUTO_APPLY=falseto review fixes before applying - Enable backups (
PFIX_CREATE_BACKUPS=true) in development - Use dry-run mode in CI/CD to preview fixes without applying
- Set
PFIX_AUTO_RESTART=truefor long-running processes - Add hints to decorators for better LLM context:
@pfix(hint="Processes CSV files")
Troubleshooting
"LLM confidence too low"
- Increase context with
@pfix(hint="...") - Check your API key is valid
- Try a different model in
PFIX_MODEL
"Could not locate function"
- Ensure the error is in a named function (not
lambdaorexec) - Use
pfix_sessionfor module-level code
Backups filling up disk
- Set
PFIX_CREATE_BACKUPS=false - Clean
.pfix_backups/periodically:rm -rf .pfix_backups/
Too many restarts
- Set
PFIX_MAX_RETRIES=1to limit attempts - Use
PFIX_AUTO_RESTART=falseto disable restarts
Dependencies
| Package | Role |
|---|---|
litellm |
LLM proxy โ OpenRouter, OpenAI, Anthropic, Ollama |
python-dotenv |
Load .env configuration |
rich |
Terminal UI (diffs, panels, tables) |
pipreqs |
Project import scanning |
pathspec |
Gitignore-aware file filtering |
mcp |
FastMCP server (optional) |
gitpython |
Git auto-commit (optional) |
watchdog |
File change watching (optional) |
License
Licensed under Apache-2.0.
Licensed under Apache-2.0.
Licensed under Apache-2.0.
Licensed under Apache-2.0.
Apache 2.0 โ Tom Sapletta / Softreck
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pfix-0.1.11.tar.gz.
File metadata
- Download URL: pfix-0.1.11.tar.gz
- Upload date:
- Size: 38.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1558aaed1c85f2b39abdc1492a8728f662e3f89f47d924859a4a6f4edf16b48
|
|
| MD5 |
0957ef25e22177618fa0bb308d7e89a2
|
|
| BLAKE2b-256 |
834f8867b0495891dd69787a0cb354982b5eaa1ed265cd5b3efc21e9ae070ced
|
File details
Details for the file pfix-0.1.11-py3-none-any.whl.
File metadata
- Download URL: pfix-0.1.11-py3-none-any.whl
- Upload date:
- Size: 29.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad7c6dd71e66ee2415092248cf711aed753da7073cf9607aa52faefbdfd8b957
|
|
| MD5 |
c85c6b3ae4a448ec17288efa14173750
|
|
| BLAKE2b-256 |
4073efd7ee195ca24f6e54d0b8da03990aab581ec4b8a3dea6222bb1cce0a058
|