Skip to content

tninja/aider.el

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

aider.el : aider (AI Pair Programming) Inside Emacs

中文版

Table of Contents

Introduction

  • 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.
    • aider.el aim to be a stable productivity tool we can use daily. I will carefully test the Features / Functions in this library before code merging.
  • Recent change history

Pros: UI, Context Awareness AI Pair Programming

  • Pop-up Menu (aider-transient-menu)

./transient_menu.png

  • Git repository-specific Aider session management
  • Integrating context (buffer / things under cursor / region) with aider, semi-automatically build up prompt. easy search / reuse previous prompt with helm
  • Menu items for AI-assistant programming workflow. TDD style loop to reduce potential AI introduced error
  • Aider prompt file to organize relative large code change task, and make it reproducible. Interacting with aider session from it following ESS way. Yasnippet support to reuse good prompts from community.

Cons: aider session in comint is not fancy

  • The current implementation is using comint to host aider session, a classic CLI interactive solution used in emacs, However, comint-mode initially doesn’t have the advance features such as codeblock color rendering and file tracking from aider.
    • color rendering markdown-mode.el is applied and largely improved this.
    • Without file tracking, aider.el cannot do AI comments. The work around we provided is ~aider-implement-todo~, It use architect command to ask aider to implement comment under cursor by default. I constantly use this feature and feel it is OK.
  • It’s generally not advantageous to interact with Aider extensively through the comint terminal directly. Instead, since 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 and manage large code change requiring more prompts and break them into sub-tasks (cause it is org), and it is easy for multi-line prompts. Recently, syntax highlight, completion and snippets were added to this file, and it is now a good place to write and organize your prompts.

Alternatives to aidermacs

  • More Focus on build prompts using your code (buffer/selection).
  • Reuse prompts easily, fuzzy search with helm.
  • Organize project with repo specific Aider prompt file
  • More Focus on code quality tool (Code Review, TDD + AI).
  • Snippets for community prompts.

Installation

  • Emacs need to be >= 26.1

Vanilla Emacs Installation

If you have Straight installed

(use-package aider
  :straight (:host github :repo "tninja/aider.el" :files ("aider.el" "aider-core.el" "aider-file.el" "aider-code-change.el" "aider-discussion.el" "aider-prompt-mode.el"))
  :config
  ;; For latest claude sonnet model
  (setq aider-args '("--model" "sonnet"))
  (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
  • if aider-args is empty (default), it will use ~/.aider.conf.yml file. In this way, aider CLI and aider.el share same configuration

With package-vc-install (Emacs 30+ built-in)

  • Install aider.el by running the following code within Emacs
    • You’ll need to manually install the required packages, such as Transient, Magit, and helm.
(package-vc-install '(aider :url "https://github.com/tninja/aider.el"))

The config part is as same as above straight one

With Melpa + package-install

Enable installation of packages from MELPA by adding an entry to package-archives after (require ‘package) and before the call to package-initialize in your init.el or .emacs file:

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; Comment/uncomment this line to enable MELPA Stable if desired.  See `package-archive-priorities`
;; and `package-pinned-packages`. Most users will not need or want to do this.
;;(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)
  • Use M-x package-refresh-contents or M-x package-list-packages to ensure that Emacs has fetched the MELPA package list
  • Use M-x package-install to install aider package

Doom Installation and Configuration

  • Add the following code to your doom/packages.el
(package! aider :recipe (:host github :repo "tninja/aider.el" :files ("aider.el" "aider-core.el" "aider-file.el" "aider-code-change.el" "aider-discussion.el" "aider-prompt-mode.el" "aider-doom.el")))
  • Adjust and add the following code to your doom/config.el
(use-package aider
  :config
  (setq aider-args '("--model" "sonnet")))

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

./doom_menus.png

  • 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 Support

Helm enables fuzzy searching functionality for command history prompts. 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.

If you used installed aider.el through melpa and package-install, just neecd to (require 'aider-helm)

Otherwise, 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-core.el" "aider-file.el" "aider-code-change.el" "aider-discussion.el" "aider-prompt-mode.el" "aider-doom.el" "aider-helm.el")))

Most used features (integrated into the aider menu)

Aider session management

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. 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.

More ways to add files to the Aider buffer

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.

Write code

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.
  • A couple common used prompts provided when you are using aider-helm.el
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.
    • The keyword (TODO by default) can be customized with the variable aider-todo-keyword-pair. One example is to use AI! comment, which is as same as aider AI comment feature.

Support for Unit Test / Test Driven Development

aider-write-unit-test
If the current buffer is main source code file, generate comprehensive unit tests for the current function or file. If the cursor is in a test source code file, when the cursor is on a test function, implement the test function. Otherwise, provide description to implement the test function (or spec).
  • If main source code break and test function fails, use aider-function-or-region-refactor on the failed test function to ask Aider to fix the code to make the test pass.

Questions on 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.
  • You can ask any question on the code. Eg. Explain the function, review the code and find the bug, etc
  • A couple common used prompts provided when you are using aider-helm.el
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 prompt file

  • Syntax highlight, aider command completion, file path completion supported
  • 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
  • C-c C-n key can be used to send the current prompt line to the comint buffer. Or batch send selected region line by line. To my experience, this is the most used method in aider prompt file.
  • C-c C-c key is for multi-line prompt. The following example shows C-c C-c key pressed when cursor is on the prompt.

./aider_prompt_file.png

  • Prompts for aider might share similar structure. Yasnippet can be used to help reusing these prompts.
  • Aider prompt file now support yasnippet. Current snippets came from this reddit post, another reddit post, and a git repo.
  • You can use
    • M-x yas-describe-tables to see the available snippets
    • M-x yas-insert-snippet to insert a snippet.
    • M-x yas-expand to expand the snippet under cursor.
  • Welcome to add more snippets / improve existing snippets in the snippets folder!

Inside comint buffer

  • / key to trigger aider command completion
  • file path completion will be triggered automatically after certain command
  • use TAB key to enter prompt from mini-buffer, or helm with completion

Be careful about AI generated code

  • 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.

A TDD-style AI programming workflow

  1. **Implement or modify code**:
    • For existing code: Use aider-function-or-region-refactor with cursor in function or on selected region
    • For new code: Use aider-implement-todo on TODO comments

    Example of adding new code:

    With cursor on this comment:

    # TODO: Implement a function that checks if a number is prime
        

    Running aider-implement-todo might generate:

    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
        

    If suggestions aren’t satisfactory, use Ask Question for refinements and Go Ahead to confirm changes.

  2. **Generate tests**: Validate your implementation with aider-write-unit-test. Do run the test to validate code behavior.
    • aider-write-unit-test can be used to write unit-test before the code is implemented, just call the function in the unit-test class. I tried it with leetcode problems and it works pretty well.
  3. **Refine code and tests**: Further refactor as needed using additional prompts or manual adjustments.
  4. Goto 1

FAQ

  • How to review / accept the code change?
    • Comparing to cursor, aider have a different way to do that. Discussion
    • Note: Aider v0.77.0 automatically accept changes for /architect command. If you want to review the code change before accepting it like before for many commands in aider.el, you can disable that flag with “–no-auto-accept-architect” in either aider-args or .aider.conf.yml.
  • How to disable to aider auto-commit?
  • What kind of model aider support? Can aider support local model?
  • How to let aider work with your speaking language?
    • use aider coding conventions. In my case, I added “- reply in Chinese” to the CONVENTIONS.md file, and load work through .aider.conf.yml. Or, put sth like following into aider-args variable.
      • “–read” (expand-file-name “~/.emacs.d/.emacs/aider/CONVENTIONS.md”)
  • 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
  • Can aider.el work with tramp? (aider running on remote machine)
    • artyom-smushkov make aider-add-current-file support tramp file: #36
    • mgcyung said it can work in this way: #85

Future work

Feature

  • More context sensitive code change / code reading commands [1/1]
    • [X] Current aider-ask-question need to be improved, since there could be so many different question to ask
    • [ ] Thinking on how to improve the candidate list for the function
    • [ ] How to port the candidate list feature to aider-plain-read-string
  • More thinking on how to simplify the menu / commands
  • More thinking on improving code quality tool such as unit-test
  • Tag release version, make it available on melpa stable

Code quality

  • Better unit-test / integration test of this package. Hopefully it is automated.

Other Emacs AI coding tool

  • 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
  • Package depends on this
    • ob-aider.el: Org Babel functions for Aider.el integration