Skip to content

Repository files navigation

human-review

A Golang TUI application built with Bubble Tea for reviewing local git changes before staging. It's the step before running git add - you review each change, approve what goes to stage, and keep unapproved changes unstaged with optional comments.

human-review TUI preview

Installation

Prerequisites

  • Go — a toolchain that satisfies the version in go.mod, with go on your PATH
  • Git — the git CLI must be available; human-review uses it for diffs and staging

Install with go install (recommended)

go install github.com/em4go/human-review@latest

This places the human-review binary in $(go env GOPATH)/bin (commonly ~/go/bin). If that directory is not already on your PATH, add it (example for zsh):

echo 'export PATH="$PATH:$(go env GOPATH)/bin"' >> ~/.zshrc
source ~/.zshrc

Open a new terminal if you prefer not to source the file.

Install from a clone

git clone https://github.com/em4go/human-review.git
cd human-review
go build -o human-review .

Move human-review to a directory on your PATH, or run it via ./human-review. You can also try the app without installing a binary: go run . from the repository root.

Run

human-review                 # review the Git repo in the current directory
human-review /path/to/repo   # review another repository

Overview

Purpose: Review unstaged git changes line-by-line with the ability to stage hunks individually, add comments to changes you want to revisit later, and selectively stage only what you approve.

Workflow:

  1. List all files with unstaged changes
  2. Select a file to view its diff
  3. Move between hunks with [ / ]; stage one hunk with s, drop it from the working tree with r, or unstage a hunk from the index when viewing the staged diff (u)
  4. Optional: e opens the file in an external editor to tweak changes, then the diff reloads (see External editor below)
  5. c queues a review note for the current line or visual selection; :w appends all queued notes to REVIEW.md (the file is not created until then). K or :review opens a draft preview where you can drop notes with D before saving

Features

  • Vim-style navigationj / k to move, Enter / l to open, Space for shortcut help
  • File list - Shows all modified files with +X -Y line counts
  • Diff viewer - Full diff with syntax highlighting via Chroma
  • Hunk-level staging - Stage individual hunks instead of whole files
  • Comment system - Add comments to hunks you want to revisit
  • Persistence - After :w, review notes are appended to REVIEW.md at the repo root
  • Color output - Syntax-highlighted diffs with terminal-friendly colors

User Flow

┌─────────────────────────────────────────────────────┐
│  human-review                                       │
├─────────────────────────────────────────────────────┤
│  Modified Files (3)                                 │
│  ─────────────────                                  │
│  > src/main.go           +10 -3   [staged: 0/3]   │
│    src/utils.go          +5  -2   [staged: 1/2]   │
│    src/config.go         +20 -0                  │
│                                                     │
│  [j/k] [Enter/l] [Space help] [1/2 sections] [q quit] │
└─────────────────────────────────────────────────────┘
          │
          ▼ (Enter on main.go)
┌─────────────────────────────────────────────────────┐
│  src/main.go                                        │
├─────────────────────────────────────────────────────┤
│  @@ -1,5 +1,7 @@                                      │
│   func main() {                                      │
│  +    // New initialization                         │
│  +    initConfig()                                   │
│     fmt.Println("hello")                            │
│  -    oldWay()                                      │
│  +    newWay()                                      │
│                                                     │
│  [[/] hunks] [s stage] [r discard] [c note] [q|h back] [Space help] │
└─────────────────────────────────────────────────────┘

Keyboard shortcuts

In normal mode (not while typing a comment, an ex command, or a discard confirmation), Space opens the in-app help overlay (same shortcuts as below; Space, Esc, or q closes it). Ctrl+r triggers an immediate rescan from the file tree or from the diff / preview buffers where noted; the app also rescans on a short timer when git is idle.

Global (normal mode)

Key Action
Space Toggle keyboard help overlay
Tab Switch focus between file tree and diff / buffer pane
: Open ex command line (see below)
K Open queued review notes as REVIEW.md (draft) preview
Ctrl+r Refresh change list and reload the current preview when git is idle (queues if git is busy)
q From file tree: quit (blocked if there are unsaved queued review notes). From diff pane: return to file tree, except on an error buffer q quits instead—use h / Left to leave an error without quitting
Ctrl+c Same as q (including error-buffer quit vs tree return)
h / Left From diff pane: return to file tree (same idea as q for the buffer)

File tree (changed files)

Key Action
j / Move selection down (live diff preview updates)
k / Move selection up
Enter / l / Right On a file: open diff. On a folder row: expand / collapse. On a section header (Staged / Changes): collapse / expand that section
1 Toggle Staged section collapsed
2 Toggle Changes section collapsed
s Stage entire file (row must be a file)
u Unstage entire file (or remove untracked file from index as applicable)
d Discard whole file (working tree, staged, or untracked by context); confirmation prompt, default No
Ctrl+r Refresh change list
: / K Same as global

Diff buffer (file diff)

Applies when viewing a real file diff (not the draft preview, generic preview, or error buffer).

Key Action
j / Move cursor down one line
k / Move cursor up one line
Ctrl+d / Ctrl+u Half-page down / up
g / G Jump to top / bottom of buffer
[ / ] Previous / next hunk (when the diff has hunks)
s Stage current hunk (working tree / Changes diff only)
r Discard current hunk from working tree (confirm); not used on staged-only diff
u Unstage current hunk (Staged / cached diff only)
e Open file in external editor at inferred line (see External editor below)
v / V Start line-wise visual selection
c Start review comment for cursor line or visual range (see Comment composer)
Y Toggle syntax highlighting on / off (file diffs only)
Ctrl+r Refresh git state and reload this diff
: Ex command line
K Open REVIEW.md (draft) preview
Tab / q / h / Left Focus file tree

Visual line mode (after v / V): j / k extend selection; c attach comment to range; Esc cancels visual mode.

REVIEW.md (draft) buffer (queued notes preview)

Key Action
j / k Scroll
D Remove the note under the cursor (header or body line)
K Refresh draft from the queue
: Open ex command line; w / wq append notes to REVIEW.md (same as :w / :wq), wq then quits
Tab / q / h / Left Back to file tree
Space Toggle help

Preview / error buffers

Key Action
j / k Scroll
Ctrl+r Refresh
Tab / h / Left Back to file tree
q On Preview buffers: back to file tree. On error buffers: quit the app (if allowed); use h / Left / Tab to return to the tree without quitting
Space Toggle help

Ex command line (:)

Key Action
Esc Cancel without running
Enter Run the command (you may type w / wq / q / … with or without a leading :)
Backspace Delete the previous character in the command line
Command Action
:w Append all queued review notes to REVIEW.md and clear the queue
:wq Same as :w, then quit
:q, :quit, :qa Quit (blocked if there are unsaved queued notes)
:q!, :quit!, :qa! Quit without saving queued notes
:review Open the REVIEW.md (draft) preview
:e / :edit Move focus to the file tree
:syntax / :syn Enable diff syntax highlighting
:nosyntax / :nosyn Disable diff syntax highlighting

Comment composer (after c on a diff)

Key Action
Enter Queue the note (empty text cancels)
Ctrl+j / Alt+Enter Insert newline in the note
Backspace Delete previous character
Alt+Backspace Delete previous word (terminal must send this sequence)
Esc / Ctrl+c Cancel composer

Discard confirmation (whole file or hunk)

Key Action
y / Y Confirm discard
n / N, Enter, Esc, q, Ctrl+c Cancel (default is No)

External editor (e)

The TUI runs your editor through sh -c with a command built for your editor family. The editor program is chosen in this order:

  1. HUMAN_REVIEW_EDITOR — use only for human-review (leaves EDITOR for Git and other tools)
  2. EDITOR
  3. VISUAL
  4. Built-in default: vi

Jump to the cursor line: e maps the diff buffer line under the cursor to a 1-based line on the new-file side of the unified diff (the +++ side). That is the working tree for a normal git diff, and the index line number for git diff --cached (still useful, but it can disagree with the on-disk file if you have mixed staged and unstaged edits).

Goto style is inferred from the basename of the first word in your editor string: hx / helix pass a single quoted path:line:1 argument (Helix’s normal CLI form, not a --goto flag); code / cursor / codium append -g path:line; zed passes a single path:line argument after your flags (for example zed --wait '…/file.go:42'); anything else uses vim-style +line before the quoted path (vi, vim, nvim, …). If you use a wrapper script whose first token is not recognized, it gets vim-style +N—adjust the script or point HUMAN_REVIEW_EDITOR at the real binary.

The status line when you press e shows the target line, the inferred family ([vim] / [helix] / …), the command prefix, and which variable supplied it.

Helix: set EDITOR=hx (or HUMAN_REVIEW_EDITOR=hx). Helix blocks until you quit, which is what human-review expects.

Zed: the CLI usually returns immediately unless you wait on the window. Use for example EDITOR='zed --wait' or HUMAN_REVIEW_EDITOR='zed --wait' (install the zed CLI from Zed’s command palette if needed).

VS Code-style: EDITOR='code --wait' works the same way.

Making it permanent (shell config)

Put an export in your login shell’s startup file so every new terminal has the variable—for zsh, usually ~/.zshrc:

# human-review only (recommended if you want a different EDITOR for Git, etc.)
export HUMAN_REVIEW_EDITOR='hx'
# or: export HUMAN_REVIEW_EDITOR='zed --wait'

Or set EDITOR (or VISUAL) there if you want the same editor for human-review and other tools that respect those variables.

Reload without opening a new terminal:

source ~/.zshrc

One-liner to append Helix for human-review only (check the line first so you do not duplicate it):

grep -q HUMAN_REVIEW_EDITOR ~/.zshrc || echo "export HUMAN_REVIEW_EDITOR='hx'" >> ~/.zshrc

On bash, use ~/.bashrc or ~/.bash_profile instead of ~/.zshrc.

Dependencies

Library Version Purpose
charm.land/bubbletea/v2 v2.0.2 (Mar 2026) TUI framework
github.com/charmbracelet/bubbles v1.0.0+ UI components
github.com/charmbracelet/lipgloss v1.1.0+ Styling
github.com/go-git/go-git/v5 v5.17.2 (Mar 2026) Git operations
github.com/alecthomas/chroma/v2 v2.23.1 (Jan 2026) Syntax highlighting

Project Structure

human-review/
├── main.go                 # Entry point
├── cmd/
│   └── root.go             # CLI root command
├── internal/
│   ├── models/
│   │   ├── file.go         # File with diff info
│   │   ├── hunk.go         # Diff hunk struct
│   │   └── comment.go      # Comment struct
│   ├── services/
│   │   ├── git.go          # Git operations (diff, stage)
│   │   └── comment.go     # Comment persistence
│   ├── tea/
│   │   ├── app.go         # Main Bubble Tea app
│   │   ├── filelist.go    # File list view model
│   │   ├── diffview.go    # Diff view model
│   │   └── styles.go      # Bubble Tea styles
│   └── utils/
│       └── highlight.go   # Chroma integration
└── go.mod

Implementation Steps

  1. Initialize Go module and install dependencies
  2. Create basic Bubble Tea app structure
  3. Implement git service to get unstaged files
  4. Build file list view with vim navigation
  5. Build diff view with hunk-level staging
  6. Add comment system with persistence
  7. Add syntax highlighting with Chroma
  8. Style and polish the UI

Edge Cases

  • No unstaged changes → Show message "No changes to review"
  • File with only additions → Show diff with just + lines
  • File with only deletions → Show diff with just - lines
  • Binary files → Show "Binary file changed" message
  • Merge conflicts → Show warning, don't allow staging

Similar Projects

  • differ - Another git diff TUI with Bubble Tea

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages