gh-review.nvim

August 1, 2026 · View on GitHub

A Neovim 0.10+ plugin for reviewing GitHub pull requests entirely within Neovim.

Side-by-side diffs, review threads, code suggestions, and review submission — all driven by the gh CLI.

Also available for Vim 9.0+: gh-review.vim.

Goal

This plugin — which is designed for the use case where you’ve already identified a specific PR or PR branch you’re ready to review — has just one single goal:

✅ provide the simplest means possible for performing a GitHub PR review within Neovim

Anything beyond that is a non-goal — for example:

❌ GitHub Issues, Notifications, Discussions, or Actions/Workflows
❌ Managing labels, assignees, or requested reviewers
❌ Browsing or searching lists of PRs
❌ Merging or closing PRs

You are expected to perform those tasks using other tooling (for example, gh-dash).

Requirements

  • Neovim 0.10 or later
  • gh CLI, authenticated

Installation

With lazy.nvim:

{ "gh-tui-tools/gh-review.nvim" }

With Neovim’s built-in package manager:

mkdir -p ~/.local/share/nvim/site/pack/plugins/start
cd ~/.local/share/nvim/site/pack/plugins/start
git clone https://github.com/gh-tui-tools/gh-review.nvim.git

No setup() call is required — commands register automatically. Call setup() only if you want to customize keymaps or folding.

Configuration

setup() is optional. These are the defaults:

require("gh_review").setup({
  fold = { enabled = true, level = 0 },
  keymaps = {
    diff = {
      thread_open  = "gt",
      comment      = "gc",
      suggestion   = "gs",
      next_thread  = "]t",
      prev_thread  = "[t",
      preview      = "K",
      toggle_files = "gf",
      goto_file    = "gF",
      close        = "q",
    },
    files = {
      open          = "<CR>",
      toggle_viewed = "<Space>",
      refresh       = "R",
      toggle_files  = "gf",
      close         = "q",
    },
    thread = {
      submit       = "<C-s>",
      resolve      = "<C-r>",
      close        = "q",
      close_insert = "<C-q>",
    },
  },
})

Write only the keys you want to change:

require("gh_review").setup({
  keymaps = {
    diff  = { preview = false },      -- keep K for LSP hover
    files = { toggle_viewed = "v" },  -- keep <Space> for your leader
  },
  fold = { level = 99 },              -- diff folds, but open on arrival
})

Keymaps

A mapping is either a string, which remaps it, or false, which drops it. Omitted keys keep their defaults. An unrecognized surface, action, or value type is reported through vim.notify and the whole setup() call is ignored, so a typo fails loudly rather than half-applying.

The reply hint in the thread buffer names whichever keys you configured, and omits any action you disabled.

Folding

ValueEffect
fold = { enabled = true, level = 0 }Default. Diff folding, everything closed.
fold = { enabled = true, level = 99 }Diff folding, everything open on arrival.
fold = falseNo fold management at all.

fold = false is shorthand for fold = { enabled = false }.

Neovim’s :diffthis sets foldmethod=diff by itself, so disabling folding means the plugin actively sets nofoldenable once. After that it leaves folding alone entirely — including declining to restore foldmethod if another plugin changes it, which it does do in the other two modes.

Workflows

The plugin has two main workflows: A “checkout” workflow, and a “no-checkout” workflow.

Checkout workflow

Typically used by a project maintainer reviewing a contributor’s PR. The branch is checked out locally so the reviewer can make edits, commit fixes, and push directly.

:GHReview 123          " PR number (checks out the branch)
:GHReview              " auto-detect from current branch
  • The right/head diff buffer is editable — :w writes to the working tree.
  • External file changes are detected and the plugin prompts to reload.
  • git push pushes changes back to the PR branch (works for fork PRs too).

No-checkout workflow

Typically used by a non-maintainer reviewer who only needs to read the diff and leave comments.

:GHReview https://github.com/owner/repo/pull/123

When the URL refers to a different repo than the current working directory, no checkout is attempted. The right/head diff buffer is read-only, but comments, suggestions, and review submission all work normally.

Quick start

:GHReview 123           Open PR #123
<CR>                    Open a file’s side-by-side diff
]t / [t                 Jump between review threads
gt                      View a thread
K                       Preview a thread (floating window)
gc                      Add a comment
gF                      Jump to the file with LSP (checkout only)
:GHReviewSubmit         Submit a review
:GHReviewClose          Close all review buffers

Commands

CommandDescription
:GHReviewOpen a PR (auto-detect, by number, or by URL)
:GHReviewFilesToggle the changed files list
:GHReviewStartStart a pending review (optional — :GHReviewSubmit works without it)
:GHReviewSubmitSubmit a review (Comment / Approve / Request changes)
:GHReviewDiscardDiscard the pending review and all its pending comments
:GHReviewCloseClose all review buffers and reset state

Files list mappings

KeyAction
<CR>Open the file’s side-by-side diff
<Space>Toggle the file’s reviewed state
RRefresh review threads from GitHub
gfClose the files list
qClose the files list

Diff mappings

KeyAction
gtOpen the review thread at the cursor line
gcCreate a new comment (visual mode: multi-line)
gsCreate a suggestion (right buffer only, visual: range)
]tJump to the next review thread
[tJump to the previous review thread
KPreview the thread at cursor (floating window)
gfToggle the files list
gFGo to file at cursor line (checkout only)
qClose the diff view

Thread mappings

KeyAction
Ctrl-SSubmit the reply
Ctrl-RToggle resolved/unresolved
qClose the thread buffer
Ctrl-QClose the thread buffer (works in insert mode)
Ctrl-X Ctrl-OComplete @-mention from thread participants

Signs and virtual text

SignMeaning
CTComment thread (blue)
CRResolved thread (green)
CPPending review comment (yellow)

Each sign is accompanied by virtual text at end-of-line showing the first comment’s author and a truncated body — giving at-a-glance context without opening the thread.

Comment reactions are displayed as emoji with counts after each comment body in the thread buffer and floating preview.

vim.ui integration

All prompts (submit review, discard review, checkout, file reload) use vim.ui.select and vim.ui.input. Plugins like dressing.nvim or fzf-lua that override these hooks will automatically provide their enhanced UIs.

Statusline

require("gh_review").statusline()

Returns "" when no review is active, or a summary like PR #42 · reviewing · 4 threads. Use it in lualine, heirline, or any statusline plugin.

Comparison with other plugins

Featuregh-review.nvimgh-review.vimghlite.nvimgh.nvimocto.nvim
PlatformNeovim 0.10+Vim 9.0+Neovim 0.10+NeovimNeovim 0.10+
PR review: side-by-side diffYesYesVia diffview.nvimYesYes
PR review: comments/threadsYesYesYesYesYes
PR review: code suggestionsYesYesNoNoYes
PR review: submit reviewYesYesYesYesYes
PR review: resolve threadsYesYesNoYesYes
PR review: thread signsYes (+ virtual text)Yes (+ virtual text)As diagnosticsNoNo
Editable diff buffersYesYesNoYes (via checkout)No
External change detectionYesYesNoNoNo
Fork PR push trackingYesYesNoYesNo
PR listing/browsingNo (non-goal)No (non-goal)YesYesYes
Merge PRsNo (non-goal)No (non-goal)YesNoYes
Labels/assignees/reviewersNo (non-goal)No (non-goal)NoNoYes
GitHub IssuesNo (non-goal)No (non-goal)NoYesYes
NotificationsNo (non-goal)No (non-goal)NoYesYes
DiscussionsNo (non-goal)No (non-goal)NoNoYes
Actions/WorkflowsNo (non-goal)No (non-goal)NoNoYes
ReactionsNo (non-goal)No (non-goal)NoNoYes
Dependenciesgh CLIgh CLIgh CLIgh CLI, litee.nvimgh CLI, plenary.nvim, picker

Documentation

See :help gh-review for full documentation.

See DESIGN.md for architecture and implementation details.