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

Reviewing in lazygit and Other Tools

If you already review changes in lazygit, vim-fugitive, or git add -p, you can review heph's changes there. Set the tool in config:

[review]
interactive = "lazygit"

Then Enter on the brief suspends heph's screen and opens the tool in the conversation's worktree, with the whole proposed change staged against the turn's starting snapshot. It is an ordinary git checkout with an index; the tool needs to know nothing about heph.

The protocol

Still staged means accepted. Unstaged means rejected.

Unstage the hunks you do not want. Edit files if you like, and stage what you edited. Then quit the tool. When it exits zero, heph reads the index back: every hunk of the brief that is still staged is accepted, every hunk that is not is rejected. The index is the verdict.

In lazygit: select the file, press Enter to see its hunks, move to a hunk and press Space to unstage it (or in the unstaged pane, to stage it back), q to quit.

Comments, after

Once the tool exits, heph's screen returns and asks about each rejected hunk in turn:

┌ review: comments ───────────────────────────────────────────────────────────┐
│2 accepted, 1 rejected. A comment on each rejection answers the model's       │
│stated reason; Enter skips.                                                   │
│                                                                              │
│> [1/1] src/auth.rs hunk 1 (23-31)                                            │
│      why: Read the JWT secret from the environment so the key never lands    │
│           in the binary.                                                     │
│                                                                              │
│@@ -23,7 +23,9 @@ impl Auth {                                                  │
│-    let secret = "s3cr3t";                                                   │
│+    let secret = std::env::var("JWT_SECRET")                                 │
│+        .expect("JWT_SECRET must be set");                                   │
│                                                                              │
│> put it in the config file instead, not the environment                      │
│                                                                              │
│Enter: next    Shift+Tab: back    Esc: done, with the comments so far         │
└──────────────────────────────────────────────────────────────────────────────┘

Each rejected hunk is shown with the model's reason and, for the one being asked about, its diff, so you answer with both in view. Type a comment and press Enter, or press Enter on an empty line to skip. Shift+Tab goes back to the previous rejection with its comment ready to edit. Esc finishes at once: the comments given so far stand, the current one included, and the remaining rejections go without. Up, Down, PgUp, PgDn, and the mouse wheel scroll a long list. When every rejected hunk has been asked about, the review is done and the turn continues as with the built-in review.

If nothing was rejected, there is nothing to ask; the change is applied.

A tool that exits non-zero

A tool that is killed, crashes, or exits non-zero has decided nothing. Heph resets the index, applies nothing, and says so; the review is offered again from the brief. A half-finished index is never read as a verdict.

The tools

interactive = RunsNotes
"builtin"heph's own screenThe default. The Built-in Review.
"lazygit"lazygitIts staging view; Space toggles a hunk.
"git add -p"git reset -q && git add -pEverything starts unstaged; answer y to the hunks you accept.
"fugitive"nvim -c Gstatusvim-fugitive's status buffer; - toggles staging, dp for hunks.
"$EDITOR"$EDITOR .Your editor on the worktree; stage with whatever git integration it has.
anything elseThat command, via sh -cRun in the worktree; must leave the index as the verdict and exit 0.

Whatever the tool, it runs in the worktree, never in your own tree, and your own index is never touched.

What the tool sees

The worktree's HEAD is detached, for the review, at a commit whose message is the brief: it has the turn's starting snapshot as its tree and its parent, so git diff --cached there is exactly the proposed change, the commit's own diff is empty, and git log shows your project's history beneath it. That is how the reasons reach a tool that has no idea heph exists: in lazygit, the top entry in the commits panel is heph review: 2 files, 3 hunks -- each hunk's reason below, and selecting it shows the brief in the main panel while you stage and unstage. Other tools show it wherever they show the log. The commit is heph's, not part of your history; it disappears when the review ends. The private per-call commits are under refs/heph/turns/<turn>/, out of the way. A tool that shows branches will show (no branch): that is expected.

Do not commit in the tool. A commit would move the detached HEAD and the verdict is read from the index; heph resets the worktree after every review regardless, so nothing you commit there survives, but it can confuse the read back.