Repos Worth Reading · · 1,425 words · 6 min read
Aider explained: repo maps, edit formats, and why it still matters
Aider read at commit 5dc9490b. How the tree-sitter repo map is ranked and budgeted, what each edit format does, and a stdlib repo-map script you can run.
aider repo map edit formats architecture
Aider is the oldest agentic coding tool still in wide use, and two of its ideas are now everywhere: a ranked, token-budgeted map of the repository, and a strict contract for how the model is allowed to express an edit. This piece reads the repository at a named commit, explains both ideas from the docs, and ships a small standard-library script that builds a repo map for Python code so you can see the mechanism on your own files.
The repository on 2026-09-05
Read through the GitHub API on 2026-09-05, Aider-AI/aider had 48,775 stars, 4,921 forks, 1,855 open issues, an Apache-2.0 license, and Python as its top language. The latest release tag was v0.86.0, published 2025-08-09. The latest commit on main was 5dc9490bb35f from 2026-05-22, a merge of a pull request adding a model entry to the Anthropic models list. Two observations follow from the dates alone: the last tagged release is thirteen months old, and the last commit is three and a half months old. I state that as what the dates say, not as a judgment about the project's future.
The README at that commit opens with "AI Pair Programming in Your Terminal" and lists the features that matter here: "Aider makes a map of your entire codebase, which helps it work well in larger projects," and "Aider automatically commits changes with sensible commit messages. Use familiar git tools to easily diff, manage and undo AI changes." The model list in the README's first feature line still names Claude 3.7 Sonnet, DeepSeek R1, o1 and GPT-4o, which dates the text.
The repo map
The docs page describes the map as "the most important classes and functions along with their types and call signatures," chosen with a graph ranking algorithm that analyzes dependencies between files. Its stated purposes are to help "aider understand the code it's editing and how it relates to the other parts of the codebase," to let the model "figure out which files it needs to look at," and to let aider "write new code that respects and utilizes existing libraries, modules and abstractions."
The 2023 blog post gives the mechanism. "Tree-sitter parses source code into an Abstract Syntax Tree (AST) based on the syntax of the programming language." From the AST, aider identifies "where functions, classes, variables, types and other definitions occur in the source code" and "where else in the code these things are used or referenced." It then ranks with "a graph ranking algorithm, computed on a graph where each source file is a node and edges connect files which have dependencies," and "optimizes the repo map by selecting the most important parts of the codebase which will fit into the token budget assigned by the user (via the --map-tokens switch, which defaults to 1k tokens)." The current docs add that "Aider adjusts the size of the repo map dynamically based on the state of the chat."
The motivation sentence is the one to keep: "most real code is not pure and self-contained, it is intertwined with and depends on code from many different files in a repo." A map is a way to give the model the shape of that entanglement without paying for the whole repository in context.
A miniature repo map you can run
The shipped script does the same three steps for Python with nothing but the standard library: the ast module instead of tree-sitter, an import graph instead of a full reference graph, and a fifty-iteration PageRank power iteration for ranking. It prints one block per file, best-ranked first, and stops adding whole files when the chars/4 heuristic says the budget is spent. The heuristic is the "1 token is approximately 4 characters" figure from the Anthropic pricing FAQ; it is not a tokenizer, and the script labels its estimates as such.
def pagerank(files, damping=0.85, iters=50):
names = list(files)
edges = {n: set() for n in names}
for n, info in files.items():
for imp in info["imports"]:
target = files.get(imp) and imp or short.get(imp)
if target and target != n:
edges[n].add(target)
rank = {n: 1.0 / len(names) for n in names}
for _ in range(iters):
new = {n: (1.0 - damping) / len(names) for n in names}
for src, targets in edges.items():
share = rank[src] / len(targets) if targets else rank[src] / len(names)
for t in (targets or names):
new[t] += damping * share
rank = new
return rank
What ran here: on 2026-09-05, with Python 3.13.12 on Windows, I pointed the script at the static-site engine folder that builds this site (ten Python files, read only) with a 600-token budget and a top-10 cutoff. The first lines of the real output:
..\..\_blogkit\engine.py: (rank 0.188)
class Site
def __init__(self, root: str)
def parse_post(path: str)
def load_posts(site: Site)
def render_md(text: str)
...
def build(root: str)
def main(root: str)
..\..\_blogkit\gate.py: (rank 0.102)
def fail(m)
def warn(m)
def read(p)
def visible_text(h)
def prose_only_md(md)
def main(root: str)
..\..\_blogkit\newsite.py: (rank 0.102)
def mix(hex1, hex2, t)
def rgba(hexcol, alpha)
def scaffold(root: str, force=False)
...
... ..\..\_blogkit\research\hibp_breaches.py omitted (22 est. tokens over budget)
... ..\..\_blogkit\research\steam_app.py omitted (29 est. tokens over budget)
[map: ~580 est. tokens of 600 budget, chars/4 heuristic]
The ranking is sensible and also shows the limit of an import-only graph: engine.py is the one module the others import, so it gets rank 0.188 and everything else ties at 0.102. Aider's real map also counts references to individual symbols, which breaks ties like that and is why the tree-sitter tags matter. The script's job is to make the mechanism visible, not to replace the original.
Run it on your own code with:
python aider-repo-map-edit-formats-explained.py path/to/project --map-tokens 1000 --top 20
Edit formats
The second idea is the edit format, and it is the one I think people underrate. The model has to say what to change, and the harness has to apply it without corrupting the file. The docs page lists the formats:
| Format | What the docs say | Where it was used |
|---|---|---|
whole |
"The simplest possible editing format. The LLM is instructed to return a full, updated copy of each source file that needs changes." | small files, weak models |
diff |
"An efficient format, because the model only needs to return parts of the file which have changes." Search/replace blocks with syntax "similar to git merge conflict markings." | the default for most strong models |
diff-fenced |
"Based on the diff format, but the file path is placed inside the fence." | "primarily used with the Gemini family of models, which often fail to conform to the fencing approach specified in the diff format" |
udiff |
"Based on the widely used unified diff format, but modified and simplified." | "mainly used to the GPT-4 Turbo family of models, because it reduced their 'lazy coding' tendencies" |
editor-diff, editor-whole |
"Streamlined versions of the diff and whole formats, intended to be used with --editor-edit-format when using architect mode." |
the second model in architect mode |
Every row is a model-specific accommodation, documented as such. That is the discipline worth copying: measure which output contract each model can hold, and route each model to the contract it can hold, rather than assuming a universal edit syntax.
The aider/coders directory at the commit shows how literally this is implemented. The listing I read on 2026-09-05 includes base_coder.py, editblock_coder.py, editblock_fenced_coder.py, editblock_func_coder.py, udiff_coder.py, udiff_simple.py, wholefile_coder.py, wholefile_func_coder.py, patch_coder.py, architect_coder.py, ask_coder.py, help_coder.py, context_coder.py, editor_diff_fenced_coder.py, editor_editblock_coder.py, editor_whole_coder.py, and search_replace.py, each with a matching _prompts.py file. One coder class per edit format, one prompt file per coder. The name patch_coder.py suggests a further format that the docs page I read does not describe, so I do not describe it either.
Chat modes and the two-model split
The modes page lists four: code ("Aider will make changes to your code to satisfy your requests"), ask ("Aider will discuss your code and answer questions about it, but never make changes"), architect ("Like code mode, aider will change your files"), and help. Architect mode is the interesting one: "First, it sends your request to the main model which will act as an architect to propose how to solve your coding request," then "Aider then sends another request to an 'editor model', asking it to turn the architect's proposal into specific file editing instructions." Switch per message with /code, /architect, /ask, /help, or persistently with /chat-mode <mode>, or at launch with --chat-mode or --architect.
This is the same reasoning-versus-editing split that later shows up as plan modes and cheaper subagents in other harnesses, and aider had it as a first-class option with its own edit formats.
Why it still matters
The current generation of harnesses mostly hands the model a shell and a file editor and lets it read what it needs, an approach discussed in the SWE-agent reading. Aider's approach was to precompute what the model should know and to constrain what the model could say. Both ideas survive. Repo-level context is now often built by the model exploring, but the ranked-map idea is the cheap version, and the one you reach for when a session's context is the scarce resource, as the cost numbers in what one task costs make plain. And every harness that applies model output to files still has an edit format, whether or not it names one.
What I did not verify: I did not run aider itself in this session, so I have no measurement of the real map's size or of the edit-format failure rates the docs allude to. The docs pages are the versions live on 2026-09-05 and are not pinned to the commit; the repository facts and the directory listing are.
Code and data
- aider-repo-map-edit-formats-explained.py — the complete listing used in this article.
Sources
- Aider-AI/aider, "README at commit 5dc9490bb35f, repository metadata, and the aider/coders directory listing (read 2026-09-05)"
- Aider docs, "Repository map" (read 2026-09-05)
- Aider blog, "Building a better repository map with tree sitter" (2023-10-22, read 2026-09-05)
- Aider docs, "Edit formats" (read 2026-09-05)
- Aider docs, "Chat modes" (read 2026-09-05)
- Anthropic, "Pricing" (the chars-per-token FAQ figure, read 2026-09-05)