.aider.conf.yml recipes that actually pay off
Published 2026-05-11 by Owner
Aider accepts dozens of CLI flags. Most of them you set once per project and never want to type again. That’s what .aider.conf.yml is for — a YAML file that Aider reads on startup, so the right model, edit format, and conventions load without flags.
There are two config locations. ~/.aider.conf.yml is your global default. .aider.conf.yml at the project root overrides the global file on a per-key basis. Flags passed on the command line override both. The precedence chain is: CLI > project > global.
That chain matters. Keep model keys and API credentials in your global config. Keep project conventions, lint commands, and format choices in the project file. Commit the project file; never commit the global one.
The five recipes worth setting permanently
1. Main model
The --model flag is the one most people set interactively and forget they’re setting every session.
# .aider.conf.yml
model: claude-sonnet-4-5
If your team standardizes on a model, this is where to enforce it. A junior developer opening the project gets the same model as everyone else without knowing to pass a flag.
One detail that trips people up: the key in the config file drops the leading --. --model becomes model, --edit-format becomes edit-format. The YAML keys mirror the long form of the CLI flag with hyphens preserved. When in doubt, run aider --help and strip the dashes.
2. Weak model
Aider uses a “weak model” for lower-stakes tasks like generating commit messages. The default is often whatever cheap model Aider bundles. If your main model is Sonnet, the default weak model is fine. If you’re running a local model via Ollama as your main, set the weak model explicitly:
model: ollama/qwen2.5-coder:32b
weak-model: claude-haiku-4-5
The weak model only runs for commit summaries and internal reasoning steps, so a fast hosted model here is cheap even if your main model is local.
If you don’t set a weak model, Aider picks one based on your main model’s provider. For Claude models, that default is usually Haiku. For OpenAI models, it’s usually GPT-4o-mini. Setting it explicitly removes the guesswork and keeps the cost predictable.
3. Edit format
Aider supports several formats for how it edits files: whole, diff, diff-fenced, udiff. The default varies by model.
model: claude-sonnet-4-5
edit-format: diff
diff is the most reliable format for models that support it — it minimizes re-transmission of unchanged code and makes conflicts easier to review. If you’re hitting edit failures where Aider applies a diff to the wrong location, switch to whole. Whole-file replacement is slower but doesn’t misalign.
The format that causes the most trouble is udiff — it’s efficient but picky about context lines. Unless your model specifically benefits from it, stay on diff.
4. Conventions via read-only files
The --read flag adds files to context as read-only references. This is the right place for CONVENTIONS.md, ADRs, or a style guide.
read:
- CONVENTIONS.md
- docs/architecture/decisions.md
Unlike Cursor rules, Aider doesn’t have a native “always load this as context” concept beyond this flag. The read list is your convention injection mechanism. Keep it short — two or three files — so you’re not eating context budget on documentation Aider doesn’t need for the current task.
The read-only flag means Aider sees these files but won’t attempt to edit them. That distinction matters: if CONVENTIONS.md were in the regular file list, Aider might update it when asked to “follow the project conventions.” Read-only ensures the file is reference material, not an edit target.
5. Lint and test commands
If your project has a lint command or a fast test runner, register them so Aider auto-checks after edits:
lint-cmd: bun run lint
test-cmd: bun run test --run
auto-test: false
auto-lint: true
auto-lint: true with auto-test: false is the most useful combination. Running the linter after every edit catches malformed output quickly without burning tokens on a full test suite for every change. Enable auto-test only if your tests are fast (under 10 seconds) — otherwise the session becomes a test-waiting loop.
The one config that breaks more than it fixes
auto-commits: true is on by default. It sounds convenient: Aider commits every successful edit automatically with a generated message.
The problem surfaces when your repo has pre-commit hooks — Husky, lint-staged, or any CI-enforced hook. Aider generates a commit, the hook runs, the hook fails (often because Aider edited a file that now fails a type check or lint rule in a different file), and the commit is blocked. Aider doesn’t recover gracefully from this. It either stalls waiting for user input or tries to re-apply the same edit in a loop.
The fix:
auto-commits: false
With auto-commits off, Aider still tracks what it changed. You review the diff, run your hooks manually, and commit. This is more work per change, but you’re not fighting a commit loop midway through a multi-file refactor.
The corollary: if your repo has no pre-commit hooks and you trust Aider’s output, auto-commits are genuinely useful. The config is context-dependent. Audit your hooks before leaving the default on.
There’s a related flag worth knowing: dirty-commits. When enabled, Aider will commit even if there are uncommitted changes in your working tree before it starts. The default is to refuse if the tree is dirty. Leaving dirty-commits: false (the default) is a guardrail worth keeping — starting an Aider session on a dirty tree makes it harder to isolate what Aider did from what you had in-progress.
Sharing config across the team via git
Committing .aider.conf.yml to the project root is usually the right call. It means:
- Everyone on the team runs the same model and edit format without coordination overhead
- New hires get the right setup on first clone
- Config drift (“why does your Aider behave differently?”) disappears
The one risk: model keys. Never put openai-api-key or anthropic-api-key in the project config. Those belong in the global ~/.aider.conf.yml or in environment variables. The project file should contain nothing that varies by developer (keys, personal paths) and everything that should be consistent (model choice, format, lint commands).
A second risk worth naming: different developers may have API access to different models. If the project config specifies model: claude-opus-4-5 and a contractor only has access to Sonnet, they’ll get an auth error. One solution is to set a reasonable default in the project config and let individuals override locally with their own global config. The override chain handles this — project sets the floor, global sets the ceiling.
A real project’s conf, annotated
This is the config for a TypeScript monorepo using Bun:
# .aider.conf.yml
# ── Model ──────────────────────────────────────────────────────────────────
model: claude-sonnet-4-5
# Weak model handles commit messages only; haiku is cheap enough to not matter
weak-model: claude-haiku-4-5
# diff format is stable with Sonnet; avoids full-file re-transmission
edit-format: diff
# ── Context ────────────────────────────────────────────────────────────────
# CONVENTIONS.md is ~200 lines; ADRs are numbered, add the relevant one at CLI
read:
- CONVENTIONS.md
# ── Quality gates ──────────────────────────────────────────────────────────
lint-cmd: bun run lint
# Tests are fast in this project; auto-test off anyway — long sessions get noisy
test-cmd: bun run test --run
auto-lint: true
auto-test: false
# ── Commits ────────────────────────────────────────────────────────────────
# Pre-commit hooks in this repo — auto-commits cause hook failures mid-session
auto-commits: false
# ── Misc ───────────────────────────────────────────────────────────────────
# Suppresses "files changed externally" noise from IDE saves
watch-files: false
A few notes on this config:
watch-files: false suppresses a notification Aider emits when it detects a file was changed outside its own edits. If you save a file in your editor while Aider is mid-session, it would normally interrupt and ask about the external change. With watch off, it doesn’t. Whether this is right depends on your workflow — if you’re editing alongside Aider, leave watch on so it doesn’t clobber your changes.
The read list has only one entry. That’s intentional. CONVENTIONS.md here is 200 lines; loading 5 more docs would eat context budget that’s better spent on code. Longer files that aren’t needed for every task belong on the CLI flag for that session: aider --read docs/architecture/decisions/007-auth.md.
auto-lint: true with this project’s lint command means every Aider edit is checked by Biome before Aider continues. Lint errors show up in the next turn, and Aider self-corrects. This alone catches about 40% of malformed diffs before a human sees them.
Project config vs global config in practice
The split that works:
Global ~/.aider.conf.yml — credentials (via env var references or nothing), personal model preferences, any flags you want everywhere but can be overridden.
Project .aider.conf.yml — model choice for this project, edit format, lint/test commands, convention files. This is the file you commit.
The one thing the project file cannot do is reference environment variables with ${VAR} syntax — Aider doesn’t expand them in the config file. If you need environment-dependent config (staging vs production API endpoints), pass those flags at the CLI. Everything static lives in the file.
There’s also a per-directory config option worth knowing. If you run Aider from a subdirectory, it looks for .aider.conf.yml in that directory first, then walks up to the project root. A monorepo can have a root config that sets the model and a subdirectory config in packages/api/ that overrides the lint command to run the backend-specific checker. That level of nesting is rarely needed but it’s there.
Once the project config is dialed in, the day-to-day command shortens to aider src/lib/auth.ts and the flags disappear. That’s the point. The config file is doing the coordination work that used to live in muscle memory or a team wiki page nobody reads.