
Terminal, Git and global search integrated in Neovim
Never leaving Neovim
Four tools turn Neovim into a complete development cockpit: toggleterm for an integrated terminal, lazygit for Git, grug-far for bulk search-and-replace, trouble.nvim for diagnostics.
Integrated terminal with Toggleterm
`Ctrl-`` pops a horizontal terminal at the bottom: no overlapping windows, just a terminal that toggles in and out.
{
"akinsho/toggleterm.nvim",
version = "*",
opts = {
size = 15,
open_mapping = [[<c-`>]],
hide_numbers = true,
shade_terminals = true,
shading_factor = 2,
start_in_insert = true,
persist_size = true,
direction = "horizontal",
},
}
Three qualities that matter:
- Persistence: start
bun dev, close the terminal, edit code, reopen it — the server is still running. - Visual shading: the terminal is dimmed relative to the code, so the distinction is instant.
- Multiple terminals: each with its own session, pwd and running processes.
Running a build, executing tests, starting a dev server: no reason to leave the editor, and no lost context.
Visual Git with Lazygit
For some operations — interactive rebase, conflict resolution, cherry-pick — a TUI is far more efficient than the command line. Lazygit plugs into Neovim through toggleterm:
-- Lazygit as a floating terminal
local Terminal = require("toggleterm.terminal").Terminal
local lazygit = Terminal:new({
cmd = "lazygit",
dir = "git_dir",
direction = "float",
float_opts = {
border = "rounded",
},
on_open = function(term)
vim.cmd("startinsert!")
end,
on_close = function(_)
vim.cmd("startinsert!")
end,
})
-- Keymap: <leader>gg to open lazygit
vim.keymap.set("n", "<leader>gg", function()
lazygit:toggle()
end, { desc = "Lazygit" })
<leader>gg opens a floating window: staging file by file or hunk by hunk, commit, push, pull, interactive rebase, stash, visual diffs.
What the TUI adds over command-line git:
- Visual diff: you see line by line what you're staging, so no surprises at commit time.
- Interactive rebase: reordering, squashing or editing commits is arrow keys and enter.
- Conflict resolution: side-by-side view, pick one version or the other, no manual text merging.
Global search-and-replace with Grug-far
Renaming a variable across the project, fixing a recurring pattern, migrating an API: grug-far, powered by ripgrep, covers those cases.
{
"MagicDuck/grug-far.nvim",
opts = {
headerMaxWidth = 80,
},
cmd = "GrugFar",
keys = {
{
"<leader>S",
function()
local grug = require("grug-far")
local ext = vim.bo.buftype == "" and vim.fn.expand("%:e")
grug.open({
transient = true,
prefills = {
filesFilter = ext and ext ~= "" and "*." .. ext or nil,
},
})
end,
mode = { "n", "v" },
desc = "Search and Replace",
},
{
"<leader>sw",
function()
local grug = require("grug-far")
grug.open({
transient = true,
prefills = {
search = vim.fn.expand("<cword>"),
},
})
end,
desc = "Search word under cursor",
},
},
}
<leader>S opens the search panel in a vertical split, pre-filtered on the current file's extension; <leader>sw searches the word under the cursor directly.
What separates grug-far from plain sed: real-time preview of replacements, file-by-file review with individual accept or reject, the full power of ripgrep regex, and centralised exclusion patterns (node_modules, .git, .next, dist, lock files, minified assets).
Diagnostics navigation with Trouble.nvim
Trouble.nvim aggregates every project diagnostic into a navigable list:
{
"folke/trouble.nvim",
opts = {
use_diagnostic_signs = true,
},
cmd = "Trouble",
keys = {
{ "<leader>xx", "<cmd>Trouble diagnostics toggle<cr>", desc = "Diagnostics (Trouble)" },
{ "<leader>xX", "<cmd>Trouble diagnostics toggle filter.buf=0<cr>", desc = "Buffer diagnostics" },
{ "<leader>xq", "<cmd>Trouble qflist toggle<cr>", desc = "Quickfix list (Trouble)" },
{ "<leader>xl", "<cmd>Trouble loclist toggle<cr>", desc = "Location list (Trouble)" },
},
}
<leader>xx: every diagnostic in the project — errors, warnings, hints.<leader>xX: filters to the current file, useful while fixing one specific file.<leader>xqand<leader>xl: quickfix and location list inside Trouble, far more readable than Vim's native versions.
LSP integration is transparent: TypeScript errors, ESLint warnings and Python diagnostics all show up and navigate with normal keys.
The daily workflow
- Edit code — main buffer, window navigation (
C-h,C-j,C-k,C-l) and buffer navigation (S-h,S-l) - Check diagnostics —
<leader>xxto confirm it compiles and lints - Bulk refactor —
<leader>Sfor grug-far, do the replacement, validate - Commit —
<leader>ggfor lazygit: stage, message, push - Run tests — `Ctrl-`` for the integrated terminal
Zero mouse, and save (<leader>w) plus quit (<leader>q) complete a fully keyboard-driven workflow.
Wrapping up
Four plugins turn Neovim from a text editor into a complete development environment: an integrated terminal instead of overlapping windows, fast visual Git, stress-free large-scale refactoring, and every problem in one list. Once it's muscle memory, the time saved per session is real.
Related articles