Stacking float terminal manager for Neovim.
- Vertically stacked floating terminals on the left or right side of the editor
- Horizontally stacked floating terminals on the top or bottom of the editor
- Toggle all terminals (show/hide) with a single key
- Create multiple terminals that automatically resize and reflow
- Navigate between terminals with next/previous keys
- Maximize/restore individual terminals to full height/width
- Focus editor while keeping terminals visible, and focus back with a single key
- Custom shell support per terminal or global default
- Full keymap customization
- Border highlighting for active and inactive terminals (customizable)
- Winbar showing running process or cwd (customizable)
- Neovim >= 0.7.0
Using lazy.nvim:
{
"ruicsh/termite.nvim",
opts = {}
}require("termite").setup({
width = 0.5, -- Fraction of editor width for left/right positions (0.0 - 1.0)
height = 0.5, -- Fraction of editor height for top/bottom positions (0.0 - 1.0)
position = "right", -- Panel position: "left", "right", "top", or "bottom"
border = "light", -- Border style: "light", "heavy", "double", "double-dash", "triple-dash", "quadruple-dash"
shell = nil, -- Shell command (nil = default $SHELL)
start_insert = true, -- Enter insert mode when focusing a terminal
winbar = true, -- Show winbar with running process or cwd
keymaps = {
toggle = "<C-\\>", -- Toggle all terminals (terminal mode)
create = "<C-t>", -- Create new terminal
next = "<C-n>", -- Focus next terminal in stack
prev = "<C-p>", -- Focus previous terminal in stack
focus_editor = "<C-e>", -- Return focus to editor window
normal_mode = "<C-[>", -- Exit terminal insert mode
maximize = "<C-z>", -- Maximize/restore focused terminal
close = "q", -- Close current terminal (normal mode)
},
wo = { -- Window options applied to terminal windows
signcolumn = "yes:1",
},
highlights = {
border_active = "TermiteBorder", -- Highlight for active terminal border (string = hl group, table = direct definition)
border_inactive = "TermiteBorderNC", -- Highlight for inactive terminal borders (string = hl group, table = direct definition)
border_single = "TermiteBorderSingle", -- Highlight for single terminal border (string = hl group, table = direct definition)
winbar = "TermiteWinbar", -- Highlight for winbar
},
})termite.nvim uses three highlight groups for terminal window borders:
TermiteBorderSingle- Applied when there's only one terminal visibleTermiteBorder- Applied to the active (focused) terminal's outer edge when there are 2+ terminalsTermiteBorderNC- Applied to inactive (non-focused) terminal borders
The outer edge is:
- Left border when
position = "right" - Right border when
position = "left" - Top border when
position = "bottom" - Bottom border when
position = "top"
This means only the border facing the editor is highlighted, while the separators between stacked terminals remain dimmed.
By default, the highlight groups link to:
TermiteBorderSingle→FloatBorder(single terminal)TermiteBorder→FloatBorder(active terminal outer edge with 2+ terminals)TermiteBorderNC→Comment(inactive terminal outer edges)TermiteWinbar→Normal(winbar text)
These defaults use default = true, so they can be overridden by colorschemes or user configuration.
Define the highlight groups in your colorscheme or init.lua:
-- Customize single terminal border
vim.api.nvim_set_hl(0, "TermiteBorderSingle", { fg = "#61afef", bg = "NONE" })
-- Customize active terminal border (2+ terminals)
vim.api.nvim_set_hl(0, "TermiteBorder", { fg = "#ff6b6b", bg = "NONE", bold = true })
-- Customize inactive terminal borders
vim.api.nvim_set_hl(0, "TermiteBorderNC", { fg = "#4a4a4a", bg = "NONE" })
-- Customize winbar
vim.api.nvim_set_hl(0, "TermiteWinbar", { fg = "#a0a0a0", bg = "NONE" })You can specify highlights in two ways:
1. Use custom highlight group names:
require("termite").setup({
highlights = {
border_single = "MyCustomSingle",
border_active = "MyCustomActive",
border_inactive = "MyCustomInactive",
},
})2. Define colors directly:
require("termite").setup({
highlights = {
border_single = { fg = "#61afef", bg = "NONE" },
border_active = { fg = "#00ff00", bg = "NONE" },
border_inactive = { fg = "#ff0000", bg = "NONE" },
},
})Keymaps are buffer-local to terminal windows and can be customized or disabled.
To disable a keymap, set its value to false or nil:
require("termite").setup({
keymaps = {
close = false, -- Disable 'q' to close in normal mode
},
})Default keymaps:
| Mode | Key | Action |
|---|---|---|
| Terminal | <C-\> |
Toggle all terminals (smart: focus back) |
| Terminal | <C-t> |
Create new terminal |
| Terminal | <C-n> |
Focus next terminal |
| Terminal | <C-p> |
Focus previous terminal |
| Terminal | <C-e> |
Focus editor window |
| Terminal | <C-[> |
Exit to normal mode |
| Terminal | <C-z> |
Maximize/restore terminal |
| Normal | q |
Close current terminal |
Additionally, toggle and create keymaps are available in normal mode globally:
| Mode | Key | Action |
|---|---|---|
| Normal | <C-\> |
Toggle all terminals (smart: focus back) |
| Normal | <C-t> |
Create new terminal |
Smart toggle behavior: When terminals are visible and you press <C-\> while focus is on the editor, it focuses the terminals instead of hiding them. This lets you switch between editor and terminals with the same key.
The :Termite command accepts subcommands:
:Termite " Toggle all terminals (default)
:Termite toggle " Toggle all terminals (smart: focuses terminals if in editor)
:Termite create " Create new terminal
:Termite maximize " Maximize/restore current terminal
:Termite close " Close current terminal
:Termite next " Focus next terminal
:Termite prev " Focus previous terminal
:Termite editor " Focus editor window
:Termite terminals " Focus the terminal stacklocal termite = require("termite")
-- Configuration
termite.setup(opts) -- Configure the plugin
-- Terminal management
termite.toggle() -- Toggle all terminals (show/hide)
-- Smart toggle: if terminals visible and focus is on editor, focuses terminals
-- otherwise toggles visibility
termite.create() -- Create a new terminal
termite.close_current() -- Close the focused terminal
-- Navigation
termite.focus_next() -- Focus next terminal in stack
termite.focus_prev() -- Focus previous terminal in stack
termite.focus_editor() -- Focus editor window
termite.focus_terminals() -- Focus the terminal stack (last terminal)
-- Window state
termite.toggle_maximize() -- Maximize/restore focused terminallocal highlights = require("termite.highlights")
-- Highlight groups
highlights.BORDER_SINGLE -- "TermiteBorderSingle"
highlights.BORDER_ACTIVE -- "TermiteBorder"
highlights.BORDER_INACTIVE -- "TermiteBorderNC"
-- Re-initialize highlight groups (useful after colorscheme change)
highlights.setup()Tests use plenary.nvim. Install it as a dev dependency:
-- lazy.nvim
{
"ruicsh/termite.nvim",
dependencies = { "nvim-lua/plenary.nvim", optional = true },
}Run tests:
make test # Run all tests
make test-file FILE=spec/config_spec.lua # Run specific test fileMIT License - see LICENSE
