Understand what your agents are building. vert is a terminal UI that shows a
live, labelled feed of a git repository's changes, uncommitted work
included. From the feed you can open syntax-highlighted diffs, search files
and contents, and see where change is concentrating. The Branches tab lists
every worktree, branch and open pull request, so you can follow agents that
work in parallel.
◆ vert │ nibble ⎇ main ✦ 2 new ● live
1 Feed 2 Hotspots 3 Search 4 Branches
╭ Changes 143 ─────────────────────────────────────────────────────────────────────────╮
│▌ now working Uncommitted changes across 2 modules +26 ■■■■■ 1 file│
│ ✦ 1d 0ceae5a fix(status): replace racy hook ▴ medium +55 −38 ■■■■■ 2 files│
│ 2d e0fcba1 Merge remote-tracking branch ⇄ wide ▲ xl +7044 −13682 ■■■■■ 88 files│
- Live change feed: commits plus a pinned
workingrow for uncommitted, staged and untracked changes. It updates within about 300 ms of an agent touching a file. Commits that arrive while vert is open are marked✦, andnjumps to the next one. - Labels:
small/medium/large/xlby lines changed,widewhen a change touches many modules, plusrevertedandrevertdetection. - Diff view: a file list and a syntax-highlighted diff with old and new line
numbers.
n/Njump between hunks. An open working-tree diff refreshes in place as files change. - Search: fuzzy file names, or content search using ripgrep's engine (smart
case, regex with literal fallback, respects
.gitignore). - Hotspots: files or modules ranked by how often they change over 24h, 7d,
30d or all loaded history.
⏎filters the feed to that file or module. - Branches, worktrees and pull requests: one row per line of work. A
row shows the checkout it's in, uncommitted files (
●3), commits ahead and behind the base branch, its size, and the matching open pull request with its CI checks (✓ passing, ✗ failing, ● running). Pull requests without a local branch get their own rows.⏎opens the most relevant diff: uncommitted work first, then the branch against the point where it left the base, then the pull request.bandppick the branch or pull request diff.ffilters by kind,/narrows rows by name, anddremoves a line of work — a linked worktree together with its branch — after a confirmation that warns about unmerged commits and open pull requests. vert never removes the checkout it runs in, the repository's main checkout, remote-tracking branches or pull requests, and a checkout with uncommitted changes is refused — re-checked at removal time, so files that arrived while the confirmation was open are safe too. Diffs of linked worktrees stay live, and files open from the worktree they belong to. - File viewer: shows the full file, with lines added by the change you came
from marked in the gutter.
eopens$VISUAL/$EDITORat that line (vim, nvim, helix, VS Code, Cursor, …). - Inherits your terminal theme: it only uses the 16 ANSI colours.
Works on Linux and macOS. You need Rust and git; on macOS,
xcode-select --install provides git and the C compiler the build needs. Then:
curl -fsSL https://raw.githubusercontent.com/adlrocha/vert/main/install.sh | bashThe installer clones the source to ~/.local/share/vert/src, builds it, and
puts the binary in ~/.local/bin/vert.
To update, run the same command again. It fetches the latest main,
rebuilds, and swaps the binary in place, or tells you it's already up to date.
vert also checks once a day whether main has moved past the commit it was
built from, and shows ↑ update available in the header when it has.
--no-update-check (or --no-network) turns that off.
| Option / env var | Default | Purpose |
|---|---|---|
--bin-dir DIR / VERT_BIN_DIR |
~/.local/bin |
Where the binary goes |
--ref REF / VERT_REF |
main |
Branch or tag to build |
--source DIR |
— | Build a local checkout instead |
--uninstall |
— | Remove the binary and source |
Pass options through the pipe with bash -s --, for example
curl -fsSL …/install.sh | bash -s -- --bin-dir /usr/local/bin.
From a clone you can also run ./install.sh --source . or cargo install --path ..
vert # the repository containing the current directory
vert ~/code/app # or any path inside a repositoryPress ? inside vert for all keys. The essentials:
| Where | Keys |
|---|---|
| Anywhere | 1 2 3 4 / tab switch tab · j k move · ⏎ open · esc back · q quit |
| Feed | n next new change · esc clear filter · r reload |
| Hotspots | w time window · m files/modules · ⏎ filter feed · o/e view/edit |
| Change | tab switch pane · J K scroll · n N hunks · ← → sideways · e edit |
| Search | type to search · tab files/text · ctrl-w/ctrl-u delete · ctrl-e edit |
| Branches | ⏎ open · b branch diff · p PR diff · f filter kinds · / filter names · d remove · r refresh |
vert lists open pull requests when origin is on GitHub. It needs a token
and looks for one in this order:
GH_TOKENGITHUB_TOKENgh auth token, if the GitHub CLI is logged in
If no token is found, the Branches tab says so and shows everything else.
vert only reads from GitHub: it lists open pull requests with their check
status, and fetches a pull request's diff when you open it. It never fetches
or writes to your repository. Besides your repository, vert sends one
unauthenticated request a day to api.github.com for its own latest commit —
no account, token or repository data involved — which is what powers the
update notice. --no-network turns all GitHub access off.
| Flag | Default | Meaning |
|---|---|---|
--limit |
500 | Commits loaded into the feed and hotspots |
--module-depth |
1 | Directory depth that defines a module |
--wide-modules |
3 | Modules touched for a change to count as wide |
--medium-lines / --large-lines / --xl-lines |
50 / 200 / 1000 | Size thresholds (added + removed) |
--debounce-ms |
300 | Quiet period before reacting to file changes |
--max-search-results |
2000 | Content-search match cap |
--max-highlight-lines |
20000 | Longer files and diffs skip syntax colours |
--max-file-kb |
4096 | Largest file the viewer opens |
--no-watch |
off | Disable live updates |
--base |
auto | Branch to compare against (origin/HEAD, else main/master) |
--max-branches |
30 | Branches without a worktree to show, newest first |
--branch-refresh-secs |
5 | Branches tab rescan interval |
--pr-refresh-secs |
60 | Pull request refresh interval |
--max-prs |
50 | Open pull requests to list (at most 100) |
--github-api |
https://api.github.com |
API URL; for GitHub Enterprise https://HOST/api/v3 |
--github-timeout-secs |
15 | GitHub request timeout |
--no-network |
off | Never contact GitHub |
--no-update-check |
off | Never ask GitHub whether a newer vert exists |
cargo test # unit, render and doc tests
tests/install_test.sh # installer end-to-end tests
cargo clippy --all-targets -- -D warnings # pedantic lints, zero warnings
cargo fmt
cargo llvm-cov --summary-only # coverageApp::update(msg) -> Vec<Effect> is a pure state machine. Keys, loads and
file changes come in as Msgs. I/O goes out as Effects, which jobs::run
performs on worker threads. The binary (main.rs) is only terminal setup and
the event loop. This keeps all interaction logic testable without a terminal.
| Module | Responsibility |
|---|---|
git |
Feed entries (with a per-commit cache), branches and worktrees, structured diffs |
github |
origin detection, token lookup, open pull requests and their diffs |
labels |
Size, breadth and revert classification |
hotspots |
Ranking by change frequency |
search |
Fuzzy file names (nucleo) and content search (ripgrep crates) |
watch |
inotify/FSEvents, ignoring reads and .gitignored paths |
highlight |
syntect with an ANSI theme |
ui |
ratatui rendering |