Skip to content
rsdltPublic

About

The fastest blade for your git history. Fuzzy search for you, plain text for your agents.

Topics

Resources

Contributing

Stars

8 stars

Watchers

0 watching

Forks

Repository files navigation

levi: two crossed blades over a git commit graph
The fastest blade for your git history. Fuzzy search for you, plain text for your agents.

levi

CI levi on The Terminal Index

Tch. Your history is filthy. Let's look at it properly.

levi browses the commits on your branch, the files each one touched, and their diffs. Type to search commits and files fzf style, and add /c to search the code itself: levi finds the commit that added or removed any line you name.

levi browsing its own history: a fuzzy search, a diff in syntax colors with tinted changes, Ctrl-Y copying a sha, /c finding the commit that added a line, Ctrl-O opening it in Neovim, Enter printing the sha, levi --filter running the same search without the TUI, and in herdr, a pick landing in an agent's input

Why levi

You and your agents made forty commits since lunch, and now the parser is broken. Finding the commit that did it takes git a git log -p scrolled by hand, or a git log -G that leaves you waiting.

levi does that one job: find the change and show it. Named after humanity's strongest soldier, he's small, swift and precise. Captain Levi doesn't carry gear he won't use.

Why not tig or lazygit? Those are full squads. Levi is one soldier, two blades and no small talk.

Speed

levi loads history on every core at once and searches it in memory. On git.git, with 82,513 commits, on an Apple M4 Pro (12 cores), against the git command that does the same job:

Job levi git
Load all history, with the files each commit touched 0.86 s 2.8 s, git log --name-status
Search every diff for a line of code 6.6 s 19.1 s, git log -G

levi searched more, too: git log -G skips merge commits, and levi checks those against their first parent. You never wait for the full load: the first screen lands in 50 ms, and history streams in behind it while you type. Each keystroke refilters all 82k commits in 5 to 12 ms.

Rerun it on any big repository: time levi --filter '' against git log --name-status, and levi --filter '/c some_function' against git log -i -G some_function.

Enlist

You need git 2.31 or newer.

brew install rsdlt/tap/levi

With Rust, run cargo install levi-git, or cargo binstall levi-git for a prebuilt binary. Someone else took the name levi on crates.io; the command is still levi. The latest release has binaries for macOS, Linux and Windows.

Orders

Run levi inside a git repository. He patrols the current branch. Name a revision and he covers that ground instead:

levi main..HEAD    # what your branch adds to main
levi v1.0..        # everything since a tag

He keeps watch while you work. Commit, pull or rebase in another terminal, or let your agent do it, and levi catches up within two seconds, without losing your place.

What isn't committed yet sits on top, in red: working uncommitted changes, staged, unstaged and untracked files together. Watch an agent's edits land in the diff as it writes them, or search them with /c before they're ever committed.

Enter prints the selected commit's sha and quits, so levi works as a picker: git show $(levi).

Key Action
type search
↑ ↓ move
Tab switch pane: commits, files, diff
PgUp PgDn scroll the diff
S-↑ S-↓ jump between hunks, across files
S-← S-→ scroll the diff sideways
Enter print the sha and quit
C-y copy the sha
C-o open the file in your editor at the line you're reading
Esc clear the search, or quit

The mouse works too: click to select, scroll with the wheel, drag to copy, drag a border to resize the panes. levi --help lists every key. Set NO_COLOR for plain black and white.

Hunting

The search narrows commits and files together. It matches subjects, authors, sha prefixes and the paths each commit touched, so parse.rs lists the commits that changed parse.rs. fzf syntax works: 'exact, ^prefix, suffix$, !not.

Two commands share the search bar:

  • /c text searches the code: the lines each commit added or removed. levi keeps the commits where text appears as you typed it, spaces included, and jumps to the first match. Lowercase matches any case; a capital makes it exact. Fuzzy terms before /c pick which commits and files levi searches, which also makes it faster.
  • /r switches to the reflog, with commits from branches you deleted.
/c git_parse_ssize_t    which commits touched this function?
parse.rs /c let x =     the code `let x =`, in commits that touched parse.rs
/r /c experiment        that code, from a branch you deleted

Reconnaissance: levi and coding agents

Brats. They change forty files before lunch and can't tell you which commit broke the build.

Agents like Claude Code can't work a TUI, so levi reports to them in plain text. levi --filter runs the same search without the screen and prints one <sha> <subject> line per match, best first. Ask your agent which commit made the layout stack on narrow terminals, and it runs:

$ levi --filter 'ui.rs /c STACK_BELOW'
d3a93ab5f5c98621cbaf9079d0c952786239d221 Stack the lists above the diff on narrow terminals

Then it reads that commit with git show. levi exits 1 when nothing matches, so the agent can tell an empty search from a broken one. Add a revision to search only its ground: levi --filter 'login' main..HEAD.

Brief your agent once, in CLAUDE.md or AGENTS.md:

To find the commits that touched some code, run `levi --filter '<query>'`. The query is fuzzy
over commit subject, author, sha and file paths; `/c <text>` keeps only commits whose diffs add
or remove `<text>` (literal, smart case), and `/r` searches the reflog. It prints
`<sha> <subject>`, best match first. Then read one with `git show <sha>`. When I say "what I
have open in levi", run `levi --focus`: it prints the commit, file and lines I'm looking at.

Orders go the other way too. Keep levi open in another pane, and levi --focus tells the agent what's on your screen:

$ levi --focus
commit d3a93ab ("Stack the lists above the diff on narrow terminals"), src/ui.rs lines 27-40

So "why is the layout stacking in what I have open in levi?" just works, in the session you already have, with any agent that runs commands. It's the lines in view, or the ones under a drag. levi keeps that note in your temp directory, never in the repository, and --focus exits 1 when no levi is open there.

Or do it by hand: C-y copies the sha and a drag over the diff copies the code, ready to paste into the agent's chat.

With herdr

In herdr, levi reports straight to your agent. Install the plugin, then bind a key in herdr's config.toml:

herdr plugin install rsdlt/levi/herdr
[[keys.command]]
key = "prefix+l"
type = "plugin_action"
command = "rsdlt.levi.pick"

In your agent's pane, press prefix l. levi opens over it, in the agent's repository. Find the commit, scroll to the lines you mean (or drag over them), and press Enter. levi closes and types the reference into the agent's input, unsent:

In commit d3a93ab ("Stack the lists above the diff on narrow terminals"), src/ui.rs lines 27-40:

Finish the question and send it. Levi did the scouting; the agent only has to listen.

With tmux

Same orders in tmux 3.2 or newer. With TPM, add to tmux.conf and press prefix I:

set -g @plugin 'rsdlt/levi'

In your agent's pane, press prefix G. levi pops up over it, in the pane's directory; Enter types the reference into the pane, unsent. See tmux/README.md for another key, or for tmux without TPM.

Joint operations

C-o opens the file in your editor at the line you're reading. Quit the editor and levi waits where you left him. Inside Neovim's terminal, the file opens in a new tab of that Neovim. A file you deleted since then opens read-only, as it was in that commit.

To run levi in a floating window inside Neovim, see docs/neovim.md.

Field report

  • Precise. levi lights the words that changed in each line, like git's diff-highlight. Code takes syntax colors from your terminal's palette. On terminals like Ghostty, changed lines also get a soft tint that suits your theme, dark or light.
  • Small. About 3,500 lines of Rust and a 4 MB binary.
  • Clean. levi runs your own git, never writes to your repository, and leaves your terminal as he found it, even after a crash.

License

MIT. Free to use, like a cup of black tea, held however you like.

About

The fastest blade for your git history. Fuzzy search for you, plain text for your agents.

Topics

Resources

Contributing

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages