lattice2.5.0 Install

A terminal UI for git history

Navigate the graph,
not the log.

Lattice draws a repository as the DAG it actually is: lanes, merges and refs, at sixty frames a second across 1.4 million commits. It is keyboard-first, it never shells out to git log in a loop, and it opens a monorepo faster than you can finish typing git log.

brew install lattice See how it renders
  • macOS · Linux · Windows
  • git 2.32 or newer
  • 4.2 MB binary, no runtime

linux.git · cold cache · median of ten

Indexed
1.4Mcommits
To first frame
0.4ms
Resident
12MB
Pan
60fps
lattice ~/work/kernel 1 364 802 commitsmain

lattice log --graph --since=90d

  • a1f9c02 scheduler: split tick from queue drainHEAD → main Brandt·3 h
  • 7d4b8e1 merge: parallel pack writes (index-shard) Kovac·1 d
  • c03f5aa index: shard pack writes across coresindex-shard Adeyemi·1 d
  • 9b21d7e fs: drop stale mtime after rebase Lund·2 d
  • 4ec7a10 traverse: yield on interrupt while walking Brandt·3 d
  • f82a0c4 merge: object cache v2 (object-cache) Kovac·5 d
  • 2d65b91 cache: arena-backed mmap object cacheobject-cache Vasquez·6 d
  • 5a08e3c release: 2.5.0v2.5.0 Kovac·1 w
  • b7c1d40 delta: bound window size at 96 MiB Adeyemi·2 w
  • e91f6a2 wip: revwalk cancellation hooksnext Lund·3 w
  • 3c40d8b release: 2.4.0v2.4.0 Kovac·5 w
  • 0a5b7c9 fs: add lock-free index reader Vasquez·6 w
  • f6d2a41 init: lattice skeleton Kovac·4 mo
a1f9c02 HEAD → main

scheduler: split tick from queue drain

Lena Brandt <lena@lattice.sh>
Tue 08 Oct 2026, 14:02:11 +0200

Moves the timer callback out of the drain loop so a slow filesystem cannot starve the tick. Flat on the fast path, 4 percent better at p99 on linux.git.

src/core/sched/tick.c+128 -44
src/core/sched/queue.c+36 -12
tests/sched/drain_test.c+91 -0

signed (ed25519) 3 files, +255 -56

jk move gG ends ↵ open y copy hash / search ? keys 13 in range · commit 1 of 13

Keys

The mouse is optional.

Every action is bound before it is drawn. The defaults are the ones you already know from less and normal-mode vim, and all of it is one file in ~/.config/lattice/keys.toml.

Move

  • j▼

    next commit

  • k▲

    previous commit

  • Ctrld

    half page down

  • gg

    first commit in range

  • G

    last commit in range

  • hl

    jump lanes, follow an edge

Read

  • ↵

    open the commit

  • p

    toggle the patch

  • f

    blame the file under point

  • a

    show all parents side by side

  • ][

    next and previous ref

  • q

    quit, always

Act

  • /

    search forward

  • ?

    search backward

  • F

    filter, keep the graph intact

  • b

    start a bisect on this range

  • C

    cherry-pick into the buffer

  • y

    copy the full hash


Graph

Lanes, merges and refs, drawn from the object store.

A log flattens a graph and then asks you to imagine it back. Lattice keeps it: the walk is a topological order, the edges are real, and refs are drawn where they point instead of in a legend.

01

Two parents, one line

Merges are rings, not words. Follow an edge with l and Lattice walks it, including the parent nobody rebased onto main.

02

Refs where they belong

Branch heads, tags and remotes are painted on their own commit. A dangling tip in the middle of the history stays visible instead of sorting away.

03

Any depth

Lanes are assigned as you scroll, so a decade of history fits one screen without collapsing into a column of hashes.

init index-shard object-cache HEAD

Query

Ask in one line.

A grammar of facets, filterable while you type, with the graph preserved. It is not a query language to learn: it is the flags you already remember, plus the ones you kept meaning to add.

lattice session: ~/work/kernel
$ lattice log --graph \
  author:brandt since:90d path:src/fs/** revs:v2.4..main \
  --grep="cache" --no-merges --stat=inline

1 364 802 commits → 41 in range · 2 lanes · 0 merges · 3.1 ms
author: / co-author:
name, email or a git identity from .mailmap. Prefix with ! to negate.
path:
globs over the tree at that commit, not just the diff. src/fs/** includes the submodules you forgot about.
since: / until:
90d, 2026-03, v2.4, or any revspec. Timezone-aware, no quoting rules.
revs:
a range expression, kept as a range. Filters narrow what is drawn; they never redraw the graph.
--grep / --diff
searches commit messages or content, using git's own index when one is warm.

Performance

For the repositories people refuse to open.

Lattice reads packs directly, mmaps what it can and decodes lazily. It paints the first screen before the walk is finished, then fills in the lanes as objects resolve.

Nothing is cached to disk in a form git does not already own: delete .git/lattice and the next start is simply a cold one. Timings below are median of ten on a 2024 laptop, NVMe, page cache cold.

0.41.14.831128 50100150200 ms to first frame 1k10k100k1M5M 5.1M commits, still under 130 ms

Install

One binary. Nothing else.

Homebrew, an installer script or your package manager. Lattice reads .git the way git does and writes nothing you cannot delete.

macOS
brew install lattice
Linux · installer
curl -fsSL lattice.sh/i | sh
any · package manager
mise use -g lattice@latest
~/.config/lattice/config.toml the whole file, usually
[ui]
theme        = "graphite"     # 8 built in, none of them loud
lanes        = "auto"         # or a fixed count

[walk]
order        = "topo"         # topo | date | author
max-resident = "64 MiB"

[ref]
decorate     = ["head", "tag", "remote"]

Requires

git 2.32 or newer. Works in worktrees, submodules and bare clones.

Terminal

Any truecolor terminal. 24-bit depth optional, it degrades to 16 without losing a lane.

Scripts

lattice --json emits the same DAG the UI draws. Pipe it to anything.

Sizes

4.2 MB signed binary. No telemetry, no update checker, no config schema to guess.