Reviewing AI code changes in VS Code with DejaReview

October 19, 2026 10 min read
Tools AI VS Code

These days a big part of my work is reviewing code written by AI agents, and they are very willing to produce huge changes. Several hundreds of changed files is nothing unusual, and without a well established review routine this can easily bring stress and even depression. It is very tempting to just "accept it all".

So I tried to bring some discipline into it. Code that I reviewed and found acceptable I stage with git, so staging means "accepted". For code I didn't like I wanted an easy way to leave notes for the agent and keep track of them. Without that I kept reviewing the same files again and again, with a strong feeling of déjà vu, not sure if I had already written a note about it or not.

So I wrote a small VS Code extension and called it DejaReview. The idea is not super original, and a colleague of mine already had his own take on it, but this one does exactly what I want. And I did not write a single line of it by hand: all code was generated by AI agents, I only gave them instructions.

TL;DR

  • DejaReview lets me stage what is good, leave notes right in the code and diffs for the rest, and copy all notes with their context to the agent in one click.
  • All code was written by AI agents in OpenCode, and from the second day I was reviewing the extension with itself.
  • AI agents can build exactly what you want and cover it with tests without being asked. But you only find out what you want when you use it.
  • The first versions seemed to work fine, but they were full of performance problems wasting time and CPU, and at one point the tests even ate 10 GB of memory. Then a big review made everything too complex. Simplification had to be asked for explicitly.
  • For critical code careful human review is still important, and making it easier is worth it.

How it works

The loop is simple: review the changes, stage what is good, leave notes for the rest, copy the notes to the agent, repeat.

To add a note, I select some lines in a file or in a diff and press Cmd+Alt+M, or click the + in the gutter. It works on both sides of a comparison, so deleted code can be commented too. All notes are shown as cards in the "Review Notes" panel, and there are also general notes which are not attached to any code.

The "Files to Review" list shows changed files which are not staged yet and have no notes, with buttons to revert a file, add a note to the whole file, or stage it. After staging the first file the next one opens automatically, so a big change is just read and "Stage", read and "Stage".

The "Copy Review Notes & Clear" button puts all notes into the clipboard as Markdown, with file paths, lines and code snippets. Here is a real example:

Please address these review notes and summarize your changes here. Leave staging to me.

## `.vscodeignore`:5-8 (Modified: Working tree vs HEAD)

```
out/test/**
out/**/*.map
out/src/dashboardClient.js
out/src/dashboardClientEntry.js
```

💬 it looks like whole 'out' dir should be ignored, correct?

The header also says which side of which comparison the snippet comes from, because the same file can look different in HEAD, in the staging area and in the working tree. By the way, the agent answered "No" to this note, because the extension runs from out/src. Good that it did not just agree with me.

Notes work for documents too. Once the agent ended its analysis with a table of questions for me, and I simply answered them with notes on the table rows:

## `docs/simplification.md`:27 (Working tree)

```
| Q3 | Is the gutter `+` needed, or is the shortcut/context menu enough? | Command-only capture (B6) | Part of D2 and D3 |
```

💬 yes, gutter is needed, its  very handy to add notes in VSCode

## `docs/simplification.md`:29 (Working tree)

```
| Q5 | Which Files to Review extras matter: `+N -M` counts, Revert, auto-advance, exit animation? | Drop or simplify each (B1–B4) | D6, D7 |
```

💬 this is all needed

If I forget to paste the notes, the last copied batch can be restored. Everything stays on my machine: the extension does not call any AI and has no runtime dependencies.

How it was built

The extension was built in OpenCode during about six weeks, but in spurts: a few intensive days, then weeks of nothing.

gantt
  dateFormat YYYY-MM-DD
  axisFormat %b %d
  todayMarker off
  section First version
    Spec and first build : 2026-09-07, 1d
  section Features
    Dogfooding, note format, panel : 2026-09-08, 1d
    Files to Review, Stage, Revert : 2026-09-08, 3d
    Whole-file notes, next file : 2026-09-15, 1d
  section Quality
    Review and refactor everything : 2026-09-08, 2d
    Performance on big changes : 2026-09-11, 1d
    Performance on big changes : 2026-09-16, 1d
    Code style, Preact : 2026-09-17, 2d
  section Simplification
    Complexity analysis : 2026-10-10, 1d
    Central storage : 2026-10-14, 1d
    Final review and merge : 2026-10-19, 1d

Most of the code was written by GPT-6 Astra. Later I also used Claude Opus 5, Claude Opus 5.5 and GPT-6.1 Sol, sometimes just to get a fresh review.

I started with a brief specification and the repository of my colleague's approach, which was a web UI for the whole review, outside of VS Code. In about 15 minutes the agent made a plan for a VS Code extension, and less than an hour after my "OK, seems good to me, go and implement it" I had a working extension with unit tests and integration tests.

Reviewing it with itself

From the second day almost every prompt was a review pass copied from the extension itself. This turned out to be the best part of the project, because every inconvenience I noticed immediately became the next note.

For example, the first note header looked like this:

## File: `src/dashboardHtml.ts`; Lines: 82-85; Origin: changed; Side: document

After a few rounds of "can it all be simplified", it became just:

## `src/git.ts`:275 (Modified: Working tree vs Staging area)

The instruction at the top of the clipboard went the same way, from a paragraph of 88 words to "Please address these review notes and summarize your changes here. Leave staging to me."

Requirements change when you use it

The original specification said "no revert actions" and "no unreviewed counters". Both came back, because in real use I wanted them. Notes were first kept in a Markdown file in the project root, the main idea of the whole design. Later it turned out to be annoying to see this file in the project, so notes moved to a central storage, separate for each checkout folder. Some bugs only appeared in real work, for example a file like pages/[versionId]/page.ts could not be staged, because square brackets have a special meaning for git.

Also, agents follow the rules in AGENTS.md very literally, even the rules they wrote themselves. When I asked for a "Stage" button, the agent refused, because its rules said git access must be read-only. I had to tell it to "alter the rules".

Too simple, then too complex

The first implementations seemed to work fine, but they were full of performance problems. Staging one file in a list of 65 took about a second, because the extension re-checked all other files one by one. After the next fix all files blinked "loading..." three times after each stage, and my next prompt started with "WHY??". Much later a review found that every keystroke in any open file rebuilt everything and started new git show processes. Each problem was fixed quickly, but only after I noticed it.

Then it went to the other extreme. After I asked to review everything against common pitfalls and refactor it all, the agent found real bugs, but also started to handle every possible race: what if the folder changes while copying to the clipboard, what if two windows write at the same time. In one commit, together with some new features, the source grew from about 2,100 to 5,500 lines, and tests from 2,000 to almost 11,000.

At some point I felt a bit lost in my own project. I wrote that "this whole thing is just notes taking to support agent in the loop development", and asked for a ground up analysis of the problems. The agent wrote six design documents and found that most complexity came from eight early decisions. The code could shrink from about 6,600 to 2,500 lines, but only by dropping features I wanted. So I kept the features and dropped the biggest source of complexity, the notes file in the project. The code size did not change much, but now the reason for every part is written down.

Code style

I also did not like the code style: dense one-line conditions, nested ternaries, long validation blocks. So I added a code style guide to AGENTS.md and asked to refactor everything. The agent reported it was done, but when I asked "so what about code quality in terms of readability", the answer was "Readability improved, but the repository is not yet consistently at the standard we defined". One more round followed.

The panel UI was written with plain DOM calls, and I felt that "some small scale UI rendering library might help a lot". So it was rewritten with Preact, bundled with esbuild, still with zero runtime dependencies.

This gave the most interesting bug of the project: the tests ran out of memory. The agent tried several theories about memory leaks, and all of them were wrong. The real cause was one assert.deepEqual on two lists of DOM attributes. In a real DOM every attribute links back to the document and the window, so Node walked the whole object graph and used 10 GB of memory. After the fix, that test file went from almost 3 minutes to less than half a second.

At the end there are 672 unit tests and 23 integration tests in a real VS Code, and the test code is two times bigger than the source. Still, how the UI looks and feels was checked only by me.

Lessons learned

  1. AI agents can build exactly what you want, but you only find out what you want when you use it. Using the tool to build itself was the fastest way.
  2. Tests come almost for free. I never asked for them, but every change came with them.
  3. A review of everything finds real bugs, but also brings a lot of defensive code. What helped me was not "simplify it", but asking to document the root causes of the complexity and then deciding myself what to keep.
  4. AGENTS.md needs the same attention as the code, because agents follow it literally.
  5. Summaries can be too optimistic. A simple "so what is actually done?" is worth asking.

Human in the loop

There are quite different views now on how much a human should look at AI generated code at all. For many tasks it is fine to let an agent work on its own. But for critical code, especially legacy code and important production places, I still think it is important to review and stage every file myself. Staging is my approval, and the agent never stages anything.

And if this manual step is important, then making it easier is worth it. It is a very nice bit of life quality improvement, and this is exactly what makes me feel better every time I use the extension at work.

The extension is not published to the marketplace yet, but it can be built from source and installed in VS Code. In case you are interested, source code is available on Github.

P.S. This article was also generated by AI. I used basic prompts to reconstruct the events from my session history and git log, and to highlight the most interesting things, and my main points were the basis for it. And of course I reviewed it with DejaReview.