Enterprise DNA

Omni by Enterprise DNA

Enterprise DNA Resources

Step-by-step how-tos. Practical AI operating-system thinking for owners, operators, and teams doing real work.

220k+

Data professionals

Omni

AI agents and apps

Audit

Map the manual work

Guide Intermediate General

Aider Tutorial: A Practical Guide to Git-Native AI Coding

A hands-on Aider tutorial covering setup, real commands, key settings, and a workflow pattern for using this terminal-based AI pair programmer with git.

Sam McKay |
Aider Tutorial: A Practical Guide to Git-Native AI Coding

What Aider actually is

Aider is a terminal-based AI pair programmer that lives inside your git repository. It is not a chat window, not an IDE plugin, and not a hosted service. It is a Python CLI that talks to large language models, reads your files, edits them in place, and commits each change to git as it goes.

Under the hood, Aider maintains a structured conversation with the model, but it also maintains a “repo map,” which is a compressed, tree-style summary of your codebase that gets fed into the context window. When you ask it to do something, it figures out which files are relevant, pulls them into context, proposes edits, applies them, and then runs git commit with a message it writes for you.

The technical model matters because it explains why Aider behaves differently from Copilot or Cursor. Those tools are inline completion engines or IDE-aware editors. Aider is closer to a junior developer who can see your whole repo, make coordinated changes across multiple files, and check their work into version control as they go. It is also stateless across sessions in the sense that you can leave and come back, and your git history is the source of truth for what happened.

Aider is open source, written in Python, and distributed via pip. It supports any model that exposes an OpenAI-compatible or Anthropic-compatible API, plus local models through Ollama. The current version supports GPT-4o, Claude 3.5 Sonnet, Claude 3.7 Sonnet, DeepSeek, and a growing list of open-weight models.

Setup and authentication

Aider is a Python package, so you need Python 3.8 or newer. The cleanest install uses the dedicated installer, which handles virtual environments and keeps Aider isolated from your system Python.

Run python -m pip install aider-install followed by aider-install. This drops a self-contained aider binary in your home directory. Add ~/.local/bin to your PATH if it is not already there.

If you prefer a plain pip install, pip install aider-chat works the same way. The trade-off is that you manage the virtual environment yourself.

Authentication depends on which model provider you want to use. For OpenAI, export OPENAI_API_KEY in your shell. For Anthropic, export ANTHROPIC_API_KEY. For local models through Ollama, no key is needed but you do need Ollama running and the model pulled.

A practical setup looks like this. Add to your ~/.zshrc or ~/.bashrc:

export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...

Then source the file. You can verify with aider --models which lists every model Aider knows how to call.

Aider also expects to be run inside a git repository. If you launch it in a folder that is not a git repo, it will offer to run git init for you. Accept that offer, or run git init yourself first.

First working example

Create a small project to test against. Make a directory, initialize git, and add a single Python file.

mkdir aider-demo
cd aider-demo
git init
echo 'def add(a, b):\n    return a + b\n\ndef subtract(a, b):\n    return a - b' > calc.py
git add calc.py
git commit -m "initial calc"

Now launch Aider pointing at the file you want it to work on.

aider calc.py

You will see a chat prompt. Type something concrete and scoped:

add a multiply function and a divide function that raises an error on zero

Aider will read calc.py, propose an edit, show you a diff, and ask for confirmation. Press y to accept. It will then run git commit with a message like “added multiply and divide functions with zero-check.”

Type /exit or press Ctrl-D to leave the session. Run git log and you will see two commits, the initial one and the one Aider made.

That is the entire core loop. Every Aider session is a series of natural-language requests, each producing a diff and a commit.

A more realistic second request would be:

write pytest tests for all four functions in tests/test_calc.py

Aider will create the new file, populate it, and commit it. You now have a small repo with a feature, tests, and a clean git history that you can git revert or git bisect against.

Key settings that matter

Most Aider users run it with defaults and never touch the configuration. That works, but a handful of flags change the experience significantly.

--model selects the underlying LLM. The default is usually GPT-4o or whichever provider it detects. For serious refactor work, Claude 3.5 Sonnet and Claude 3.7 Sonnet tend to perform well on multi-file edits. For local-only work, ollama_chat/deepseek-coder-v2 or similar is a reasonable starting point.

--architect enables a two-model workflow. Aider calls a “planner” model to design the change, then a “coder” model to implement it. This produces better results on complex tasks at the cost of roughly double the tokens. Pair it with --weak-model to use a cheaper model for one of the two roles.

--auto-commits and --no-auto-commits control whether Aider commits after every accepted edit. Auto-commits are useful because they give you a granular history you can revert. Some people prefer --no-auto-commits and commit manually so they can batch related changes.

--map-tokens controls how much of your repo map gets fed into context. The default is sensible but if you have a large codebase you may want to raise it. If responses feel slow or expensive, lower it.

--edit-format selects how Aider formats its edits. The options are diff, whole, and udiff. diff is the default and works well with most models. Some models perform better with whole because they struggle with unified diff syntax.

--lint-cmd and --auto-lint let Aider run a linter after each edit and feed the output back to the model. For Python, --lint-cmd 'ruff check' is a strong default. For TypeScript, --lint-cmd 'npx eslint' works. Auto-lint catches a surprising number of mistakes the model would otherwise miss.

--test-cmd and --auto-test do the same thing for tests. Point them at your test runner and Aider will run tests after each change and use failures to drive the next edit.

You can persist these in a .aider.conf.yml file at the root of your repo. Example:

model: claude-3-5-sonnet-20241022
auto-commits: true
auto-lint: true
lint-cmd: ruff check
auto-test: true
test-cmd: pytest -q

Aider also reads .aiderignore, which works like .gitignore. Use it to keep generated files, lockfiles, and large data directories out of the repo map.

Where it shines

Aider is at its best on tasks that span multiple files and benefit from a tight feedback loop with git. Concrete scenarios where it genuinely excels:

Multi-file refactors where you need to rename a function, update its callers, and adjust tests in one pass. Aider reads the repo map, identifies the call sites, and produces a coherent set of edits in a single request.

Adding a new feature to an existing codebase that follows an established pattern. If your project already has a clear structure for routes, services, or components, Aider will mirror that structure without much hand-holding.

Generating test coverage for code that lacks it. Point Aider at a module, ask for tests, and it will usually produce something runnable on the first attempt. The --auto-test flag then closes the loop by running the tests and feeding failures back.

Migrating between library versions or API surfaces. Aider handles the “find every callsite and update it” pattern well, especially when combined with --architect for the planning pass.

Working in unfamiliar codebases. The repo map gives Aider a structural overview that lets it answer questions like “where is authentication handled” or “what calls this function” without you having to read the code yourself.

Long sessions where you want a paper trail. Because every accepted edit becomes a commit, you can review the session later, revert specific changes, or hand the branch to a colleague.

Where it fails

Aider has real limitations and pretending otherwise wastes time.

Very large codebases hit context window limits. The repo map helps but it is still a summary. If your monorepo has tens of thousands of files, Aider will struggle to keep the relevant ones in scope. Splitting work into smaller repos or using --map-tokens aggressively helps, but does not fully solve the problem.

Tasks that require deep architectural judgment are not Aider’s strength. It can implement a design you describe, but it will not push back on a bad design the way a senior engineer would. You still need to make the structural calls.

Ambiguous requests produce ambiguous results. If you say “make this better,” Aider will guess what you mean and you will spend more time undoing guesses than you saved. The tool rewards precise, scoped instructions.

Some languages have weaker support than others. Python, JavaScript, TypeScript, Go, and Rust are well covered because they are common in training data and have good tooling for linting and testing. Less common languages may produce lower-quality output or fail to parse correctly.

Cost can creep up on long sessions. Each request sends the full conversation plus the repo map plus the relevant files. A 50-message session on a large codebase can use a meaningful fraction of your monthly API budget. Use --weak-model for the architect role and consider local models for routine work.

Aider also does not run your application. It can read code, edit code, lint code, and test code, but it cannot click through your UI or watch your server logs. For tasks that require runtime feedback, you still need to be at the keyboard.

Practical workflow pattern

The pattern that works in practice looks like this.

Start every Aider session on a fresh branch. Run git checkout -b feature/<short-description> before launching Aider. This keeps the main branch clean and makes it trivial to abandon a session by deleting the branch.

Write a short note describing what you want before you start. Two or three sentences is enough. The note becomes your reference point when Aider’s edits drift from your intent.

Launch Aider with the specific files you want it to touch. aider src/auth.py src/routes/login.py tests/test_auth.py is better than aider with no arguments because it constrains the scope.

Make one request at a time. Wait for the diff. Read the diff. Accept or reject. The temptation is to chain requests, but each request should be reviewable on its own.

Use /undo liberally. Aider keeps a stack of edits within the session and /undo reverts the last one. This is faster than git revert and does not pollute your history.

Commit messages from Aider are decent but not great. After a productive session, run git rebase -i HEAD~n and rewrite the messages to match your team’s conventions.

For continuous work on a long-running task, --watch mode re-runs Aider whenever files change. This is useful for “keep improving this until tests pass” loops but can be expensive.

When you finish, review the diff against main with git diff main..feature/<name>. If the diff is clean, merge. If it is messy, you have full history to revert selectively.

The honest summary is that Aider is a tool that rewards the same discipline as working with any other engineer. Clear instructions, scoped requests, careful review, and a willingness to throw away bad output. Used that way, it is one of the more productive AI coding tools available today.

If this is the kind of problem agents can help with, the free Working With Claude field guide is the practical next step. Thirty-two pages, no fluff. Get the free guide.