A tool to generate and apply git diffs using LLMs
Project description
GPTDiff
Transform your codebase with natural language. GPTDiff lets you describe code changes in plain English and automatically generates and applies the diffs for you—one command at a time, or continuously with agent loops.
# Install and configure
pip install gptdiff
export GPTDIFF_LLM_API_KEY='your-api-key' # Get one at https://nano-gpt.com/api
# Make changes with a single command
gptdiff "Add input validation to all form fields" --apply
# Or run continuously for autonomous improvement
while true; do gptdiff "Fix code quality issues" --apply; sleep 5; done
That's it. GPTDiff reads your entire project, understands the context, generates a unified diff, and applies it. Run it once for quick changes, or loop it for hands-off continuous improvement.
📚 Full documentation at gptdiff.255labs.xyz
Quick Start
Step 1: Install
pip install gptdiff
Step 2: Set Your API Key
# Linux/macOS
export GPTDIFF_LLM_API_KEY='your-api-key'
# Windows
set GPTDIFF_LLM_API_KEY=your-api-key
Get your API key at nano-gpt.com/api.
Step 3: Run Your First Command
Navigate to any project directory and describe what you want to change:
cd your-project
gptdiff "Add type hints to all functions" --apply
What happens:
- GPTDiff scans your codebase (respecting
.gitignore) - Sends context + your instruction to an AI model
- Receives a unified diff
- Applies the changes to your files
Three Ways to Use GPTDiff
| Command | What It Does | When to Use |
|---|---|---|
gptdiff "prompt" |
Generates prompt.txt only |
Preview what will be sent to the LLM |
gptdiff "prompt" --call |
Generates diff, saves to diff.patch |
Review changes before applying |
gptdiff "prompt" --apply |
Generates and applies diff automatically | When you're ready to make changes |
Examples:
# Just generate the prompt (no API call)
gptdiff "Improve error messages"
# → Creates prompt.txt - useful for manual LLM experimentation
# Generate diff but don't apply it
gptdiff "Add API documentation" --call
# → Creates diff.patch - review before applying
# Generate and apply in one step
gptdiff "Add button animations on press" --apply
# → Changes applied directly to your files
See It In Action
GPTDiff doesn't just run commands—it transforms your code. Here are real before/after examples:
Example 1: Add Type Hints
Command:
gptdiff "Add type hints to all functions" --apply
Before:
def calculate_total(items, tax_rate):
subtotal = sum(item['price'] * item['quantity'] for item in items)
return subtotal * (1 + tax_rate)
def format_currency(amount):
return f"${amount:.2f}"
After:
def calculate_total(items: list[dict], tax_rate: float) -> float:
subtotal = sum(item['price'] * item['quantity'] for item in items)
return subtotal * (1 + tax_rate)
def format_currency(amount: float) -> str:
return f"${amount:.2f}"
Example 2: Add Error Handling
Command:
gptdiff "Add try/except blocks with proper error messages to all file operations" --apply
Before:
def read_config(path):
with open(path) as f:
return json.load(f)
After:
def read_config(path):
try:
with open(path) as f:
return json.load(f)
except FileNotFoundError:
raise ConfigError(f"Configuration file not found: {path}")
except json.JSONDecodeError as e:
raise ConfigError(f"Invalid JSON in config file {path}: {e}")
Example 3: Refactor Across Multiple Files
Command:
gptdiff "Rename the User class to Account and update all imports and references" --apply
Before (models/user.py):
class User:
def __init__(self, name: str, email: str):
self.name = name
self.email = email
Before (services/auth.py):
from models.user import User
def get_current_user() -> User:
return User("John", "john@example.com")
After (models/account.py): (file renamed)
class Account:
def __init__(self, name: str, email: str):
self.name = name
self.email = email
After (services/auth.py):
from models.account import Account
def get_current_user() -> Account:
return Account("John", "john@example.com")
GPTDiff understands your entire codebase—it updates class definitions, imports, type hints, and references across all files in one operation.
Why Choose GPTDiff?
| Feature | Benefit |
|---|---|
| Agent loops | Ship improvements while you sleep—one loop took tests from 18 to 127 overnight |
| Plain English instructions | No need to learn complex refactoring tools |
| Full project context | AI sees all your files, understands relationships |
| Smart conflict resolution | Handles merge conflicts automatically |
| Git-native workflow | Review changes with git diff, undo with git checkout |
| You control everything | Preview with --call, apply only when ready |
Agent Loops: Continuous Code Improvement
Run GPTDiff in a loop for autonomous, iterative improvements to your codebase:
# Copy-paste this and run tonight:
while true; do
gptdiff "Add missing test cases for edge conditions" --apply
git add -A && git commit -m "Auto-improvement $(date +%H:%M)" 2>/dev/null
sleep 30
done
Each improvement auto-commits with a timestamp, giving you a clean history to review in the morning.
Real Results: One test coverage loop running overnight:
| Metric | Before | After |
|---|---|---|
| Test files | 3 | 14 |
| Test cases | 18 | 127 |
| Functions with tests | 12% | 71% |
What else Agent Loops can do:
| Use Case | Example Prompt |
|---|---|
| Security Hardening | "Find and fix OWASP Top 10 vulnerabilities" |
| Tech Debt Reduction | "Refactor functions with high complexity scores" |
| Documentation Sync | "Update documentation to match current implementation" |
Each cycle analyzes your code, generates targeted improvements, and applies them—building better software automatically.
For detailed automation recipes, see the Automation Guide.
Choosing a Model
Different AI models have different strengths. Reasoning models produce more accurate results for complex refactoring but take longer. Fast models are better for simple, straightforward changes.
| Model | Best For | Speed | Notes |
|---|---|---|---|
gemini-3-pro-preview |
General code changes, refactoring | Fast | Recommended default - great balance |
gpt-4o |
Complex multi-file changes | Medium | Reliable for most tasks |
claude-sonnet-4-20250514 |
Nuanced code understanding | Medium | Great for context-sensitive changes |
gemini-2.0-flash |
Simple text changes, translations | Very fast | Most cost-effective option |
gpt5-mini |
Applying diffs (smartapply) | Very fast | Best for GPTDIFF_SMARTAPPLY_MODEL |
Quick rule: Use gemini-3-pro-preview as your default. For applying diffs, set gpt5-mini as your smartapply model.
# Recommended setup
export GPTDIFF_MODEL='gemini-3-pro-preview'
export GPTDIFF_SMARTAPPLY_MODEL='gpt5-mini'
# Use a specific model for one command
gptdiff "Convert callbacks to async/await" --model gpt-4o
Advanced Configuration
Environment Variables
| Variable | Purpose | Default |
|---|---|---|
GPTDIFF_LLM_API_KEY |
Your API key (required) | - |
GPTDIFF_MODEL |
Model for diff generation | gemini-3-pro-preview |
GPTDIFF_SMARTAPPLY_MODEL |
Model for applying diffs | gpt5-mini |
GPTDIFF_LLM_BASE_URL |
API endpoint | https://nano-gpt.com/api/v1/ |
Excluding Files
Prevent files from being sent to the LLM by adding them to .gitignore or .gptignore:
# .gptignore example
*.env
secrets/
node_modules/
gptpatch: Apply Diffs Directly
gptpatch is a companion command-line tool to GPTDiff that applies unified diffs directly to your project.
Usage
Apply a diff provided directly:
gptpatch --diff "<diff text>"
Or apply a diff from a file:
gptpatch path/to/diff.patch
Options
- --project-dir: Specify the target project directory (default: current directory)
- --model: (Optional) Specify the LLM model for advanced conflict resolution
- --max_tokens: (Optional) Define the maximum token count for LLM responses during patch application
- --nobeep: Disable the completion beep notification
Workflow
gptpatch first attempts to apply the diff using standard patch logic. If that fails, it automatically falls back to a smart apply mechanism that leverages AI-powered conflict resolution.
For more details, see the gptpatch documentation on our docs site.
CLI Options Reference
| Option | Description |
|---|---|
--apply |
Generate diff and apply it automatically |
--call |
Generate diff and save to diff.patch (for review) |
--model <name> |
Specify which LLM to use |
--temperature <0-2> |
Control creativity (default: 0.7) |
--nobeep |
Disable completion notification sound |
--prepend <file> |
Prepend custom instructions to the prompt |
--image <path> |
Include images for visual context |
Target specific files:
gptdiff "Add logging" src/api/ src/utils/helpers.py
For the complete CLI reference, see cli.md.
Documentation
Preview API docs locally using MkDocs:
pip install .[docs]
mkdocs serve
Open http://localhost:8000 to view the documentation
Python API
Integrate GPTDiff directly into your Python workflows:
from gptdiff import generate_diff, smartapply
import os
os.environ['GPTDIFF_LLM_API_KEY'] = 'your-api-key'
# Create files dictionary
files = {"main.py": "def old_name():\n print('Need renaming')"}
# Generate transformation diff using an environment string built from the files dictionary
environment = ""
for path, content in files.items():
environment += f"File: {path}\nContent:\n{content}\n"
diff = generate_diff(
environment=environment,
goal='Rename function to new_name()',
model='deepseek-reasoner'
)
# Apply changes safely using the files dict
updated_files = smartapply(diff, files)
print("Transformed codebase:")
print(updated_files["main.py"])
Batch Processing Example:
from gptdiff import generate_diff, smartapply
files = load_your_codebase() # Dict of {path: content}
transformations = [
"Add python type annotations",
"Convert string formatting to f-strings",
"Update deprecated API calls"
]
for task in transformations:
files = smartapply(generate_diff(build_environment(files), task), files)
Integration Note: GPTDiff leverages the AI Agent Toolbox for seamless tool usage across AI models and frameworks, making it ideal for both single responses and complex agent workflows.
Core Functions
-
generate_diff(environment: str, goal: str, model: str) -> str
Generates a git diff implementing the requested changesmodelparameter defaults toGPTDIFF_MODELenvironment variable -
smartapply(diff_text: str, environment_str: str, model: str) -> str
Applies complex diffs while preserving file context
Testing
To run the test suite:
pip install -e .[test]
pytest tests/
This will execute all unit tests verifying core diff generation and application logic.
plangptdiff: Generate plan prompts that call GPTDiff
plangptdiff scans your repo with ripgrep, selects only the files likely to
change (always including anything named schema), and writes a ready‑to‑paste
prompt to planprompt.txt:
# Prompt only
plangptdiff "add validation to the signup form"
# Prompt that will auto‑apply the diff
plangptdiff "upgrade to Django 5" --apply
The file list is appended to the generated gptdiff command so the LLM sees
only the files that matter, keeping prompts lean and costs down.
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 gptdiff-0.5.2.tar.gz.
File metadata
- Download URL: gptdiff-0.5.2.tar.gz
- Upload date:
- Size: 39.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4bbb35df51972dff08c68e58c63182aae8cf6df44dcd005965ae40b399ac8219
|
|
| MD5 |
eae72005d12f7a5d3d23182081d5078c
|
|
| BLAKE2b-256 |
460cacabbb07c2d2d25e887f4a7cf0cf416ee0e81fb77ddb9abcd25b55699415
|
File details
Details for the file gptdiff-0.5.2-py3-none-any.whl.
File metadata
- Download URL: gptdiff-0.5.2-py3-none-any.whl
- Upload date:
- Size: 29.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75242cd29019543b17b0251604804cad1f48e88b95724667f881602fd6f72ea8
|
|
| MD5 |
fb6d34ea4bbdece0c3e149f7272e9319
|
|
| BLAKE2b-256 |
618ea2bd73f6546606c5d00ed72f4c27c92e8b1dc44b5f7971386f7233e317fc
|