Public Wiki40,409View on GitHub
Want aider-ai/aider knowledge in your AI?

aider

Aider is an AI-powered pair programming CLI tool that uses LLMs (GPT-4, Claude, etc.) to edit code directly in your local git repository. It provides multiple code editing strategies (whole-file replacement, search/replace blocks, unified diffs) and manages the full workflow of sending code context to LLMs, applying their suggested edits, and committing changes to git.

Tech Stack

React

Key Features

  • Strategy-based Code Editing
  • Git-integrated Workflow
  • Repository Map Generation
  • Interactive Slash Commands
  • Multi-model Benchmarking Suite
  • Lint and Auto-fix Loop
  • Browser-based GUI
  • Documentation-aware Help System
  • Privacy-respecting Analytics
  • GitHub Issue Management Automation

Entry Points

Start here when working with this codebase

CLI Entry Point
aider/__main__.py

Executable entry point that bootstraps the aider CLI application via `python -m aider`

Start here when tracing how the application launches, understanding the boot sequence, or adding pre-initialization logic

Argument Parser & Configuration
aider/args.py

Defines ALL command-line arguments, environment variable mappings, and config file options using argparse

Start here when adding a new CLI flag, configuration option, or changing default values

Interactive Command Dispatcher
aider/commands.py

Handles all slash commands (/add, /drop, /run, /help, etc.) in the interactive REPL, routing user input to coder, git, and model subsystems

Start here when adding a new slash command or modifying how existing commands behave

Web GUI Interface
aider/gui.py

Browser-based Streamlit UI that mirrors CLI functionality with visual controls and chat interface

Start here when modifying the web interface or adding UI-only features

Benchmark Orchestrator
benchmark/benchmark.py

Runs AI models against standardized programming exercises, collects metrics, and generates reports

Start here when adding new benchmark exercises, modifying scoring logic, or integrating new model evaluation workflows

Package Version
aider/__init__.py

Defines and validates the package version string used across the application

Start here when bumping the version or changing version validation logic

Analytics System
aider/analytics.py

Manages analytics consent, routes events to providers, and respects privacy preferences

Start here when adding new tracked events, modifying consent flow, or integrating a new analytics provider

Help & Documentation Search
aider/help.py

Builds and queries a vector search index over aider documentation to answer /help questions

Start here when modifying how documentation is indexed or how help queries are answered

How to Make Changes

Common modification patterns for this codebase

Add a new CLI argument or configuration option

1
aider/args.py

Add a new argument definition using `group.add_argument(...)` inside the appropriate argument group (e.g., `model_group`, `output_group`, `git_group`). Include `--flag-name`, `type`, `default`, `help`, and optionally `env_var` for environment variable support.

Pattern: Follow the pattern of existing arguments like `--model` or `--auto-commits` in aider/args.py — each uses `group.add_argument` with metavar, default, help text, and const/action for boolean flags

2
aider/commands.py

If the new option needs to be changeable at runtime via a slash command, add a handler method `cmd_<name>(self, args)` and register it in the command dispatch logic

Pattern: See how `cmd_model` or `cmd_map_tokens` is implemented in aider/commands.py — each reads from `self.coder` or `self.coder.main_model` and updates state

3
aider/format_settings.py

If the argument contains sensitive data (API keys, tokens), add it to the masking logic so it is redacted in logs and settings output

Pattern: See how aider/format_settings.py masks sensitive fields — it checks argument names against known sensitive patterns and replaces values with masked strings

4
tests/basic/test_args.py

Add a test that verifies the new argument is parsed correctly with expected defaults and type coercion

Pattern: Follow the test structure in tests/basic/ where each test function creates an argument parser via `get_parser()` and asserts parsed values

Conventions to follow:

Boolean flags use `action='store_true'` or `const=True` with `nargs='?'`All arguments should have a `help` string for auto-generated documentationEnvironment variable overrides use the `env_var` parameter or `AIDER_` prefix conventionSensitive arguments must be masked in aider/format_settings.py

Add a new slash command to the interactive REPL

1
aider/commands.py

Add a new method named `cmd_<commandname>(self, args)` to the `Commands` class. The method receives the user's arguments as a string. Use `self.io` for output, `self.coder` for accessing the current coder state, and `self.coder.repo` for git operations.

Pattern: See how `cmd_add(self, args)` and `cmd_drop(self, args)` are implemented in aider/commands.py — they parse the args string, validate input, interact with `self.coder.abs_fnames`, and call `self.io.tool_output()` for feedback

2
aider/commands.py

Add a docstring to the new `cmd_<commandname>` method. The first line of the docstring becomes the help text shown when users type `/help`.

Pattern: See how `cmd_help` reads docstrings from all `cmd_*` methods to build the help listing in aider/commands.py

3
aider/commands.py

If the command needs tab-completion, add a `completions_<commandname>(self)` method that returns a list of completion strings

Pattern: See how `completions_add(self)` returns file paths and `completions_model(self)` returns model names in aider/commands.py

4
tests/basic/test_commands.py

Add test cases for the new command, mocking `self.io` and `self.coder` as needed

Pattern: See how tests in tests/basic/test_commands.py create a `Commands` instance with mock IO and coder objects, then call `cmd_*` methods directly and assert outcomes

Conventions to follow:

Command methods must be named `cmd_<name>` — the name after `cmd_` becomes the slash commandThe first line of the docstring is the short help text; subsequent lines are detailed helpUse `self.io.tool_output()` for informational output and `self.io.tool_error()` for errorsCommands that modify file lists should update `self.coder.abs_fnames` and call `self.coder.check_added_files()`Tab completion methods must be named `completions_<name>` matching the command name

Add a new coder strategy (edit format)

1
aider/coders/base_coder.py

Understand the base coder class which defines the interface all coder strategies must implement: `get_edits()`, `apply_edits()`, prompt template attributes (`main_system`, `example_messages`, etc.), and the `edit_format` class attribute

Pattern: Read aider/coders/base_coder.py to understand the abstract interface — all coders inherit from `Coder` and override `get_edits()` and `apply_edits()`

2
aider/coders/editblock_coder.py

Use this as the reference implementation for creating a new coder. Create a new file `aider/coders/<newformat>_coder.py` with a class that inherits from `Coder`, sets `edit_format = '<newformat>'`, and implements `get_edits()` to parse LLM output and `apply_edits()` to modify files

Pattern: See how `EditBlockCoder` in aider/coders/editblock_coder.py defines `edit_format = 'diff'`, sets prompt template paths, implements `get_edits()` to parse SEARCH/REPLACE blocks, and `apply_edits()` to apply them

3
aider/coders/editblock_prompts.py

Create a corresponding prompts file `aider/coders/<newformat>_prompts.py` with a class containing `main_system`, `example_messages`, and `files_content_prefix` string attributes that define the LLM prompt templates for the new format

Pattern: See how aider/coders/editblock_prompts.py defines `EditBlockPrompts` with multi-line string attributes for system prompts and example conversations

4
aider/coders/__init__.py

Register the new coder by importing it and adding it to the coder registry so it can be selected via CLI arguments

Pattern: See how aider/coders/__init__.py imports `EditBlockCoder`, `WholeFileCoder`, `UnifiedDiffCoder` and makes them available for selection

5
aider/args.py

Add the new edit format as a valid choice for the `--edit-format` argument

Pattern: See how `--edit-format` in aider/args.py lists valid format strings that map to coder classes

6
tests/basic/test_coder.py

Add tests for the new coder's `get_edits()` parsing and `apply_edits()` file modification logic

Pattern: See how tests/basic/test_coder.py tests coder instantiation, edit parsing, and file application for existing coder types

Conventions to follow:

Each coder strategy lives in its own file: `aider/coders/<format>_coder.py`Each coder has a companion prompts file: `aider/coders/<format>_prompts.py`The `edit_format` class attribute must be a unique string identifierCoders must inherit from `Coder` (defined in aider/coders/base_coder.py) and implement `get_edits()` and `apply_edits()`Prompt classes use plain string attributes, not methods — the base coder reads them as templates

Add support for a new LLM model or provider

1
aider/models.py

Add the new model's metadata to the model registry. Define its name pattern, context window size, default edit format, and any provider-specific settings. If the model needs special handling, add a conditional block.

Pattern: See how aider/models.py defines model entries with attributes like `name`, `edit_format`, `weak_model_name`, `use_repo_map`, `send_undo_reply`, `accepts_images`, and `max_chat_history_tokens` — follow the pattern of existing GPT-4 or Claude model definitions

2
aider/sendchat.py

If the new provider requires custom API call handling (non-standard auth, custom headers, streaming differences), modify the `send_completion()` function to handle the provider's specifics

Pattern: See how aider/sendchat.py wraps litellm completion calls with retry logic, streaming handling, and hash-based caching — add provider-specific branches where needed

3
aider/exceptions.py

If the new provider returns unique error codes or exception types, add mappings so they produce user-friendly error messages

Pattern: See how aider/exceptions.py maps LiteLLM exception types to human-readable descriptions with retry guidance

4
aider/args.py

If the provider needs a dedicated CLI shortcut flag (like `--openai` or `--anthropic`), add it to the model argument group

Pattern: See how `--model` and provider-specific shortcut flags are defined in aider/args.py

5
tests/basic/test_models.py

Add tests verifying the new model's metadata is correctly loaded and its edit format, context window, and capabilities are set properly

Pattern: See how tests/basic/test_models.py tests model lookup, attribute resolution, and fallback behavior

Conventions to follow:

Model definitions in aider/models.py use a declarative style with attribute dictionariesAll LLM API calls go through litellm — avoid direct provider SDK importsAPI keys are read from environment variables following the `<PROVIDER>_API_KEY` conventionModel name patterns use prefix matching (e.g., `gpt-4`, `claude-3`) for family-level defaultsSensitive API keys must never appear in logs — use aider/format_settings.py masking

Add a new benchmark exercise or modify benchmark scoring

1
benchmark/benchmark.py

Modify the exercise loading, execution, or scoring logic. To add a new exercise set, update the directory scanning and test execution pipeline. To change scoring, modify the result collection and pass/fail determination.

Pattern: See how benchmark/benchmark.py iterates over exercise directories, runs the coder against each, executes test suites, and collects pass/fail results with timing metrics

2
benchmark/plots.py

Update visualization code if the new benchmark data needs new chart types or if scoring changes affect how results are displayed

Pattern: See how benchmark/plots.py uses matplotlib to generate bar charts and comparison plots with model names on axes and percentage scores — add new plot functions following the same `plt.figure()` / `plt.savefig()` pattern

3
benchmark/problem_stats.py

Update the aggregation logic if new metrics or difficulty classifications are needed

Pattern: See how benchmark/problem_stats.py aggregates results across models and languages, computing solve rates and difficulty tiers

4
benchmark/over_time.py

If adding a new model to benchmarks, ensure its release date is included so it appears on the timeline visualization

Pattern: See how benchmark/over_time.py maps model names to release dates and plots performance trends chronologically

Conventions to follow:

Benchmark results are stored as JSON files with standardized schemaPlot functions in benchmark/plots.py should produce publication-quality output with consistent stylingExercise directories follow a convention with instructions, source files, and test filesBenchmark runs are idempotent — re-running should produce consistent results

Add a new analytics event or tracking metric

1
aider/analytics.py

Add a new event tracking method or extend an existing one. Define the event name and the properties dictionary to be sent to the analytics provider.

Pattern: See how aider/analytics.py defines event methods that check consent status before calling the provider's `track()` method with an event name string and properties dict

2
aider/coders/base_coder.py

If the event should fire during coding operations (e.g., after an edit is applied, after a message is sent), add the analytics call at the appropriate point in the coder lifecycle

Pattern: See how aider/coders/base_coder.py calls analytics methods after key operations like sending messages or applying edits

3
aider/commands.py

If the event should fire when a slash command is used, add the analytics call inside the relevant `cmd_*` method

Pattern: See how aider/commands.py integrates with the analytics system by calling tracking methods from command handlers

Conventions to follow:

All analytics calls must check user consent before sending — never bypass the consent checkEvent names use snake_case stringsProperties dicts should contain only non-sensitive, aggregatable dataAnalytics must be non-blocking — failures should be silently caught, never crash the app

Add or modify Git integration behavior

1
aider/repo.py

Modify the `GitRepo` class to add new git operations (e.g., new commit strategies, branch handling, diff generation). This is the central abstraction over git operations.

Pattern: See how aider/repo.py wraps gitpython calls in methods like `commit()`, `get_diffs()`, `get_tracked_files()` — each method handles error cases and returns clean Python objects

2
aider/repomap.py

If the change affects how the repository map (code structure summary sent to the LLM) is generated, modify the repo map builder here

Pattern: See how aider/repomap.py uses tree-sitter to parse source files, extract symbols, and build a ranked map of the most relevant code structures

3
aider/commands.py

If the git feature needs a user-facing command, add a `cmd_*` method that calls the new `GitRepo` method

Pattern: See how `cmd_commit` and `cmd_diff` in aider/commands.py delegate to `self.coder.repo` methods

4
tests/basic/test_repo.py

Add tests for the new git operations using temporary git repositories

Pattern: See how tests/basic/test_repo.py creates temp directories with `git init`, makes commits, and tests `GitRepo` methods against real git state

Conventions to follow:

All git operations go through the `GitRepo` class in aider/repo.py — never call gitpython directly from coders or commandsGit operations must handle detached HEAD, dirty working tree, and missing repo gracefullyCommit messages follow a consistent format with aider attributionThe repo map in aider/repomap.py is regenerated per-request and should be efficient for large repos

Add or modify web scraping and help documentation features

1
aider/scrape.py

Modify the web scraping logic to handle new content types, change parsing behavior, or add new scraping targets

Pattern: See how aider/scrape.py fetches URLs, extracts text content from HTML, and returns cleaned text suitable for LLM consumption

2
aider/help.py

Modify the documentation indexing or query logic. This file builds a vector search index from markdown docs and retrieves relevant passages for /help queries.

Pattern: See how aider/help.py loads markdown files, chunks them, builds embeddings, and performs similarity search to find relevant documentation passages

3
aider/commands.py

If adding a new help-related command or modifying how `/help` or `/web` works, update the corresponding `cmd_*` method

Pattern: See how `cmd_help` and `cmd_web` in aider/commands.py call into aider/help.py and aider/scrape.py respectively

Conventions to follow:

Scraped content must be cleaned of HTML artifacts before being sent to the LLMThe help index is built lazily on first /help query and cached for the sessionWeb requests should have timeouts and graceful error handling for network failures

Coding Conventions

Standards and patterns used in this codebase

Architecture

Coder classes follow an inheritance hierarchy with a base Coder class and specialized subclasses for different edit formats, each paired with corresponding prompt template files

EditBlockCoder extends Coder, with prompts in editblock_prompts.py; WholeFileCoder extends Coder with wholefile_prompts.py
aider/coders/base_coder.pyaider/coders/editblock_coder.pyaider/coders/editblock_prompts.py
Entry Points

Use __main__.py as a thin entry point that delegates to a main() function, keeping the module executable via python -m

from aider.main import main; main()
aider/__main__.py
CLI & Configuration

Arguments are defined using argparse with extensive use of environment variable fallbacks (via env_var in add_argument), grouped into logical argument groups, and support YAML/config file overrides

group.add_argument('--model', env_var='AIDER_MODEL', help='...') with configargparse.YAMLConfigFileParser
aider/args.py
Testing

Tests use unittest.TestCase as the base class, with GitTemporaryDirectory context managers for isolated filesystem/git testing environments

with GitTemporaryDirectory() as tmpdir: ... creates a temp dir with git init for test isolation
tests/basic/test_commands.pytests/basic/test_coder.py
Prompt Engineering

Prompt templates are stored in dedicated *_prompts.py files as class attributes (main_system, example_messages, system_reminder) on a PromptClass, separating prompt content from logic

class EditBlockPrompts: main_system = '''...'''; example_messages = [...]
aider/coders/editblock_prompts.pyaider/coders/wholefile_prompts.py
Error Handling

Use broad try/except blocks with informative error messages via self.io.tool_error() or self.io.tool_warning(), avoiding silent failures and providing user-actionable feedback

try: ... except Exception as e: self.io.tool_error(f'Error processing {fname}: {e}')
aider/commands.pyaider/coders/base_coder.py
Naming

Module-level constants use UPPER_SNAKE_CASE, classes use PascalCase, methods/functions use snake_case, and private/internal methods are prefixed with underscore

DEFAULT_MODEL_NAME = 'gpt-4'; class EditBlockCoder; def get_edits(self); def _parse_response(self)
aider/models.pyaider/coders/editblock_coder.py
Dependencies

Heavy or optional dependencies are imported lazily inside functions rather than at module top level, to reduce startup time and handle missing packages gracefully

def function(): import numpy as np; import matplotlib.pyplot as plt (inside function body)
benchmark/plots.pybenchmark/over_time.pyaider/scrape.py
IO Abstraction

All user-facing input/output goes through an InputOutput (io) abstraction layer rather than direct print/input calls, enabling testability and consistent formatting

self.io.tool_output('message'); self.io.tool_error('error'); self.io.confirm_ask('proceed?')
aider/io.pyaider/commands.pyaider/coders/base_coder.py
Version Management

Package version is defined as a string constant in __init__.py and validated at import time to ensure it's not accidentally corrupted

__version__ = '0.50.0'; assert re.match(r'^\d+\.\d+\.\d+', __version__)
aider/__init__.py
Data Visualization

Benchmark plotting scripts follow a consistent pattern: load YAML data, process into dataframes or dicts, generate matplotlib figures, and save to specific output paths

Load YAML results → filter/transform → plt.figure() → plt.barh() → plt.savefig('output.png')
benchmark/plots.pybenchmark/over_time.pybenchmark/problem_stats.py
Git Integration

Git operations use the gitpython library wrapped in helper methods, with automatic dirty-state detection, commit message generation, and safe rollback capabilities

self.repo.git.add(fname); self.repo.git.commit('-m', message); repo.is_dirty()
aider/repo.pyaider/commands.py