mech.app
Dev Tools

Hunk: Review-First Terminal Diff Viewer Shows How Agent-Generated Code Changes Need Different UX

Agent changesets arrive in multi-file batches with inline annotations. Hunk's TUI architecture reveals the plumbing needed when humans review machine code.

Source: github.com
Hunk: Review-First Terminal Diff Viewer Shows How Agent-Generated Code Changes Need Different UX

Agent-generated code arrives differently than human commits. A coding agent writes 15 files in 30 seconds, embeds reasoning inline, and expects a human to approve or reject the batch. Traditional git diff shows line-by-line changes but offers no structure for multi-file review, no space for agent annotations, and no way to watch a directory as an agent writes.

Hunk is a terminal diff viewer built for this workflow. It treats agent changesets as review units, not individual commits. The tool sits between agent output and human acceptance, providing split/stack layouts, inline AI notes, watch mode for live file updates, and Git difftool integration. At 5,361 stars and trending #11 on GitHub for TypeScript, it exposes the plumbing gap between agent-generated code and the review interfaces developers actually need.

Why Agent Changesets Break Traditional Diff UX

Human developers commit incrementally. Agents produce multi-file batches with embedded reasoning. The mismatch creates three problems:

  1. Batch review scope: An agent might touch 20 files to implement a feature. Reviewing each file in isolation loses context. Reviewing all 20 in a single pager scroll loses structure.

  2. Inline annotations: Agents often explain their changes in comments or metadata. Traditional diff tools strip this context or bury it in commit messages.

  3. Live updates: When an agent runs in watch mode or iterates on feedback, files change rapidly. Reloading git diff manually breaks flow.

Hunk addresses these by treating the changeset as the atomic unit. It provides a sidebar for file navigation, inline rendering of AI annotations, and a watch mode that reloads the diff when files change.

Architecture: OpenTUI + Pierre Diffs + Layout Engine

Hunk is built on two libraries:

  • OpenTUI: A terminal UI framework that handles keyboard, mouse, and pager integration. Provides the event loop and rendering primitives.
  • Pierre diffs: A diff library that parses Git diffs, file pairs, and patches into structured data. Handles unified diff format, hunk metadata, and line-level changes.

The core architecture has three layers:

  1. Input layer: Watches file system events, Git working tree changes, or Jujutsu/Sapling revsets. Feeds raw diffs to the parser.
  2. Layout engine: Decides whether to render split view (side-by-side), stack view (vertical), or responsive auto layout based on terminal width and file count.
  3. Render layer: Streams diff hunks to the terminal, injects inline AI annotations, and handles scrolling, selection, and navigation.

Layout Decision Tree

Hunk chooses layout based on terminal dimensions and changeset size:

Terminal WidthFile CountLayout ChoiceRationale
< 120 colsAnyStackSide-by-side unreadable
≥ 120 cols1-5 filesSplitFull context visible
≥ 120 cols6+ filesSplit + sidebarNavigation needed
Watch modeAnyPrevious choicePreserve state on reload

The layout engine recalculates on terminal resize events. If width drops below 120 columns mid-review, it collapses split view to stack view without losing scroll position.

Watch Mode: File System Events and Diff Reload

Watch mode monitors the file system for changes and reloads the diff automatically. This is critical when an agent writes files in rapid succession or iterates on feedback.

The implementation uses fs.watch (or equivalent) to monitor:

  • Working tree files in Git mode
  • Specific file paths in raw file mode
  • Commit objects in hunk show mode (watches .git/refs for new commits)

When a change event fires, Hunk:

  1. Debounces events (100ms window to batch rapid writes)
  2. Re-parses the diff using Pierre
  3. Preserves scroll position and selected file in the sidebar
  4. Re-renders only changed hunks

This avoids full-screen flicker and keeps the review context stable. If the agent deletes a file mid-review, Hunk removes it from the sidebar and advances to the next file.

Handling Rapid Agent Writes

Agents often write files faster than humans can review. If an agent writes 10 files in 2 seconds, watch mode:

  • Batches all 10 changes into a single reload
  • Updates the sidebar file list atomically
  • Highlights new files in the sidebar
  • Does not auto-scroll unless the current file was deleted

This prevents the UI from jumping around while the agent is still writing.

Inline AI Annotations: Embedding Agent Reasoning

Hunk renders inline annotations beside code changes. These annotations come from:

  • Comments in the diff (e.g., // AI: Refactored for clarity)
  • Metadata in commit messages (parsed from structured formats)
  • External annotation files (JSON or YAML sidecar files)

The annotation format is flexible. Hunk looks for markers like AI:, Agent:, or Note: in comments and renders them in a separate column. For structured metadata, it expects:

{
  "file": "src/handler.ts",
  "line": 42,
  "annotation": "Replaced callback with async/await to avoid nested promises"
}

Annotations appear in the right margin in split view or inline in stack view. They scroll with the code and can be toggled on/off with a keybinding.

Annotation Rendering Trade-offs

ApproachProsCons
Inline commentsNo external files neededClutters code, hard to strip later
Sidecar JSONClean separation, structuredRequires agent to write extra file
Commit message metadataGit-native, version-controlledLimited space, hard to parse

Hunk supports all three. The default is inline comments because most agents already write them.

Git Difftool Integration: Replacing git diff in Workflows

Hunk registers as a Git difftool, so you can replace git diff with hunk diff in existing workflows:

git config --global diff.tool hunk
git config --global difftool.hunk.cmd 'hunk diff "$LOCAL" "$REMOTE"'
git difftool HEAD~1

This works with:

  • git difftool for staged changes
  • git difftool --cached for index vs. HEAD
  • git difftool <commit> for historical diffs

Hunk also supports Jujutsu and Sapling revsets. Inside a jj workspace, hunk diff @ shows changes in the current revision. Inside a Sapling workspace, hunk show . shows the current commit.

The tool auto-detects VCS type by checking for .git, .jj, or .sl directories. You can override this with a config file:

# ~/.config/hunk/config.toml
vcs = "git"  # or "jj" or "sl"

Performance Boundaries: Reviewing 50+ File Changesets

Hunk is fast for typical agent changesets (5-20 files). Performance degrades when:

  • File count exceeds 50: Sidebar rendering slows. Scrolling becomes laggy.
  • Diff hunks exceed 10,000 lines: Syntax highlighting blocks the event loop.
  • Watch mode monitors 100+ files: File system events flood the debounce buffer.

Mitigation strategies:

  1. Lazy rendering: Only render visible hunks. Scroll events trigger incremental rendering.
  2. Syntax highlighting off by default: Enable only for small diffs.
  3. File filtering: Allow users to exclude files by pattern (e.g., *.lock, dist/*).

For changesets above 50 files, Hunk recommends splitting the review into multiple sessions or using a web-based review tool.

Failure Modes and Edge Cases

1. Agent Writes Binary Files

Hunk cannot diff binary files. If an agent writes an image or compiled asset, Hunk shows a placeholder:

[Binary file changed: 42KB → 58KB]

Users can open the file externally with a keybinding.

2. Agent Deletes Files Mid-Review

If the agent deletes a file while the user is reviewing it, Hunk:

  • Removes the file from the sidebar
  • Advances to the next file
  • Shows a notification: “File deleted, moved to next”

This prevents the user from reviewing a non-existent file.

3. Terminal Resize During Review

If the terminal resizes below 120 columns, Hunk collapses split view to stack view. Scroll position is preserved, but the user may need to re-orient.

4. Conflicting Watch Events

If two agents write to the same file simultaneously, watch mode reloads twice. The second reload overwrites the first. This is acceptable because the user is reviewing the final state, not intermediate writes.

Code Example: Parsing Inline Annotations

Here’s how Hunk extracts inline AI annotations from diff comments:

interface Annotation {
  file: string;
  line: number;
  text: string;
}

function parseInlineAnnotations(diff: string): Annotation[] {
  const annotations: Annotation[] = [];
  const lines = diff.split('\n');
  let currentFile = '';
  let lineNumber = 0;

  for (const line of lines) {
    // Track current file from diff header
    if (line.startsWith('diff --git')) {
      currentFile = line.split(' ')[2].replace('b/', '');
      lineNumber = 0;
    }

    // Track line numbers from hunk headers
    if (line.startsWith('@@')) {
      const match = line.match(/\+(\d+)/);
      lineNumber = match ? parseInt(match[1], 10) : 0;
    }

    // Extract AI annotations from comments
    if (line.startsWith('+') && line.includes('// AI:')) {
      const text = line.split('// AI:')[1].trim();
      annotations.push({ file: currentFile, line: lineNumber, text });
    }

    if (line.startsWith('+')) lineNumber++;
  }

  return annotations;
}

This parser walks the unified diff format, tracks file and line context, and extracts comments prefixed with // AI:. It handles multi-line annotations by continuing until the next non-comment line.

Technical Verdict

Use Hunk when:

  • You review agent-generated changesets with 5-50 files
  • You need inline AI annotations visible during review
  • You want watch mode for live agent iteration
  • You work in a terminal-first workflow and want Git difftool integration

Avoid Hunk when:

  • Your changesets exceed 50 files (performance degrades)
  • You need web-based review with team collaboration features
  • You review binary files or large assets (Hunk cannot diff them)
  • You prefer IDE-integrated diff tools with richer syntax highlighting

Hunk fills the gap between agent output and human review. It is not a replacement for GitHub PRs or GitLab MRs, but it is faster and more focused for solo developers reviewing agent code locally. The watch mode and inline annotations are the key differentiators. If your workflow involves agents writing code while you review, Hunk is worth testing.