From scalpels to self-driving cars
Last time we looked into aider, a precise and powerful tool for writing code.
Unlike Cursor, Cline, and others, Aider has a tight, pre-scripted control loop, which includes you – the human operator.
In a way, Aider is like a scalpel – a sharp tool, excellent for precise cuts.
If you know exactly what you need to do, this magic scalpel can do it much faster than you could do it yourself.
Contrast this with agentic coding environments like Cursor.
They don’t have a pre-scripted top-level loop.
Instead, the model decides on the fly, what it should do next.
You still need a rough idea of where you want to go.
But the “how” is taken care of by the agent.
Like a self-driving a car – you give it the destination and then supervise the process of actually reaching the destination.
Drawing a map
Using agentic coding tools daily now, here is what works best in my experience.
Define the “what”
First, you define the “what” by creating a specification of the desired outcome.
You don’t need to write this yourself.
Use an agent to iterate on a Markdown file until the outcome is crystal clear.
In this phase, you want to:
seed conversations with all relevant context,
get the agent to ask you questions about the design,
and end up with a very detailed spec.
Example: a large scale refactoring
Here is an example from Petrock, a web framework I’m writing at the moment.
Define the how
Once you are done with the spec, it’s time to turn it into a series of concrete steps.
Again, this will take multiple iterations, so tell your agent to work with you on the plan Markdown file.
We’re still not writing code.
You should seed the context with the specification from earlier and relevant bits about code that the specification touches upon.
Use your agent to help you here.
What makes a plan good
A good plan has:
clear identifiers for tasks,
a definition of done for each task,
references to relevant parts of the code for each task,
and examples of patterns you want to see respected.
If you include all of this information, the agent will be able to work through the plan step by step with little oversight.
Here’s the plan for implementing the specification above:
Taking off
With everything in place, you can finally take off.
Here’s the prompt I use to start the agent:
Implement the plan, task by task:
1. pick the next unfinished task
2. implement it
3. mark the task as DONE in the plan file
4. commit the changes, including the plan file.
5. Ask the user whether you should continue
Only implement one task at a time.
This is essentially the same loop that Aider is using, except that we don’t have to hardcode it, but just need to tell the agent.
At this point it’s almost becoming like a video game:
the agent implements a change,
you check quickly whether it’s deviating from the plan (usually it’s not)
you say “continue”
And then you keep turning the crank until you reach the end of the plan.
Orienting yourself
Naturally, the first question is “but what about reviewing the code?”.
Yes, reviewing the code is important.
But more important are the general direction and approach you are taking when making a large-scale change.
By now you will have reached a destination:
the plan is executed,
you have a documented history of all changes in git
This is a good time to reorient yourself: is this the place you want to be in?
If it’s not, you have two choices:
make small adjustments (your almost where you need to be),
or go through the spec-plan-execute process again for larger changes.
In any case, a little bit of planning allows you to go much faster.
Concrete examples
You can find the entire conversation for implementing the refactoring here.
After the agent was done, I had a lot of compilation errors left, which got fixed here.
The agent was working through this refactoring in 45 minutes while I was writing this blog post.