hunk
Hunk is an interactive terminal diff viewer for reviewing code changes, built on OpenTUI and Pierre diffs.
- multi-file review stream with sidebar navigation
- inline AI and agent annotations beside the code
- split, unified, and responsive auto layouts
- watch mode for auto-reloading file and Git-backed reviews
- keyboard, mouse, pager, and Git difftool support
Split view with sidebar and inline AI notes |
Unified view and mouse-selectable menus |
Install
On macOS and Linux, install the standalone binary:
curl -fsSL https://hunk.dev/install.sh | shWindows users can install with npm or mise. Other installation methods are also available:
npm i -g hunkdiff # macOS, Linux, or Windows; requires Node.js 22+ brew install hunk # macOS or Linux mise use -g hunk # macOS, Linux, or Windows
Note
If you previously installed hunk via modem-dev/tap, be sure to uninstall it first with brew uninstall modem-dev/tap/hunk.
Windows requires mise 2026.8.6 or newer. Nix users can use the default package exported in flake.nix; see the Nix guide for details. Hunk also ships as a default tool in Omarchy, installed through mise.
Requirements:
- macOS, Linux, or Windows
- On x86-64, a CPU with SSE4.2 (Intel Nehalem 2008+, AMD Bulldozer 2011+); arm64 has no CPU feature floor
- Node.js 22+ for the npm install; the install script, Homebrew, mise, and Nix ship a standalone binary that does not require Node.js
- Git recommended for most workflows
Update Hunk
For npm, Homebrew, and default install-script installs (Hunk 0.20+):
hunk update # install the newest release hunk update --check # check without installing hunk update 0.20.0 # select an exact npm or default install-script release
On an older release, update once with the installer or package manager that installed Hunk, then use hunk update going forward. Custom HUNK_INSTALL_DIR installs must re-run the installer with the same directory; mise, Nix, and source installs use their owning tools instead.
Quick start
hunk # show help hunk --version # print the installed version
Working with Git
Use familiar Git commands to open changes in Hunk:
hunk diff # review current repo changes, including untracked files hunk diff --watch # auto-reload as the working tree changes hunk show # review the latest commit hunk show HEAD~1 # review an earlier commit hunk log # browse history on a terminal; print when redirected hunk log --static # force static output, paging when needed hunk status # view workspace status and sibling worktrees (Git) hunk status --static # print one read-only workspace snapshot hunk status --json # emit one versioned workspace snapshot
hunk status is read-only: it does not fetch or change the repository. See workspace status for details.
hunk log opens an interactive history browser in a terminal and prints text when piped or redirected. Use --oneline for compact output. In the browser, enable Graph view from the View menu to see commit branches, or press v to select a commit range. Quit a commit review to return to history.
Working with GitHub
Hunk bundles hunk gh, so pull requests, commits, and comparisons open directly without the
GitHub CLI or a separate extension:
hunk gh pr # infer the open PR for the current branch hunk gh pr 123 # infer the repository from origin hunk gh pr 'modem-dev/hunk#123' # quote this form for shells that treat # as a comment hunk gh commit a1b2c3d --repo modem-dev/hunk hunk gh compare main...feature --repo modem-dev/hunk
Public repositories work anonymously. Set GH_TOKEN, or GITHUB_TOKEN when it is absent, for
private repositories and higher API limits. GitHub Enterprise is not currently supported.
Working with Jujutsu and Sapling
Hunk auto-detects Jujutsu and Sapling checkouts, so hunk diff [revset] and hunk show [revset] use native revsets inside jj or Sapling workspaces. hunk log --vcs jj also reads JJ history directly, including in a non-colocated workspace. To override VCS detection, set vcs = "git" or vcs = "jj" or vcs = "sl" in config.
Viewing complete files and browsing directories
hunk open # browse the current directory hunk open README.md # view a complete, syntax-highlighted document hunk open path/to/project # browse another directory without requiring a repository
Use arrows and Enter to navigate, Tab to switch focus, i to show hidden/Git-ignored entries, and e to edit the displayed file in $EDITOR. See the open workflow for details and file limits.
Working with raw files and patches
hunk diff --files before.ts after.ts # compare two files directly hunk diff --files before.ts after.ts --watch # auto-reload when either file changes git diff --no-color | hunk patch - # review a patch from stdin
Working with agents
- Open Hunk in another terminal with
hunk difforhunk show. - Tell your agent to add the skill file returned by
hunk skill path. - Ask your agent to use the skill against the live Hunk session.
A good generic prompt is:
Load the Hunk skill and use it for this review. Run `hunk skill path` to get the skill path.
See the agent workflow guide for live sessions, --agent-context, and experimental rich notes.
Feature comparison
| Capability | hunk | lumen | difftastic | delta | diff-so-fancy | diff |
|---|---|---|---|---|---|---|
| Review-first interactive UI | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Multi-file review stream + sidebar | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Inline agent / AI annotations | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Responsive auto split/unified layout | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Mouse support inside the viewer | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Runtime view toggles | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Syntax highlighting | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| Structural diffing | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Pager-compatible mode | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
Advanced
Config
You can persist preferences to a config file:
~/.config/hunk/config.toml.hunk/config.toml
Persistent state uses $XDG_STATE_HOME/hunk/state.json when the variable is
absolute, or ~/.local/state/hunk/state.json otherwise. Hunk preserves existing
state by copying the old config-directory file on first use, keeping the original
and falling back to it if migration fails. Global extension paths are unchanged.
For example:
theme = "terminal" mode = "auto" # auto, split, unified auto_split_min_width = 160 # minimum available diff columns for split in auto mode line_numbers = true wrap_lines = false
See the configuration guide for command overrides and examples, the full reference for every option, or the theme guide to customize colors.
Keybindings
Remap shortcuts with a [keybindings] table in your user config. See the keybinding guide for available commands, default keys, and examples.
Git integration
Set Hunk as your Git pager so git diff and git show open in Hunk automatically:
Note
Untracked files are auto-included only for Hunk's own hunk diff working-tree loader. If you open git diff through hunk pager, Git still decides the patch contents, so untracked files will not appear there.
git config --global core.pager "hunk pager"Or in your Git config:
[core] pager = hunk pager
If you want to keep Git's default pager and add opt-in aliases instead:
git config --global alias.hdiff "-c core.pager=\"hunk pager\" diff" git config --global alias.hshow "-c core.pager=\"hunk pager\" show"
Jujutsu pager integration
To use Hunk as jj's pager, run jj config edit --user and update:
[ui] pager = ["hunk", "pager"] diff-formatter = ":git"
Sapling pager integration
To use Hunk as Sapling's pager, run sl config -u and update:
[pager] pager = hunk pager
Extensions (experimental)
The extension API is experimental and may change in breaking ways between minor releases while it stabilizes; breaking changes are called out in release notes.
Hunk loads plain TypeScript extensions from ~/.config/hunk/extensions/, from a
repository's .hunk/extensions/ (after you explicitly trust that repository),
and from --extension <path> for development. --no-extensions turns those off
for one run; Hunk's own bundled backends (Git, Jujutsu, and Sapling) stay loaded.
Extensions can add commands, themes, VCS backends, custom sidebars, and more. For example, filter lockfiles out of a review:
// ~/.config/hunk/extensions/collapse-lockfiles.ts import type { HunkExtensionAPI } from "hunkdiff/extension"; export default function (hunk: HunkExtensionAPI) { hunk.transformChangeset((changeset, ctx) => { const files = changeset.files.filter((file) => !file.path.endsWith(".lock")); ctx.notify(`Collapsed ${changeset.files.length - files.length} lockfiles`); return { ...changeset, files }; }); }
Extensions shared as git repositories install straight from their host, and a
hunk-extension GitHub topic marks community ones:
hunk extension install acme/hunk-word-diff@v1.2.0 # or git:host/path, a URL, a local path hunk extension list # then update [name] / remove <name>
Browse community extensions at github.com/topics/hunk-extension; publish yours by pushing the extension to a repository root and adding that topic.
See the extension guide for the API, configuration, and publishing instructions. Installable examples include review triage, review snapshot export, an optional rendered Markdown file view, and a Vim navigation mode built from public semantic commands.
OpenTUI component
Hunk also publishes HunkDiffView and lower-level primitives from hunkdiff/opentui for embedding the same diff renderer in your own OpenTUI app.
See the OpenTUI component guide for install, API, and runnable examples.
Examples
Ready-to-run demo diffs live in the examples directory.
Each example includes the exact command to run from the repository root.
Contributing
💬 Chat with users/contributors on the Modem Discord server
See CONTRIBUTING.md for development setup and contribution guidelines.
Sponsor
Sponsored by Modem.

