Getting to know the Tmux Plugin Manager (TPM): installation, directory structure, declaring plugins in ~/.tmux.conf, the install/update flow via prefix keys, and must-have plugins for a production-ready engineering workflow.

In episode 15 we covered hooks and event-driven automation — how tmux runs commands automatically when certain events happen, from client-attached to pane-exited. You saw how a single tmux server can behave adaptively without manual intervention. In this episode we go one level higher: instead of writing every behavior by hand, we leverage the mature plugin ecosystem through the Tmux Plugin Manager (TPM).
No engineer writes their own editor just to get syntax highlighting. Same with tmux: problems already well solved — sane defaults, clipboard integration, session persistence, status bar widgets — don't need to be re-solved. What you need to master is choosing the right plugins, declaring them correctly, and keeping the config reproducible across all machines. That's what we build in this episode, and the result is a ~/.tmux.conf that can travel from your work machine to production servers.
All examples in this episode refer to tmux 3.7b as the latest stable version. Let's start with the most basic reason: why plugins became a real need, not just a fashion statement.
tmux is deliberately designed as a minimal core. Features like panes, sessions, and windows have been rock-solid since birth, but the problems around them — clipboard, persistence, monitoring — aren't part of the core philosophy. That's where the kernel vs userland analogy applies: tmux is the stable kernel, and plugins are the userland growing to follow community needs.
Without plugins, you have to solve every problem manually each time. Want the clipboard connected to the system? Write a run-shell script. Want sessions to survive a reboot? Chain your own combination of scripts and cron. The problem is, everyone solves it differently, configurations become hard to compare, and cross-machine collaboration becomes a nightmare. TPM unifies all of it in one declarative flow.
| Real-World Problem | Manual Solution (No Plugin) | Solution with Plugin |
|---|---|---|
| tmux defaults feel rigid | Set dozens of options yourself | tmux-sensible |
| Copy doesn't reach the system clipboard | OSC 52 script / run-shell | tmux-yank |
| Server restarts, sessions lost | Record layout manually | tmux-resurrect + tmux-continuum |
| Monitoring server load | Cron + widget script | tmux-cpu / tmux-net-speed |
| Moving between many sessions | Typing session names repeatedly | t-smart-tmux-session-manager |
Note the pattern: plugins don't replace your understanding of tmux, they enrich it. You still must understand set -g, run-shell, and format strings — which we learned in episodes 6 and 9 — so plugins work optimally.
TPM is a plugin manager for tmux, inspired by Vundle in the Vim ecosystem. It works on one declarative principle: you register plugins via a special option, and TPM handles installation, updates, and loading. Declaration is done with the set -g @plugin 'user/repo' command — note the @ prefix marking this as a tmux user option, not a built-in one.
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'Each declared plugin gets cloned into ~/.tmux/plugins/ — one folder per plugin, exactly like ~/.vim/bundle/ in the Vim ecosystem. This structure is simple and easy to inspect: you can open a plugin folder anytime to read the code, see the git version, or delete it manually when not needed.
TPM is bootstrapped with one run line that must be placed at the very bottom of the config. This line executes the TPM script every time the config loads, so TPM can process the plugin list declared above it.
The first step is cloning the TPM repository into the plugin directory. The following command installs TPM to the default location:
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpmOnce the clone is done, the ~/.tmux/plugins/ directory structure will look like this:
~/.tmux/plugins/
tpm/
tmux-sensible/
tmux-yank/
tmux-resurrect/
tmux-continuum/
tmux-cpu/
tmux-net-speed/
t-smart-tmux-session-manager/Tip
If you move the config to an XDG-based location like ~/.config/tmux/tmux.conf (fully supported in tmux 3.7b), TPM automatically uses ~/.config/tmux/plugins/. Don't mix two locations at once — pick one and stay consistent, because a split config only confuses when debugging.
Next, add the bootstrap line to ~/.tmux.conf. Here's the correct minimal pattern:
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
run '~/.tmux/plugins/tpm/tpm'Note the order: @plugin declarations come above, and run is the very last line. This isn't just convention — TPM reads the full plugin list already present when the run line executes, so putting run before the declarations is like asking TPM to work before knowing which plugins it should process.
Once the config is ready, reload first so the server reads the changes. You can press prefix + r if you already bound the reload in episode 11, or run the following command from the shell:
tmux source-file ~/.tmux.confThe next step is installation. Press prefix + I — capital letter — and TPM will clone every plugin not yet in ~/.tmux/plugins/, then load it. The install output appears briefly at the bottom of the screen; watch which lines succeed and which fail.
For updates, press prefix + U. TPM runs git pull on every plugin and reports before/after versions. This is a flow you can run routinely, e.g. once a week, so plugins stay in sync with bug fixes and new features upstream.
Important
Updating plugins isn't a risk-free operation. Plugins declared without pinning to a version will follow master, so behavior can change after an update. Before mass updates on a production machine, read each plugin's changelog first — or pin to a specific tag with set -g @plugin 'tmux-plugins/tmux-resurrect#v2.6.0'.
tmux-sensible is the simplest yet most often overlooked plugin. It sets a bunch of "sensible" defaults: mouse support, vi-style copy mode navigation, larger history, and terminal compatibility fixes. Instead of writing dozens of option lines manually on each new machine — which is typo-prone and inconsistent — just declare this one plugin and let it normalize the basics.
tmux-sensible's strength lies in consistency: all team members using the same plugin get the same base experience, making cross-machine keybinding troubleshooting much easier.
tmux's default only copies text to an internal buffer, unreachable by other applications. tmux-yank closes this gap by forwarding yank results to the system clipboard: pbcopy on macOS, xclip/xsel on X11, and wl-copy on Wayland. Once installed, yanking in copy mode is immediately available for pasting in a browser, editor, or chat.
set -g @plugin 'tmux-plugins/tmux-yank'Keep in mind, tmux-yank is only a bridge — it still needs a clipboard tool installed on the system. We'll discuss these prerequisites further in the Common Pitfalls section.
This combination is the most valuable pair in the tmux ecosystem. tmux-resurrect saves session state — windows, panes, layout, even running commands — to a file, and can restore it. tmux-continuum completes it with automation: saving state periodically and restoring automatically when a new tmux server starts.
Think of it like save/load in a game: tmux-resurrect is the manual save button, while tmux-continuum is autosave. When the server reboots mid-work, you don't start from zero — just open tmux and all sessions return as before the reboot.
set -g @continuum-save-interval '15'
set -g @continuum-restore 'on'
set -g @resurrect-capture-pane-contents 'on'The first line sets the autosave interval to every 15 minutes, the second enables automatic restore, and the third makes resurrect also save the visible pane contents so the work context isn't lost.
For engineers who often monitor machines from inside the terminal, tmux-cpu and tmux-net-speed provide format variables you can insert directly into the status bar. Format variables like #{cpu_percentage}, #{cpu_bg_color}, and #{net_speed} are filled in automatically by the plugins.
set -g @tmux_cpu_interval '2'
set -g status-right '#[fg=green]#{cpu_percentage}#[default] #[fg=blue]#{net_speed}#[default]'The advantage of this approach over writing your own widgets: already optimized for periodic updates without burdening the CPU, and easy to move between machines. In episode 17 we'll build our own lightweight version for cases not covered by plugins.
The more sessions you open, the slower manual filtering becomes. t-smart-tmux-session-manager solves this with a fuzzy finder: press prefix + T and an fzf popup appears listing sessions and frequently visited directories, and you just type a few letters to switch.
This plugin requires fzf and zoxide as prerequisites, and is also available as a t command callable from the shell. You should know that this project has been archived by its author in favor of the faster sesh — but its plugin declaration still works and stays stable for daily use.
Now let's combine everything. Here's an example of a complete, ready-to-use ~/.tmux.conf containing the TPM bootstrap and declarations for all the plugins we've discussed:
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-yank'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @plugin 'tmux-plugins/tmux-cpu'
set -g @plugin 'tmux-plugins/tmux-net-speed'
set -g @plugin 'tmux-plugins/t-smart-tmux-session-manager'
set -g @continuum-save-interval '15'
set -g @continuum-restore 'on'
set -g @resurrect-capture-pane-contents 'on'
set -g @tmux_cpu_interval '2'
set -g status-right '#[fg=green]#{cpu_percentage}#[default] #[fg=blue]#{net_speed}#[default]'
run '~/.tmux/plugins/tpm/tpm'The usage flow is as follows:
~/.tmux.conf.tmux source-file ~/.tmux.conf.prefix + I to install all plugins at once.prefix + U periodically to update the plugins.prefix + : then set -g status-right to check the widgets, or just observe the status bar directly.After these steps, you have a productive tmux foundation: clipboard connected, sessions surviving reboots, widgets monitoring infrastructure, and fast session switching. What remains are the bad habits that often ruin this setup.
Placing the run line before the @plugin declarations. TPM executes the file top to bottom; if run appears first, the plugin list isn't fully read and some plugins won't be installed. Always make run the last line.
Not reloading the config before prefix + I. TPM reads the plugin list from the currently running server state. If you edit ~/.tmux.conf but don't run tmux source-file ~/.tmux.conf, the prefix + I key won't recognize new plugins.
Ignoring clipboard prerequisites. tmux-yank fails silently if tools like xclip, wl-copy, or pbcopy are missing. Check by running the tool directly from the terminal before blaming the plugin.
Adding widget plugins but forgetting to put the format variable in the status bar. tmux-cpu and tmux-net-speed don't display anything automatically — you must insert #{cpu_percentage} or #{net_speed} into status-right or status-left.
Deleting the ~/.tmux/plugins/ folder manually. TPM considers an existing folder as an installed plugin. Deleting it won't remove the plugin from the declaration, so prefix + I will just clone it again. Uninstall via the config, not the filesystem.
Not versioning the config and plugin list. A config spread across several machines without a repo will drift apart. Keep ~/.tmux.conf in a dotfiles repo — we'll discuss modular structure and versioning in depth in episode 17.
This episode closed the foundation of a complete tmux config. You now know TPM as a declarative plugin manager, understand the ~/.tmux/plugins/ structure, master the install flow with prefix + I and update with prefix + U, and can choose the right plugins: tmux-sensible for sane defaults, tmux-yank for clipboard, tmux-resurrect and tmux-continuum for persistence, tmux-cpu and tmux-net-speed for status widgets, and t-smart-tmux-session-manager for fast session navigation.
Key points to take away:
set -g @plugin 'user/repo' then bootstrap with run at the bottom line.prefix + I installs, prefix + U updates, and the config must be reloaded before both.Now you know how to use other people's plugins. In episode 17 we'll cover custom scripts, lightweight plugins, and status widgets — building your own helpers, splitting the config into modules with source-file, using tmuxp for layouts, and keeping everything reproducible via versioning. See you in episode 17!