- Do you enjoy the AI features of the Cursor AI Code Editor but prefer working within Emacs?
- Aider is a well-known and highly effective AI pair programming tool for the terminal.
- The `aider.el` package offers an interactive interface to communicate with Aider in Emacs.
- Most of the Elisp code in this repository was generated by Aider or `aider.el`.
- Pop-up Menu: No need to remember commands. (aider-transient-menu)
- The following commands are integrated into the aider menu:
- (`aider-run-aider`): Creates a comint-based, git repo-specific Aider session for interactive conversation.
- Git repository identification is based on the current file’s path
- Multiple Aider sessions can run simultaneously for different Git repositories
When being called with the universal argument (`C-u`), a prompt will offer the user to change the content of `aider-args` for this session.
- (`aider-switch-to-buffer`): Switch to the Aider buffer.
- use “^” in the menu to toggle open aider session in other window inside current frame, or open a dedicate frame for aider session
- (`aider-change-model`): Interactively select and change AI model in current aider session
- Customize `aider-popular-models` to define your preferred models list. Default models are (as date of 2025-01-26):
- anthropic/claude-3-5-sonnet-20241022 (really good in practical)
- o3-mini (new released. very powerful, not expensive)
- gemini/gemini-exp-1206 (free)
- r1 (performance matches o1, price << claude sonnet. weakness: small context)
- deepseek/deepseek-chat (chatgpt-4o level performance, price is 1/100. weakness: small context)
- use “@” in the menu to toggle add file between read-write mode and read-only mode
- (`aider-add-current-file`): Add the current buffer file.
- (`aider-add-files-in-current-window`): Add all buffers in the current window.
- (`aider-add-same-type-files-under-dir`): Add all files with the same suffix as the current file under the current directory to Aider.
- (`aider-batch-add-dired-marked-files`): Add multiple Dired marked files to the Aider buffer.
- (`aider-function-or-region-refactor`): If a region is selected, ask Aider to refactor the selected region. Otherwise, ask Aider to change / refactor the function under the cursor.
- (`aider-implement-todo`): Implement requirement in comments in-place, in current context.
- If cursor is on a comment line, implement that specific comment in-place.
- If cursor is inside a function, implement TODOs for that function.
- Otherwise implement TODOs for the entire current file.
- (`aider-ask-question`): Ask Aider a question about the code in the current context. If a region is selected, use the region as context.
- (`aider-function-or-region-explain`): If a region is selected, ask Aider to explain the selected region. Otherwise, ask Aider to explain the function under the cursor.
- (`aider-explain-symbol-under-point`): Ask Aider to explain the symbol under cursor, given the line as context.
- (`aider-write-unit-test`): Generate comprehensive unit tests for the current function or file. The generated tests will include normal cases, edge cases, and error handling scenarios.
- (`aider-fix-failing-test-under-cursor`): Place cursor on a failing test function and ask Aider to analyze and fix the code to make tests pass.
You can add your own Elisp functions to support your specific use cases. Feel free to ask Aider/`aider.el` to help you create them.
- Emacs need to be >= 26.1
- Install aider
- Install the emacs dependency library Transient, and Magit using your package manager.
- Install aider.el with the following code:
With Straight
If you have Straight installed
(use-package aider
:straight (:host github :repo "tninja/aider.el" :files ("aider.el"))
:config
;; Use claude-3-5-sonnet cause it is best in aider benchmark
(setq aider-args '("--model" "anthropic/claude-3-5-sonnet-20241022"))
(setenv "ANTHROPIC_API_KEY" anthropic-api-key)
;; Or use chatgpt model since it is most well known
;; (setq aider-args '("--model" "o3-mini"))
;; (setenv "OPENAI_API_KEY" <your-openai-api-key>)
;; Or use gemini v2 model since it is very good and free
;; (setq aider-args '("--model" "gemini/gemini-exp-1206"))
;; (setenv "GEMINI_API_KEY" <your-gemini-api-key>)
;; Or use your personal config file
;; (setq aider-args `("--config" ,(expand-file-name "~/.aider.conf.yml")))
;; ;;
;; Optional: Set a key binding for the transient menu
(global-set-key (kbd "C-c a") 'aider-transient-menu))
With package-vc-install (emacs built-in)
Install Aider.el by running the following code within Emacs
(package-vc-install '(aider :url "https://github.com/tninja/aider.el"))
Add the config
(use-package aider
:config
;; Use claude-3-5-sonnet cause it is best in aider benchmark
(setq aider-args '("--model" "anthropic/claude-3-5-sonnet-20241022"))
(setenv "ANTHROPIC_API_KEY" anthropic-api-key)
;; Or use chatgpt model since it is most well known
;; (setq aider-args '("--model" "o3-mini"))
;; (setenv "OPENAI_API_KEY" <your-openai-api-key>)
;; Or use gemini v2 model since it is very good and free
;; (setq aider-args '("--model" "gemini/gemini-exp-1206"))
;; (setenv "GEMINI_API_KEY" <your-gemini-api-key>)
;; Or use your personal config file
;; (setq aider-args `("--config" ,(expand-file-name "~/.aider.conf.yml")))
;; ;;
;; Optional: Set a key binding for the transient menu
(global-set-key (kbd "C-c a") 'aider-transient-menu))
- Add the following code to your doom/packages.el
(package! aider :recipe (:host github :repo "tninja/aider.el" :files ("aider.el" "aider-doom.el")))
- Adjust and add the following code to your doom/config.el
(use-package aider
:config
(setq aider-args '("--model" "o3-mini")))
The aider prefix is “A”.
- Start and open the aider buffer:
[SPC] A o
- Add the current file with
[SPC] A a c
- Reset the aider session with
[SPC] A r
Helm enables fuzzy searching functionality for command history prompts
You can enable Helm-based completion with the following code:
(use-package aider
:straight (:host github :repo "tninja/aider.el" :files ("aider.el" "aider-helm.el")))
- If you prefer writing Aider commands in a separate file and sending them to an Aider session (similar to working with Python or R scripts and sending code blocks to a REPL), you might want to try aider-minor-mode. It provides the following key bindings:
- C-c C-n: If region is active, send selected region line by line; otherwise, send current line
- C-c C-c: Send current region line by line to aider session
- C-c C-r: Send current region as a single block to aider session
- Enable aider-minor-mode for your editing buffer
- To automatically enable aider-minor-mode for any file with “aider” in its filename:
(add-hook 'find-file-hook
(lambda ()
(when (and (buffer-file-name)
(string-match-p "aider" (buffer-file-name)))
(aider-minor-mode 1))))
- Here I just share my personal experience. You might have different / better way to use aider.el.
To develop new features effectively with aider.el, follow these steps:
- Start an Aider session specific to your current git repository by running the command “aider-run-aider”. This links your session to your project context.
- Add relevant files to the session using commands such as “aider-add-current-file”, “aider-add-files-in-current-window”, etc, so that the AI has access to the complete codebase.
- Use the in-place implementation commands—for example, “aider-implement-todo” to implement requirements directly in comments or “aider-function-or-region-refactor” to make code change or refactor existing code—since these approaches are preferred for feature development as they apply minimal, context-aware changes.
- For inline one-line comment implementations:
For example, if you have the following Python code snippet:
# TODO: Implement a function that checks if a number is prime
Place the cursor on the TODO comment line and run “aider-implement-todo”. This command will send only that inline comment to Aider, which will then generate new code—for example, a complete implementation of an is_prime function—while leaving existing code unchanged. A possible generated output might be:
def is_prime(n): if n <= 1: return False for i in range(2, int(n ** 0.5) + 1): if n % i == 0: return False return True
This example demonstrates using aider-implement-todo to generate entirely new code rather than modifying existing code.
Actually, this function can also help writing document.
- If you are not satisfied with the change aider suggested. You can enter N to refuse accept that, and then use Ask Question (or /ask in aider session buffer) to ask aider modify the change given your more specific requirement. When you satisfy with that, use “Go Ahead” (or “go ahead” in aider session buffer)
- When you need to adjust an existing function, class, or code block, do the following:
- If you wish to change only a part of the code, select that region; otherwise, simply place the cursor inside the target function or block.
- Run “aider-function-or-region-refactor”.
- When prompted, enter a clear code change / refactoring instruction (for example, “Rename variable ‘temp’ to ‘result’” or “Make the function static”).
- Aider will process your instruction and return a revised version of the code with your changes applied in place while preserving the overall structure.
- Review the output and, if needed, refine your instructions further (e.g., by using “Ask Question”) to get the desired result.
- aider-architect-discussion and aider-code-change are also helpful, but it is less context aware than the above two commands.
- For inline one-line comment implementations:
For example, if you have the following Python code snippet:
- Validate and evolve your feature with test-driven commands like “aider-write-unit-test” and “aider-fix-failing-test-under-cursor” as needed.
AI-generated code is beneficial for quickly implementing features but can sometimes introduce subtle bugs or inconsistencies. That’s why Unit Test (or even more, Test-Driven Development) is critical: by writing tests before and after integrating AI-generated changes, you ensure that each incremental improvement is validated immediately. Implement your tests in small iteration steps—running your full test suite after each change—to catch issues early and maintain robust control over your codebase.
Right now I am using projectile function to jump between main code and test code, and add them to session. It would be better if there is a way to easily add test code to session.
- The screenshot above shows Aider being asked to generate an aider-help function and add its corresponding entry to the menu (top right window).
- Aider successfully received the command and generated the appropriate commit (bottom left).
- Inspired by, and Thanks to:
- ancilla.el: AI Coding Assistant support code generation / code rewrite / discussion
- chatgpt-shell: ChatGPT and DALL-E Emacs shells + Org Babel, comint session based idea
- copilot.el: Emacs plugin for GitHub Copilot
- copilot-chat.el: Chat with GitHub Copilot in Emacs
- gptel: Most stared / widely used LLM client in Emacs