One screen, one question.
What the change is for, what it actually does, and the gap between the two. Then the route. Then, before a single line of code: does this make sense, done this way?
margin-tuimargin-guiCode review, annotated.margin opens any git change in your terminal or a desktop window with a coding agent beside you. It plans the route, writes a note beside every change, answers questions on the line, and tells you when you are done.
margin-tuimargin-gui
There are plenty of places to look at a diff. margin is the one that makes sure you actually read it, and can tell you when you are done. Here is what people say before they try it.
GitHub already has code review.it has a comment box.
A pull request page lists files alphabetically and lets you approve without opening half of them. margin plans the route, and exports the review to GitHub when you are done.
My agent can just review it for me.and here it does — in the margin.
The agent writes a note beside every change and answers on the line. You make the call. It never approves anything, and blind mode lets you read first.
I'll just read the diff.for the first 400 lines, maybe.
margin cuts the change into a few stops, keeps the import churn for the end, counts what you read and tells you when it is time for a break.
The tests pass. Ship it.do they test this line?
Per-line coverage shows what no test runs. Then break the line yourself, in place, with vim keys, and watch which tests notice.
Another AI thing touching my code.read-only. honestly.
margin runs nothing from the repository and changes nothing, unless you try a change yourself. That one is put back the moment its tests end.
I live in the terminal. / I don't.both. same review.
margin-tui runs beside your agent in tmux; margin-gui is a desktop window with the agent inside. Start in one, finish in the other.
| A pull request page | “Review this” to an agent | margin | |
|---|---|---|---|
| A reading order, with reasons | alphabetical | if you ask | stops, risky first |
| A note beside every change | none | one long reply | on the line |
| Ask about a line, get the answer there | comment, then wait | a new chat | a, answer in place |
| Which tests run this line | no | no | in the gutter |
| Break a line, see if a test notices | no | no | i, edit, :w |
| Knows what you have not read | viewed checkboxes | no | the recap lists it |
| You make the call | yes | it does | yes, with a recommendation |
| Before you push, offline | no | yes | any branch, commit or worktree |
Changes arrive faster than ever, many of them written by agents. Skimming a wall of red and green is how bugs get approved. margin turns the wall into a route.
space go on · b go back · c comment · a ask. Everything else can wait behind H.
What the change is for, what it actually does, and the gap between the two. Then the route. Then, before a single line of code: does this make sense, done this way?
margin-tuimargin-guiWhat it is, how risky, why it comes now, and the one thing to check. You know what you are looking for before you look.
margin-tuimargin-guiA whole reading unit, with the agent's notes numbered beside their lines and a question to answer before space. Import churn is batched at the end so it never interrupts.
margin-tuimargin-guiProblems to agree with, calls to make, questions only the author can answer — listed right under the code they are about. Nothing piles up for the end.
margin-tuimargin-guic asks the kind first — issue, suggestion, question, nitpick, praise, thought — and coaches you while you type. S sends them; the agent fixes the code or explains why not.
margin-tuimargin-guiApprove, request changes, or not finished — with the reasons and every open item one enter away. margin-tui export makes it a PR review you post yourself.
margin-tuimargin-guiA note says a check matters. Does any test agree? Change the line and find out, without leaving the review or touching your branch.
cw, dd, ciw, x, ., u, visual mode. Delete the whole check if you like.✓→✗ means a test caught it.
✓→✓ means nobody would have noticed.
Already on screen, one key away, without leaving the review.
The agent measures coverage per test. Untested lines glow in the gutter, u jumps between them, t lists the tests that run a line, spotlights one or runs them.
margin-tuimargin-guimargin-tui # uncommitted margin-tui --staged # the index margin-tui feature-x # a branch margin-tui a1b2c3d # a commit margin-tui --pr 123 # a pull request margin-tui pick # from a list
Or pick any of them in margin-gui's sidebar, or ctrlk.
Who calls the function you are reading, what it did before and does now, and the commits that shaped it. enter peeks.
margin-tuimargin-guiPick a test and every line it does not run dims. See exactly which path it takes.
margin-tuimargin-guiT runs exactly the tests that run the selected line, with the command you set up once for the repository: go test, docker compose run, pytest. Each test gets its ✓ or ✗; the command lives in your settings, never in the repository.
i turns a line, or a V block, into a vim right where it stands, in both apps. See it run ↑ — or keep your own: E opens $EDITOR.
margin-tuimargin-guiCode that only moved is shown as moved — not as a deletion and an addition you compare by eye.
v hides the agent's notes on high-risk stops, so you form your own view before you see theirs.
Come back tomorrow, in either app. Verdicts, marks, comments and notes are exactly where you left them.
Changes no stop shows get a stop of their own, and ignored or binary files are listed, so the route never hides part of the diff.
s splits any stop, d hides removed lines, f shows the whole file and + more around the change.
/ searches the code of the whole review, n and N jump between the matches.
Markdown to paste, or --format github for gh api with the right event. margin never posts for you.
.margin/ignore skips generated files. .margin/instructions tells every review what deserves care — read from the base commit, so a change cannot rewrite its own rules.
# .margin/instructions Migrations must be reversible. Every handler checks the tenant. # .margin/ignore *.pb.go dist/
Both read and write the same review files. Start in one, go on in the other.
The review in your terminal, the agent in a tmux pane beside it. Everything is a key; the mouse picks lines, blocks and stops.
go install github.com/redrick/margin/cmd/margin-tui@latest margin-tui pick
Your repositories, worktrees, branches and pull requests in a sidebar, the agent in a terminal inside the window. No tmux.
go install github.com/redrick/margin/cmd/margin-gui@latest margin-gui --install # into your launcher
Claude Code by default; Codex, Gemini CLI, OpenCode or any agent CLI that takes a prompt and runs shell commands. margin-tui config set agent codex.
In .margin/reviews/ of the repository, ignored by git, by default. Or a private folder, or your notes vault: ~/notes/{project}/topics/{topic}.
The agent answers each comment in a markdown note. margin-gui shows it with A; reply under an answer or edit the note in place.
margin-tui skill install claude (or codex) teaches an agent you started yourself how margin works, so it can prepare a review for you to open. Claude Code can also add it as a plugin: /plugin marketplace add redrick/margin.
Every part of the walk follows a published result about how people actually review code.
Design comments come first; the details may not survive them.
Google, navigating a CL →Strict step-by-step guidance helped on small changes but got in the way on large ones.
Gonçalves et al., 2022 →Reviewers prefer reading what is used before what uses it, and get lost in orders they cannot follow.
Baum et al., 2017 →More defects are found when the order follows the code's relations rather than file names.
Baum et al., 2019 →Whatever a reviewer reads last gets fewer comments.
Fregnan et al., 2022 →Labelling each comment tells the author what is a request and what is a thought.
Conventional Comments →margin treats the repository under review as untrusted. You can point it at a stranger's pull request.
--end-of-options. The one fetch is a pull request you click Fetch and review on in margin-gui..margin/ settings come from the commit compared against, so a change cannot loosen its own review.Install one, run margin-tui in a repository with uncommitted changes or open it in margin-gui, and press space.