These days most of the code in my side projects is written by Claude Code. I describe what I want, it writes, I review. My job moved from writing code to reviewing it.
And reviewing in a terminal is bad. You get a wall of diff, scroll up, scroll down, and then type something like "in server.ts, around line 40, the host should be configurable" into the chat. It works, but it's nothing like a real code review. So I built a small tool for it. It's called Feedbacker, and it gives the agent a merge request page it can open for me.
In this post, I'll walk you through:
- what Feedbacker does
- how the agent asks for a review
- what I changed after the first real reviews
- the decisions and gotchas along the way
The itch
A few years ago I wrote about how to be good at code reviews. Most of it still holds when the author is an AI. What doesn't hold is the tooling. GitHub and GitLab are great for reviewing, but I don't want to push every half-done change to a branch and open an MR just to tell the agent it named something wrong.
Two more things made it worse for me:
- Several repos at once. One task often touches more than one repo, and I want to see the whole change together.
- Git worktrees. I sometimes run more than one agent in parallel, each in its own worktree. Reviewing that in a terminal is no fun at all.
What I wanted: the agent finishes, opens a page in my browser with the diffs of everything it changed, I comment on lines like in an MR, click a button, and my comments go back to the agent.
What it does
-
All repos on one page. The agent passes a list of repo paths, anywhere on disk, each with its own base. With
--worktreesit pulls in every worktree of a repo, labelled with its branch. - Line comments. Click a line number to comment, shift-click to cover a range. A comment is either Comment (change something) or Ask (a question the agent has to answer).
- Approve or Request changes. That sends everything back to the agent and closes the page.
- Where to look. The agent writes a short summary and points me to the places it thinks matter most.
- Sorted by kind. Code first, then tests, config, docs and generated files (lock files, build output). Only code starts expanded.
-
Local only. It runs on
127.0.0.1with a random token in the URL, only reads git, and nothing leaves my machine.
How the agent asks
The easiest way is the Claude Code plugin:
claude plugin marketplace add PavlikPolivka/feedbacker
claude plugin install feedbacker@feedbacker
Then I just say "let me review it". The plugin gives Claude an MCP tool, request_review, and a skill that tells it when to use it. The tool call blocks until I submit, and the result is markdown the agent can act on:
# Review feedback
Verdict: **changes requested**
## Comments
### /home/me/Projects/api
**src/server.ts:6** (new side)
```diff
+ server.listen(port, "127.0.0.1");
```
Make the host configurable too.
Every comment carries the code it refers to. If the lines move, the agent still knows what I meant.
It also works without Claude Code. Any agent that speaks MCP can run it with npx -y agent-feedbacker mcp, and anything with a shell can use the CLI:
feedbacker ~/Projects/api ~/Projects/web@main -m "Bind the API to localhost"
It blocks, and when I submit it prints the feedback and exits.
Feedback on the feedback tool
The first real review was Feedbacker reviewing itself. I had the agent rewrite the review page in React in a separate worktree, and then I reviewed that change in the old page. It worked, which was a nice moment.
Then I used it for a few more changes and wrote down what annoyed me:
- The agent's questions felt random. I had made it possible for the agent to ask me questions. In practice it asked things just to ask something. What I actually wanted was the other way around: to ask it about a line. That's where Ask came from. The agent can still ask, but only about a decision it can't make alone.
- The summary was unreadable. The agent wrote a long paragraph and the page showed it as one huge heading. Now it's short markdown: one lead sentence and a list.
-
I don't want to review everything. Lock files,
CLAUDE.md, build output. Now files are grouped by kind and the boring ones are collapsed. Tests are detected by path in most languages (*.spec.ts,*_test.go,test_*.py,FooTest.java). - Tell me where to look. A good MR description points the reviewer at the tricky parts. The agent should do the same, so now it can.
Funny thing. Most of this is the same advice I'd give a human developer opening an MR. Write a short description, point at what matters, don't make the reviewer read generated files.
Decisions
- No runtime dependencies. Plain Node with a hand-written minimal MCP server (it's just JSON-RPC over stdio) instead of the SDK. The page is a small React app, but the bundle is committed, so using it needs no install or build.
- Own diff table. I wanted to use diff2html, but it has no inline comments. The table is small and makes anchoring comments easy. Syntax highlighting is highlight.js.
- One blocking tool call. I expected timeouts and planned two tools, one to start a review and one to wait for it. Claude Code kept the call open for over three minutes without complaining, so one tool it is.
Gotchas
The agent commits along the way. Then "diff against HEAD" is empty and the review shows nothing. The plugin now uses hooks to record where each repo stood when the session first touched it, and the review shows exactly what changed in this session. Uncommitted work is snapshotted with git stash create, which touches neither your working tree nor your stash list.
You can't see the URL. Claude Code doesn't show an MCP server's output, so if the browser doesn't open, the link is lost. feedbacker list prints the reviews waiting for you.
The name was taken. feedbacker on npm belongs to someone else. The package is agent-feedbacker, the command is still feedbacker.
CI hung forever. The end-to-end test runs the page in headless Chrome, and Chrome's sandbox doesn't start on GitHub's Ubuntu 24.04 runners. It didn't fail, it just hung.
Other tools
I'm not the first one with this idea. When I looked, there were already several: Plannotator, difit, claude-diff-review and more. Plannotator is the closest. It can even review several repos, if they all sit under one parent folder.
I looked at them, but they felt too complex for what I wanted. And I wanted any repos from anywhere and parallel worktrees side by side in one review. So I built my own small one. If one of those fits you better, use it. The idea matters more than the tool.
Is it worth it?
For me, yes. It's still early and the roadmap is long (replies to comments, showing only what changed since the last round), but reviewing in a browser is so much nicer than typing line numbers into a chat. And the agent gets better feedback, because I actually read the diff.
The code is on GitHub and the package is agent-feedbacker on npm.
How do you review what your agent writes? Drop a comment, I'm curious.

Top comments (8)
The 'Ask' inversion is the sharpest bit here — most review tooling assumes the human asks and the agent answers, but with agent-written code the human is the one who needs to interrogate a line. Sorting by kind with lock files collapsed is the kind of small mercy that decides whether a review tool gets used daily. Do you find the agent actually uses the 'where to look' summary well, or does it point at the safest files instead of the riskiest ones?
Per-change not per-batch is the big one for me. Once 4 agent PRs pile up you basically start approving on vibes. What helped me most was reviewing the plan before any code exists, so the diff later is mostly checking it did what we agreed on. (I'm building something in this space, Coppice, so I'm biased toward plan-first.)
Line comments on a page instead of typing "server.ts, around line 40" into the chat is a real improvement. Seeing changes across several repos and worktrees in one place is the part GitHub cannot give you without pushing half-done branches. Does the agent get the comments back as one batch when you click the button, or one at a time so it can answer each?
I batch all judgement into one weekend slot. During the week the agent executes and logs; on Sunday I read the log once and decide everything at once. Splitting execution and judgement by weekday is the only reason this fits next to a full-time job.
The merge request shape is the right one, especially across worktrees. I still open the test files first, before the summary of where to look, because that is usually where an agent asserts the behaviour it just invented.
What worked for me is reviewing the agent's work in small pieces, not at the end of a long session. I ask for one change at a time, read it, and only then let it continue. When something is off, I say what I expected in one sentence instead of re-explaining everything, and the next attempt usually lands much closer.
The "where to look" list has the same blind spot as the code it describes: the agent points at what it thought was tricky, so a file it changed without thinking twice is the one it will not mention. A cheap counterweight is a second list that the tool computes rather than the agent writes, the changed files the summary does not name, shown above the agent's picks. That also answers the question above about whether it points at the safest files, because the gap between the two lists is visible on every review.
The empty-diff-after-the-agent-commits problem has a cheap fix if the agent works on its own branch: run it in a worktree on a branch of its own, and "what changed" is that branch against where it started, however many commits it made. Your hook plus git stash create snapshot covers what that can't, which is an agent working directly in your checkout.
For "show only what changed since the last round" on your roadmap, recording the commit each round started from would give you the same thing.