kunkka19xx/lgtm

Read what your agent wrote before you say LGTM. A fast TUI in Zig for reviewing code with vim motions.

Zig

52

168 commits

updated Sep 21, 2026

See the code
agent
agentic-ai
agentic-workflow
agents
claude-code
cli
cli-tool
codex
developer-tools
diff
hunk
hunkdiff
lgtm
tmux
tui
vim
zig
zig-lang

See what people are saying (1)

SourceMessageScoreDate

Review code on your terminal with vim motions (r/SideProject)

A TUI tool for reviewing code. Not only reviewing code changes in local, you can review PR, branches... You can also comment, push comment to your agents. This works really well with tmux. [https://github.com/kunkka19xx/lgtm](https://github.com/kunkka19xx/lgtm) Appreciate any feedback πŸ™

1

Sep 21, 2026

README

lgtm

β–ˆβ–ˆβ•—      β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ–ˆβ•—
β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•”β•β•β•β•β• β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ•‘
β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ•‘ πŸ‘
β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘
β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β•šβ•β• β–ˆβ–ˆβ•‘
β•šβ•β•β•β•β•β•β• β•šβ•β•β•β•β•β•    β•šβ•β•   β•šβ•β•     β•šβ•β•

Read what your agent wrote - before you say LGTM.

A terminal diff reviewer for agentic coding. It runs in a pane beside your agent, shows what changed as it changes, and lets you point at exact lines when you reply.

You keep your editor, and review code with vim motions.

https://github.com/user-attachments/assets/0eb27774-9c64-43c2-ba22-b392fb58c734

  • Side-by-side diff view
side-by-side

It began a long time ago as a Go tool for reading diffs in a terminal. This is a rewrite in Zig, rebuilt around a coding agent rather than a person: the diff re-renders as the agent writes, references go straight to its input, and comments follow the code when it rewrites the file underneath them. The loop works end to end.

Why

Reviewing an agent is not reviewing a person: more code, arriving faster, with no prior about where the risk is. Without this, the loop goes - the agent edits six files, you scroll git diff in a pager, you spot something at src/auth.zig:47, and you retype that path into the chat. lgtm removes the retyping.

Install

macOS, from the tap:

brew install kunkka19xx/tap/lgtm

Linux, any distribution - the binary is static, so the distro doesn't matter. (Also macOS):

curl -fsSL https://raw.githubusercontent.com/kunkka19xx/lgtm/main/scripts/install.sh | sh

arm64 and x86_64. No sudo: one binary into ~/.local/bin, checked against the release's checksums. --uninstall removes it.

Nix - the flake ships the binary, not just a dev shell:

nix run --refresh github:kunkka19xx/lgtm          # run once, install nothing
nix profile add --refresh github:kunkka19xx/lgtm  # keep it on PATH

--refresh is not optional: Nix caches what a github: ref points at for an hour, and without it you can get handed a build you already have.

Upgrading is a different command, and this is the one that catches people:

nix profile upgrade --refresh lgtm

add does not upgrade. A profile entry is locked to the commit it was installed from, so running the install line again will not move it - add refuses to install over itself, and --refresh only re-checks where the github: ref points, not where your entry is pinned. upgrade re-resolves the URL the entry was added with and re-locks it to whatever main is now. nix profile list prints the locked commit and store path, which is the quickest way to see that a stale entry, not the release, is why lgtm -v still says the old number.

Arch, from the AUR: lgtm-bin (the release binary) or lgtm-git (builds main), with any helper or makepkg -si from a clone.

From source - needs Zig, the version pinned in .zigversion:

make local          # build and install to ~/.local/bin
make clean-local    # remove it, restoring whatever it displaced
make dev            # install as lgtm-dev, beside a packaged lgtm
make clean-dev      # remove that one

You also need git - and you can type it through lgtm. Any word lgtm has no command of its own for goes straight to git with your arguments untouched, so lgtm log -p and lgtm commit -m x work, while lgtm diff, lgtm status and lgtm risk are the ones lgtm answers itself - the last of those being a question git has no answer to at all:

lgtm risk      # did the agent quietly delete a test, or skip one? exits 1 if so

alias git=lgtm holds: what lgtm cannot express it hands to git verbatim, exit code and all. tmux is optional: without it, references go to the clipboard over OSC 52, which works over SSH.

From your phone

Walk away and keep talking to your agents. With lgte version (inprogress), and Tailscale on both ends:

lgtm serve --listen $(tailscale ip -4)   # every agent in tmux, herdr, WezTerm, kitty
lgtm agent claude                        # an agent in any other terminal joins the list

Scan the code it prints. The phone lists every agent on the machine, the one waiting for you first, shows each one's screen and takes your replies, and reviews the diff the same way this pane does, comments included. Nothing goes through a cloud service. Guide.

Configure

Nothing to write: lgtm runs on defaults, and lgtm --init drops a commented starter when you want to change one. Settings load from ~/.config/lgtm/config.toml, then .lgtm/config.toml in the repo, merged key by key. A bad key is reported on the status line; it never stops the tool starting.

[review]
ignore = ["package-lock.json", "**/*.pb.go"]   # generated files .gitignore can't hide

[presets]
why  = "why this approach?"
perf = "is this hot path allocating?"

[ui]
icons = "nerd"        # or "unicode", "ascii"
comments = "inline"   # or "marker": just the gutter dot

[theme]
name = "gruvbox"      # seven bundled; `lgtm themes` shows them all

[keys]
next_hunk = ["]h", "<Space>nh"]
compose_presets = ["<C-p>"]   # the box's keys are bindings too

Every key is remappable, inside the compose box as well as outside it - only the vim motions are fixed, because in a text box every printable key is data.

Guide is install, the loop and every key. Configuration is every setting, command name and theme slot.

License

Apache-2.0. See LICENSE.

Contributors

kunkka19xx

166 commits

khongtrunght

1 commits

sanglam2806

1 commits

kunkka19xx/lgtm

Read what your agent wrote before you say LGTM. A fast TUI in Zig for reviewing code with vim motions.

Zig

52

168 commits

updated Sep 21, 2026

See the code
agent
agentic-ai
agentic-workflow
agents
claude-code
cli
cli-tool
codex
developer-tools
diff
hunk
hunkdiff
lgtm
tmux
tui
vim
zig
zig-lang

See what people are saying (1)

SourceMessageScoreDate

Review code on your terminal with vim motions (r/SideProject)

A TUI tool for reviewing code. Not only reviewing code changes in local, you can review PR, branches... You can also comment, push comment to your agents. This works really well with tmux. [https://github.com/kunkka19xx/lgtm](https://github.com/kunkka19xx/lgtm) Appreciate any feedback πŸ™

1

Sep 21, 2026

README

lgtm

β–ˆβ–ˆβ•—      β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ–ˆβ•—
β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•”β•β•β•β•β• β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ•‘
β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ•‘ πŸ‘
β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘
β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β•šβ•β• β–ˆβ–ˆβ•‘
β•šβ•β•β•β•β•β•β• β•šβ•β•β•β•β•β•    β•šβ•β•   β•šβ•β•     β•šβ•β•

Read what your agent wrote - before you say LGTM.

A terminal diff reviewer for agentic coding. It runs in a pane beside your agent, shows what changed as it changes, and lets you point at exact lines when you reply.

You keep your editor, and review code with vim motions.

https://github.com/user-attachments/assets/0eb27774-9c64-43c2-ba22-b392fb58c734

  • Side-by-side diff view
side-by-side

It began a long time ago as a Go tool for reading diffs in a terminal. This is a rewrite in Zig, rebuilt around a coding agent rather than a person: the diff re-renders as the agent writes, references go straight to its input, and comments follow the code when it rewrites the file underneath them. The loop works end to end.

Why

Reviewing an agent is not reviewing a person: more code, arriving faster, with no prior about where the risk is. Without this, the loop goes - the agent edits six files, you scroll git diff in a pager, you spot something at src/auth.zig:47, and you retype that path into the chat. lgtm removes the retyping.

Install

macOS, from the tap:

brew install kunkka19xx/tap/lgtm

Linux, any distribution - the binary is static, so the distro doesn't matter. (Also macOS):

curl -fsSL https://raw.githubusercontent.com/kunkka19xx/lgtm/main/scripts/install.sh | sh

arm64 and x86_64. No sudo: one binary into ~/.local/bin, checked against the release's checksums. --uninstall removes it.

Nix - the flake ships the binary, not just a dev shell:

nix run --refresh github:kunkka19xx/lgtm          # run once, install nothing
nix profile add --refresh github:kunkka19xx/lgtm  # keep it on PATH

--refresh is not optional: Nix caches what a github: ref points at for an hour, and without it you can get handed a build you already have.

Upgrading is a different command, and this is the one that catches people:

nix profile upgrade --refresh lgtm

add does not upgrade. A profile entry is locked to the commit it was installed from, so running the install line again will not move it - add refuses to install over itself, and --refresh only re-checks where the github: ref points, not where your entry is pinned. upgrade re-resolves the URL the entry was added with and re-locks it to whatever main is now. nix profile list prints the locked commit and store path, which is the quickest way to see that a stale entry, not the release, is why lgtm -v still says the old number.

Arch, from the AUR: lgtm-bin (the release binary) or lgtm-git (builds main), with any helper or makepkg -si from a clone.

From source - needs Zig, the version pinned in .zigversion:

make local          # build and install to ~/.local/bin
make clean-local    # remove it, restoring whatever it displaced
make dev            # install as lgtm-dev, beside a packaged lgtm
make clean-dev      # remove that one

You also need git - and you can type it through lgtm. Any word lgtm has no command of its own for goes straight to git with your arguments untouched, so lgtm log -p and lgtm commit -m x work, while lgtm diff, lgtm status and lgtm risk are the ones lgtm answers itself - the last of those being a question git has no answer to at all:

lgtm risk      # did the agent quietly delete a test, or skip one? exits 1 if so

alias git=lgtm holds: what lgtm cannot express it hands to git verbatim, exit code and all. tmux is optional: without it, references go to the clipboard over OSC 52, which works over SSH.

From your phone

Walk away and keep talking to your agents. With lgte version (inprogress), and Tailscale on both ends:

lgtm serve --listen $(tailscale ip -4)   # every agent in tmux, herdr, WezTerm, kitty
lgtm agent claude                        # an agent in any other terminal joins the list

Scan the code it prints. The phone lists every agent on the machine, the one waiting for you first, shows each one's screen and takes your replies, and reviews the diff the same way this pane does, comments included. Nothing goes through a cloud service. Guide.

Configure

Nothing to write: lgtm runs on defaults, and lgtm --init drops a commented starter when you want to change one. Settings load from ~/.config/lgtm/config.toml, then .lgtm/config.toml in the repo, merged key by key. A bad key is reported on the status line; it never stops the tool starting.

[review]
ignore = ["package-lock.json", "**/*.pb.go"]   # generated files .gitignore can't hide

[presets]
why  = "why this approach?"
perf = "is this hot path allocating?"

[ui]
icons = "nerd"        # or "unicode", "ascii"
comments = "inline"   # or "marker": just the gutter dot

[theme]
name = "gruvbox"      # seven bundled; `lgtm themes` shows them all

[keys]
next_hunk = ["]h", "<Space>nh"]
compose_presets = ["<C-p>"]   # the box's keys are bindings too

Every key is remappable, inside the compose box as well as outside it - only the vim motions are fixed, because in a text box every printable key is data.

Guide is install, the loop and every key. Configuration is every setting, command name and theme slot.

License

Apache-2.0. See LICENSE.

Contributors

kunkka19xx

166 commits

khongtrunght

1 commits

sanglam2806

1 commits

Languages

Zig

98.4%