Transform your codebase with natural language. GPTDiff lets you describe code changes in plain English and automatically generates and applies the diffs for you.
# 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" --applyThat's it. GPTDiff reads your entire project, understands the context, generates a unified diff, and applies it—all in one command.
📚 Full documentation at gptdiff.255labs.xyz
pip install gptdiff# Linux/macOS
export GPTDIFF_LLM_API_KEY='your-api-key'
# Windows
set GPTDIFF_LLM_API_KEY=your-api-keyGet your API key at nano-gpt.com/api.
Navigate to any project directory and describe what you want to change:
cd your-project
gptdiff "Add type hints to all functions" --applyWhat 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
| 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 filesGPTDiff doesn't just run commands—it transforms your code. Here are real before/after examples:
Command:
gptdiff "Add type hints to all functions" --applyBefore:
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}"Command:
gptdiff "Add try/except blocks with proper error messages to all file operations" --applyBefore:
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}")Command:
gptdiff "Rename the User class to Account and update all imports and references" --applyBefore (models/user.py):
class User:
def __init__(self, name: str, email: str):
self.name = name
self.email = emailBefore (services/auth.py):
from models.user import User
def get_current_user() -> User:
return User("John", "[email protected]")After (models/account.py): (file renamed)
class Account:
def __init__(self, name: str, email: str):
self.name = name
self.email = emailAfter (services/auth.py):
from models.account import Account
def get_current_user() -> Account:
return Account("John", "[email protected]")GPTDiff understands your entire codebase—it updates class definitions, imports, type hints, and references across all files in one operation.
| Feature | Benefit |
|---|---|
| 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 |
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| 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/ |
Prevent files from being sent to the LLM by adding them to .gitignore or .gptignore:
# .gptignore example
*.env
secrets/
node_modules/gptpatch is a companion command-line tool to GPTDiff that applies unified diffs directly to your project.
Apply a diff provided directly:
gptpatch --diff "<diff text>"Or apply a diff from a file:
gptpatch path/to/diff.patch- --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
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.
| 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.pyFor the complete CLI reference, see cli.md.
Preview API docs locally using MkDocs:
pip install .[docs]
mkdocs serveOpen http://localhost:8000 to view the documentation
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.
-
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
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 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" --applyThe file list is appended to the generated gptdiff command so the LLM sees
only the files that matter, keeping prompts lean and costs down.