Why try anything else than Copilot?
A few months ago, a friend recommended the CLI pair programming tool, Aider, to me. As a cloud engineer and developer, I had already been experimenting with AI-based coding tools like GitHub Copilot, using it for code completion, chat, and its “agent” mode. Once I was able to use an API-based model with my company’s account, I decided to give Aider a try.
In this article, I’ll share my thoughts on Aider, discuss its pros and cons, and walk you through my experience using it to code a small microservice.
How is Aider compared to tools like Github Copilot?
The first thing to know is that Aider is a CLI-based tool, which means you primarily use it in your terminal. This approach comes with some nice advantages:
Flexible IDE Choice
You can use Aider in any coding environment you prefer, such as your operating system’s terminal or your IDE’s integrated terminal.
Faster Workflow
Compared to GUI-based tools, I found a significant boost in my workflow speed. For example, handling different read/edit operations or switching chat modes in Aider can all be done with your keyboard, eliminating the need to use a mouse. Once I got used to this style of interaction, I really appreciated its efficiency.
After installing Aider, you need to set up your API key to connect the tool to your LLM provider. The documentation provides a great starting point for configuration.your LLM provider. The documentation provides a great starting point for configuration.
$ aider --model deepseek/deepseek-coder --chat-language english
──────────────────────────────────────────────────────────────────
No git repo found, create one to track aider's changes (recommended)? (Y)es/(N)o
[Yes]: yes
Added .aider* to .gitignore
Git repository created in /Users/philipp/aider
Aider v0.85.0
Model: deepseek/deepseek-coder with diff edit format, prompt cache, infinite
output
Git repo: .git with 0 files
Repo-map: using 4096 tokens, auto refresh
Chat Modes
After starting Aider, you are start in '/code' mode and will make changes directly to your code to satisfy your request. In Aider you have access to three different chat-modes:
- /code
- /architect
- /ask
If you switch to '/ask' mode with the command:
/chat-mode ask
Aider will never make any changes but gives you its preferred answer or implementation suggestion. In '/architect' mode, the model will make changes to your files like in code mode, but the implementation has a two-step approach: an architect model (e.g. a reasoning model) proposes changes for a more complex request, and an editor model translates that into specific file edits.
To see the available models in Aider, type '/models' and pick the model you like with the '/model' command. Aider can be configured to use different models for the available chat modes. Have a look at the documentation to find the right parameters.
Building Context
Since modern Large Language Models are so capable right now, getting good results for difficult problems becomes more and more a matter of good context. Building context with Aider is really easy. You can add files to the context of your system prompt with '/add'. These files will be edited when Aider thinks this is necessary for solving the problem. If you just want to give Aider information about a file, add it with '/read-only'. The name speaks for itself, I guess. For example, if I want to add additional tests to the test_car.py file and be sure that Aider doesn’t make any changes to your car.py file, make the file read-only.
car.py test_car.py
ask> /read-only car.py
Moved /Users/philipp/aider/car.py from editable to read-only files in the chat
──────────────────────────────────────────────────────────────────────────────────────────
Readonly: car.py
Editable: test_car.py
ask>
You can even further enhance the context of your prompt if you add some documentation of a specific library you want to use. This is especially helpful when the library is not so widely used or if you are using an LLM that wasn’t trained on a huge amount of web data. In Aider, you can simply add the webpage containing the needed documentation to the chat window, or you can use '/web' to scrape the page’s content and add it directly to your prompt.
For example, we can ask Aider to give us a summary of all released versions which are present on Aider’s documentation: https://aider.chat/HISTORY.html
> Give me a summary list of all release version of Aider which are present on this web page: https://aider.chat/HISTORY.html
https://aider.chat/HISTORY.html
Add URL to the chat? (Y)es/(N)o/(D)on't ask again [Yes]: yes
Scraping https://aider.chat/HISTORY.html...
Here's a summary list of all Aider release versions from the HISTORY.html page:
v0.85.2 v0.85.1 v0.85.0 v0.84.0 v0.83.2 v0.83.1 v0.83.0 v0.82.3 v0.82.2 v0.82.1 v0.82.0 v0.81.3 v0.81.2 v0.81.1 v0.81.0 v0.80.4 v0.80.3 v0.80.2 v0.80.1
v0.80.0 v0.79.2 v0.79.1 v0.79.0 v0.78.0 v0.77.1 v0.77.0 v0.76.2 v0.76.1 v0.76.0 v0.75.3 v0.75.2 v0.75.1 v0.75.0 v0.74.3 v0.74.2 v0.74.1 v0.74.0 v0.73.0
v0.72.3 v0.72.2 v0.72.1 v0.72.0 v0.71.1 v0.71.0 v0.70.0 v0.69.1 v0.69.0 v0.68.0 v0.67.0 v0.66.0 v0.65.1 v0.65.0 v0.64.1 v0.64.0 v0.63.2 v0.63.1 v0.63.0
v0.62.0 v0.61.0 v0.60.1 v0.60.0 v0.59.1 v0.59.0 v0.58.1 v0.58.0 v0.57.1 v0.57.0 v0.56.0 v0.55.0 v0.54.12 v0.54.11 v0.54.10 v0.54.9 v0.54.8 v0.54.7 v0.54.6
v0.54.5 v0.54.4 v0.54.3 v0.54.2 v0.54.0 v0.53.0 v0.52.1 v0.52.0 v0.51.0 v0.50.1 v0.50.0 v0.49.1 v0.49.0 v0.48.1 v0.48.0 v0.47.1 v0.47.0 v0.46.1 v0.46.0
v0.45.1 v0.45.0 v0.44.0 v0.43.4 v0.43.3 v0.43.2 v0.43.1 v0.43.0 v0.42.0 v0.41.0 v0.40.6 v0.40.5 v0.40.1 v0.40.0 v0.39.0 v0.38.0 v0.37.0 v0.36.0 v0.35.0
v0.34.0 v0.33.0 v0.32.0 v0.31.0 v0.30.1 v0.30.0 v0.29.2 v0.29.1 v0.29.0 v0.28.0 v0.27.0 v0.26.1 v0.26.0 v0.25.0 v0.24.1 v0.24.0 v0.23.0 v0.22.0 v0.21.1
v0.21.0 v0.20.0 v0.19.1 v0.19.0 v0.18.1 v0.18.0 v0.17.0 v0.16.3 v0.16.2 v0.16.1 v0.16.0 v0.15.0 v0.14.2 v0.14.1 v0.14.0 v0.13.0 v0.12.0 v0.11.1 v0.11.0
v0.10.1 v0.10.0 v0.9.0 v0.8.3 v0.8.2 v0.8.1 v0.8.0 v0.7.2 v0.7.1 v0.7.0 v0.6.2 v0.5.0
The list shows Aider has had 136 releases from v0.5.0 up to the current v0.85.2.
Coding Example
We are now able to switch to the '/ask' mode and prompt what we want to be implemented. The cool thing about this mode is that Aider doesn’t start directly implementing my prompt. Instead, it gives me an example of what it thinks is the right solution for my problem or prompt. After that, I can give it the go-ahead with '/code implement' or ask for something to add or change (like I did in the example below).
> /ask
ask> Create a simple python example where an object (car) can be instanciated. The object should have the following getter attributes: 'get_color' and 'get_brand'.
Here's a simple Python example with a Car class that has the requested getter methods:
class Car:
def __init__(self, color, brand):
self._color = color
self._brand = brand
def get_color(self):
return self._color
def get_brand(self):
return self._brand
# Example usage:
my_car = Car("red", "Toyota")
print(my_car.get_color()) # Output: red
print(my_car.get_brand()) # Output: Toyota
Key points:
• The class uses _color and _brand (with underscore prefix) to indicate these are intended as protected attributes
• Simple getter methods return the attribute values
• The object is instantiated with color and brand parameters
Would you like me to modify or expand this example in any way?
Tokens: 119 sent, 176 received. Cost: $0.000066 message, $0.000066 session.
──────────────────────────────────────────────────────────────────────────────────────────
ask> Also add two attributes 'get_state_of_charge' and 'set_state_of_charge'
Here's the updated Car class with battery state of charge management:
class Car:
def __init__(self, color, brand, state_of_charge=0):
self._color = color
self._brand = brand
self._state_of_charge = state_of_charge # Typically 0-100%
def get_color(self):
return self._color
def get_brand(self):
return self._brand
def get_state_of_charge(self):
return self._state_of_charge
def set_state_of_charge(self, new_charge):
# Basic validation
if 0 <= new_charge <= 100:
self._state_of_charge = new_charge
else:
raise ValueError("Charge must be between 0 and 100")
# Example usage:
electric_car = Car("blue", "Tesla", 50)
print(electric_car.get_state_of_charge()) # Output: 50
electric_car.set_state_of_charge(75)
print(electric_car.get_state_of_charge()) # Output: 75
Changes made:
1 Added _state_of_charge attribute initialized in __init__
2 Added getter method get_state_of_charge()
3 Added setter method set_state_of_charge() with basic range validation
Would you like me to add any additional features or validations?
Tokens: 320 sent, 284 received. Cost: $0.00012 message, $0.00019 session.
If you like Aider’s code suggestion, start the implementation by '/code go ahead‘ or whatever you want to write behind the code section.
ask> /code implement
I'll implement this as a Python file. Here's the SEARCH/REPLACE block to create the file:
car.py
<<<<<<< SEARCH
=======
class Car:
def __init__(self, color, brand, state_of_charge=0):
"""Initialize a Car with color, brand and optional state of charge (0-100%)."""
self._color = color
self._brand = brand
self._state_of_charge = state_of_charge # Typically 0-100%
def get_color(self):
"""Return the car's color."""
return self._color
def get_brand(self):
"""Return the car's brand."""
return self._brand
def get_state_of_charge(self):
"""Return the current state of charge (0-100%)."""
return self._state_of_charge
def set_state_of_charge(self, new_charge):
"""
Set the state of charge.
Args:
new_charge (int): New charge percentage (0-100)
Raises:
ValueError: If charge is outside 0-100 range
"""
if 0 <= new_charge <= 100:
self._state_of_charge = new_charge
else:
raise ValueError("Charge must be between 0 and 100")
if __name__ == "__main__":
# Example usage
electric_car = Car("blue", "Tesla", 50)
print(f"Brand: {electric_car.get_brand()}")
print(f"Color: {electric_car.get_color()}")
print(f"Current charge: {electric_car.get_state_of_charge()}%")
electric_car.set_state_of_charge(75)
print(f"Updated charge: {electric_car.get_state_of_charge()}%")
>>>>>>> REPLACE
You can test the implementation by running:
python3 car.py
The implementation includes:
1 A complete Car class with all requested getters and setters
2 Input validation for state of charge (0-100%)
3 Docstrings for all methods
4 Example usage in the __main__ block
5 Proper error handling for invalid charge values
Would you like me to make any adjustments to this implementation?
Tokens: 2.8k sent, 467 received. Cost: $0.00053 message, $0.00072 session.
car.py
Create new file? (Y)es/(N)o [Yes]: yes
Applied edit to car.py
Commit 21dfc1e feat: implement Car class with getters and charge management
python3 car.py
Run shell command? (Y)es/(N)o/(D)on't ask again [Yes]: yes
Running python3 car.py
Brand: Tesla
Color: blue
Current charge: 50%
Updated charge: 75%
Add command output to the chat? (Y)es/(N)o/(D)on't ask again [Yes]: yes
Added 5 lines of output to the chat.
The console output now shows that Aider is taking its latest suggested implementation and starting to code the Car class, the object instantiation, and some print statements. A commit, including a generated commit message, is created right below. Aider even asks you to run the shell command to test its Python script, and if you want, you can add the output to the chat. This is very helpful if the script execution raises an error, as the output would be used as context input for Aiderto solve the problem.
As the next step, we let Aider code some unit tests in pytest for the Car class. Pytest is currently not installed as a module, and we will see that Aider can solve this without a problem.
ask> Create unit tests in pytest for the `Car` class
I'll create a test file test_car.py with comprehensive unit tests for the Car class using pytest. Here's the implementation:
import pytest
from car import Car
class TestCar:
def test_initialization(self):
"""Test that a car is initialized with correct attributes."""
car = Car("red", "Ferrari", 80)
assert car.get_color() == "red"
assert car.get_brand() == "Ferrari"
assert car.get_state_of_charge() == 80
def test_default_charge(self):
"""Test that state_of_charge defaults to 0 when not provided."""
car = Car("black", "BMW")
assert car.get_state_of_charge() == 0
def test_set_valid_charge(self):
"""Test setting a valid state of charge."""
car = Car("white", "Tesla", 50)
car.set_state_of_charge(75)
assert car.get_state_of_charge() == 75
@pytest.mark.parametrize("invalid_charge", [-1, 101, 150, -0.1])
def test_set_invalid_charge(self, invalid_charge):
"""Test that invalid charge values raise ValueError."""
car = Car("blue", "Nissan", 20)
with pytest.raises(ValueError, match="Charge must be between 0 and 100"):
car.set_state_of_charge(invalid_charge)
def test_edge_case_charges(self):
"""Test that edge cases (0 and 100) work correctly."""
car = Car("silver", "Audi", 50)
car.set_state_of_charge(0)
assert car.get_state_of_charge() == 0
car.set_state_of_charge(100)
assert car.get_state_of_charge() == 100
Key features of these tests:
1 Tests for proper initialization with all parameters
2 Test for default charge value
3 Tests for valid charge updates
4 Parameterized test for various invalid charge values
5 Tests for edge cases (0% and 100% charge)
6 Clear docstrings explaining each test case
To run these tests:
pytest test_car.py -v
The tests will verify:
• All getters return correct values
• Default initialization works
• Charge validation works properly
• Edge cases are handled correctly
• Error messages are appropriate
Would you like me to add any additional test cases or make any adjustments to these tests?
Tokens: 1.8k sent, 515 received. Cost: $0.00039 message, $0.0011 session.
──────────────────────────────────────────────────────────────────────────────────────────
car.py
ask> /code go ahead
I'll create the test file using a SEARCH/REPLACE block:
test_car.py
<<<<<<< SEARCH
=======
import pytest
from car import Car
class TestCar:
def test_initialization(self):
"""Test that a car is initialized with correct attributes."""
car = Car("red", "Ferrari", 80)
assert car.get_color() == "red"
assert car.get_brand() == "Ferrari"
assert car.get_state_of_charge() == 80
def test_default_charge(self):
"""Test that state_of_charge defaults to 0 when not provided."""
car = Car("black", "BMW")
assert car.get_state_of_charge() == 0
def test_set_valid_charge(self):
"""Test setting a valid state of charge."""
car = Car("white", "Tesla", 50)
car.set_state_of_charge(75)
assert car.get_state_of_charge() == 75
@pytest.mark.parametrize("invalid_charge", [-1, 101, 150, -0.1])
def test_set_invalid_charge(self, invalid_charge):
"""Test that invalid charge values raise ValueError."""
car = Car("blue", "Nissan", 20)
with pytest.raises(ValueError, match="Charge must be between 0 and 100"):
car.set_state_of_charge(invalid_charge)
def test_edge_case_charges(self):
"""Test that edge cases (0 and 100) work correctly."""
car = Car("silver", "Audi", 50)
car.set_state_of_charge(0)
assert car.get_state_of_charge() == 0
car.set_state_of_charge(100)
assert car.get_state_of_charge() == 100
def test_color_and_brand_immutability(self):
"""Test that color and brand cannot be changed after initialization."""
car = Car("green", "Jaguar")
# Verify there are no setter methods
assert not hasattr(car, "set_color")
assert not hasattr(car, "set_brand")
>>>>>>> REPLACE
I've added one more test case that verifies:
• Color and brand are immutable (no setter methods exist)
• This ensures the class maintains its encapsulation as designed
You can run the tests with:
pytest test_car.py -v
The tests will show verbose output with all test cases and their docstrings. All tests should pass with the current Car implementation.
Would you like me to add any other specific test cases or make any adjustments to the existing ones?
Tokens: 4.5k sent, 537 received. Cost: $0.00078 message, $0.0019 session.
test_car.py
Create new file? (Y)es/(N)o [Yes]: yes
Applied edit to test_car.py
Commit 7d263c0 test: add pytest unit tests for Car class
pytest test_car.py -v
Run shell command? (Y)es/(N)o/(D)on't ask again [Yes]: yes
Running pytest test_car.py -v
zsh:1: command not found: pytest
Add command output to the chat? (Y)es/(N)o/(D)on't ask again [Yes]: yes
Added 2 lines of output to the chat.
Since we are in '/ask' mode, Aider gives us a suggestion of how it would solve the problem. After I agreed, the TestCar class, including the file and commit, is created. We also get the suggestion to run the shell command, which raised a “command not found” error. Even if the workflow is stuck at this point, we have the possibility to intervene and call a new command directly from Aider with the '/run' command:
/run python3 -m pytest test_car.py -v
This command also gives us an error, but Aider now directly suggests to fix the problem. If we hit ENTER, we get a new step list to solve the problem.
──────────────────────────────────────────────────────────────────────────────────────────
car.py test_car.py
ask> /run python3 -m pytest test_car.py -v
/Library/Frameworks/Python.framework/Versions/3.11/bin/python3: No module named pytest
Add 0.0k tokens of command output to the chat? (Y)es/(N)o [Yes]: yes
Added 1 line of output to the chat.
──────────────────────────────────────────────────────────────────────────────────────────
car.py test_car.py
ask> What's wrong? Fix
The error indicates that pytest isn't installed in your Python environment. Let's fix this:
1 First, install pytest using pip:
python3 -m pip install pytest
2 Then run the tests again:
python3 -m pytest test_car.py -v
If you're using a virtual environment (recommended), make sure to:
1 Create and activate the virtual environment first:
python3 -m venv venv
source venv/bin/activate # On Linux/Mac
# OR
venv\Scripts\activate # On Windows
2 Then install pytest and run the tests as shown above.
The tests should now run and show output like:
============================= test session starts ==============================
platform linux -- Python 3.x.y, pytest-x.y.z, py-x.y.z, pluggy-x.y.z
rootdir: /your/project/path
collected 6 items
test_car.py::TestCar::test_initialization PASSED [ 16%]
test_car.py::TestCar::test_default_charge PASSED [ 33%]
test_car.py::TestCar::test_set_valid_charge PASSED [ 50%]
test_car.py::TestCar::test_set_invalid_charge[-1] PASSED [ 66%]
test_car.py::TestCar::test_set_invalid_charge[101] PASSED [ 83%]
test_car.py::TestCar::test_edge_case_charges PASSED [100%]
============================== 6 passed in 0.02s ===============================
If you still get errors after installing pytest, try:
python3 -m pip install --upgrade pip
python3 -m pip install pytest
Let me know if you encounter any other issues!
Tokens: 3.5k sent, 379 received. Cost: $0.00060 message, $0.0025 session.
I now only ask it to go ahead with all steps and add a note to use the calls for my Apple operating system.
──────────────────────────────────────────────────────────────────────────────────────────
car.py test_car.py
ask> /code go ahead with all the steps. Note that I am using a mac.
Here are the complete steps for your macOS system:
1 First, let's ensure pip is up to date and install pytest:
python3 -m pip install --upgrade pip
python3 -m pip install pytest
2 (Recommended) Create and activate a virtual environment:
python3 -m venv venv
source venv/bin/activate
3 Now install pytest in the virtual environment:
pip install pytest
4 Finally, run the tests with verbose output:
python3 -m pytest test_car.py -v
If you get any permission errors during installation, you might need to use:
python3 -m pip install --user pytest
The expected output should show all 6 tests passing with detailed information about each test case. The virtual environment helps keep your project
dependencies isolated from your system Python.
Let me know if you encounter any issues with these steps!
Tokens: 6.2k sent, 202 received. Cost: $0.00092 message, $0.0034 session.
python3 -m pip install --upgrade pip
python3 -m pip install pytest
Run shell commands? (Y)es/(N)o/(S)kip all/(D)on't ask again [Yes]: yes
Running python3 -m pip install --upgrade pip
Requirement already satisfied: pip in /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages (22.3)
Collecting pip
Downloading pip-25.1.1-py3-none-any.whl (1.8 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.8/1.8 MB 6.5 MB/s eta 0:00:00
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 22.3
Uninstalling pip-22.3:
Successfully uninstalled pip-22.3
Successfully installed pip-25.1.1
Running python3 -m pip install pytest
Collecting pytest
Downloading pytest-8.4.1-py3-none-any.whl.metadata (7.7 kB)
Collecting iniconfig>=1 (from pytest)
Downloading iniconfig-2.1.0-py3-none-any.whl.metadata (2.7 kB)
Requirement already satisfied: packaging>=20 in /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages (from pytest) (25.0)
Collecting pluggy<2,>=1.5 (from pytest)
Downloading pluggy-1.6.0-py3-none-any.whl.metadata (4.8 kB)
Requirement already satisfied: pygments>=2.7.2 in /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages (from pytest) (2.19.2)
Downloading pytest-8.4.1-py3-none-any.whl (365 kB)
Downloading pluggy-1.6.0-py3-none-any.whl (20 kB)
Downloading iniconfig-2.1.0-py3-none-any.whl (6.0 kB)
Installing collected packages: pluggy, iniconfig, pytest
Successfully installed iniconfig-2.1.0 pluggy-1.6.0 pytest-8.4.1
Add command output to the chat? (Y)es/(N)o/(D)on't ask again [Yes]: yes
Added 38 lines of output to the chat.
python3 -m venv venv
source venv/bin/activate
Run shell commands? (Y)es/(N)o/(S)kip all/(D)on't ask again [Yes]: yes
Running python3 -m venv venv
Running source venv/bin/activate
pip install pytest
Run shell command? (Y)es/(N)o/(S)kip all/(D)on't ask again [Yes]: yes
Running pip install pytest
Requirement already satisfied: pytest in /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages (8.4.1)
Requirement already satisfied: iniconfig>=1 in /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages (from pytest) (2.1.0)
Requirement already satisfied: packaging>=20 in /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages (from pytest) (25.0)
Requirement already satisfied: pluggy<2,>=1.5 in /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages (from pytest) (1.6.0)
Requirement already satisfied: pygments>=2.7.2 in /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages (from pytest) (2.19.2)
Add command output to the chat? (Y)es/(N)o/(D)on't ask again [Yes]: yes
Added 6 lines of output to the chat.
python3 -m pytest test_car.py -v
Run shell command? (Y)es/(N)o/(S)kip all/(D)on't ask again [Yes]: yes
Running python3 -m pytest test_car.py -v
============================= test session starts ==============================
platform darwin -- Python 3.11.0, pytest-8.4.1, pluggy-1.6.0 -- /Library/Frameworks/Python.framework/Versions/3.11/bin/python3
cachedir: .pytest_cache
rootdir: /Users/philipp/aider
plugins: anyio-4.9.0
collected 9 items
test_car.py::TestCar::test_initialization PASSED [ 11%]
test_car.py::TestCar::test_default_charge PASSED [ 22%]
test_car.py::TestCar::test_set_valid_charge PASSED [ 33%]
test_car.py::TestCar::test_set_invalid_charge[-1] PASSED [ 44%]
test_car.py::TestCar::test_set_invalid_charge[101] PASSED [ 55%]
test_car.py::TestCar::test_set_invalid_charge[150] PASSED [ 66%]
test_car.py::TestCar::test_set_invalid_charge[-0.1] PASSED [ 77%]
test_car.py::TestCar::test_edge_case_charges PASSED [ 88%]
test_car.py::TestCar::test_color_and_brand_immutability PASSED [100%]
============================== 9 passed in 0.02s ===============================
Add command output to the chat? (Y)es/(N)o/(D)on't ask again [Yes]: yes
Added 20 lines of output to the chat.
Aider has executed all commands and successfully passed all tests. As you have noticed, we need to manually approve all the steps. This is a default behavior in Aider and can be changed by adding the parameter '--yes-always'.
After the second prompt, we can have a look at our git history and see two commits done by our tool:
7d263c0 - Philipp Knoechel: test: add pytest unit tests for Car class
21dfc1e - Philipp Knoechel: feat: implement Car class with getters and charge management
If we notice the LLM has done something unexpected, the latest step can be easily undone with '/undo'.
Summary
I had the chance to evaluate Aider in the last months extensively in a work project where I couI had the chance to evaluate Aider extensively in a work project over the last few months, where I coded a Go-based REST API service from scratch. During that time, I used Aider a lot and had the chance to compare it to GitHub CoPilot. Here are my key takeaways from working with Aider:
- Its tracking of all changes with a deep git integration is a top feature.
- Having fast and specific manageable context not only gives you transparency; it also enhances the quality of your output.
- For complex features/subtasks, it is a good practice to ask the LLM in
'/ask'mode for its implementation and refine its ideas with your own improvements. After you are satisfied, let the LLM implement the feature step by step. Keep the changes and iterations small. - Let Aider implement tests for every feature and execute the tests before a single commit is added by Aider. This can be added via the
'--auto-test'parameter or done by yourself.
I hope my first blog post was not too long and you can get some inspiration for the first use of Aider. Feel free to leave a comment or a personal mail if you have questions.

Leave a Reply