The first time I rebuilt my editor from scratch, I told myself it was an investment.
The second time, I had a reason. A plugin had changed an API and my config broke the morning of a demo. I fixed it in a panic, then spent the weekend rewriting the whole thing properly, because a configuration you cannot explain is one you do not own.
By the third time I could type the setup from memory: plugin manager, leader key, the twenty keymaps I used daily and the hundred I had copied from someone else’s dotfiles and never pressed. I was fast. I was also reading more plugin changelogs than other people’s code.
That was the year I learned the wrong lesson. I thought I was good at my editor. I was good at rebuilding it.
Five eras later I can say the thing I could not say then: the editor was never the point.
Five eras, one direction
| Era | The editor did | What I optimised | What broke |
|---|---|---|---|
| IDE (GoLand, VS Code) | compile, debug, refactor, navigate | which IDE had the better debugger | the editor was the whole environment |
| Dotfiles (neovim, zsh, vim) | whatever I configured | keystrokes per minute | every plugin update was a small project |
| Language servers | completion, diagnostics, navigation | nothing, which was the point | my config stopped being a differentiator |
| AI editor | completion at keystroke speed | accepting suggestions | still one person, one cursor |
| Agents | the task, across files | the harness, the checks, the review | believing “done” |
The direction is consistent. Intelligence moved out of the editor and into services, then out of the keystroke and into the task. Each step made the editor less interesting and the repository more so.
The configuration trap
The neovim years were not wasted. I learned how my tools work, and that knowledge still pays when something misbehaves at an inconvenient moment.
But the return was thin. The recurring cost was real: a plugin ecosystem that moves, a shell config that breaks after an upgrade, an afternoon lost to a colour scheme that looked wrong under a different terminal. And the payoff was speed in a job whose bottleneck turned out to be decisions, not keystrokes.
The language server moved the intelligence out
The Language Server Protocol is the quiet turning point [2]. The editor became a client. Completion, diagnostics, go-to-definition and rename stopped being features of one program and became services any program could consume.
The practical effect was that switching editors stopped being a rewrite. The intelligence stayed the same while the window changed. My carefully tuned configuration had been a moat around a castle that moved somewhere else.
That is also when I stopped recommending editors to people. The useful recommendation became the language server and a working setup for it, because that is what actually follows you.
Autocomplete got good, and the unit changed
The AI editor era was a genuine improvement. Suggestion quality crossed a line where accepting a completion was usually faster than typing it, and the editor got a sense of the file’s shape rather than the current line.
It was still one person and one cursor. The work was measured in keystrokes, which meant the ceiling was my typing speed and my attention span.
Then the unit of work changed from the keystroke to the task. An agent can read an unfamiliar corner of a repository, make a change across several files, run the checks, and come back with a diff. That is not autocomplete with a bigger context window. It is a different loop.
The difference is easiest to see in what I do all day. It is also the shift other engineers report from the same fifteen months, from one companion beside the work to several supervised tasks [1]. I read more diffs than I write lines. I spend more time deciding what should be true than making it true. My editor is where I read and where I fix the last mile, not where the work happens.
The interface became a sentence
Ten years ago the interface was a cursor. I typed the text, copied a stack trace into a chat window, pasted the answer back, and corrected whatever survived the trip. The editor was a clipboard with syntax highlighting.
Now the interface is a sentence. “Find out why this endpoint returns a 500 on Thursdays” is a complete instruction. The agent chooses its tools, and the wiring that used to cost an afternoon is part of the work it does: an MCP server gets configured, a token gets checked, a tool gets called, and the agent finds out whether it works by using it rather than by asking me to restart something.
That is the part people underestimate. Connecting a service used to be JSON, environment variables, a restart, and a silent failure nobody noticed for a week. Now the setup is a conversation, and the proof is that the tool answered a question.
The work itself turned forensic. A bug is rarely a line. It is a sequence: a config that changed three weeks ago, a retry that hid the failure, a log line that only appears under load. An agent can hold that timeline, line up the deploys, the issues, the commits and the metrics, and come back with the sequence instead of the symptom. It reads like a detective’s notebook, and that is closer to what debugging always was than the find-the-typo version we like to describe.
The caveat is the same as everywhere else in this post. It can also invent a timeline with complete confidence. The method still needs evidence: timestamps, hashes, a reproduction. The detective is fast. The case still has to be proven.
What the agent era rewards
Here is the part that surprised me. The conventions I had written down for humans turned out to be exactly what makes an agent useful, and where they were missing, the agent was useless in a very confident way.
These are the ones that survived, in the order they earn their keep.
One rules file, short, with a long document behind it. Agents read the short one every time, which means it has to be small enough to read and precise enough to act on. The long document holds the reasoning. Duplicating rules between the two is how they drift apart, so the short one points and the long one explains.
Verification by artifact, not by claim. A build that exits, a page that loads, a test that fails before the fix and passes after. A sentence saying the work is done is not evidence. The most expensive mistake of my year was a status code read through a pipe, which reported success for a command that had failed.
Small, reversible changes. An agent can produce a large diff quickly, and a large diff is a large review. The change that is easy to judge is the change that is easy to revert.
Fresh eyes, enforced. The context that wrote something cannot judge it. Reviews run from a clean context that sees the artifact and its sources but not the conversation that produced them [3], and reviewers report rather than edit.
Claims carry confidence and limits. Every factual claim gets a source and a ceiling. When a measurement cannot be repeated, the claim drops to “observed once” rather than disappearing. This is the difference between a record and a boast.
Instrument before guessing. When something does not work, the fastest path is usually a log line at the boundary that is suspect, not a fifth hypothesis. I have watched a day of payload guessing end in one instrumented request that named the answer.
Boring tools, and fewer of them. The best service in our house is a 33 KB launcher that starts in 615 ms, written because the stock one started in 1.7 seconds and carried 100 MB of things nobody asked for. That is not a story about AI. It is the same instinct as deleting a dotfile: if it does not change a decision, it is weight.
Review moved, it did not disappear
Ten years ago a review was where I re-read every line, because I had typed most of them. Now I review changes I did not type, and the job is different.
For a small diff I still read all of it. For a large one, reading every line is the wrong use of an hour, and pretending otherwise is how a review becomes a rubber stamp. What I do instead:
- Start from the claim. What does the pull request say it changes, and what would be true if it worked?
- Read the files that carry risk first: schema and migrations, authentication and permissions, error paths, anything that deletes.
- Follow the flow end to end rather than the syntax. Does the change fit the shape of the system, and does it follow the convention the repository already states?
- Eyeball the places where a machine is weak: a name that reveals intent, a comment that explains why, a test that would have caught the bug.
The mechanical half moved to gates. Build, tests, lint, secret and policy scans run on every change and must pass; a failure is not a discussion.
The judgment half moved to lenses. Instead of one reviewer with one prompt, several adversarial reviewers examine the same change with different purposes: security, correctness and edge cases, conventions and consistency, performance and cost, and one whose only question is whether the change belongs at all. A synthesizer deduplicates what they find, and the loop stops when findings stop changing rather than when they reach zero.
What this does not fix: reviewers built from the same model share blind spots, and a reviewer that never disagrees is not adding much. The lenses help, the human decision at the end is what makes the review real, and I still eyeball the parts where being wrong is expensive.
What did not change
The parts that survived every era are the ones with no tool in them.
Reading the parts of the source that decide the outcome. Understanding the failure instead of the error message. Writing the test that proves the bug was real. Writing a commit message someone can read in six months. Owning what ships.
The harness improved the speed at which those things can happen. It did not change the standard, and where I skipped them, the speed only produced mistakes faster.
What I got wrong
Three things, in escalating order of cost.
I treated the editor as the moat. It was a moat around territory that kept moving.
I optimised keystrokes when the bottleneck was decisions. The dotfiles were a proxy for progress that was easy to measure and hard to matter.
I believed “done” because the sentence was well formed. The fix was not scepticism for its own sake, it was making done mean something checkable: a build, a diff, a test, a measurement that repeats.
Where this leaves the editor
I still open one most days. It is where I read unfamiliar code, chase a stack trace, and make the small corrections that are not worth a task. The completion is good and I am glad it exists.
It is no longer where the work happens, and it never really was. What moved the work forward in every era was the same: a standard that a change can be checked against, by me or by something I delegate to. The dotfiles were fun. The standard is the thing that shipped.
References
[1] My AI Engineering Setup, 15 Months Later: the parallel-agent workflow and the pressure it puts on review, which set the frame for this post.
[2] Language Server Protocol specification: the protocol that moved completion, diagnostics and navigation out of the editor and into services.
[3] elephant-goldfish-model: the fresh-context review protocol the workspace borrowed from, including the convergence stop condition and the rule that reviewers are read-only.