Skip to main content
The tmux API provides functions for managing tmux windows and panes through Harpoon. This allows you to control tmux sessions directly from Neovim.
The tmux API manages tmux windows/panes. For Neovim’s built-in terminal, see the Terminal API.

gotoTerminal

Navigate to a tmux window/pane by index or identifier.
require("harpoon.tmux").gotoTerminal(idx)
idx
number | string
required
  • number: Window index (1-based), creates new window if doesn’t exist
  • string: Tmux pane identifier (e.g., "%2", "{right}", "{top-left}")

Behavior

  • Numeric index: Creates or selects a tmux window at that index
  • String identifier: Selects a tmux pane using tmux target syntax
  • Creates new tmux window if it doesn’t exist
  • Uses tmux select-window for windows, tmux select-pane for panes
  • Throws error if tmux command fails

Examples

local tmux = require("harpoon.tmux")

-- Navigate to window 1 (creates if doesn't exist)
tmux.gotoTerminal(1)

-- Navigate to window 2
tmux.gotoTerminal(2)

-- Common keymap setup
vim.keymap.set("n", "<leader>t1", function()
    tmux.gotoTerminal(1)
end, { desc = "Go to tmux window 1" })

vim.keymap.set("n", "<leader>t2", function()
    tmux.gotoTerminal(2)
end, { desc = "Go to tmux window 2" })

Tmux Target Syntax

When using string identifiers, Harpoon passes them directly to tmux. Valid formats:

Pane ID

%2, %5 - Direct pane identifiers

Directional

{left}, {right}, {top}, {bottom}

Positional

{top-left}, {top-right}, {bottom-left}, {bottom-right}

Special

{last}, {next}, {previous}

sendCommand

Send a command to a tmux window/pane.
require("harpoon.tmux").sendCommand(idx, cmd, ...)
idx
number | string
required
  • number: Window index (creates if doesn’t exist)
  • string: Tmux pane identifier
cmd
string | number
required
Command string to send, or command index from config
...
any
Format arguments for string.format() if cmd contains format specifiers

Behavior

  • Sends command using tmux send-keys
  • Creates tmux window if using numeric index and doesn’t exist
  • Appends newline if enter_on_sendcmd is enabled in config
  • If cmd is a number, retrieves command from harpoon.setup({ ... term = { cmds = {...} } })
  • Supports string.format() style arguments
  • Throws error if tmux command fails

Examples

local tmux = require("harpoon.tmux")

-- Send command to window 1
tmux.sendCommand(1, "npm run dev")

-- Send to window 2
tmux.sendCommand(2, "git status")

-- Send to specific pane
tmux.sendCommand("%2", "ls -la")
tmux.sendCommand("{right}", "npm test")

clear_all

Close and delete all Harpoon-managed tmux windows.
require("harpoon.tmux").clear_all()

Behavior

  • Closes all tmux windows created by Harpoon (numeric indices)
  • Uses tmux kill-window for each tracked window
  • Does not affect manually created tmux windows
  • Does not affect panes referenced by string identifiers
  • Clears internal window registry
  • Window indices can be reused after clearing
This only clears windows created through numeric indices, not panes accessed via string identifiers.

Example

local tmux = require("harpoon.tmux")

-- Clean up all Harpoon tmux windows
tmux.clear_all()

-- Useful in cleanup keymaps
vim.keymap.set("n", "<leader>tc", function()
    require("harpoon.tmux").clear_all()
end, { desc = "Clear all Harpoon tmux windows" })

Auto-close Configuration

You can configure Harpoon to automatically close tmux windows when exiting Neovim:
require("harpoon").setup({
    tmux_autoclose_windows = true,  -- Auto-close on VimLeave
})
tmux_autoclose_windows
boolean
default:"false"
Automatically call clear_all() when exiting Neovim
When enabled, Harpoon registers a VimLeave autocmd that calls clear_all() automatically.

Configuration

The tmux API respects these configuration options:
require("harpoon").setup({
    -- Global settings
    enter_on_sendcmd = true,        -- Auto-append newline to commands
    save_on_change = true,          -- Auto-save terminal commands
    tmux_autoclose_windows = true,  -- Auto-close windows on exit

    -- Terminal/tmux command presets
    term = {
        cmds = {
            "npm run dev",
            "npm test",
            "docker-compose up",
            "git status",
        }
    }
})

Config Options

enter_on_sendcmd
boolean
default:"false"
Automatically append \n to commands sent via sendCommand()
save_on_change
boolean
default:"false"
Automatically save terminal command list when modified
tmux_autoclose_windows
boolean
default:"false"
Automatically close Harpoon-created tmux windows on VimLeave
term.cmds
string[]
default:"[]"
List of preset commands accessible by index in sendCommand()

Complete Workflow Examples

-- In your Neovim config
require("harpoon").setup({
    enter_on_sendcmd = true,
    tmux_autoclose_windows = true,
    term = {
        cmds = {
            "npm run dev",
            "npm test -- --watch",
            "docker-compose up",
        }
    }
})

local tmux = require("harpoon.tmux")

-- Window navigation
vim.keymap.set("n", "<leader>t1", function()
    tmux.gotoTerminal(1)
end, { desc = "Go to tmux window 1" })

vim.keymap.set("n", "<leader>t2", function()
    tmux.gotoTerminal(2)
end, { desc = "Go to tmux window 2" })

-- Pane navigation
vim.keymap.set("n", "<C-h>", function()
    tmux.gotoTerminal("{left}")
end, { desc = "Go to left pane" })

vim.keymap.set("n", "<C-l>", function()
    tmux.gotoTerminal("{right}")
end, { desc = "Go to right pane" })

-- Send preset commands
vim.keymap.set("n", "<leader>td", function()
    tmux.sendCommand(1, 1)  -- Start dev server
end, { desc = "Start dev server" })

vim.keymap.set("n", "<leader>tt", function()
    tmux.sendCommand(2, 2)  -- Run tests
end, { desc = "Run tests" })

-- Send custom commands
vim.keymap.set("n", "<leader>ts", function()
    local cmd = vim.fn.input("Command: ")
    tmux.sendCommand(1, cmd)
end, { desc = "Send command to window 1" })

Tmux Pane Identifiers Reference

Complete reference of valid pane identifiers for string-based targeting:

Direct Identifiers

PatternDescriptionExample
%<id>Pane ID%2, %5
{start}Start of range{start}..{end}
{end}End of range{start}..{end}
{last}Last active pane{last}
{next}Next pane{next}
{previous}Previous pane{previous}

Directional

PatternDescription
{left}Pane to the left
{right}Pane to the right
{up}Pane above
{down}Pane below
{top}Top pane
{bottom}Bottom pane

Positional

PatternDescription
{top-left}Top-left pane
{top-right}Top-right pane
{bottom-left}Bottom-left pane
{bottom-right}Bottom-right pane

Session/Window Targeting

PatternDescriptionExample
<session>:<window>Specific session and windowdev:1
<session>:<window>.<pane>Session, window, and panedev:1.2
<window>.<pane>Window and pane in current sessionmywindow.1
=<title>Pane with specific title=dev-server

Internal Functions

These functions are available but typically not needed for normal usage:

get_length

Get the number of configured terminal commands.
local count = require("harpoon.tmux").get_length()

valid_index

Check if a terminal index is valid.
local is_valid = require("harpoon.tmux").valid_index(idx)

add_cmd

Add a command to the terminal command list.
require("harpoon.tmux").add_cmd("npm run build")

rm_cmd

Remove a command from the terminal command list by index.
require("harpoon.tmux").rm_cmd(2)  -- Remove second command

Build docs developers (and LLMs) love