How to Integrate External Diff Tools with Lazygit: Delta and Difft Configuration Guide
Lazygit integrates with external diff tools by treating them as pagers or full-diff drivers, executing commands inside a pseudo-terminal (PTY) to preserve color output and hyperlinks, and dynamically injecting Git's diff.external configuration when required.
Lazygit provides native support for lazygit external diff tools integration through a flexible pager configuration system in the jesseduffield/lazygit repository. By leveraging Git's diff.external mechanism and running commands inside a pseudo-terminal, Lazygit enables syntax-highlighted diffs and advanced comparison features directly within the terminal UI.
Understanding the Integration Architecture
Lazygit's integration operates through four distinct layers that translate user configuration into rendered diff output.
User Configuration Layer
Users declare external tools in ~/.config/lazygit/config.yml under the git.pagers array. Each entry specifies either a pager for piped output (suitable for delta) or an externalDiffCommand for full diff drivers (required for difft).
git:
pagers:
- pager: delta --dark --paging=never
- externalDiffCommand: difft --color=always
According to the source code documentation in docs/Custom_Pagers.md, this configuration supports multiple entries that can be cycled at runtime using the | key.
The PagerConfig Object
In pkg/config/pager_config.go, the PagerConfig struct parses these settings and exposes helper methods to retrieve the active command. The GetExternalDiffCommand() method returns the command string when an external diff driver is configured, as shown in lines 60-66.
// pkg/config/pager_config.go
func (self *PagerConfig) GetExternalDiffCommand() string {
currentPagerConfig := self.currentPagerConfig()
if currentPagerConfig == nil {
return ""
}
return currentPagerConfig.ExternalDiffCommand
}
Similarly, GetPagerCommand() returns pager commands such as delta with user-specified flags, while GetUseExternalDiffGitConfig() checks whether to fall back to Git's global settings.
Git Diff Command Construction
The DiffCommands.DiffCmdObj function in pkg/commands/git_commands/diff.go constructs the actual git diff invocation. When GetExternalDiffCommand() returns a non-empty string, Lazygit injects diff.external=<cmd> into Git's configuration and appends the --ext-diff flag to force Git to use the external driver.
// pkg/commands/git_commands/diff.go
func (self *DiffCommands) DiffCmdObj(diffArgs []string) *oscommands.CmdObj {
extDiffCmd := self.pagerConfig.GetExternalDiffCommand()
useExtDiff := extDiffCmd != ""
useExtDiffGitConfig := self.pagerConfig.GetUseExternalDiffGitConfig()
return self.cmd.New(
NewGitCmd("diff").
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
ArgIfElse(useExtDiff || useExtDiffGitConfig, "--ext-diff", "--no-ext-diff").
// ... additional arguments
)
}
Pseudo-Terminal (PTY) Execution
When a pager or external diff driver is required, Lazygit executes the Git command inside a pseudo-terminal via Gui.newPtyTask in pkg/gui/pty.go. This forces Git to treat the output as an interactive terminal, enabling color codes, hyperlinks, and proper formatting that would otherwise be stripped in pipe mode.
// pkg/gui/pty.go
func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error {
pager := gui.stateAccessor.GetPagerConfig().GetPagerCommand(width)
externalDiffCommand := gui.stateAccessor.GetPagerConfig().GetExternalDiffCommand()
useExtDiffGitConfig := gui.stateAccessor.GetPagerConfig().GetUseExternalDiffGitConfig()
if pager == "" && externalDiffCommand == "" && !useExtDiffGitConfig {
// No pager / external diff → run without PTY
return gui.newCmdTask(view, cmd, prefix)
}
// ... PTY execution logic follows
}
Configuring Delta as a Syntax-Highlighting Pager
Delta functions as a pager that receives diff output via stdin. To enable delta with hyperlink support for file navigation, configure the pager with the lazygit-edit:// protocol handler as documented in docs/Custom_Pagers.md.
# ~/.config/lazygit/config.yml
git:
pagers:
- pager: delta --dark --paging=never \
--line-numbers --hyperlinks \
--hyperlinks-file-link-format="lazygit-edit://{path}:{line}"
When viewing a file diff in Lazygit, delta renders syntax-highlighted output with clickable line numbers. Selecting a hyperlink opens the file at the specific line in your configured editor, provided your terminal supports the lazygit-edit:// protocol.
Configuring Difft as an External Diff Driver
Difftastic (difft) requires the full diff stream and operates as an external diff driver rather than a pager. Configure it using the externalDiffCommand key in your Lazygit configuration.
git:
pagers:
- externalDiffCommand: difft --color=always --display=inline
With this configuration, pressing Ctrl-t (<c-t>) on a file invokes git difftool --no-prompt, which Git routes through difft because of the injected diff.external setting. Lazygit displays the processed structural diff output in the main view.
Advanced Configuration Options
Using Git's Global diff.external Setting
Rather than specifying the command directly in Lazygit's configuration, you can instruct Lazygit to respect Git's global diff.external setting by enabling useExternalDiffGitConfig.
git:
pagers:
- useExternalDiffGitConfig: true
If you have previously configured git config --global diff.external difft, Lazygit automatically invokes that external driver when useExternalDiffGitConfig is enabled, as implemented in the DiffCmdObj logic referenced above.
Cycling Between Multiple Pagers
Lazygit supports defining multiple pager configurations and cycling between them at runtime. Press the | (pipe) key to rotate through the list defined under git.pagers. The currently active pager appears in the UI status bar, allowing quick switching between delta for syntax highlighting and standard diff output.
Summary
- Lazygit external diff tools integration relies on three core components: the
PagerConfigobject inpkg/config/pager_config.go, dynamic Git command construction inDiffCmdObj, and PTY execution innewPtyTask. - Delta operates as a pager receiving stdin, requiring the
pagerconfiguration key with optional hyperlink formatting for editor integration vialazygit-edit://URLs. - Difft requires full diff stream access and uses the
externalDiffCommandkey, invoked via Git'sdiff.externalmechanism with the--ext-diffflag. - Commands execute inside a pseudo-terminal when external tools are active, ensuring color output and terminal features render correctly.
- Multiple pagers can be defined and cycled using the
|key, withuseExternalDiffGitConfigproviding fallback to global Git settings as documented indocs/Config.md.
Frequently Asked Questions
Can I use both delta and difft simultaneously in Lazygit?
No, you cannot use both tools simultaneously for the same diff operation. However, you can define both in your git.pagers array and press | to cycle between them at runtime according to the source code in pkg/config/pager_config.go. Delta works best as a pager for syntax-highlighted patches, while difft excels at structural comparisons requiring the externalDiffCommand configuration.
Why does Lazygit use a pseudo-terminal for external diff tools?
Lazygit executes external diff commands inside a pseudo-terminal (PTY) to force Git into "terminal mode" rather than pipe mode. According to the implementation in pkg/gui/pty.go, this ensures tools like delta receive the isatty() response they expect, enabling color codes, hyperlinks, and formatted output that would otherwise be stripped when Git detects a non-interactive pipe.
How do I make delta hyperlinks open files in my editor?
Configure delta with the --hyperlinks-file-link-format="lazygit-edit://{path}:{line}" argument in your config.yml. This generates lazygit-edit:// URLs that Lazygit intercepts. Ensure your terminal emulator supports hyperlink protocols and that Lazygit's os.open command is configured to handle the lazygit-edit scheme with your preferred editor.
What happens if no external diff tool is configured?
When git.pagers is empty or no pager matches the current context, Lazygit falls back to standard Git diff output without PTY execution. The raw diff displays in the main view without syntax highlighting, and no external processes are spawned for diff generation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →