Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Built-in Review

With [review] interactive = "builtin" (the default), Enter on the brief walks the hunks one at a time in heph's own screen. It needs no other program and always works.

┌ review: main ───────────────────────────────────────────────────────────────┐
│[1/3] src/auth.rs  (+14 -3)                                                   │
│hunk 1 (lines 23-31)                                                          │
│why: Read the JWT secret from the environment so the key never lands in the   │
│     binary.   (edit #4)                                                      │
│                                                                              │
│@@ -23,7 +23,9 @@ impl Auth {                                                  │
│-    let secret = "s3cr3t";                                                   │
│+    let secret = std::env::var("JWT_SECRET")                                 │
│+        .expect("JWT_SECRET must be set");                                   │
│                                                                              │
│(a)ccept (r)eject (c)omment (e)dit (s)kip  (q) reject rest  (u)ndo  Esc: stop │
└──────────────────────────────────────────────────────────────────────────────┘

The header counts the hunks and names the file with its total added and removed lines. why: is the rationale, with the calls behind it in parentheses. The diff is colored: additions green, removals red, hunk headers cyan. Up, Down, PgUp, and PgDn scroll a long hunk.

The keys

KeyDoes
aAccept the hunk as it is.
rReject it without comment. The model is told it was refused.
cReject it with a comment. A line opens; type why, Enter sends, Esc cancels the comment (the hunk stays undecided). An empty comment is a plain rejection.
eEdit the file in your editor. The file opens as the model proposed it; what you save is the file as it will be applied. Quitting without saving leaves the hunk undecided.
sSkip. The hunk is rejected without comment, exactly as r.
qReject everything not yet decided and end the review.
u, BackspaceUndo: back to the previous hunk, its decision taken back. From the first hunk, back to the brief.
EscStop here. What you decided stands; the hunks you did not reach wait in the worktree for the next review. Before any decision, back to the brief.

After the last hunk the review closes and heph does the rest: keeps what you accepted, records what you rejected, and either applies or sends the model another round (Rejections, Comments, and the Next Round).

Stopping partway

Esc in the middle of a review is not a cancel. The hunks you accepted are kept, the ones you rejected are gone and become constraints, and the ones you never reached are left in the worktree on top of what you accepted, still unreviewed. The turn ends with the review waiting; the model gets no round meanwhile, but is told what was decided so far. /review picks the review up with exactly the undecided hunks, each with its reason; so does your next prompt, before its turn starts. Nothing is lost by stepping away, and nothing undecided is ever taken as accepted or rejected.

Editing a hunk

e is for when the model's change is nearly right. Heph copies the file as the worktree holds it, with every hunk of the proposed change in it, to a temporary file and opens $VISUAL (or $EDITOR, or vi) on the copy, suspending its screen while the editor runs. Save and quit, and the saved text is the file as it will be applied, committed on the turn's chain as user: edited in review.

Because the whole file is what you saved, an edit decides the file's other hunks too: what is in the saved file is what lands, whatever you pressed on them. If nothing else in the review was rejected or commented on, the turn ends there with your version applied; the model is not consulted again. If something was, the model's next round is told the hunk was EDITED BY THE USER; the file now holds their version, and it works from your text. Use e when you want the last word on a file, c when you want the model to try again.

A comment is worth more than a rejection

r tells the model that a hunk was refused. c tells it why, in your words, beside the reason it gave. The model converges in one round on a comment where a bare rejection often takes two or three, because it can see which reasoning was wrong. When you know why you are rejecting, say so.

Rendering diffs with a pager

[review] pager names a program that renders each hunk before it is shown, for the review heph exec runs on a plain terminal:

[review]
pager = "delta"

There the hunk is piped through it and its output shown in place of heph's own coloring; anything that reads a unified diff on stdin and writes to stdout works, and a pager that fails falls back to the plain coloring. The interactive session draws its own diffs and does not use the pager yet.