Introduction to Aider and Local LLMs
Aider is an open-source AI pair programming tool that runs in your terminal and edits code directly in your local Git repository. While many developers associate Aider with cloud-hosted models like GPT-4 or Claude, it also supports local LLMs through providers such as Ollama, LM Studio, and llama.cpp. Pairing Aider with a local model gives you a fully offline, privacy-preserving coding assistant that can read, modify, and refactor your codebase without sending a single byte to a third-party server.
This tutorial walks through everything you need to know to set up Aider with a local LLM, configure it for best results, and adopt workflows that make the most of on-device pair programming.
Why Pair Programming with Local LLMs Matters
Running your AI coding assistant locally offers several compelling advantages:
- Privacy: Your source code never leaves your machine, which is critical for proprietary or compliance-sensitive projects.
- Cost: No per-token API charges. You pay only for the hardware you already own.
- Offline access: Works on planes, trains, or behind corporate firewalls.
- Control: You choose the model, its quantization, and its system prompt behavior.
- Reproducibility: A pinned local model behaves consistently across sessions.
The trade-off is that local models are typically smaller and less capable than frontier cloud models. However, modern 7B–34B parameter coding models like Qwen2.5-Coder, DeepSeek-Coder, and Codestral are surprisingly effective for everyday refactoring, test generation, and bug fixing when paired with Aider's structured editing workflow.
Prerequisites and Installation
Installing Aider
Aider is a Python package. Install it with pip or pipx (recommended for isolated environments):
# Using pipx (recommended)
pipx install aider-chat
# Or with pip
pip install aider-chat
# Verify installation
aider --version
Installing a Local LLM Runtime
The easiest way to run a local LLM is Ollama, which exposes an OpenAI-compatible API on localhost:11434. Install it from the official site, then pull a coding-focused model:
# Pull a strong coding model
ollama pull qwen2.5-coder:7b
# Or a larger variant if you have the VRAM
ollama pull qwen2.5-coder:32b
# Verify it runs
ollama run qwen2.5-coder:7b "Say hello"
Alternative runtimes like LM Studio or llama.cpp also work, as long as they expose an OpenAI-compatible endpoint.
Connecting Aider to Your Local Model
Aider uses LiteLLM under the hood, which means you reference local models with an ollama/ prefix. Launch Aider inside a Git repository and point it at your local model:
cd my-project
aider --model ollama/qwen2.5-coder:7b
If you are using LM Studio, start its local server (default port 1234) and connect like this:
aider --model openai/your-model-name \
--openai-api-base http://localhost:1234/v1 \
--openai-api-key dummy
You can also persist configuration by creating an .aider.conf.yml file in your home directory or project root:
# .aider.conf.yml
model: ollama/qwen2.5-coder:7b
auto-commits: true
dark-mode: true
Basic Pair Programming Workflow
Once Aider launches, you are dropped into an interactive chat. Aider automatically tracks which files you add to the chat, sends their contents to the model, and applies the model's proposed edits directly to disk. Every change is committed to Git with a descriptive message.
Adding Files to the Chat
# Inside the Aider prompt
/add src/auth.py src/auth_test.py
Requesting a Change
# Ask for a refactor
Refactor the login function to use async/await and add input validation.
Aider will respond with a diff, apply it to src/auth.py, and commit the change. You can review the commit with git log or git show HEAD.
Useful In-Chat Commands
/add <file>— add a file to the chat context/drop <file>— remove a file from context/clear— reset the conversation history/undo— undo the last Aider commit/diff— show uncommitted changes/tokens— inspect token usage for the current context/help— list all commands
Working with Larger Codebases
Local models have smaller effective context windows than cloud models, so context management is critical. Aider provides a repository map feature that builds a compact summary of your entire codebase using tree-sitter. This lets the model "see" the structure of files it has not been explicitly given.
# Enable a repo map with a token budget
aider --model ollama/qwen2.5-coder:7b \
--map-tokens 1024 \
--map-refresh auto
For very large projects, consider disabling the repo map and adding only the specific files relevant to your task:
aider --model ollama/qwen2.5-coder:7b --no-map
Practical Example: Adding a Feature
Suppose you have a small Flask app and want to add rate limiting. Here is how a typical session looks.
Project structure:
my-app/
├── app.py
├── requirements.txt
└── tests/
└── test_app.py
Launch Aider and add the relevant files:
$ cd my-app
$ aider --model ollama/qwen2.5-coder:7b
Aider v0.x.x
Model: ollama/qwen2.5-coder:7b
Git repo: .git with 12 files
> /add app.py tests/test_app.py
Added app.py to the chat.
Added tests/test_app.py to the chat.
> Add a simple in-memory rate limiter that allows
at most 60 requests per minute per client IP.
Apply it to all routes. Also add tests for it.
Aider will edit app.py to introduce a rate limiter, update tests/test_app.py with new test cases, and commit each logical change. A typical generated implementation might look like:
# app.py
from flask import Flask, request, jsonify
from collections import defaultdict
import time
app = Flask(__name__)
RATE_LIMIT = 60
RATE_WINDOW = 60 # seconds
request_log = defaultdict(list)
def rate_limited():
now = time.time()
ip = request.remote_addr
request_log[ip] = [t for t in request_log[ip] if now - t < RATE_WINDOW]
if len(request_log[ip]) >= RATE_LIMIT:
return jsonify({"error": "rate limit exceeded"}), 429
request_log[ip].append(now)
return None
@app.before_request
def enforce_rate_limit():
response = rate_limited()
if response:
return response
@app.route("/")
def index():
return jsonify({"message": "hello"})
if __name__ == "__main__":
app.run(debug=True)
And the corresponding tests:
# tests/test_app.py
import pytest
from app import app
@pytest.fixture
def client():
app.config["TESTING"] = True
with app.test_client() as c:
yield c
def test_index_ok(client):
r = client.get("/")
assert r.status_code == 200
def test_rate_limit_enforced(client):
for _ in range(60):
assert client.get("/").status_code == 200
assert client.get("/").status_code == 429
Run the tests to verify:
pytest -q
Best Practices for Local LLM Pair Programming
Choose the Right Model Size
Match the model to your hardware. As a rough guide:
- 7B models (e.g., qwen2.5-coder:7b): run on 8 GB VRAM GPUs. Good for small, focused edits.
- 14B–32B models: require 16–32 GB VRAM. Noticeably better at multi-file refactors.
- Quantization: use Q4_K_M or Q5_K_M GGUF quants to fit larger models into limited memory.
Keep Tasks Small and Focused
Local models struggle with long, multi-step instructions. Break work into small, verifiable chunks: one feature, one bug, or one test at a time. Use /clear between unrelated tasks to avoid context drift.
Use Git as Your Safety Net
Aider auto-commits every change, which means you can always git revert or /undo a bad edit. Review diffs before accepting them:
git diff HEAD~1
Provide Explicit Context
Unlike frontier models, local models benefit from explicit instructions. Mention file names, function names, and expected behavior directly in your prompt. For example:
In src/payment.py, rename process_payment() to charge_card()
and update all callers in src/api.py and src/webhooks.py.
Keep the function signature the same.
Use Architect Mode for Complex Tasks
Aider supports an "architect" mode where one model designs a plan and another (the "editor") applies edits. You can use a stronger local model as the architect and a smaller one as the editor:
aider --model ollama/qwen2.5-coder:7b \
--architect \
--editor-model ollama/qwen2.5-coder:7b
Watch Token Usage
Run /tokens periodically to ensure you are not exceeding your model's context window. If you are, drop files with /drop or reduce --map-tokens.
Troubleshooting Common Issues
- "Model not found": ensure the model name after
ollama/exactly matches whatollama listreports. - Slow responses: reduce model size, lower context length with
--max-chat-history-tokens, or use a GPU. - Bad edits / malformed diffs: switch to a model specifically trained for coding, or enable
--edit-format difffor models that prefer unified diffs. - Out-of-memory errors: use a smaller quantization or close other GPU processes.
Conclusion
Aider combined with a local LLM gives you a capable, private, and cost-effective pair programmer that lives entirely on your machine. By choosing a coding-tuned model like Qwen2.5-Coder, keeping tasks focused, leveraging Aider's repository map, and relying on Git as a safety net, you can integrate AI-assisted development into your workflow without depending on any external API. As local models continue to improve, this offline-first approach is becoming a practical and sustainable option for everyday software development.