Clone URL: https://github.com/moses-y/serie


The Problem

Viewing a full git commit history in a terminal is usually a flat git log or a crude ASCII graph that quickly becomes unreadable as the history grows. Developers who need to explore branching, merging, and tag topology must either switch to a GUI or memorise complex git log flags. There is no single TUI that renders a rich, interactive commit graph using terminal image protocols.

What This Does

Serie is a Rust‑based TUI that draws commit graphs via terminal emulators’ graphics protocols (iTerm2, Kitty, kitty‑unicode). The core logic lives in src/app.rs (entry point run at line 149, which reaches 153 functions) and src/graph/image.rs (48 functions that prepare and upload rasterised graph images).

Key flows, measured from the internal call graph (654 resolved edges):

  • run → init_with_context → reset_refs_with → reset_tree_status (filesystem write).
  • commit is called from 22 places; init from 20; copy_git_dir from 19; generate_and_output_graph_images from 19.
  • The largest files by function count are src/widget/commit_list.rs (83 functions), src/app.rs (39 functions, 18 callees, file‑I/O), and src/graph/image.rs (48 functions, 3 callers).
  • src/config.rs defines config loading (load, read_config_from_path) and is called from 3 other modules; src/git.rs (34 functions) runs external git commands and is the only module that touches the filesystem outside the process.

Execution starts at run (src/app.rs:149); it cascades through open_user_command → render → image generation, then exits. No network or database is involved—only git repository reads/writes and terminal image output.

How It Is Wired

  1. run (src/app.rs:149) is the sole entry point; it parses CLI args, loads config, and calls init_with_context.
  2. init_with_context (src/app.rs:649) sets up the app state, reads the git repo via src/git.rs, and registers event handlers.
  3. Event loop in src/event.rs forwards key presses to open_user_command (src/app.rs:445), which dispatches to render (src/app.rs:321).
  4. render triggers generate_and_output_graph_images (src/graph/image.rs) that builds a PNG/ASCII representation using the chosen protocol (iTerm/Kitty).
  5. The image is uploaded to the terminal via the detected protocol (detect_kitty_graphics_protocol / detect_tmux in src/protocol.rs).

Files with the widest blast radius: src/app.rs (18 callees, file I/O), src/widget/commit_list.rs (83 functions, called from 5 others), and src/graph/image.rs (image upload path). Changing the graph‑rendering pipeline touches at least three of these modules.

How To Use It

Setup

# Install the binary (locked to the crate version)
cargo install --locked serie
# or use the prebuilt binary from the releases page

Configuration Config files are loaded in priority order:

  • $SERIE_CONFIG_FILE (if set, must exist)
  • $XDG_CONFIG_HOME/serie/config.toml (defaults to ~/.config/serie/config.toml)

If the file is absent, defaults apply. Example config.toml (TOML) may set graph_width, graph_style, or override the initial selection.

Running it

# In any git repository directory
serie
# Or with flags (see README for full list)
serie -n 30 -p kitty -o topo -g double -s angular

Real‑World Use

A developer exploring a large monorepo can quickly assess branch topology without leaving the terminal:

serie -n 50 -p iterm -o chrono -s rounded

Press ? to view default keybindings; j/k navigate commits, o opens a diff panel, and q quits. The graph renders via the iTerm2 inline image protocol, so the commit DAG appears as a scalable vector graphic inside the terminal.

Code Health & Issues

  • MEDIUM – Declare least‑privilege permissions for GITHUB_TOKEN in .github/workflows/build.yml (2 workflows have no permissions declaration). Add permissions: contents: read at the top and widen per‑job as needed.
  • MEDIUM – Enable Dependabot or Renovate. No update bot is configured for the single manifest; add .github/dependabot.yml covering Rust and GitHub Actions ecosystems.
  • MEDIUM – Gate pull requests on a dependency vulnerability scan. CI lacks a dependency‑review step; add dependency-review-action on pull_request or osv-scanner on push/schedule.
  • MEDIUM – Set persist-credentials: false on checkout in .github/workflows/build.yml. The token persists in .git/config for later steps; restrict it with with: persist-credentials: false and pass an explicit token only to the push step.
  • LOW – Set timeout-minutes on workflow jobs. Four jobs have no timeout, risking overlap on a two‑hourly schedule; add a realistic bound per job.

The Bottom Line

Serie delivers a polished, protocol‑driven commit‑graph TUI with a small, well‑scoped codebase (133 files, 28 Rust source files). Its strength lies in rapid terminal‑based graph visualization and minimal external dependencies. The main risk surfaces in CI hygiene (token permissions, dependency scanning) and in the moderately nested, duplicated logic within src/app.rs, src/config.rs, and src/widget/commit_list.rs—areas that benefit from refactoring to reduce cognitive load. Teams that need an in‑terminal commit‑graph view without a heavy GUI will find Serie pragmatic; those requiring deep UI customisation or extensive git client features should look elsewhere.