Skip to content
Back to top

# kitty-diff

A fast side-by-side diff tool with syntax highlighting and images

## Major Features

- Displays diffs side-by-side in the kitty terminal

- Does syntax highlighting of the displayed diffs, asynchronously, for maximum speed

- Displays images as well as text diffs, even over SSH

- Does recursive directory diffing

Screenshot, showing a sample diff

## Installation

Simply install kitty.

## Usage

In the kitty terminal, run:

    kitten diff file1 file2

to see the diff between `file1` and `file2`.

Create an alias in your shell’s startup file to shorten the command, for example:

    alias d="kitten diff"

Now all you need to do to diff two files is:

    d file1 file2

You can also pass directories instead of files to see the recursive diff of the directory contents.

## Keyboard controls

Action | Shortcut
--- | ---
Quit | `Q`
Scroll line up | `K`, `Up`
Scroll line down | `J`, `Down`
Scroll page up | `PgUp`
Scroll page down | `PgDn`
Scroll to top | `Home`
Scroll to bottom | `End`
Scroll to next page | `Space`, `PgDn`, `Ctrl`+`F`
Scroll to previous page | `PgUp`, `Ctrl`+`B`
Scroll down half page | `Ctrl`+`D`
Scroll up half page | `Ctrl`+`U`
Scroll to next change | `N`
Scroll to previous change | `P`
Increase lines of context | `+`
Decrease lines of context | `-`
All lines of context | `A`
Restore default context | `=`
Search forwards | `/`
Search backwards | `?`
Clear search or exit | `Esc`
Scroll to next match | `>`, `.`
Scroll to previous match | `<`, `,`
Copy selection to clipboard | `y`
Copy selection or exit | `Ctrl`+`C`

## Integrating with git

Add the following to `~/.gitconfig`:

    [diff]
        tool = kitty
        guitool = kitty.gui
    [difftool]
        prompt = false
        trustExitCode = true
    [difftool "kitty"]
        cmd = kitten diff $LOCAL $REMOTE
    [difftool "kitty.gui"]
        cmd = kitten diff $LOCAL $REMOTE

Now to use kitty-diff to view git diffs, you can simply do:

    git difftool --no-symlinks --dir-diff

Once again, creating an alias for this command is useful.

## Why does this work only in kitty?

The diff kitten makes use of various features that are kitty only, such as the kitty graphics protocol, the extended keyboard protocol, etc. It also leverages terminal program infrastructure I created for all of kitty’s other kittens to reduce the amount of code needed (the entire implementation is under 3000 lines of code).

And fundamentally, it’s kitty only because I wrote it for myself, and I am highly unlikely to use any other terminals :)

## Configuration

You can configure the colors used, keyboard shortcuts, the diff implementation, the default lines of context, etc. by creating a `diff.conf` file in your kitty config folder. See below for the supported configuration directives.

## Diffing

syntax_aliases

    syntax_aliases pyj:py pyi:py recipe:py

File extension aliases for syntax highlight. For example, to syntax highlight `file.xyz` as `file.abc` use a setting of `xyz:abc`. Multiple aliases must be separated by spaces.

num_context_lines

    num_context_lines 3

The number of lines of context to show around each change.

diff_cmd

    diff_cmd auto

The diff command to use. Must contain the placeholder `_CONTEXT_` which will be replaced by the number of lines of context. A few special values are allowed: `auto` will automatically pick an available diff implementation. `builtin` will use the anchored diff algorithm from the Go standard library. `git` will use the git command to do the diffing. `diff` will use the diff command to do the diffing.

replace_tab_by

    replace_tab_by \x20\x20\x20\x20

The string to replace tabs with. Default is to use four spaces.

ignore_name

A glob pattern that is matched against only the filename of files and directories. Matching files and directories are ignored when scanning the filesystem to look for files to diff. Can be specified multiple times to use multiple patterns. For example:

    ignore_name .git
    ignore_name *~
    ignore_name *.pyc

mark_moved_lines

    mark_moved_lines yes

Highlight lines that are moved, that is removed from the left and added to the right differently, using the `moved_bg` color.

word_diff_mode

    word_diff_mode words

The algorithm to use for highlighting which parts of changed lines differ. When set to `words`, changed words in each changed line are highlighted. When set to `central`, the central changed region of each changed line is highlighted at the byte level. The `words` mode is generally more useful as it shows exactly which words changed. Note that the `words` mode only applies when a changed chunk has equal numbers of added and removed lines.

word_regex

    word_regex [^\s\p{P}]+

The regular expression used to define a word when `word_diff_mode` is `words`. The default value matches any run of non-whitespace and non-punctuation characters. The expression must be a valid Go regular expression. If an invalid expression is provided, diff will fail with an error.

## Colors

color_scheme

    color_scheme auto

Whether to use the light or dark colors. The default of `auto` means to follow the parent terminal color scheme. Note that the actual colors used for dark schemes are set by the `dark_*` settings below and the non-prefixed settings are used for light colors.

pygments_style

    pygments_style default

The pygments color scheme to use for syntax highlighting. See pygments builtin styles for a list of schemes. Note that this does not change the colors used for diffing, only the colors used for syntax highlighting. To change the general colors use the settings below. This sets the colors used for light color schemes, use `dark_pygments_style` to change the colors for dark color schemes.

dark_pygments_style

    dark_pygments_style github-dark

The pygments color scheme to use for syntax highlighting with dark colors. See pygments builtin styles for a list of schemes. Note that this does not change the colors used for diffing, only the colors used for syntax highlighting. To change the general colors use the settings below. This sets the colors used for dark color schemes, use `pygments_style` to change the colors for light color schemes.

foreground, dark_foreground, background, dark_background

    foreground      black
    dark_foreground #f8f8f2
    background      white
    dark_background #212830

Basic colors

title_fg, dark_title_fg, title_bg, dark_title_bg

    title_fg      black
    dark_title_fg white
    title_bg      white
    dark_title_bg #212830

Title colors

margin_bg, dark_margin_bg, margin_fg, dark_margin_fg

    margin_bg      #fafbfc
    dark_margin_bg #212830
    margin_fg      #aaaaaa
    dark_margin_fg #aaaaaa

Margin colors

removed_bg, dark_removed_bg, highlight_removed_bg, dark_highlight_removed_bg, removed_margin_bg, dark_removed_margin_bg

    removed_bg                #ffeef0
    dark_removed_bg           #352c33
    highlight_removed_bg      #fdb8c0
    dark_highlight_removed_bg #5c3539
    removed_margin_bg         #ffdce0
    dark_removed_margin_bg    #5c3539

Removed text backgrounds

added_bg, dark_added_bg, highlight_added_bg, dark_highlight_added_bg, added_margin_bg, dark_added_margin_bg

    added_bg                #e6ffed
    dark_added_bg           #263834
    highlight_added_bg      #acf2bd
    dark_highlight_added_bg #31503d
    added_margin_bg         #cdffd8
    dark_added_margin_bg    #31503d

Added text backgrounds

moved_bg, dark_moved_bg, moved_margin_bg, dark_moved_margin_bg

    moved_bg             #fffde7
    dark_moved_bg        #003333
    moved_margin_bg      #fff3b0
    dark_moved_margin_bg #00495b

Moved text backgrounds (same text that was removed in one place and added in another)

filler_bg, dark_filler_bg

    filler_bg      #fafbfc
    dark_filler_bg #262c36

Filler (empty) line background

margin_filler_bg, dark_margin_filler_bg

    margin_filler_bg      none
    dark_margin_filler_bg none

Filler (empty) line background in margins, defaults to the filler background

hunk_margin_bg, dark_hunk_margin_bg, hunk_bg, dark_hunk_bg

    hunk_margin_bg      #dbedff
    dark_hunk_margin_bg #0c2d6b
    hunk_bg             #f1f8ff
    dark_hunk_bg        #253142

Hunk header colors

search_bg, dark_search_bg, search_fg, dark_search_fg, select_bg, dark_select_bg, select_fg, dark_select_fg

    search_bg      #444
    dark_search_bg #2c599c
    search_fg      white
    dark_search_fg white
    select_bg      #b4d5fe
    dark_select_bg #2c599c
    select_fg      black
    dark_select_fg white

Highlighting

## Keyboard shortcuts

Quit

    map q quit
    map esc quit

Scroll down

    map j scroll_by 1
    map down scroll_by 1

Scroll up

    map k scroll_by -1
    map up scroll_by -1

Scroll to top

    map home scroll_to start

Scroll to bottom

    map end scroll_to end

Scroll to next page

    map page_down scroll_to next-page
    map space scroll_to next-page
    map ctrl+f scroll_to next-page

Scroll to previous page

    map page_up scroll_to prev-page
    map ctrl+b scroll_to prev-page

Scroll down half page

    map ctrl+d scroll_to next-half-page

Scroll up half page

    map ctrl+u scroll_to prev-half-page

Scroll to next change

    map n scroll_to next-change

Scroll to previous change

    map p scroll_to prev-change

Scroll to next file

    map shift+j scroll_to next-file

Scroll to previous file

    map shift+k scroll_to prev-file

Show all context

    map a change_context all

Show default context

    map = change_context default

Increase context

    map + change_context 5

Decrease context

    map - change_context -5

Search forward

    map / start_search regex forward

Search backward

    map ? start_search regex backward

Scroll to next search match

    map . scroll_to next-match
    map > scroll_to next-match

Scroll to previous search match

    map , scroll_to prev-match
    map < scroll_to prev-match

Search forward (no regex)

    map f start_search substring forward

Search backward (no regex)

    map b start_search substring backward

Copy selection to clipboard

    map y copy_to_clipboard

Copy selection to clipboard or exit if no selection is present

    map ctrl+c copy_to_clipboard_or_exit

## Source code for diff

The source code for this kitten is available on GitHub.

## Command Line Interface

    kitten diff [options] file_or_directory_left file_or_directory_right

Show a side-by-side diff of the specified files/directories. You can also use ssh:hostname:remote-file-path to diff remote files.

### Options

--context <CONTEXT>

  Number of lines of context to show between changes. Negative values use the number set in `diff.conf`. Default: `-1`

--config <CONFIG>

  Specify a path to the configuration file(s) to use. All configuration files are merged onto the builtin `diff.conf`, overriding the builtin values. This option can be specified multiple times to read multiple configuration files in sequence, which are merged. Use the special value `NONE` to not load any config file.

  If this option is not specified, config files are searched for in the order: `$XDG_CONFIG_HOME/kitty/diff.conf`, `~/.config/kitty/diff.conf`, `$XDG_CONFIG_DIRS/kitty/diff.conf`. The first one that exists is used as the config file.

  If the environment variable `KITTY_CONFIG_DIRECTORY` is specified, that directory is always used and the above searching does not happen.

  If `/etc/xdg/kitty/diff.conf` exists, it is merged before (i.e. with lower priority) than any user config files. It can be used to specify system-wide defaults for all users. You can use either `-` or `/dev/stdin` to read the config from STDIN.

--override <OVERRIDE>, -o <OVERRIDE>

  Override individual configuration options, can be specified multiple times. Syntax: name=value. For example: -o background=gray

## Sample diff.conf

You can download a sample `diff.conf` file with all default settings and comments describing each setting by clicking: `sample diff.conf`.