Aider describes itself as "AI pair programming in your terminal." You open it inside a git repo, describe a change in plain language, and it edits your files and commits the result. We already know this loop works with a frontier cloud model. The question was whether it survives contact with a 986 MB model on the same laptop, with no API key in sight.

So we ran the loop twice. Same aider version, same Ollama container, same qwen2.5-coder:1.5b, the same request to the character. The first run produced a diff for code that does not exist in our file and changed nothing. The second produced a correct patch, applied it, and committed it with a sensible message. Between the two runs we changed exactly one thing, and it was not the model.

Everything below comes from a session captured on 22 July 2026. Output is pasted verbatim, failure included. The failure is the lesson.

v0.86.2Aider version we pinned — the official Docker image and PyPI both ship it, published Feb 2026
986 MBqwen2.5-coder:1.5b, the local model we used, per ollama list
07fca48The commit aider made on its own after the successful edit — no git command typed by us
Apache-2.0License; the repo now lives in the Aider-AI GitHub org, history intact
★47.6kGitHub stars — RECATOOLS traction data, 22 Jul 2026

Prerequisites are short. You need Docker (the official aider image publishes arm64 manifests, so Apple Silicon runs natively) and a configured git identity, because aider's Docker docs tell you to set git config user.email and user.name before running. If you followed our LiteLLM walkthrough, the two-containers-on-a-private-network pattern will look familiar.

Step 1: A repo, a network, and a 986 MB model

Aider is meant to work inside a git repository. Its docs put it plainly: "Aider works best with code that is part of a git repo." We gave it a deliberately small one. The whole project is a 34-line todo.py that can list tasks and add tasks, with no way to complete one. That missing feature is the job we will hand to the model.

Ollama runs as a container on a private Docker network, pinned to 0.32.1, with a named volume for model storage.

Terminal — repo, network, model
mkdir -p ~/aider-box/todo-cli && cd ~/aider-box/todo-cli && git init
cat > todo.py   # 34-line todo CLI: list + add, no way to complete a task yet
git add todo.py && git commit -m "todo CLI: list and add"
docker network create aider-net && docker run -d --name ollama --network aider-net -v ollama-models:/root/.ollama ollama/ollama:0.32.1
54b40fddc682
docker exec ollama ollama pull qwen2.5-coder:1.5b
pulling manifest
verifying sha256 digest
success
docker exec ollama ollama list
NAME                  ID              SIZE      MODIFIED
qwen2.5-coder:1.5b    d7372fd82851    986 MB    Less than a second ago

Aider's own Ollama page has a warning for anyone scaling this up: "Ollama uses a 2k context window by default" and it "silently discards context that exceeds the window." Aider adjusts the context window dynamically by default, and our file is tiny, so we ran Ollama as-is. For real repos, the docs' fix appears later in this guide.

Step 2: Pull aider, pinned

The official image is paulgauthier/aider. We pinned the version tag rather than trusting latest, though today they are the same thing — Docker Hub shows latest pointing at v0.86.2, pushed 12 February 2026, which is also exactly what pip install aider-chat resolves to. That date gets an honest paragraph in the cadence section below.

Terminal — pull aider v0.86.2
docker pull paulgauthier/aider:v0.86.2
v0.86.2: Pulling from paulgauthier/aider
8e64454218c6: Pulling fs layer

Digest: sha256:0d54037f6c97c85a926ebc3c903e27446f5bca96823d9f68902f1e623289b556
Status: Downloaded newer image for paulgauthier/aider:v0.86.2

Step 3: First attempt — a confident diff that never lands

Aider's Docker docs give this run form, built around your repo root mounted at /app and your own user id so the container does not litter root-owned files into the repo:

docker pull paulgauthier/aider
docker run -it --user $(id -u):$(id -g) --volume $(pwd):/app paulgauthier/aider --openai-api-key $OPENAI_API_KEY [...]

We kept their --user and --volume shape and swapped the cloud key for a local backend. Two adjustments are ours. The docs set OLLAMA_API_BASE=http://127.0.0.1:11434, correct for a host install; inside a container that address is the container itself, so on our shared network the value becomes the service name, http://ollama:11434. And since qwen2.5-coder:1.5b is not in aider's model database, we passed --no-show-model-warnings to silence the unknown-model notice ("Unknown context window size and costs, using sane defaults," per the docs) plus --yes-always to auto-accept prompts such as the offer to add .aider* files to .gitignore. The model prefix follows the docs: "Using ollama_chat/ is recommended over ollama/."

Here is the first attempt. Note what is missing from the command: we never told aider which file to work on.

Terminal — attempt 1: file not in the chat
docker run --rm --network aider-net -e OLLAMA_API_BASE=http://ollama:11434 \
    --user $(id -u):$(id -g) --volume $(pwd):/app paulgauthier/aider:v0.86.2 \
    --model ollama_chat/qwen2.5-coder:1.5b --no-show-model-warnings --yes-always \
    --message "Add a 'done N' command that removes task number N from the list, with a helpful error if N is out of range. Update the usage line."
+        if command == "done 1":
+            # Remove the first task
+            del tasks[0]
+        elif command.startswith("done"):
+            try:
+                task_number = int(command.split()[1])
+                del tasks[task_number-1]
+            except ValueError:
+        command = input("Enter command: ")
+        if command == "done 1":
+            # Remove the first task
+            del tasks[0]
+        elif command.startswith("done"):
+            try:
+                task_number = int(command.split()[1])
+                del tasks[task_number-1]
+            except ValueError:
+                print("Error: Invalid task number.")
+        elif command == "exit":
+            break
+        else:
+            print("Error: Unknown command.")
-if __name__ == "__main__":
+if __name__ == '__main__':
     main()
Make sure to add these files to the chat before proceeding.
Tokens: 814 sent, 213 received.
todo.py
Sure, I'll add the todo.py file to the chat.
Tokens: 1.2k sent, 15 received.

Read that diff against what our program actually is. The model wrote patches for an interactive REPL — an input("Enter command: ") loop with an exit command — and patched it twice, with a dangling except in the first pass. Our todo.py has none of that; it parses command-line arguments. The file was never in the chat, so the model invented a plausible todo app from the request alone and edited its own invention.

The safety outcome was good. There was no "Applied edit" line and no commit, leaving todo.py untouched; the only new file was the .gitignore aider itself offered to create. Aider asked for the file to be added, the model agreed, and the single-shot session ended, two thousand tokens spent on nothing. This is precisely the failure mode aider's docs warn about with small models: "Be aware that aider may not work well with less capable models. If you see the model returning code, but aider isn't able to edit your files and commit the changes… this is usually because the model isn't capable of properly returning 'code edits'."

Step 4: Same request, one word added

Aider's usage docs say to launch it with the files you want edited, and to be stingy about it: "Only add the files that need to be edited for your task. Don't add a bunch of extra files." So attempt two names todo.py on the command line. Everything else — model, network, request text — is unchanged.

Terminal — attempt 2: todo.py named
# attempt 2 — name the file so it is in the chat from the start:
docker run --rm --network aider-net -e OLLAMA_API_BASE=http://ollama:11434 \
    --user $(id -u):$(id -g) --volume $(pwd):/app paulgauthier/aider:v0.86.2 \
    todo.py --model ollama_chat/qwen2.5-coder:1.5b --no-show-model-warnings --yes-always \
    --message "Add a 'done N' command that removes task number N from the list, with a helpful error if N is out of range. Update the usage line."
     elif args[0] == "add" and len(args) > 1:
         tasks.append(" ".join(args[1:]))
         save_tasks(tasks)
         print("added")
+    elif args[0] == "done" and len(args) > 1:
+        try:
+            task_number = int(args[1])
+            if task_number < 1 or task_number > len(tasks):
+                raise ValueError("Task number out of range.")
+            del tasks[task_number - 1]
+            save_tasks(tasks)
+            print(f"done {task_number}")
+        except ValueError as e:
+            print(e)
     else:
-        print("usage: todo.py [list|add <task>]")
+        print("usage: todo.py [list|add <task>|done N]")
 if __name__ == "__main__":
     main()
This file now includes a new command done N that removes the task number N from
the list. It also updates the usage line to reflect this change.
Tokens: 976 sent, 351 received.
Applied edit to todo.py
Commit 07fca48 feat(todo): add 'done N' command to remove task number N from the
list

This diff is against the real file. It hooks into the existing args[0] dispatch, adds a range check with the exact error behaviour we asked for, and updates the usage line. Then the two lines that make aider aider: "Applied edit to todo.py" and an automatic commit, 07fca48, with a message in Conventional Commits shape — which is what the git docs promise, since aider "automatically commits every edit" with generated messages by default.

The variable was context, not the model

Same weights on both runs, same request. What changed is that in attempt two, the contents of todo.py travelled with it — 976 tokens sent instead of 814 — the difference is about the size of the 34-line file. Aider does build a repo map that tells the model what files exist and how they relate, but a map is not the territory; it names todo.py without pasting its 34 lines. Handed only a filename and a feature request, our 1.5B model filled the gap with the most statistically likely todo app, which happened to be a REPL. Handed the actual code, the same model produced a patch a reviewer would wave through.

This is a familiar result. In our AnythingLLM guide, a small model answered wrongly from its own weights and correctly the moment retrieval put the source document in front of it. The aider version of the lesson is sharper because the failure is not a wrong answer, it is a phantom refactor. What lands in the context window matters more than how many parameters sit behind it.

Honesty about our model choice cuts the other way too. Aider's own example Ollama configuration uses qwen2.5-coder:32b-instruct-fp16, an order of magnitude larger than ours, and its docs list frontier cloud models as what the tool "works best" with — advice frozen with the v0.86.x docs, so read the specific names as period pieces. Our 1.5B run shows the floor: small, well-scoped edits on a file that is in the chat. A way to learn the workflow for free, not a claim that tiny models can maintain your codebase.

Step 5: Prove the feature actually works

A commit is not a working feature. We checked the log, then exercised the new command, including the out-of-range path.

Terminal — verify the commit and the command
git log --pretty="%h %an — %s" -2
07fca48 reca — feat(todo): add 'done N' command to remove task number N from the list
8d6aa5d reca — todo CLI: list and add
python3 todo.py add "write the guide" && python3 todo.py add "verify it" && python3 todo.py add "ship it"
added
python3 todo.py done 2 && python3 todo.py list
done 2
1. write the guide
2. ship it
python3 todo.py done 9
Task number out of range.

done 2 removed "verify it" and left the list renumbered; done 9 refused with the message the model wrote. The feature we described in one sentence exists, works, and is in git history.

Condensed terminal session showing the aider run: Ollama model pull, the failed first attempt with a hallucinated REPL diff, the applied edit with auto-commit 07fca48, and the working done command
The session end to end — setup, the diff that never landed, the one that did, and the proof — captured 22 Jul 2026.

Auto-commits, /undo, and the chat modes

Aider's git integration is opinionated and, once you trust it, comfortable. Every applied edit becomes its own commit, which means undoing the AI is a first-class operation rather than an archaeology project. The docs also note that aider "takes special care before editing files that already have uncommitted changes," committing your dirty work separately before layering its own. The in-chat commands you will actually use:

/add <file>        put a file in the chat
/diff              show the last change
/undo              revert aider's last commit
/commit            commit your own dirty changes
/git <cmd>         run a raw git command

/ask               discuss, never edit
/code              default editing mode
/architect         one model plans, an editor model applies

aider --no-auto-commits    keep aider's edits uncommitted
aider --no-dirty-commits   don't pre-commit your changes
aider --no-git             disable git entirely

Code mode, the default we used, is where "Aider will make changes to your code to satisfy your requests." Ask mode will "discuss your code and answer questions about it, but never make changes"; the docs suggest agreeing a plan there, then switching to code mode to execute. Architect mode splits the job across a proposer and an editor model, aimed at stronger pairings than ours. One Docker caveat from the install docs: /run executes inside the container, where your host toolchain is not, and /voice needs audio passthrough.

We also found an attribution wrinkle. The git docs state that when aider authors changes, "(aider)" is "appended to the git author and git committer name metadata," with flags like --no-attribute-author to turn that off. Our commit carries no such suffix.

Terminal — commit identity check
git log -1 --format="author: %an <%ae>%ncommitter: %cn <%ce>"
author: reca <[email protected]>
committer: reca <[email protected]>

Commit 07fca48 carries the plain repo identity in both fields, nothing appended, under v0.86.2 with our flags and repo config. We will not guess why. If your audit trail depends on AI-authored commits being labelled, verify the labelling on your own setup instead of taking the documentation's word for it.

Release cadence and license, stated precisely

Aider's project state is easy to misread. Here is what we verified from primary sources on 22 July 2026. The GitHub Releases page stops at v0.86.0, published 9 August 2025 — but PyPI's latest is 0.86.2, uploaded 12 February 2026, both 0.86.1 and 0.86.2 exist as git tags the releases page never picked up, and the official Docker image ships the same 0.86.2. The repo itself kept moving: merges through 22 May 2026, including model-support updates, and a populated unreleased changelog listing new model settings, an /ok command, and additional repo-map languages. Slow release cadence, demonstrably live code. Community issue #5242 asks the project to automate releases; no maintainer statement explaining the gap turned up in our sources, so we offer none.

This means you need some discipline. Pin the image tag and date-stamp your notes; "current aider" has meant February 2026 code for months. If you pip-install instead of using Docker, aider-chat 0.86.2 requires Python 3.10 through 3.12 — 3.13 is unsupported, per PyPI metadata.

The license is Apache-2.0, clean and unqualified. The project was created and is overwhelmingly authored by Paul Gauthier, and the repository moved from his personal account to the Aider-AI organisation — the old path 301-redirects to the same repo id, history intact. It carries ★47.6k GitHub stars in our 22 July 2026 traction snapshot; tracked history is on our aider entry in the AI directory.

Footprint

Session numbers, each from the transcript that produced it.

986 MB
qwen2.5-coder:1.5b
ollama list, 22 Jul 2026
1,327
tokens, successful run
976 sent + 351 received, aider's own meter
34 lines
todo.py before the edit
our test repo, one file
2
attempts to a commit
file out of chat, then in

Teardown

Nothing in this setup persists outside Docker and the working directory. Three commands return the machine to zero.

Terminal — full teardown
docker rm -f ollama && docker network rm aider-net && docker volume rm ollama-models
ollama
aider-net
ollama-models
docker rmi paulgauthier/aider:v0.86.2 ollama/ollama:0.32.1
4
cd ~ && rm -rf ~/aider-box

If you keep going instead, the context-window fix promised in Step 1 is aider's own YAML, dropped into .aider.model.settings.yml — their example targets the 32B model:

- name: ollama/qwen2.5-coder:32b-instruct-fp16
  extra_params:
    num_ctx: 65536

Or start Ollama with OLLAMA_CONTEXT_LENGTH=8192 ollama serve, the sequence the docs document, so the 2k default never silently truncates your repo out of the conversation.

FAQ

Can a 1.5B model really handle aider?

For small, precisely scoped edits on a file that is in the chat — in our run, yes, on the second attempt. Aider's docs warn that models weaker than GPT-3.5 "may have problems working well with aider," and their example Ollama config uses a 32B model. Learn the workflow on the tiny model; step up before trusting it with more.

Why did the first run fail?

The file was not in the chat. Aider's repo map told the model that todo.py existed, but a map carries names and structure, not contents, so the model invented a REPL-style program and edited that. Aider applied nothing. Naming the file on the command line put its 34 lines into the request, and the same model produced a correct patch.

Is aider still maintained?

The code is active; the releases are slow. We verified merges into the repo through 22 May 2026 and a populated unreleased changelog, while the newest installable version, 0.86.2, dates to February 2026 and the GitHub Releases page still shows v0.86.0 from August 2025. No maintainer statement explains the release gap, so we report the observable facts and leave it there.

How do I stop aider committing automatically?

Launch with --no-auto-commits and aider leaves its edits uncommitted for you to review; --no-dirty-commits stops it pre-committing your own uncommitted changes, and --no-git disables the integration entirely. With auto-commits on, /undo reverts aider's last commit in one step — the small, visible, reversible rhythm that runs through our guides hub.

Sources & verification