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 log --graph --since=90d
- a1f9c02 scheduler: split tick from queue drainHEAD → main
- 7d4b8e1 merge: parallel pack writes (index-shard)
- c03f5aa index: shard pack writes across coresindex-shard
- 9b21d7e fs: drop stale mtime after rebase
- 4ec7a10 traverse: yield on interrupt while walking
- f82a0c4 merge: object cache v2 (object-cache)
- 2d65b91 cache: arena-backed mmap object cacheobject-cache
- 5a08e3c release: 2.5.0v2.5.0
- b7c1d40 delta: bound window size at 96 MiB
- e91f6a2 wip: revwalk cancellation hooksnext
- 3c40d8b release: 2.4.0v2.4.0
- 0a5b7c9 fs: add lock-free index reader
- f6d2a41 init: lattice skeleton
scheduler: split tick from queue drain
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.
signed (ed25519) 3 files, +255 -56
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.
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.
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.
Any depth
Lanes are assigned as you scroll, so a decade of history fits one screen without collapsing into a column of hashes.
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 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.
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.
brew install lattice
curl -fsSL lattice.sh/i | sh
mise use -g lattice@latest
[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.