- 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 simple UI to communicate with Aider in Emacs. It aim to minimize the user’s effort using 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
)
- Work directly on the code without switching contexts. Git repository-specific Aider session mapped to current buffer given git repo info.
- Pass your Emacs editing context to Aider, including details such as the active function or class and any selected code. This minimizes manual typing.
- Designed for everyday programming tasks, such as adding or modifying code with AI assistance, write unit-test / TDD assist, and help reading code written by others.
- The current implementation is using comint to host aider session, a classic CLI interactive solution used in emacs, However, comint-mode doesn’t have the advance features such as codeblock color rendering and file tracking from aider.
- Some work-around for code color was applied, but we still don’t have a fundamental solution for this right now. Vterm is good but I don’t want to depend on it at this moment.
- Would be great if someone can solve this problem, or make it better without introduce too many complexity.
- There is no advantage interacting with aider through this comint terminal. But the comint terminal is well integrated with other parts of emacs, it is encouraged to generate and send prompt to it, either from:
- Code buffer directly by aider code change related commands or ask question related commands. It make less context switching, and it help building up prompt, reducing manual typing.
- Aider prompt file (
aider-open-prompt-file
,C-c a p
). This is the traditional way in emacs to communicate with comint buffer (just like ESS, python-mode, scala-mode, etc). It is easy to revisit your used commands, organize large code change into several small prompts, and it is easy for multi-line prompts
- 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
;; For claude-3-5-sonnet
(setq aider-args '("--model" "anthropic/claude-3-5-sonnet-20241022"))
(setenv "ANTHROPIC_API_KEY" anthropic-api-key)
;; Or chatgpt model
;; (setq aider-args '("--model" "o3-mini"))
;; (setenv "OPENAI_API_KEY" <your-openai-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))
- aider-args just passed directly to aider CLI, aider options reference
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"))
The config part is as same as above straight one
- 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
- However, transient menu is more recommended than doom menu, cause I constantly use that one so it is better maintained.
- Anyone want to contribute to doom menu, feel free to help on it. Thanks.
Helm enables fuzzy searching functionality for command history prompts, the prompts are ordered based on used frequency and time. Since it is very possible that we use prompt written before, it could potentially save lots of time typing. This plugin is highly recommended if you are OK with helm.
You can have helm-based completion with run the following code, after install helm library:
(use-package aider
:straight (:host github :repo "tninja/aider.el" :files ("aider.el" "aider-helm.el")))
- Use
C-c a p
to open the repo specific prompt file. You can use this file to organize tasks, and write prompt and send them to the Aider session. multi-line prompts are supported. - People happy with sending code from editor buffer to comint buffer (eg. ESS, python-mode, scala-mode) might like this. This is a interactive and reproducible way
- The following example shows
C-c C-r
key pressed when cursor is on the prompt.
- 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 ofaider-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. This is useful when there is more than one monitor, and one frame / monitor is used to hold multi buffers for code, and another frame / monitor hold aider session.
- use
- aider-add-current-file-or-dired-marked-files
- Add the current buffer file. If it is used in dired buffer, add all dired marked files.
C-u
prefix to add files read-only.
- aider-add-files-in-current-window
- Add all buffers in the current window.
- 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 there is a selection region of multi-line comments, implement code for those comments in-place.
- If cursor is inside a function, implement TODOs for that function.
- Otherwise implement TODOs for the entire current file.
- aider-write-unit-test
- Generate comprehensive unit tests for the current function or file. If the cursor is on a test function, implement the test function.
- 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 provide more information of failed test case to help aider figuring out how to fix the source code.
- 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-go-ahead
- When you are asking aider to suggest a change using above command, maybe even after several round of discussion, when you are satisfied with the solution, you can use this command to ask Aider to go ahead and implement the change.
- 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.
- Thanks to LLM. It is so easy to generate bunch of code with AI. But generating code doesn’t complete the work.
- There might be potential bug hidden inside. It need to be verified that the feature work as expected, and code change didn’t break existing features.
- Developer might be lack of understanding of AI generated code. If there is too many code developer don’t quite understand, the project could be out of control.
- Unit-test can be useful on both of the above concern. And aider can help writing unit tests.
- The AI generated test need to be manually checked / fixed. But generally test code is easier to understand.
- Running the unit-tests can help verifying the correctness / identifying the bug of code. It also help developer better understanding how the AI generated code work, and it can give developer more confidence on the new code.
- When making changes, you might be either adding new code or modifying existing code.
- Adding new code via one-line comment implementation:
For instance, suppose you encounter the following Python snippet:
# TODO: Implement a function that checks if a number is prime
With the cursor positioned on the TODO comment line, running
aider-implement-todo
will send only that inline comment to Aider, which may then generate revised code—for example, a complete implementation of anis_prime
function—while preserving the existing code. For instance, Aider might produce: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 how
aider-implement-todo
can assist in introducing new code. (This command may also be useful for some documentation tasks.)- If the suggested change is not completely satisfactory, you can decline it (for example, by entering
N
). After declining, use theAsk Question
command (or type/ask
in the aider session buffer) to request further modifications with detailed guidance. Once you receive an acceptable suggestion, confirm it using theGo Ahead
command (or typego ahead
in the aider session buffer).
- If the suggested change is not completely satisfactory, you can decline it (for example, by entering
- Change existing code for an existing function, class, or code block:
- If you only need to modify a portion of the code, select the relevant region; otherwise, simply place the cursor inside the target function or class.
- Execute the
aider-function-or-region-refactor
command. - When prompted, provide a clear description of the intended change (e.g., “Rename variable ‘temp’ to ‘result’” or “Make the function static”).
- A revised version of the code, incorporating your suggestions, will be generated while preserving the overall structure.
- Review the output; if further refinement is required, request additional adjustments using
Ask Question
and confirm them withGo Ahead
until the desired result is achieved.
- Note: Alternative commands like
aider-architect-discussion
andaider-code-change
are also available, though they may offer less context sensitivity than the commands described above.
- Adding new code via one-line comment implementation:
For instance, suppose you encounter the following Python snippet:
- Generate tests
It is recommended to validate and iteratively improve the feature using unit test commands such as
aider-write-unit-test
andaider-fix-failing-test-under-cursor
. Although AI-generated code can provide a valuable starting point, it may sometimes introduce subtle issues. Running tests both before and after integrating changes ensures that each modification is verified. Running the full test suite after every change is advised to catch any issues early.(As an aside, a projectile function is currently employed to switch between the main code and test code and add them to the session—but further improvements to include test code seamlessly are always welcome.)
- Refactor code and tests Finally, you can further refactor the AI-generated code and tests as needed—either using additional prompts or manual adjustments—to best meet the project’s requirements.
- How to enter multi-line prompts in aider session buffer?
- aider itself support that, doc.
- use aider prompt file (
aider-open-prompt-file
,C-c a p
) to write multi-line prompts (we don’t want them to go away right? especially if it is not perfect and need to be modified, and we might want to reuse it sometime later).
- [ ] More useful context sensitive code change / explaining commands
- [ ] Better and stable color coding solution
- [ ] Better support for aider prompt file
- [ ] Better unit-test / integration test of this package. Hopefully it is automated.
- 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