Introduction
Serie (/zéːriə/) is a TUI application that uses the terminal emulators' image display protocol to render commit graphs like git log --graph --all.
(This demo shows Ratatui repository!)
Why?
While some users prefer to use Git via CLI, they often rely on a GUI or feature-rich TUI to view commit logs. Others may find git log --graph sufficient.
Personally, I found the output from git log --graph difficult to read, even with additional options. Learning complex tools just to view logs seemed cumbersome.
Goals
- Provide a rich
git log --graphexperience in the terminal. - Offer commit graph-centric browsing of Git repositories.
Non-Goals
- Implement a fully-featured Git client.
- Create a TUI application with a complex UI.
- Works in any terminal environment.
Getting Started
Requirements
- Git
- Supported terminal emulator
- Refer to Compatibility for details.
Installation
Cargo
$ cargo install --locked serie
Arch Linux
$ pacman -S serie
Homebrew
$ brew install serie
or from tap:
$ brew install lusingander/tap/serie
NetBSD
$ pkgin install serie
Downloading binary
You can download pre-compiled binaries from releases.
Build from source
If you want to check the latest development version, build from source:
$ git clone https://github.com/lusingander/serie.git
$ cd serie
$ cargo build --release # Unless it's a release build, it's very slow.
$ ./target/release/serie
Basic Usage
Run serie in the directory where your git repository exists.
$ cd <your git repository>
$ serie
If you want to specify it using command line options, see Command Line Options.
Command Line Options
-p, --protocol <TYPE>
A protocol type for rendering images of commit graphs.
Possible values: auto, iterm, kitty
By default auto will guess the best supported protocol for the current terminal (if listed in Supported terminal emulators).
-o, --order <TYPE>
Commit ordering algorithm.
Possible values: chrono, topo
chrono will order commits by commit date if possible.
topo will order commits on the same branch consecutively if possible.
-g, --graph-width <TYPE>
The character width that a graph image unit cell occupies.
Possible values: auto, double, single
If not specified or auto is specified, double will be used automatically if there is enough width to display it, single otherwise.
-s, --graph-style <TYPE>
The commit graph image edge style.
Possible values: rounded, angular
rounded will use rounded edges for the graph lines.
angular will use angular edges for the graph lines.
-i, --initial-selection <TYPE>
The initial selection of commit when starting the application.
Possible values: latest, head
latest will select the latest commit.
head will select the commit at HEAD.
--preload
By default, graph images are generated and loaded lazily as needed.
If --preload is specified, all graph images will be generated and loaded at startup. This can result in smoother scrolling, as the images are already available, and might reduce memory usage. However, this may lead to slower startup times, especially for large repositories.
Compatibility
Supported terminal emulators
These image protocols are supported:
The terminals on which each has been confirmed to work are listed below.
Inline Images Protocol
| Terminal emulator | Note |
|---|---|
| iTerm2 | But slower than other terminals |
| WezTerm | |
| VSCode integrated terminal * | Requires the terminal.integrated.enableImages setting to be enabled |
*Not only the VSCode integrated terminal, but any terminal emulator using xterm.js may basically work in the same way as long as image display feature is enabled.
Terminal graphics protocol
Unsupported environments
- Sixel graphics is not supported.
- Terminal multiplexers (screen, tmux, Zellij, etc.) are not supported.
Configurations
You can use config.toml to configure various aspects of your application.
Config files are loaded in the following order of priority:
$SERIE_CONFIG_FILE- If
$SERIE_CONFIG_FILEis set but the file does not exist, an error occurs.
- If
$XDG_CONFIG_HOME/serie/config.toml- If
$XDG_CONFIG_HOMEis not set,~/.config/will be used instead.
- If
If the config file does not exist, the default values will be used for all items. If the config file exists but some items are not set, the default values will be used for those unset items.
Config File Format
The values set in this example are the default values.
[core.option]
# The protocol type for rendering images of commit graphs.
# The value specified in the command line argument takes precedence.
# type: enum (possible values: "auto", "iterm", "kitty")
protocol = "auto"
# The commit ordering algorithm.
# The value specified in the command line argument takes precedence.
# type: enum (possible values: "chrono", "topo")
order = "chrono"
# The character width that a graph image unit cell occupies.
# The value specified in the command line argument takes precedence.
# type: enum (possible values: "auto", "double", "single")
graph_width = "auto"
# The commit graph image edge style.
# The value specified in the command line argument takes precedence.
# type: enum (possible values: "rounded", "angular")
graph_style = "rounded"
# The initial selection of commit when starting the application.
# The value specified in the command line argument takes precedence.
# type: enum (possible values: "latest", "head")
initial_selection = "latest"
[core.search]
# Whether to enable ignore case by default.
# type: boolean
ignore_case = false
# Whether to enable fuzzy matching by default.
# type: boolean
fuzzy = false
[core.user_command]
# The command definition for generating the content displayed in the user command view.
# Multiple commands can be specified in the format commands_{n}.
# For details about user command, see the separate User command section.
# type: object
commands_1 = { name = "git diff", commands = ["git", "--no-pager", "diff", "--color=always", "{{first_parent_hash}}", "{{target_hash}}"]}
# The number of spaces to replace tabs in the user command output.
# type: u16
tab_width = 4
[core.external]
# Configuration for external commands used by the application.
# The clipboard command to use for copy operations.
# - "Auto": Use the default clipboard library
# - { Custom = { commands = ["..."] } }: Use a custom command that receives text via stdin
# type: enum
# Examples:
# clipboard = "Auto"
# clipboard = { Custom = { commands = ["wl-copy"] } }
# clipboard = { Custom = { commands = ["xclip", "-selection", "clipboard"] } }
clipboard = "Auto"
[ui.common]
# The type of a cursor to display in the input.
# If `cursor_type = "Native"` is set, the terminal native cursor is used.
# If `cursor_type = { "Virtual" = "|" }` is set, a virtual cursor with the specified string will be used.
# type: enum
cursor_type = "Native"
[ui.list]
# The minimum width of a subject in the commit list.
# type: u16
subject_min_width = 20
# The date format of a author date in the commit list.
# The format must be specified in strftime format.
# https://docs.rs/chrono/latest/chrono/format/strftime/index.html
# type: string
date_format = "%Y-%m-%d"
# The width of a author date in the commit list.
# type: u16
date_width = 10
# Whether to show a author date in the commit list in local timezone.
# type: boolean
date_local = true
# The width of a author name in the commit list.
# type: u16
name_width = 20
[ui.detail]
# The height of a commit detail area.
# type: u16
height = 20
# The date format of a author/committer date in the commit detail.
# The format must be specified in strftime format.
# https://docs.rs/chrono/latest/chrono/format/strftime/index.html
# type: string
date_format = "%Y-%m-%d %H:%M:%S %z"
# Whether to show a author/committer date in the commit list in local timezone.
# type: boolean
date_local = true
[ui.user_command]
# The height of a user command area.
# type: u16
height = 20
[ui.refs]
# The width of a refs list area.
# type: u16
width = 26
[graph.color]
# Colors should be specified in the format #RRGGBB or #RRGGBBAA.
# Array of colors used for the commit graph.
# type: array of strings
branches = [
"#E06C76",
"#98C379",
"#E5C07B",
"#61AFEF",
"#C678DD",
"#56B6C2",
]
# Color of the edge surrounding the commit circles in the graph.
# type: string
edge = "#00000000"
# Background color of the commit graph.
# type: string
background = "#00000000"
[color]
# The colors of each element of the application.
# Note: Graph colors are specified with [graph.color].
#
# Colors should be specified in one of the following formats:
# - ANSI color name
# - "red", "bright-blue", "light-red", "reset", ...
# - 8-bit color (256-color) index values
# - "34", "128", "255", ...
# - 24-bit true color hex codes
# - "#abcdef", ...
# type: string
fg = "reset"
bg = "reset"
list_selected_fg = "white"
list_selected_bg = "dark-gray"
list_ref_paren_fg = "yellow"
list_ref_branch_fg = "green"
list_ref_remote_branch_fg = "red"
list_ref_tag_fg = "yellow"
list_ref_stash_fg = "magenta"
list_head_fg = "cyan"
list_subject_fg = "reset"
list_name_fg = "cyan"
list_hash_fg = "yellow"
list_date_fg = "magenta"
list_match_fg = "black"
list_match_bg = "yellow"
detail_label_fg = "reset"
detail_name_fg = "reset"
detail_date_fg = "reset"
detail_email_fg = "blue"
detail_hash_fg = "reset"
detail_ref_branch_fg = "green"
detail_ref_remote_branch_fg = "red"
detail_ref_tag_fg = "yellow"
detail_file_change_add_fg = "green"
detail_file_change_modify_fg = "yellow"
detail_file_change_delete_fg = "red"
detail_file_change_move_fg = "magenta"
ref_selected_fg = "white"
ref_selected_bg = "dark-gray"
help_block_title_fg = "green"
help_key_fg = "yellow"
virtual_cursor_fg = "reset"
status_input_fg = "reset"
status_input_transient_fg = "dark-gray"
status_info_fg = "cyan"
status_success_fg = "green"
status_warn_fg = "yellow"
status_error_fg = "red"
divider_fg = "dark-gray"
[keybind]
# See default-keybind.toml for a specific example configuration.
# ...
Keybindings
You can see the keybindings by pressing the ? key.
The default key bindings can be overridden.
List of all default keybindings
Common
| Key | Description | Corresponding keybind |
|---|---|---|
| Ctrl-c q | Quit app | force_quit quit |
| ? | Open help | help_toggle |
Commit List
| Key | Description | Corresponding keybind |
|---|---|---|
| Down/Up j/k | Move down/up | navigate_down navigate_up |
| J/K | Move down/up | select_down select_up |
| Alt-Down Alt-j | Move to parent commit | go_to_parent |
| g/G | Go to top/bottom | go_to_top go_to_bottom |
| Ctrl-f/b | Scroll page down/up | page_down page_up |
| Ctrl-d/u | Scroll half page down/up | half_page_down half_page_up |
| Ctrl-e/y | Scroll down/up | scroll_down scroll_up |
| H/M/L | Select top/middle/bottom of the screen | select_top select_middle select_bottom |
| Enter | Show commit details Apply search (if searching) | confirm |
| Tab | Open refs list | ref_list_toggle |
| / | Start search | search |
| Esc | Cancel search | cancel |
| n/N | Go to next/previous search match | go_to_next go_to_previous |
| Ctrl-g | Toggle ignore case (if searching) | ignore_case_toggle |
| Ctrl-x | Toggle fuzzy match (if searching) | fuzzy_toggle |
| c/C | Copy commit short/full hash | short_copy full_copy |
| d | Toggle custom user command view | user_command_view_toggle_1 |
Commit Detail
| Key | Description | Corresponding keybind |
|---|---|---|
| Esc Backspace | Close commit details | close cancel |
| Down/Up j/k | Scroll down/up | navigate_down navigate_up |
| Ctrl-f/b | Scroll page down/up | page_down page_up |
| Ctrl-d/u | Scroll half page down/up | half_page_down half_page_up |
| g/G | Go to top/bottom | go_to_top go_to_bottom |
| J/K | Select older/newer commit | select_down select_up |
| Alt-Down Alt-j | Select parent commit | go_to_parent |
| c/C | Copy commit short/full hash | short_copy full_copy |
| d | Toggle custom user command view | user_command_view_toggle_1 |
Refs List
| Key | Description | Corresponding keybind |
|---|---|---|
| Esc Backspace Tab | Close refs list | close cancel ref_list_toggle |
| Down/Up j/k | Move down/up | navigate_down navigate_up |
| J/K | Move down/up | select_down select_up |
| g/G | Go to top/bottom | go_to_top go_to_bottom |
| Right/Left l/h | Open/Close node | navigate_right navigate_left |
| c | Copy ref name | short_copy |
User Command
| Key | Description | Corresponding keybind |
|---|---|---|
| Esc Backspace | Close user command | close cancel |
| Down/Up j/k | Scroll down/up | navigate_down navigate_up |
| J/K | Scroll down/up | select_down select_up |
| Ctrl-f/b | Scroll page down/up | page_down page_up |
| Ctrl-d/u | Scroll half page down/up | half_page_down half_page_up |
| g/G | Go to top/bottom | go_to_top go_to_bottom |
| J/K | Select older/newer commit | select_down select_up |
| Alt-Down Alt-j | Select parent commit | go_to_parent |
Help
| Key | Description | Corresponding keybind |
|---|---|---|
| Esc Backspace ? | Close help | close cancel help_toggle |
| Down/Up j/k | Scroll down/up | navigate_down navigate_up |
| J/K | Scroll down/up | select_down select_up |
| Ctrl-f/b | Scroll page down/up | page_down page_up |
| Ctrl-d/u | Scroll half page down/up | half_page_down half_page_up |
| g/G | Go to top/bottom | go_to_top go_to_bottom |
Custom Keybindings
You can set your own custom key bindings.
Custom key bindings can be applied by writing them in the [keybind] section of the config file.
The default key binding settings are described in ./assets/default-keybind.toml.
You can set key bindings for each action in the same format.
- It is possible to set multiple key bindings for one action.
- If you do not set key bindings for an action, the default key bindings will be assigned.
- You can disable an action by setting
[]as the key bindings.
Key Formats
You can use the following formats to define key bindings.
Modifier Keys
ctrl-alt-shift-
Modifiers can be combined, for example: ctrl-shift-a.
Special Keys
| Key | Description |
|---|---|
esc | Escape |
enter | Enter |
left | Left arrow |
right | Right arrow |
up | Up arrow |
down | Down arrow |
home | Home |
end | End |
pageup | Page Up |
pagedown | Page Down |
backtab | Back Tab (Shift + Tab) |
backspace | Backspace |
delete | Delete |
insert | Insert |
f1 - f12 | Function keys |
space | Space |
hyphen, minus | Hyphen (-) |
tab | Tab |
Character Keys
Any single character not listed above (e.g., a, b, 1, !) can be used as a key.
Features
User Command
The User command view allows you to display the output (stdout) of your custom external commands. This allows you to do things like view commit diffs using your favorite tools.
To define a user command, you need to configure the following two settings:
- Keybinding definition. Specify the key to display each user command.
- Config:
keybind.user_command_view_toggle_{n}
- Config:
- Command definition. Specify the actual command you want to execute.
- Config:
core.user_command.commands_{n}
- Config:
Configuration example:
[keybind]
user_command_view_toggle_1 = ["d"]
user_command_view_toggle_2 = ["shift-d"]
[core.user_command]
commands_1 = { "name" = "git diff", commands = ["git", "--no-pager", "diff", "--color=always", "{{first_parent_hash}}", "{{target_hash}}"] }
commands_2 = { "name" = "xxx", commands = ["xxx", "{{first_parent_hash}}", "{{target_hash}}", "--width", "{{area_width}}", "--height", "{{area_height}}"] }
Variables
The following variables can be used in command definitions. They will be replaced with their respective values command is executed.
{{target_hash}}- The hash of the selected commit.
- example:
b0ce4cb9c798576af9b4accc9f26ddce5e72063d
{{first_parent_hash}}- The hash of the first parent of the selected commit.
- example:
c103d9744df8ebf100773a11345f011152ec5581
{{area_width}}- Width of the user command display area (number of cells).
- example:
80
{{area_height}}- Height of the user command display area (number of cells).
- example:
30
Screenshots
The following repositories are used as these examples:
FAQ
Why doesn't the graph display?
Serie displays graphs using specific terminal graphics protocols (such as Kitty and iTerm2 inline images).
If your terminal emulator doesn't support one of these protocols, Serie will not work — there is no fallback or workaround.
This is a fundamental requirement, not a limitation that can be worked around. For a list of supported terminal emulators and compatible environments, see Compatibility.
What are the advantages over other git TUI clients?
Compared to other git TUI clients, Serie offers the following advantages:
- High-quality graph visualization using terminal graphics protocols
- Simple and clean interface
On the other hand, Serie may not be for you if:
- You're satisfied with
git log --graphor the graph display in existing TUI clients - You need to perform complex git operations within a TUI client