aerie
Review every git worktree at once.
A repository with five worktrees is five separate answers to "what changed?".
aerie puts them on one screen — every worktree's changed files in a single
list, with the files more than one worktree is touching marked.
It is read-only. It cannot commit, checkout, push, fetch, or reach a
network. That is enforced by an argv allowlist, not by convention.
Status
Early, but usable. Changed files across every worktree, a split/inline diff
viewer, and a union commit history with a per-worktree presence matrix. Press
g to switch between changes and history.
From a commit, set as diff base: the changes view then shows what every
worktree has done since that commit, rather than what is merely uncommitted.
The chip in the filter bar clears it.
Click two worktrees in the history legend to compare them: the list narrows to
the commits exactly one of them has, with the authoritative counts and the
point they diverged.
Not built yet: anything that writes. See design/.
Install
go install github.com/lumiostack/aerie/cmd/aerie@latest
Or grab a binary from Releases — one static file, nothing to install alongside
it. On macOS, fetching it with curl rather than a browser avoids Gatekeeper
entirely: quarantine is set by the downloading application, not by the OS.
From source:
git clone https://github.com/lumiostack/aerie && cd aerie && make install
Use
aerie # open the current repository
aerie ~/src/myrepo # or another one
aerie --json . # the model, for scripts
aerie --no-open . # print the URL instead of launching a browser
In the history view the left gutter is a presence matrix, one column per
worktree: read down a column for one worktree's history, across a row for which
worktrees already contain that commit. The lane graph is computed from commit
parents, never parsed out of git log --graph.
Once it is open, press o (or click the repository name) to open another one:
type a path, pick from recently opened repositories, or browse for it. Point it
at any worktree and it resolves to the shared repository and shows all of them.
aerie serves a local page on 127.0.0.1 and opens it in the browser you
already have — in an app window where the browser supports one. Nothing is
bundled and nothing is installed. Closing the window stops the process.
The only state it keeps between runs is a list of recently opened
repositories, in the OS config directory. It never writes to a repository it is
reviewing, not even a dotfile.
Why it is safe to point at a repository
Every git call goes through one validated chokepoint:
- the full argv is checked against an allowlist —
worktree is pinned to
exactly worktree list --porcelain -z, so worktree prune cannot be built
- the child environment is constructed from scratch, never inherited: a
stray
GIT_DIR would silently retarget every command, and GIT_EXTERNAL_DIFF
would defeat the config hardening
--no-optional-locks, so aerie never takes index.lock and never collides
with your terminal or your agents
- repository-controlled config that executes shell —
core.fsmonitor,
diff.external, core.hooksPath — is neutralised on every invocation
- fetch, pull, push, clone and remote are absent from the allowlist, so no code
path can reach a network
The local server is the one place "read-only" does not protect you, since any
page in your browser can reach 127.0.0.1. It binds loopback only, requires a
per-run token exchanged for a SameSite=Strict cookie, and checks Origin and
Host on every request.
Build
make check # vet + tests
make build # ./aerie
make install # into ~/.local/bin (override with PREFIX=)
make dist # all five targets, from one machine
Go 1.26+, git 2.36+. No other dependencies — the UI is compiled into the binary.
License
Apache-2.0.