Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Aider Admin & Developer Guide

Generated June 2026 from Aider-AI/aider at 5dc9490

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is for the people who deploy, operate, secure, and extend Aider: platform admins standing it up for a team, DevOps engineers wiring it into CI, and developers who need to understand its internals. It documents Aider's architecture, the complete configuration surface, security posture, operational procedures, and a module-by-module developer reference.

For installation and day-to-day usage, see the companion User Guide.

What Aider is, in one sentence: a Python command-line application that mediates between a git repository and a large language model — assembling source context (including a tree-sitter "repo map"), prompting the model to produce structured edits, applying and committing those edits, and optionally linting/testing the result.


Table of Contents

  1. Executive Summary
  2. Architecture Overview
  3. Component Inventory
  4. Requirements
  5. Configuration Mastery
  6. Model Subsystem
  7. The Edit-Format / Coder System
  8. The Repo Map
  9. Git Subsystem
  10. Security
  11. Deployment Patterns
  12. Operations
  13. Developer Internals
  14. Testing Strategy
  15. Potential Improvements
  16. Quick Reference

1. Executive Summary

Attribute Value
Project Aider — AI pair programming in your terminal
Package (PyPI) aider-chat
Entry-point command aider (→ aider.main:main)
Language Python (requires >=3.10,<3.15)
License Apache-2.0
Provider abstraction LiteLLM (works with virtually any LLM)
Persistence The user's git repository (no database/server of its own)
Interfaces Interactive terminal chat, one-shot CLI, IDE watch mode, Streamlit browser GUI, web-chat copy/paste
Deployment model Local developer tool / CLI; no daemon or network service

Aider is not a client/server system. It is a single-process CLI that runs entirely on the developer's machine. Its only outbound network calls are to the configured LLM provider and (optionally) to PyPI for version checks, to product analytics, and to web pages you ask it to scrape. There is no Aider backend to operate.

Operationally, the things an admin cares about are: (1) how credentials are supplied and scoped, (2) how configuration precedence resolves across machines/teams, (3) the model/cost controls, and (4) the git safety guarantees. Those are the focus of this guide.


2. Architecture Overview

                         ┌──────────────────────────────────────────────┐
                         │                aider (CLI process)            │
                         │                                               │
  user ──prompt/voice──▶ │  InputOutput (io.py)  ◀── prompt_toolkit      │
                         │       │                                       │
                         │       ▼                                       │
                         │  Commands (commands.py)   /add /web /run ...  │
                         │       │                                       │
                         │       ▼                                       │
   git repo ◀───────────│   Coder  (coders/base_coder.py)               │
   (GitRepo, repo.py)    │     │     ├─ RepoMap (repomap.py) ──tree-sitter│
        ▲                │     │     │      └─ networkx PageRank ranking  │
        │ auto-commit    │     │     ├─ ChatSummary (history.py)         │
        │                │     │     ├─ Linter (linter.py)               │
        │                │     │     └─ edit format (EditBlock/Whole/...) │
   files ◀──apply edits──│     │                                         │
                         │     ▼                                         │
                         │   Model (models.py) ──▶ LiteLLM ──▶ provider  │
                         │                                       (HTTP)  │
                         │                                               │
                         │  Analytics (posthog/mixpanel)  Scraper(/web)  │
                         │  Voice(/voice)  FileWatcher(--watch-files)    │
                         │  GUI(gui.py, Streamlit)  Onboarding(OAuth)    │
                         └──────────────────────────────────────────────┘

Request lifecycle (interactive code mode)

  1. Startup (main.py:main) — resolve git root, build the config-file search path, parse args (via configargparse, see §5), load .env files, register model settings/metadata, select the model, construct InputOutput, Commands, GitRepo, ChatSummary, and finally the Coder via Coder.create().
  2. Prompt — InputOutput.get_input() collects the user's message (prompt_toolkit provides history, completion, multiline, vi/emacs modes).
  3. Context assembly — the Coder builds the message list: system prompt, repo map (RepoMap.get_repo_map()), in-chat file contents, read-only files, chat history (summarized by ChatSummary if too large), and the user message.
  4. Model call — Model.send_completion() calls LiteLLM, which dispatches to the provider; the response streams back through MarkdownStream.
  5. Edit extraction & application — the active coder subclass parses the model's reply in its edit format (get_edits()) and applies it to disk (apply_edits()).
  6. Post-processing — auto-lint (Linter), auto-test (/test command), then auto-commit through GitRepo.commit() with a weak-model-generated message.
  7. Loop — control returns to step 2. Mode/model switches raise SwitchCoder, which rebuilds the coder while preserving state.

Note

The whole system is filesystem- and git-centric: there is no server-side state. Chat history is a markdown file (.aider.chat.history.md), the repo map cache is on disk, and "undo" is just git revert-style rollback of Aider's own commits.


3. Component Inventory

All modules live under the aider/ package. The most important:

Module Class(es) Responsibility
main.py — Entry point; arg parsing, environment setup, object wiring, top-level control loop.
args.py get_parser() Defines every CLI flag (≈110) via configargparse; also the YAML/env config schema.
args_formatter.py YamlHelpFormatter, MarkdownHelpFormatter, DotEnvFormatter Render the sample .aider.conf.yml / .env / docs from the parser.
coders/base_coder.py Coder The core engine: context assembly, model calls, edit application, lint/test/commit orchestration. Coder.create() is the factory.
coders/*.py 14 coder subclasses One per edit format (see §7).
commands.py Commands, SwitchCoder All /slash commands (40+ cmd_* methods) and tab-completions.
models.py Model, ModelSettings, ModelInfoManager Model registry, aliases, per-model settings/metadata, sanity checks.
repomap.py RepoMap Tree-sitter symbol extraction + networkx PageRank ranking → the repo map.
repo.py GitRepo All git operations: tracked files, diffs, commit, attribution, ignore handling.
io.py InputOutput, AutoCompleter, ConfirmGroup Terminal I/O via prompt_toolkit; prompts, colors, history, completion.
history.py ChatSummary Summarizes chat history when it exceeds the token budget.
linter.py Linter, LintResult flake8 (Python) + tree-sitter syntax checks; per-language lint commands.
watch.py FileWatcher Watches files for ai/ai!/ai? comments (IDE mode).
scrape.py Scraper /web page fetching (Playwright or httpx) + pandoc → markdown.
voice.py Voice Microphone capture (sounddevice/soundfile) + Whisper transcription.
gui.py GUI, CaptureIO Streamlit browser interface.
analytics.py Analytics Opt-in anonymous usage analytics (PostHog + Mixpanel).
onboarding.py OAuthCallbackHandler OpenRouter OAuth and default-model selection for first-time users.
help.py Help In-chat /help knowledge base over Aider's own docs.
exceptions.py LiteLLMExceptions, ExInfo Maps LiteLLM exceptions to retry/no-retry behavior.
mdstream.py MarkdownStream Live markdown rendering of streamed responses (rich).
copypaste.py ClipboardWatcher Auto copy/paste mode plumbing.
deprecated.py handle_deprecated_model_args Back-compat for old --sonnet/--4o/etc. shortcut flags.
versioncheck.py — Update checks, --upgrade, --install-main-branch.
report.py — Uncaught-exception reporting and /report GitHub issue helper.

4. Requirements

Runtime

Requirement Detail
Python >=3.10,<3.15 (3.10–3.14).
OS Linux, macOS, Windows.
git Recommended; required for auto-commit/undo. Index version 1 or 2.
Network Outbound HTTPS to the chosen LLM provider.

Key dependencies (from requirements.txt)

Dependency Pinned (at this commit) Role
litellm 1.82.3 Provider-agnostic LLM gateway.
openai 2.28.0 OpenAI SDK (used via litellm).
gitpython 3.1.46 Git operations.
prompt-toolkit 3.0.52 Terminal input UI.
rich 14.3.3 Styled output / markdown rendering.
configargparse 1.7.5 Unified CLI + env + YAML config parsing.
grep-ast 0.9.0 Tree-sitter-backed code structure extraction (repo map).
tree-sitter-language-pack 0.13.0 Grammars for 100+ languages.
networkx 3.4.2 PageRank ranking for the repo map.
scipy / numpy 1.16+ / 2.3+ Numerical backing for ranking.
diskcache 5.6.3 On-disk caches (repo-map tags).
pathspec 1.0.4 .gitignore/.aiderignore matching.
beautifulsoup4, pypandoc — Web scraping → markdown.
sounddevice, soundfile, pydub — Voice capture.
posthog, mixpanel — Analytics.
watchfiles 1.1.1 File watching for IDE mode.
pillow 12.1.1 Image handling.

Optional extras

Extra Adds
aider-chat[browser] streamlit for the GUI.
aider-chat[help] Embeddings/RAG deps for /help.
aider-chat[playwright] Headless browser for JS-heavy /web pages.
aider-chat[dev] Test + lint toolchain.

5. Configuration Mastery

Precedence chain (highest → lowest)

Aider uses configargparse, which merges three sources. From main.py, the effective precedence is:

1. Command-line flags          (e.g. --model sonnet)
2. Environment variables       (incl. those loaded from .env files)
3. .aider.conf.yml             (YAML config file)
4. Built-in defaults

Two subtleties from the startup sequence:

  • Args are parsed multiple times: once to discover the git root and --env-file, then .env files are loaded (which may define variables referenced by other flags), then args are parsed again so .env-provided values take effect.
  • Every flag maps to a YAML key (the flag name without --) and an environment variable (AIDER_ + the flag name uppercased with underscores, per configargparse's auto_env_var_prefix).

Config-file search order

.aider.conf.yml is searched for in this order (later overrides earlier are reconciled by configargparse):

  1. Current working directory
  2. Git repository root
  3. Home directory (~/.aider.conf.yml)

Override entirely with --config <file> / -c.

.env search order

.env files are loaded with override=True from (first loaded wins precedence as loaded last in list, after reversal):

  1. ~/.aider/oauth-keys.env (always loaded first)
  2. Home directory ~/.env
  3. Git root .env
  4. Current directory .env
  5. --env-file <file>

Worked example: a team baseline

A team can ship a repo-root .aider.conf.yml that everyone inherits, while individuals override per-machine via their home config or CLI flags:

# <repo>/.aider.conf.yml  — checked into the project
model: sonnet
weak-model: haiku
auto-lint: true
lint-cmd:
  - "python: flake8 --select=E9,F"
test-cmd: pytest -q
auto-test: false
attribute-co-authored-by: true
# A developer overrides the model for a heavy task, without touching the repo config:
aider --model opus

Important

Secrets do not belong in .aider.conf.yml (it's often committed). Put API keys in .env or the environment. Aider auto-adds .env to .gitignore.

Caution

The YAML key for "always confirm yes" is yes-always:, not yes:. Aider detects a stray yes: line on startup and refuses to run until you fix it (an old footgun that broke arg parsing).

Configuration domains

The ~110 flags group into these domains (see §16 for the full list, and the User Guide for usage):

Domain Representative keys
Model selection model, weak-model, editor-model, edit-format, alias, reasoning-effort, thinking-tokens
Credentials api-key, openai-api-key, anthropic-api-key, openai-api-base, set-env, verify-ssl
Git git, auto-commits, dirty-commits, attribute-*, commit-prompt, subtree-only, git-commit-verify
Repo map map-tokens, map-refresh, map-multiplier-no-files
Lint/test lint-cmd, auto-lint, test-cmd, auto-test
History/cache max-chat-history-tokens, cache-prompts, cache-keepalive-pings, restore-chat-history
UI pretty, stream, dark-mode, light-mode, *-color, code-theme, vim, multiline, fancy-input, notifications
Files file, read, aiderignore, add-gitignore-files, encoding, line-endings
Voice voice-format, voice-language, voice-input-device
Analytics analytics, analytics-disable, analytics-posthog-host, analytics-posthog-project-api-key, analytics-log
Updates check-update, upgrade, install-main-branch, just-check-update

6. Model Subsystem

Model roles

Role Flag Purpose
Main --model Primary reasoning + code generation. Default gpt-4o.
Weak --weak-model Commit messages, chat-history summarization. Cheaper.
Editor --editor-model Applies edits proposed by the architect in architect mode.

Model.commit_message_models() returns the weak model (falling back to main) for commit generation — which is why commit messages can appear to "ignore" --model (see User Guide troubleshooting). Set --weak-model to control this.

Aliases (MODEL_ALIASES in models.py)

Alias Target Alias Target
sonnet claude-sonnet-4-6 deepseek deepseek/deepseek-chat
opus claude-opus-4-7 r1 deepseek/deepseek-reasoner
haiku claude-haiku-4-5 flash gemini/gemini-flash-latest
4o gpt-4o flash-lite gemini/gemini-2.5-flash-lite
4 gpt-4-0613 gemini gemini/gemini-3-pro-preview
4-turbo gpt-4-1106-preview gemini-2.5-pro gemini/gemini-2.5-pro
35turbo/3 gpt-3.5-turbo grok3 xai/grok-3-beta

Add custom aliases at runtime with --alias name:model-id (repeatable).

Model metadata & settings

Aider needs to know each model's context window, costs, and capabilities:

  • Built-in — bundled aider/resources/model-metadata.json plus LiteLLM's database.
  • .aider.model.metadata.json (--model-metadata-file) — context size & cost for models Aider doesn't recognize.
  • .aider.model.settings.yml (--model-settings-file) — capability settings (default edit format, whether it accepts reasoning_effort/thinking_tokens, prompt-cache support, etc.).

ModelInfoManager fetches/caches model info (including OpenRouter model info) and honors --no-verify-ssl. Model.sanity_check_models() warns when a model lacks metadata; suppress with --no-show-model-warnings.

Capability gating

--check-model-accepts-settings (default on) makes Aider skip applying reasoning_effort/thinking_tokens to models that don't declare support, warning instead of erroring. Force the setting with --no-check-model-accepts-settings.

Note

Because Aider delegates transport to LiteLLM, provider support is whatever LiteLLM supports — OpenAI, Anthropic, Gemini, Azure, Bedrock (AWS_PROFILE honored), DeepSeek, xAI, OpenRouter, GitHub Copilot (GITHUB_COPILOT_TOKEN), Ollama / any OpenAI-compatible base URL. Aider does not maintain its own provider integrations.


7. The Edit-Format / Coder System

Aider's central design idea: ask the model to emit changes in a structured edit format, then deterministically parse and apply them. Each format is implemented as a Coder subclass selected by Coder.create(edit_format=...).

edit_format Coder class Notes
diff EditBlockCoder SEARCH/REPLACE blocks — the default for most strong models.
diff-fenced EditBlockFencedCoder SEARCH/REPLACE inside a fence (used by some Gemini models).
whole WholeFileCoder Model returns entire files. Robust for weaker models.
udiff UnifiedDiffCoder Unified-diff hunks.
udiff-simple UnifiedDiffSimpleCoder Simplified unified diff.
patch PatchCoder Structured add/update/delete/move patch actions.
editor-diff EditorEditBlockCoder Edit-only variant for architect mode.
editor-diff-fenced EditorDiffFencedCoder Fenced editor variant.
editor-whole EditorWholeFileCoder Whole-file editor variant.
architect ArchitectCoder Two-model: plan (main) + apply (editor).
ask AskCoder Q&A, no edits.
context ContextCoder Surfaces relevant surrounding context.
help HelpCoder Answers questions about Aider.
func (function-call coders) Tool/function-calling variants (mostly internal/experimental).

Each coder pairs with a prompt class (*Prompts, e.g. EditBlockPrompts) that supplies the system prompt and format instructions. The default format per model comes from the model's settings; override with --edit-format.

Edit-application failure modes

When a model emits a malformed edit, the coder raises a descriptive error and asks the model to retry. Representative errors (from source):

  • EditBlockCoder: Unpaired ``` in SEARCH/REPLACE block, Expected DIVIDER, Expected UPDATED or DIVIDER.
  • PatchCoder (DiffError): Empty patch section found., Could not find patch context ..., Overlapping or out-of-order chunk detected., File referenced in patch not found ....
  • UnknownEditFormat (base_coder.py): raised when an invalid --edit-format is supplied.

These are the principal correctness-critical paths; they are heavily unit-tested (see §14).


8. The Repo Map

RepoMap (repomap.py) is what lets Aider work on large codebases without loading every file.

  1. Symbol extraction — for each tracked file, grep-ast + tree-sitter-language-pack parse the source and extract definitions/references (functions, classes, signatures). Tag-query files live under aider/queries/ (per-language .scm files adapted from upstream tree-sitter grammars).
  2. Ranking — references form a graph; networkx PageRank ranks symbols by importance and by relevance to the files currently in the chat (personalization).
  3. Budgeting — the top-ranked symbols are rendered into a compact map sized to --map-tokens (default derived per model via get_repo_map_tokens(); 0 disables).
  4. Caching — parsed tags are cached on disk (diskcache) so subsequent runs are fast. --map-refresh controls rebuild frequency: auto (default), always, files (refresh when the in-chat file set changes), manual (/map-refresh only).

Tip

When --cache-prompts is enabled and --map-refresh is auto, Aider switches the refresh policy to files so the cached prompt prefix stays stable (set in main.py). This is a cost optimization worth knowing about.

--map-multiplier-no-files (default 2) gives the map a larger budget when no files have been explicitly added, since the map is then the model's primary view of the code.


9. Git Subsystem

GitRepo (repo.py) wraps GitPython. Key behaviors:

  • Discovery — get_git_root() searches parent directories; if the cwd is the home directory, Aider warns rather than treating $HOME as a repo. With no repo, Aider offers to git init.
  • Tracked files — get_tracked_files() is the file universe Aider considers (minus .aiderignore).
  • Auto-commit — after applying edits, commit() generates a message (weak model, or --commit-prompt) and commits. Disable with --no-auto-commits.
  • Dirty commits — by default Aider commits pre-existing dirty changes before editing (--no-dirty-commits to disable).
  • Attribution — author/committer name rewriting and Co-authored-by trailers, plus optional aider: commit-message prefixes (--attribute-*). --attribute-co-authored-by takes precedence over author/committer attribution unless those are explicitly set.
  • Pre-commit hooks — bypassed with --no-verify unless --git-commit-verify is set.
  • Ignore files — .aiderignore (configurable via --aiderignore) plus .gitignore are honored via pathspec.
  • Sanity check — sanity_check_repo() rejects unreadable/corrupt repos and unsupported index versions (1 or 2 only), offering git update-index --index-version=2.

Important

/undo only reverts commits Aider itself authored, identified via attribution — it will not touch a developer's own commits. This is the core safety guarantee for unattended runs.


10. Security

Aider runs with the developer's full local privileges and talks to external model providers. Treat it as you would any developer tool that can execute code and reach the network.

Credentials

  • API keys are read from CLI flags (--api-key, --openai-api-key, --anthropic-api-key), environment variables, or .env/~/.aider/oauth-keys.env.
  • Aider sets provider keys into os.environ at startup so LiteLLM can use them.
  • scrub_sensitive_info() redacts keys from the logged command line.
  • Keep keys out of .aider.conf.yml (commonly committed). Aider auto-adds .env and .aider* to .gitignore.

Caution

--api-key provider=KEY and --openai-api-key KEY place secrets in your shell history and process list. Prefer environment variables or .env files for anything beyond a quick test.

Code execution surface

Aider can execute commands on your machine in several ways — each gated by a confirmation prompt unless --yes-always is set:

Vector Control
/run and ! shell commands Interactive confirmation; output optionally fed to the model.
--test-cmd / --lint-cmd Run automatically when --auto-test/--auto-lint. You define these commands.
Suggested shell commands The model may suggest commands; gated by --suggest-shell-commands (default on) and a confirmation.
File edits Applied to disk, then committed; reversible via git.

Warning

--yes-always removes all confirmation prompts, including before running shell/test commands. Only use it in trusted, sandboxed automation. Aider's own benchmark harness runs inside Docker precisely because it executes model-generated code unsupervised.

Network egress

  • LLM provider — your prompts (system prompt, repo map, in-chat file contents, chat history) are sent to the configured provider. Anything in a file you /add is shared with the model.
  • /web scraping — fetches arbitrary URLs you request (Playwright or httpx). --disable-playwright prevents installing/using a headless browser.
  • Version check — contacts PyPI on launch unless --no-check-update.
  • Analytics — opt-in (see below).
  • SSL — verified by default; --no-verify-ssl disables verification and is set into the environment (SSL_VERIFY) and litellm's HTTP clients — use only against trusted internal endpoints.

Analytics & privacy

Analytics (analytics.py) sends opt-in, anonymous usage events to PostHog/Mixpanel. The product explicitly never collects code, chat messages, API keys, or personal info. On first run Aider asks for consent; users can:

  • accept/decline at the prompt,
  • pass --analytics / --no-analytics per session,
  • --analytics-disable to permanently disable,
  • redirect to a self-hosted PostHog with --analytics-posthog-host / --analytics-posthog-project-api-key,
  • log events locally with --analytics-log.

Tip

For enterprise rollouts, set analytics-disable: true in a shared .aider.conf.yml, or set --no-verify-ssl only for explicitly approved internal model proxies (never globally).

Reported security items

  • Private Vulnerability Reporting request: issue #5217.
  • A user-reported "AI guardrails" safety report: issue #5201 — a reminder that model-generated edits and shell commands require human review unless sandboxed.

11. Deployment Patterns

Aider is a local CLI, so "deployment" means provisioning it consistently across developers or CI.

Individual developer

aider-install (uv-based isolated environment) or pipx install aider-chat. Keep keys in ~/.env or the shell environment; keep team defaults in a repo-root .aider.conf.yml.

Team / shared baseline

  • Commit a repo-root .aider.conf.yml with model, lint/test commands, and attribution policy (no secrets).
  • Distribute a ~/.aider.conf.yml template for per-user overrides.
  • Pin the Aider version in your environment manifest if you need reproducibility (aider-chat==<version>).

CI / automation

pip install aider-chat
aider --model sonnet \
      --yes-always --no-check-update --no-analytics \
      --message "Apply the changes described in CHANGE.md" \
      --message-file CHANGE.md
  • Use --message/--message-file for one-shot, non-interactive runs.
  • --yes-always to skip prompts; --no-check-update to avoid PyPI calls; disable analytics.
  • Provide keys via CI secrets → environment variables.
  • Sandbox the runner — model-generated edits and any --test-cmd execute real code.

Docker (the benchmark harness pattern)

The repo's benchmark/Dockerfile shows the recommended isolation approach for running model-generated code unsupervised: a container with the toolchains installed and aider[dev] installed editable. Adapt it for any automation that runs Aider without a human in the loop.

Containerized via published image

AIDER_DOCKER_IMAGE is honored for version-check behavior, indicating Aider is commonly run from a container image; mount your repo as a volume and pass keys as environment variables.


12. Operations

Updates

Command Action
aider --upgrade Upgrade to the latest PyPI release.
aider --install-main-branch Install the latest from the main branch.
aider --just-check-update Exit-code-only update check (good for scripts).
aider --no-check-update Skip the launch-time update check.

First-run-per-version state is tracked in ~/.aider/installs.json; release notes are offered on first run of a new version.

Logs & state on disk

Path Contents
.aider.chat.history.md Human-readable transcript (in git root).
.aider.input.history Input history.
.aider.llm.history Raw LLM request/response log (only if --llm-history-file set).
~/.aider/installs.json Per-version first-run tracking.
~/.aider/analytics.json Analytics opt-in state + anonymous UUID.
~/.aider/oauth-keys.env OAuth-obtained keys (e.g. OpenRouter).
Repo-map tag cache diskcache directory (auto-managed).

Diagnostics

aider --verbose            # print config search order, loaded .env files, model metadata/settings
aider --settings           # (in-chat /settings) dump effective settings
aider --show-repo-map      # print the repo map and exit
aider --show-prompts       # print the system prompts and exit
aider --exit               # do all startup work then exit (smoke test)

--verbose is the first stop for "why did it pick that config/model?" questions — it prints the config-file search order with existence flags, the loaded .env files, and the full resolved model metadata and settings.

Cost & throughput controls

  • --weak-model for cheap commit/summary work.
  • --cache-prompts + --cache-keepalive-pings to reuse prompt prefixes.
  • --map-tokens to bound repo-map cost; /drop unused files.
  • --max-chat-history-tokens to control when summarization kicks in.

Warning

Streaming + caching together makes cost estimates inaccurate (Aider warns). For precise accounting, disable one.

Crash reporting

report_uncaught_exceptions() installs a handler that, on an uncaught exception, points users to file a GitHub issue with environment details. /report does the same on demand.


13. Developer Internals

Repository layout

aider/
  __main__.py        # `python -m aider` → main()
  main.py            # entry point & orchestration
  args.py            # configargparse parser (the config schema)
  args_formatter.py  # YAML/.env/markdown help renderers
  coders/            # 14 edit-format coders + prompt classes + base_coder
  commands.py        # /slash command registry
  models.py          # Model/ModelSettings/aliases/metadata
  repomap.py         # tree-sitter + networkx repo map
  repo.py            # GitRepo
  io.py              # InputOutput, AutoCompleter
  history.py         # ChatSummary
  linter.py          # Linter
  watch.py           # FileWatcher (IDE mode)
  scrape.py          # /web Scraper
  voice.py           # /voice
  gui.py             # Streamlit GUI
  analytics.py       # opt-in analytics
  onboarding.py      # OpenRouter OAuth + default model
  help.py            # /help knowledge base
  exceptions.py      # LiteLLM exception mapping
  mdstream.py        # streamed markdown rendering
  queries/           # per-language tree-sitter tag queries (.scm)
  resources/         # bundled model-metadata.json, etc.
  website/           # docs site (Jekyll/just-the-docs) + install scripts
benchmark/           # Exercism-based benchmark harness (Docker)
tests/               # unit/integration tests
requirements/        # pinned requirement sets + extras

The Coder base class

coders/base_coder.py:Coder (≈80 methods) is the heart of the system. Notable responsibilities:

  • create() / clone() — factory dispatch by edit_format; clone() rebuilds a coder for mode switches.
  • format_messages() / format_chat_chunks() — assemble system prompt, repo map, files, history into ChatChunks (which also manages prompt-cache control headers via add_cache_control_headers()).
  • send_message() / run() — the model-call loop, streaming, retries.
  • get_edits() / apply_edits() — overridden per edit format.
  • auto_commit(), lint_edited(), run_tests() — post-edit pipeline.
  • get_repo_map() — delegates to RepoMap.

SwitchCoder (an exception in commands.py) is the mechanism for changing model/mode/edit-format mid-session: it's raised, caught in main.py's loop, and used to rebuild the coder while carrying over state.

Adding a new edit format (extension point)

  1. Create coders/myformat_coder.py with a MyFormatCoder(Coder) setting edit_format = "myformat" and implementing get_edits()/apply_edits().
  2. Add a matching MyFormatPrompts(CoderPrompts) with the system/format prompt.
  3. Register the class in coders/__init__.py's imports and __all__.
  4. Coder.create() will then dispatch --edit-format myformat to it.

Adding a new slash command (extension point)

Add a cmd_<name>(self, args) method to Commands in commands.py. The first-line docstring becomes the help text shown in /help. Optionally add completions_<name>() for tab-completion. The command is auto-discovered — no registration table to edit.

Exception handling

exceptions.py:LiteLLMExceptions maps each LiteLLM exception type to an ExInfo(retry, ...) record so the send loop knows whether to retry (e.g. rate limits) or surface the error. A sanity check asserts every LiteLLM exception is accounted for ({var} is in litellm but not in aider's exceptions list), so upgrading LiteLLM may require updating this map.


14. Testing Strategy

Tests live in tests/ and use unittest/pytest.

Test module Covers
tests/basic/test_main.py (TestMain, ~80 tests) End-to-end CLI: arg handling, git discovery, config, env loading.
tests/basic/test_coder.py (TestCoder) Edit permissions, file mentions, context assembly.
tests/basic/test_commands.py (TestCommands, ~70 tests) Every /slash command.
tests/basic/test_editblock.py, test_udiff.py, test_wholefile.py, test_find_or_blocks.py Edit-format parsing/application (the correctness-critical paths).
tests/basic/test_repomap.py (TestRepoMapAllLanguages) Repo map across 40+ languages.
tests/basic/test_models.py, test_model_info_manager.py Aliases, metadata, sanity checks.
tests/basic/test_repo.py (TestRepo) Git operations, commit messages, diffs.
tests/basic/test_sendchat.py, test_reasoning.py Model send loop, retries, reasoning content handling.
tests/basic/test_onboarding.py OpenRouter OAuth and default-model selection.
tests/basic/test_ssl_verification.py, test_aws_credentials.py Security-relevant config paths.
tests/scrape/, tests/browser/, tests/help/ /web scraping, GUI import, /help.

Run the suite with the dev extra installed:

pip install -e .[dev]
pytest

Benchmark harness

benchmark/ contains an Exercism-based evaluation that measures how well Aider + a given model can translate natural-language requests into passing code. It runs inside Docker (it executes model-generated code) and emits a YAML report (pass_rate_1, pass_rate_2, percent_cases_well_formed, cost, timing). Results feed the public leaderboards. Not for end users.

./benchmark/benchmark.py a-run-name --model sonnet --edit-format diff --threads 10 \
    --exercises-dir polyglot-benchmark

15. Potential Improvements

Observations from the source, framed for maintainers/operators:

  • base_coder.py is very large (≈80 methods on one class). Extracting the prompt-cache, message-assembly, and post-edit (lint/test/commit) responsibilities into collaborators would improve testability.
  • commands.py is a single ~3,100-line module with 40+ commands. The auto-discovery pattern is clean, but grouping commands into mixins by domain (files/git/models/io) would aid navigation.
  • LiteLLM exception coupling — the assertion that every LiteLLM exception is mapped means a dependency bump can break startup; consider a softer fallback (treat unknown exceptions as non-retryable + warn) to decouple upgrade cadence.
  • Deprecated edit-format coders (editblock_func_coder, wholefile_func_coder) raise RuntimeError("Deprecated, needs to be refactored ...") — dead code that could be removed.
  • Config precedence is parsed in several passes in main.py (to resolve git root → .env → re-parse). Documenting/centralizing this would reduce the risk of subtle precedence bugs.
  • Windows PATH friction on install (issue #3123) — the aider-install path is the mitigation; surfacing it more prominently for Windows users would cut support load.

16. Quick Reference

Files Aider reads/writes

File Role
.aider.conf.yml Config (YAML). Search: cwd → git root → home.
.env Secrets/env. Search includes ~/.aider/oauth-keys.env.
.aiderignore Paths Aider must not read/edit.
.aider.model.settings.yml Capabilities for unknown models.
.aider.model.metadata.json Context/cost for unknown models.
.aider.input.history, .aider.chat.history.md Session history.
~/.aider/{installs,analytics}.json, oauth-keys.env Per-user state.

Environment variables of note

Variable Effect
OPENAI_API_KEY, ANTHROPIC_API_KEY, OPENROUTER_API_KEY, GEMINI_API_KEY, DEEPSEEK_API_KEY Provider credentials.
OPENAI_API_BASE Custom/proxy/local endpoint.
AWS_PROFILE Used for Bedrock models.
GITHUB_COPILOT_TOKEN Required for Copilot models.
AIDER_* Any flag as an env var (e.g. AIDER_MODEL).
AIDER_DOCKER_IMAGE Signals containerized run (version-check behavior).
AIDER_CACHE_KEEPALIVE_DELAY Cache keepalive timing.
SSL_VERIFY Set empty by --no-verify-ssl.
EDITOR / VISUAL External editor for /editor.
NO_COLOR Disable colored output.

One-shot / non-interactive modes

Flag Exits after
--message / -m, --message-file / -f Processing one message.
--lint, --test, --commit The named action.
--apply <file> Applying edits from a file.
--show-repo-map, --show-prompts, --exit Printing/setup (debug).
--list-models, --just-check-update, --version Reporting.

Edit formats

diff · diff-fenced · whole · udiff · udiff-simple · patch · editor-diff · editor-diff-fenced · editor-whole · architect · ask · context · help · func

Chat modes

code (default) · ask · architect · context · help