ERGOTERM.NVIM(1)

NAME

ergoterm.nvimA single, powerful terminal abstraction for neovim that adapts to any CLI tool

SYNOPSIS

INFO

97 stars
4 forks
0 views

DESCRIPTION

A single, powerful terminal abstraction for neovim that adapts to any CLI tool

README

🖥️ ergoterm.nvim

A flexible terminal management plugin for Neovim that puts you in control of your workflow.

Demo

💡 Philosophy

Most Neovim terminal integration follows a tool-specific approach: specialized plugins for AI chats, testing, task runners and other CLI tools (e.g., lazygit), each with their own terminal implementation and UI decisions. This creates friction when you want consistent behavior across tools or when no plugin exists for your preferred CLI application.

ergoterm inverts this with a terminal-first approach: a single, powerful terminal abstraction that adapts to any CLI tool. Instead of conforming to various plugin constraints, you configure terminals with exactly the behavior you need.

The terminal becomes your universal integration layer. You own the workflow; the terminals adapt to it.

⚙️ Setup

Using lazy.nvim:

{
  "waiting-for-dev/ergoterm.nvim",
  config = function()
    require("ergoterm").setup()
  end
}

Using packer.nvim:

use {
  "waiting-for-dev/ergoterm.nvim",
  config = function()
    require("ergoterm").setup()
  end
}

🎯 Use Cases

🔧 Configuration

Terminal Defaults

All options can be set globally in setup() under terminal_defaults, or per-terminal when creating instances.

require("ergoterm").setup({
  terminal_defaults = {
    layout = "right",
    cleanup_on_success = false,
    auto_scroll = true
  }
})
OptionTypeDefaultDescription
auto_listbooleantrueShow terminal in default picker selection list (e.g., :TermSelect command)
auto_scrollbooleanfalseAutomatically scroll to bottom on new output
bang_targetbooleantrueInclude terminal as target for bang (!) commands
clear_envbooleanfalseClear environment variables before starting
cleanup_on_failurebooleanfalseCleanup terminal when process exits with non-zero code
cleanup_on_successbooleantrueCleanup terminal when process exits with code 0
default_actionfunctionfunction(term) term:focus() endAction performed when selecting terminal with default picker action
fixed_heightbooleantrueKeep the terminal height when new horizontal splits are opened (it depends on vim's equalalways being set)
fixed_widthbooleantrueKeep the terminal width when new vertical splits are opened (it depends on vim's equalalways being set)
float_optstableSee belowFloating window configuration options
↳ borderstring"single"Border style (see :help nvim_open_win())
↳ colnumberAuto-centeredColumn position
↳ heightnumberAuto-calculatedWindow height
↳ relativestring"editor"What the float is positioned relative to
↳ rownumberAuto-centeredRow position
↳ titlestringTerminal nameWindow title
↳ title_posstring"left"Title position
↳ widthnumberAuto-calculatedWindow width
↳ zindexnumber+1Window stacking order
float_winblendnumber10Transparency level for floating windows (0-100)
layoutstring"below"Window layout: "below", "above", "left", "right", "float", "tab", "window"
metatable{}Custom user metadata for storing arbitrary data. Useful for terminal polymorphism.
on_closefunctionNo-opCallback when terminal window closes: function(term)
on_focusfunctionNo-opCallback when terminal gains focus: function(term)
on_job_exitfunctionNo-opCallback when job exits: function(term, job, exit_code, event)
on_job_stderrfunctionNo-opCallback on stderr: function(term, channel_id, data, name)
on_job_stdoutfunctionNo-opCallback on stdout: function(term, channel_id, data, name)
on_openfunctionNo-opCallback when terminal window opens: function(term)
on_startfunctionNo-opCallback when terminal job starts: function(term)
on_stopfunctionNo-opCallback when terminal job stops: function(term)
on_unfocusfunctionNo-opCallback when terminal loses focus: function(term)
persist_modebooleanfalseRemember insert/normal mode between focus sessions
persist_sizebooleantrueRemember window size when resizing splits
scrollbacknumbervim.o.scrollbackTerminal scrollback buffer size
shellstringvim.o.shellDefault shell command to run if no cmd is given
show_on_failurebooleanfalseShow terminal window when process fails (incompatible with cleanup_on_failure)
show_on_successbooleanfalseShow terminal window when process succeeds (incompatible with cleanup_on_success)
sizetableSee belowSize for split layouts (number of rows/columns or percentage string)
↳ abovestring|number"50%"Height for above layout
↳ belowstring|number"50%"Height for below layout
↳ leftstring|number"50%"Width for left layout
↳ rightstring|number"50%"Width for right layout
start_in_insertbooleantrueStart in insert mode when focusing terminal
stickybooleanfalseKeep terminal active even after cleanup so it can be restarted
tagsstring[]{}Tags for organizing and filtering terminals
watch_filesbooleanfalseRefresh buffer when stdout is received

Picker Configuration

Configure terminal selection picker behavior:

require("ergoterm").setup({
  picker = {
    picker = "telescope",
    extra_select_actions = {
      ["<C-d>"] = { fn = function(term) term:cleanup() end, desc = "Delete terminal" }
    }
  }
})
OptionTypeDefaultDescription
extra_select_actionstable{}Additional custom keybindings merged with defaults
pickerstring|table|nilnilPicker implementation: nil (auto-detect), "telescope", "fzf-lua", "vim-ui-select", or custom picker table
select_actionstableDefault keybindingsPicker action keybindings. Defaults: default (runs default_action), <C-s> (open below), <C-v> (open right), <C-t> (open in tab), <C-f> (open float). Each action is a table with fn (callback function) and desc (description)

Text Decorators

Text decorators transform text before sending to terminals. They can be used in the :TermSend command or the term:send() API method.

require("ergoterm").setup({
  text_decorators = {
    extra = {
      timestamp = function(text)
        local timestamp = os.date("%H:%M:%S")
        local result = {}
        for _, line in ipairs(text) do
          table.insert(result, string.format("[%s] %s", timestamp, line))
        end
        return result
      end
    }
  }
})
OptionTypeDefaultDescription
defaulttableBuilt-in decoratorsBuilt-in text decorators: identity (no transformation), markdown_code (wraps in markdown code block)
extratable{}Custom text decorators. Each decorator is a function that takes string[] and returns string[]

Use with :TermSend decorator=name or term:send(input, {decorator = "name"}).

🤝 Contributing

Contributions are welcome! To get started:

  1. Clone the repository
  2. Run tests with busted
  3. Submit a pull request

Make sure all tests pass before submitting your PR.

🙏 Acknowledgments

This plugin started as a fork of toggleterm.nvim. Thanks to the original author and contributors for their foundational work.

📄 License

GPL-3.0

SEE ALSO

clihub3/4/2026ERGOTERM.NVIM(1)