In this episode we connect tmux to the developer ecosystem: seamless navigation between panes and Neovim/VS Code editors with vim-tmux-navigator, lazygit, and an fzf-based session switcher.

In episode 24 we covered performance & resource optimization — how to make tmux lightweight, fast to start, and resource-efficient. In this episode we use that foundation to build something bigger: integration with editors & the developer ecosystem. A light terminal feels pointless if it doesn't connect smoothly with the tools you use all day — the editor, git, and session picking.
There's one tension nearly every developer experiences: the editor and the terminal are two worlds that are often separated. In the editor, you have splits, tabs, and fast navigation. In tmux, you have persistent panes, windows, and sessions. Without a bridge, you switch between two "modes" with a snap: Ctrl+w in the editor for navigation, then prefix + arrow in tmux for the other — different memory, different muscle.
In this episode we'll tear down that wall. We start with seamless navigation between tmux panes and editor buffers with vim-tmux-navigator, then lazygit integration and task runners in VS Code, then build a keyboard-first workflow with fzf as a session switcher and t-smart-tmux-session-manager as a modern session manager. By the end, switching context between editor, git, and terminal will feel like one motion, not three.
The goal of integration isn't to eliminate the editor, but to make both tools reinforce each other. The editor handles code editing; tmux handles what an editor can't: sessions surviving SSH drops, windows reorganizable without touching buffers, and panes running real processes in a real environment.
There are two practical reasons senior developers often run the editor inside tmux, rather than launching an editor and opening a separate terminal:
Modern editors like Neovim already have internal splits. The question isn't "which split is better", but "when to use editor splits and when to use tmux panes". The rule of thumb: editor splits for multiple versions of the same file (separate files to compare, diff, reference); tmux panes for different processes (editor, terminal, server, log). A mix of both is the sweet spot.
In Neovim, navigation between splits uses Ctrl+w then a direction. In tmux, navigation between panes uses prefix + direction. Both coexist on the same screen: sometimes focus is on a Neovim split, sometimes on a terminal pane. The problem: Ctrl+w doesn't work in a terminal pane, and prefix + direction doesn't work inside the editor. Every context switch forces you to change your mental model.
Imagine you have a left pane running Neovim with two splits, and a right pane running a terminal. To move from the editor's bottom split to the terminal, you press Ctrl+w then Ctrl+w (exit the split), then prefix + arrow. That's not one motion but three, with two different keybinding systems. This is where vim-tmux-navigator was born.
vim-tmux-navigator is a plugin that makes one set of navigation keys work in both worlds at once: Ctrl+h/j/k/l and Ctrl+{:bash}. When focus is inside vim, those keys move between editor splits; when focus is on a tmux pane, the same keys move between panes. The plugin detects whether the active pane runs vim — if yes, the key is forwarded to vim; if not, tmux handles the pane switch.
Installation needs two sides: config in ~/.tmux.conf (so tmux knows when to forward keys) and installing the plugin in Neovim:
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
| grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'
bind -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'
bind -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'
bind -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
bind -n 'C-\\' if-shell "$is_vim" 'send-keys C-\\' 'select-pane -l'Note the is_vim line: it checks whether the active pane runs a vim/nvim process via ps. If yes, if-shell forwards the key as send-keys to the editor (the editor moves); if not, tmux directly does select-pane (tmux moves). That's an elegant context-detection pattern — one key, two behaviors, zero friction.
| Key | In a tmux pane | Inside vim/nvim |
|---|---|---|
C-h | Move to left pane | Move to left split |
C-j | Move to bottom pane | Move to bottom split |
C-k | Move to top pane | Move to top split |
C-l | Move to right pane | Move to right split |
C-{:bash} | Move to last pane | Move to last split |
Tip
Consistency is this plugin's real gift. Once C-h/j/k/l becomes reflex, you stop thinking "am I in vim or tmux" — your hand moves, and context follows automatically. That's the sign of successful integration: when you no longer notice which tool you're in.
VS Code is a different story: it has a built-in terminal (Ctrl+{:bash}) and a task runner (Tasks: Run Task). Many developers ask: "if VS Code already has a terminal and splits, why still use tmux?" The answer depends on context:
A comfortable practice: run tmux in VS Code's built-in terminal, with terminal.integrated.shellIntegration disabled so tmux doesn't fight VS Code's shell control. Keep using VS Code's task runner for quick commands like build and lint; for long-running processes (dev server, test watch, logs), prefer persistent tmux panes. With this pattern, you get the best of both worlds: VS Code's command palette for editor tasks, and tmux panes for processes that must survive.
lazygit is a terminal UI for git that makes staging, committing, branching, and logging feel visual without leaving the terminal. Its integration with tmux is very natural via display-popup (the feature we covered in episode 20): press one key, and lazygit opens in a floating window in the middle of the screen; press the key again to close it.
With a prefix + g binding, git no longer means moving to another pane or opening a new tab — it's a short moment of focus, then back to the editor. The same popup pattern works for other tools: htop, tig, or even nvim for quick notes. Popups are the modern way to "borrow context" without leaving your workflow.
The more sessions you manage (one per project, as suggested in episode 7), the more important fast session switching becomes. Without tools, switching sessions means memorizing names, then typing tmux switch-client -t <name> — slow and fragile. With fzf, session switching becomes interactive: type a little, filter, enter.
Consider a busy morning: frontend, backend, ops, and blog sessions. To reach the right session, you must remember its name, leave the current session, then attach. If you forgot the name, you type tmux ls first. All those steps can be compressed into one keybind plus one fuzzy dialog. More than convenience, it reduces the friction of starting new sessions — and low friction means workflows you actually keep using.
tmux 3.7b supports display-popup, which can run any command in a floating window. Combine it with fzf, and you have a session switcher in a few lines — complete with a lazygit popup binding and the t-session config we'll discuss:
bind-key f display-popup -h 60% -w 50% -E \
"tmux list-sessions -F '#S' | fzf --preview 'tmux capture-pane -pt {1}' | xargs -I{} tmux switch-client -t {}"Read the first tab's flow right to left: tmux list-sessions -F '#S' prints the names of all sessions; fzf shows them as a fuzzy list, complete with --preview displaying the contents of the highlighted session's pane (capture-pane); then xargs -I{} tmux switch-client -t {} moves the client to the selected session. If you cancel (Esc in fzf), nothing happens — safe.
Note
display-popup needs tmux 3.2 or newer — all examples in this episode use 3.7b as the latest stable version, so it's safe. If your team is still on an old version, upgrade or use an alternative: move the list to a full pane with new-window and tmux's built-in choose-tree.
t-smart-tmux-session-manager (often called "t-session") is a TPM plugin that brings session management to the next level: prefix + s opens a popup that can create new sessions (in a directory picked via fzf), switch to existing sessions, or rename sessions — all in one interface. Its config is in the third tab of the code-group above: two standard TPM lines we know from episode 15, then prefix + s will replace the built-in choose-tree.
The difference from the fzf switcher above: our fzf switcher moves between existing sessions; t-session also creates new sessions — it lists project directories, and picking one opens a new session in that directory. Both can coexist: prefix + f for fast switching, prefix + s for full management.
String it all into one coherent flow:
prefix + h/j/k/l (after vim-tmux-navigator) to move between panes, editor splits, or buffers.prefix + g for git in a lazygit popup.prefix + f to switch sessions with fzf.prefix + s to create or manage sessions with t-session.All operations run without taking your hands off the keyboard. This isn't about "memorizing more keys", it's about one consistent pattern across all contexts: focus, choose, continue. Once the pattern forms, you stop thinking about tools — you think about work.
Ctrl+h/j/k/l in tmux without is_vim. A direct bind -n C-h select-pane -L swallows the Ctrl+h key the editor needs for navigation. Solution: always use the if-shell "$is_vim" pattern so the key is forwarded to the editor when the editor is active.prefix + c (already "new window") for lazygit or fzf creates confusion. Use unused keys like f or g, or unbind the key you want to replace first.prefix + f (fzf) from the start so names don't need to be remembered.In episode 25, you built the bridge between tmux and the developer ecosystem: seamless navigation between panes and editor splits with vim-tmux-navigator (the is_vim + if-shell pattern), lazygit integration via display-popup, using VS Code's built-in terminal with task runners without sacrificing tmux persistence, and a keyboard-first workflow with the fzf session switcher (prefix + f) and t-smart-tmux-session-manager (prefix + s).
Key points to take away:
vim-tmux-navigator unifies pane and editor-split navigation into one key set.display-popup) are the modern pattern for "borrowing context": git, monitoring, or other tools without leaving your workflow.fzf turns session switching from memorization into an interactive dialog.Now tmux is light (episode 24) and smoothly connected to your editor (this episode). What remains is making sure this entire setup can travel anywhere. In episode 26 we'll cover production-ready setup, dotfiles & portability — storing ~/.tmux.conf and plugins in a dotfiles repo, cross-machine bootstrap scripts, conditional configs for Linux/macOS, and a safe, deterministic config checklist for teams. Because a great setup means nothing if it can't be reproduced on the next machine. Stay sharp!