👾 A git diff pager that actually wants to be looked at
Rust
144
133 commits
updated Oct 16, 2026
A git diff pager that actually wants to be looked at.
drift takes the diff you already know and drops it into a real terminal UI:
syntax highlighting, word-level change emphasis, split or unified views, a
file-list modal and a live sidebar you can click and drag to resize,
jump-to-hunk, in-file search, open-in-$EDITOR, and a live mode that repaints
the moment your index or branch moves. Point it at a commit, your staging area,
or your working tree, or just pipe a diff into it like any other pager.
No config needed to start. Themes, colors, and keys are all yours to bend later.
brew install aymanbagabas/tap/drift
scoop bucket add aymanbagabas https://github.com/aymanbagabas/scoop-bucket
scoop install drift
cargo install drift-diff
Or grab the prebuilt binary from the GitHub release instead of compiling:
cargo binstall drift-diff
npm install -g @aymanbagabas/drift
echo 'deb [trusted=yes] https://repo.aymanbagabas.com/apt/ /' | sudo tee /etc/apt/sources.list.d/aymanbagabas.list
sudo apt update && sudo apt install drift
echo '[aymanbagabas]
name=Ayman Bagabas
baseurl=https://repo.aymanbagabas.com/yum/
enabled=1
gpgcheck=0' | sudo tee /etc/yum.repos.d/aymanbagabas.repo
sudo yum install drift
yay -S drift-diff-bin
From the Nix User Repositories, install
nur.repos.aymanbagabas.drift. Or run it ad-hoc without configuring NUR:
nix-shell -p '(import (fetchTarball "https://github.com/aymanbagabas/nur/archive/master.tar.gz") {}).drift'
Grab an archive for your platform from the
latest release and put
the drift binary on your PATH.
Every method installs a drift binary.
drift completes its flags and option values, paths after --, and git
revisions: refs, commit hashes, HEAD~2 ancestors, HEAD@{1} reflog entries,
@{upstream}, HEAD:src/ paths, and both ends of a range like
main..feature.
The Homebrew, deb, rpm, apk, AUR, and Nix packages set this up for bash, zsh, and fish. Otherwise, add the line for your shell to its startup file:
eval "$(drift --completions bash)" # bash: ~/.bashrc
source <(drift --completions zsh) # zsh: ~/.zshrc, after compinit
drift --completions fish | source # fish: ~/.config/fish/completions/drift.fish
For PowerShell, add drift --completions powershell | Out-String | Invoke-Expression
to $PROFILE. For Elvish, add eval (drift --completions elvish | slurp) to
rc.elv.
zsh and fish treat an unmatched { as brace expansion, and PowerShell treats
it as the start of a script block. To complete a reflog entry in these shells,
quote the word ('HEAD@{). In zsh and fish, you can also escape the brace
(HEAD@\{).
drift # working tree vs HEAD
drift -A # ...and untracked files too
drift --staged # what's staged (alias: --cached)
drift HEAD~3 # a single commit
drift main..feature # a range
drift -w # watch the repo and refresh on every change
git diff | drift # pager mode: read a diff from stdin
[!TIP] Pair it with an AI agent. Leave
drift -wopen in a split while an agent (Copilot, Claude, etc.) works, every edit lands on screen instantly. Press F to freeze the view when you want to read, and again to resume.
Make it your default pager for git diff and git show:
git config --global pager.diff drift
git config --global pager.show drift
As the git show pager, drift shows the commit's hash, author, date, and
message above its diff. drift prints output that isn't a diff, such as
git show HEAD:README.md or git show --stat, straight to the terminal.
drift defaults to the ansi theme — your terminal's own colors, with syntax
highlighting off. Pick a theme to turn it on, globally via git config:
git config --global drift.theme onedark # onelight, dracula, nord, gruvbox-dark, ...
Some flags worth knowing:
| Flag | What it does |
|---|---|
-w, --watch | Refresh when the git index or refs change |
-A, --all | Also show untracked files (working-tree view only) |
-C, --directory DIR | Run as if started in DIR (worktrees, bare repos) |
-c, --config FILE | Use a specific config file |
--no-syntax | Turn off syntax highlighting for this run |
--no-commit-meta | Collapse the commit metadata to just the commit line |
--wrap / --no-wrap | Wrap long lines instead of scrolling horizontally |
-U, --context N | Lines of context around each change |
--ignore-whitespace | Ignore whitespace-only changes |
--diff-algorithm ALGO | myers, minimal, patience, or histogram |
-- PATHSPEC... | Limit to paths, e.g. drift -- src/ docs/ |
The footer shows your position in the whole diff: Top, a percentage such as
42%, or Bot. It shows All when the whole diff fits on screen. Percentages
use the top visible document row, including progress through a wrapped row.
The indicator stays hidden while the initial diff loads.
| Key | Action |
|---|---|
j k / ↑ ↓ | Move the cursor |
h l / ← → | Scroll horizontally (for lines wider than the view) |
0 $ | Scroll to line start / end |
d u / ^d ^u | Half page down / up |
space f ^f / b ^b | Full page down / up |
e y / ^e ^y | Scroll one line down / up |
g G | Top / bottom |
H M L | Cursor to screen top / middle / bottom |
{ } | Previous / next hunk |
[ ] / tab ⇧tab | Previous / next file |
/ | Search the current file (regex, smart-case) |
n N | Next / previous match |
s | Toggle split view |
w | Toggle line wrapping (long lines wrap instead of scrolling horizontally) |
S | File stats modal |
B | Toggle the file sidebar |
F | Toggle watch mode (follow changes, like less) |
a | Toggle untracked files (worktree view) |
V | Start / cancel a line selection; any motion key extends it |
c | Copy the selection, or the cursor line when nothing is selected |
C | Copy the whole current file |
enter | On a hunk header, expand folded context; on the commit line, expand / collapse the commit metadata |
o | Open the current file in $EDITOR |
r | Refresh |
? | Toggle the help footer |
q | Quit |
drift is fully mouse-driven too:
enter).? help badge in the status bar to toggle the help footer.Set theme = "..." in your config, or git config drift.theme .... The default
is ansi — your terminal's own 16 colors, with syntax highlighting and
word-diff emphasis left off. Any other built-in theme turns highlighting on:
onedark, onelightdraculagruvbox-dark, gruvbox-lightnordsolarized-dark, solarized-lightcatppuccin-mocha, catppuccin-lattetokyonightmonokaiansi — the default: borrows your terminal's own 16 colors so drift matches
whatever palette you already run. It leaves code text and word-diff emphasis
alone, since 16 colors are too few to layer cleanly over diff colors.A handful of syntect theme names also
work, but only the seven that ship in syntect's default set — InspiredGitHub,
Solarized (dark), Solarized (light), base16-eighties.dark,
base16-mocha.dark, base16-ocean.dark, and base16-ocean.light. They color
the code but won't repaint the UI chrome to match, and (Solarized aside) the
built-ins above already cover them with matching chrome. Any other theme name —
a custom .tmTheme, or a syntect theme not in that set — silently falls back to
onedark.
The themes/ directory has a full, commented config for every built-in theme.
Copy one and go:
mkdir -p ~/.config/drift
cp themes/dracula.toml ~/.config/drift/config.toml
drift looks for a config file, in order, at:
$XDG_CONFIG_HOME/drift/config.{toml,yaml,yml,json}~/.config/drift/config.{toml,yaml,yml,json}~/.drift.tomlTOML, YAML, and JSON all work. The top-level knobs:
theme = "onedark" # any built-in or syntect theme name
syntax = true # highlight diff content
intraline = true # word-level change emphasis
line-numbers = true # old/new line-number gutter
commit-meta = true # expand author/date/message; the commit line always shows for a single commit
wrap = false # wrap long lines instead of scrolling horizontally (toggle with w)
wrap-symbol = "↪" # symbol shown at the start of each wrapped continuation line
expand-symbol = "›" # gutter symbol on the collapsed commit line (expand to show metadata)
collapse-symbol = "⌄" # gutter symbol on the expanded commit line (collapse to hide metadata)
context-symbol = "⋯" # gutter symbol on a hunk header (reveal more context)
tab-width = 4
editor = "" # falls back to $VISUAL, then $EDITOR, then vi
sidebar = "auto" # "auto" (opens at width >= 150), "always", or "never"
sidebar-width = 30 # sidebar columns; drag its divider to resize live
sidebar-side = "left" # "left" or "right"
Colors come in two layers. [colors] is a named palette; [styles] maps UI
components to a fg bg attrs... spec resolved against that palette. Every color
token accepts a palette name, a literal #rrggbb, a 0-255 index, an ANSI color
name, or default/none/- for the terminal's own color. See any file in
themes/ for the full set with comments.
Anything you can set in a config file, you can set in git config under the
drift section, which is handy for per-repo overrides. Colors and styles go in
colors and styles subsections. Git forbids _ in a key, so a field like
add_emph becomes add-emph:
git config drift.theme nord
git config drift.line-numbers false
git config drift.colors.add '#00ff00'
git config drift.colors.add-emph '#003300'
git config drift.styles.statusbar 'foreground surface bold'
Or in ~/.gitconfig directly:
[drift]
theme = nord
line-numbers = false
[drift "colors"]
add = "#00ff00"
add-emph = "#003300"
[drift "styles"]
statusbar = "foreground surface bold"
selection = "none #ffd700"
For the full list of every setting, color, component style, and flag, see CONFIG.md.
drift's terminal UI is powered by uncurses, and its multi-channel releases are cut with GoReleaser.
MIT
4,695 followers · starred Aug 2026
3,416 followers · starred Aug 2026
269 followers · starred Aug 2026
2,582 followers · starred Aug 2026
👾 A git diff pager that actually wants to be looked at
Rust
144
133 commits
updated Oct 16, 2026
A git diff pager that actually wants to be looked at.
drift takes the diff you already know and drops it into a real terminal UI:
syntax highlighting, word-level change emphasis, split or unified views, a
file-list modal and a live sidebar you can click and drag to resize,
jump-to-hunk, in-file search, open-in-$EDITOR, and a live mode that repaints
the moment your index or branch moves. Point it at a commit, your staging area,
or your working tree, or just pipe a diff into it like any other pager.
No config needed to start. Themes, colors, and keys are all yours to bend later.
brew install aymanbagabas/tap/drift
scoop bucket add aymanbagabas https://github.com/aymanbagabas/scoop-bucket
scoop install drift
cargo install drift-diff
Or grab the prebuilt binary from the GitHub release instead of compiling:
cargo binstall drift-diff
npm install -g @aymanbagabas/drift
echo 'deb [trusted=yes] https://repo.aymanbagabas.com/apt/ /' | sudo tee /etc/apt/sources.list.d/aymanbagabas.list
sudo apt update && sudo apt install drift
echo '[aymanbagabas]
name=Ayman Bagabas
baseurl=https://repo.aymanbagabas.com/yum/
enabled=1
gpgcheck=0' | sudo tee /etc/yum.repos.d/aymanbagabas.repo
sudo yum install drift
yay -S drift-diff-bin
From the Nix User Repositories, install
nur.repos.aymanbagabas.drift. Or run it ad-hoc without configuring NUR:
nix-shell -p '(import (fetchTarball "https://github.com/aymanbagabas/nur/archive/master.tar.gz") {}).drift'
Grab an archive for your platform from the
latest release and put
the drift binary on your PATH.
Every method installs a drift binary.
drift completes its flags and option values, paths after --, and git
revisions: refs, commit hashes, HEAD~2 ancestors, HEAD@{1} reflog entries,
@{upstream}, HEAD:src/ paths, and both ends of a range like
main..feature.
The Homebrew, deb, rpm, apk, AUR, and Nix packages set this up for bash, zsh, and fish. Otherwise, add the line for your shell to its startup file:
eval "$(drift --completions bash)" # bash: ~/.bashrc
source <(drift --completions zsh) # zsh: ~/.zshrc, after compinit
drift --completions fish | source # fish: ~/.config/fish/completions/drift.fish
For PowerShell, add drift --completions powershell | Out-String | Invoke-Expression
to $PROFILE. For Elvish, add eval (drift --completions elvish | slurp) to
rc.elv.
zsh and fish treat an unmatched { as brace expansion, and PowerShell treats
it as the start of a script block. To complete a reflog entry in these shells,
quote the word ('HEAD@{). In zsh and fish, you can also escape the brace
(HEAD@\{).
drift # working tree vs HEAD
drift -A # ...and untracked files too
drift --staged # what's staged (alias: --cached)
drift HEAD~3 # a single commit
drift main..feature # a range
drift -w # watch the repo and refresh on every change
git diff | drift # pager mode: read a diff from stdin
[!TIP] Pair it with an AI agent. Leave
drift -wopen in a split while an agent (Copilot, Claude, etc.) works, every edit lands on screen instantly. Press F to freeze the view when you want to read, and again to resume.
Make it your default pager for git diff and git show:
git config --global pager.diff drift
git config --global pager.show drift
As the git show pager, drift shows the commit's hash, author, date, and
message above its diff. drift prints output that isn't a diff, such as
git show HEAD:README.md or git show --stat, straight to the terminal.
drift defaults to the ansi theme — your terminal's own colors, with syntax
highlighting off. Pick a theme to turn it on, globally via git config:
git config --global drift.theme onedark # onelight, dracula, nord, gruvbox-dark, ...
Some flags worth knowing:
| Flag | What it does |
|---|---|
-w, --watch | Refresh when the git index or refs change |
-A, --all | Also show untracked files (working-tree view only) |
-C, --directory DIR | Run as if started in DIR (worktrees, bare repos) |
-c, --config FILE | Use a specific config file |
--no-syntax | Turn off syntax highlighting for this run |
--no-commit-meta | Collapse the commit metadata to just the commit line |
--wrap / --no-wrap | Wrap long lines instead of scrolling horizontally |
-U, --context N | Lines of context around each change |
--ignore-whitespace | Ignore whitespace-only changes |
--diff-algorithm ALGO | myers, minimal, patience, or histogram |
-- PATHSPEC... | Limit to paths, e.g. drift -- src/ docs/ |
The footer shows your position in the whole diff: Top, a percentage such as
42%, or Bot. It shows All when the whole diff fits on screen. Percentages
use the top visible document row, including progress through a wrapped row.
The indicator stays hidden while the initial diff loads.
| Key | Action |
|---|---|
j k / ↑ ↓ | Move the cursor |
h l / ← → | Scroll horizontally (for lines wider than the view) |
0 $ | Scroll to line start / end |
d u / ^d ^u | Half page down / up |
space f ^f / b ^b | Full page down / up |
e y / ^e ^y | Scroll one line down / up |
g G | Top / bottom |
H M L | Cursor to screen top / middle / bottom |
{ } | Previous / next hunk |
[ ] / tab ⇧tab | Previous / next file |
/ | Search the current file (regex, smart-case) |
n N | Next / previous match |
s | Toggle split view |
w | Toggle line wrapping (long lines wrap instead of scrolling horizontally) |
S | File stats modal |
B | Toggle the file sidebar |
F | Toggle watch mode (follow changes, like less) |
a | Toggle untracked files (worktree view) |
V | Start / cancel a line selection; any motion key extends it |
c | Copy the selection, or the cursor line when nothing is selected |
C | Copy the whole current file |
enter | On a hunk header, expand folded context; on the commit line, expand / collapse the commit metadata |
o | Open the current file in $EDITOR |
r | Refresh |
? | Toggle the help footer |
q | Quit |
drift is fully mouse-driven too:
enter).? help badge in the status bar to toggle the help footer.Set theme = "..." in your config, or git config drift.theme .... The default
is ansi — your terminal's own 16 colors, with syntax highlighting and
word-diff emphasis left off. Any other built-in theme turns highlighting on:
onedark, onelightdraculagruvbox-dark, gruvbox-lightnordsolarized-dark, solarized-lightcatppuccin-mocha, catppuccin-lattetokyonightmonokaiansi — the default: borrows your terminal's own 16 colors so drift matches
whatever palette you already run. It leaves code text and word-diff emphasis
alone, since 16 colors are too few to layer cleanly over diff colors.A handful of syntect theme names also
work, but only the seven that ship in syntect's default set — InspiredGitHub,
Solarized (dark), Solarized (light), base16-eighties.dark,
base16-mocha.dark, base16-ocean.dark, and base16-ocean.light. They color
the code but won't repaint the UI chrome to match, and (Solarized aside) the
built-ins above already cover them with matching chrome. Any other theme name —
a custom .tmTheme, or a syntect theme not in that set — silently falls back to
onedark.
The themes/ directory has a full, commented config for every built-in theme.
Copy one and go:
mkdir -p ~/.config/drift
cp themes/dracula.toml ~/.config/drift/config.toml
drift looks for a config file, in order, at:
$XDG_CONFIG_HOME/drift/config.{toml,yaml,yml,json}~/.config/drift/config.{toml,yaml,yml,json}~/.drift.tomlTOML, YAML, and JSON all work. The top-level knobs:
theme = "onedark" # any built-in or syntect theme name
syntax = true # highlight diff content
intraline = true # word-level change emphasis
line-numbers = true # old/new line-number gutter
commit-meta = true # expand author/date/message; the commit line always shows for a single commit
wrap = false # wrap long lines instead of scrolling horizontally (toggle with w)
wrap-symbol = "↪" # symbol shown at the start of each wrapped continuation line
expand-symbol = "›" # gutter symbol on the collapsed commit line (expand to show metadata)
collapse-symbol = "⌄" # gutter symbol on the expanded commit line (collapse to hide metadata)
context-symbol = "⋯" # gutter symbol on a hunk header (reveal more context)
tab-width = 4
editor = "" # falls back to $VISUAL, then $EDITOR, then vi
sidebar = "auto" # "auto" (opens at width >= 150), "always", or "never"
sidebar-width = 30 # sidebar columns; drag its divider to resize live
sidebar-side = "left" # "left" or "right"
Colors come in two layers. [colors] is a named palette; [styles] maps UI
components to a fg bg attrs... spec resolved against that palette. Every color
token accepts a palette name, a literal #rrggbb, a 0-255 index, an ANSI color
name, or default/none/- for the terminal's own color. See any file in
themes/ for the full set with comments.
Anything you can set in a config file, you can set in git config under the
drift section, which is handy for per-repo overrides. Colors and styles go in
colors and styles subsections. Git forbids _ in a key, so a field like
add_emph becomes add-emph:
git config drift.theme nord
git config drift.line-numbers false
git config drift.colors.add '#00ff00'
git config drift.colors.add-emph '#003300'
git config drift.styles.statusbar 'foreground surface bold'
Or in ~/.gitconfig directly:
[drift]
theme = nord
line-numbers = false
[drift "colors"]
add = "#00ff00"
add-emph = "#003300"
[drift "styles"]
statusbar = "foreground surface bold"
selection = "none #ffd700"
For the full list of every setting, color, component style, and flag, see CONFIG.md.
drift's terminal UI is powered by uncurses, and its multi-channel releases are cut with GoReleaser.
MIT
4,695 followers · starred Aug 2026
3,416 followers · starred Aug 2026
269 followers · starred Aug 2026
2,582 followers · starred Aug 2026