Tmux with Zero Plugins
Intro
What’s up guys, my name is Tony, and today I’m gonna give you a quick and painless guide on configuring tmux with ZERO plugins.
Tmux is probably the most essential tool in my development workflow. It’s a terminal multiplexer that allows you to split your terminal into multiple panes, create multiple windows, and detach/reattach sessions.
In the past, I relied on TPM as a plugin manager, but taking inspiration from Henry Misc, I decided to debloat my entire config into a plugin-less config. This means I don’t need to rely on any plugins, and can just use the native Tmux settings.
Let’s jump into it.
What is Tmux?
Tmux stands for “Terminal Multiplexer”. Here’s what that means:
- Sessions: A tmux session is like a workspace. You can detach from it, close your terminal, and reattach later - everything is still there.
- Windows: Think of these like browser tabs. Each window is a full terminal view.
- Panes: These are splits within a window. You can have multiple terminals visible at once.
This is crucial if you SSH into servers, work on multiple projects, or just want to keep your terminal organized without using a tiling window manager.
Installation
Alright so I’m on arch linux, btw, but this is going to work on literally any distro. Tmux is in every package manager.
For arch:
sudo pacman -S tmux
For Ubuntu/Debian:
sudo apt install tmux
NixOS… just add `tmux` to wherever you install your nixpkgs.
That’s it. No plugins, no plugin managers, nothing. Just tmux.
Key Pivotal Binds
Prefix Key
The most important concept in tmux is the prefix key. By default, it’s Ctrl-b, but we’re gonna change it to Ctrl-a because it’s way easier to reach.
Every tmux command starts with the prefix. So when I say “prefix + c”, that means:
- Press
Ctrl-a - Release
- Press
c
Sessions, Windows & Panes
Here’s the hierarchy:
- A session contains multiple windows
- A window contains multiple panes
Think of it like this:
- Session = Project
- Window = Task within that project
- Pane = Terminal view for that task
Pane Navigation
These are the binds you’ll use 1000 times a day:
| Bind | Action |
|---|---|
prefix + \vert |
Split vertically |
prefix + - |
Split horizontally |
prefix + h/j/k/l |
Navigate panes (vim-like) |
Alt + h/j/k/l |
Navigate without prefix |
Window Management
| Bind | Action |
|---|---|
prefix + c |
Create new window |
prefix + n |
Next window |
prefix + p |
Previous window |
Alt + 1-9 |
Jump to window 1-9 |
Copy Mode
Copy mode lets you scroll through terminal history and copy text:
| Bind | Action |
|---|---|
prefix + [ |
Enter copy mode |
v |
Start selection (vim-like) |
Ctrl-v |
Rectangle selection |
y |
Copy selection |
q |
Exit copy mode |
Configuration
Let’s build a clean, readable config with zero plugins.
Basic Settings
Create ~/.config/tmux/tmux.conf:
# Enable 256 color support
set -g default-terminal "tmux-256color"
set -ga terminal-overrides ",*:RGB"
# Enable mouse support
set -g mouse on
# Enable clipboard
set -g set-clipboard on
Let me break these down:
default-terminal "tmux-256color"tells tmux to advertise itself as a 256-color terminal, which is essential for proper color rendering in modern terminal applications like Neovim.terminal-overrides ",*:RGB"enables true color (24-bit RGB) support, giving you access to millions of colors instead of just 256. This is what makes your color schemes look properly vibrant.mouse onis controversial in the terminal purist community, but it’s genuinely useful for quickly clicking between panes or dragging borders to resize them. You can always disable it later if you go full keyboard-only.set-clipboard onallows tmux to integrate with your system clipboard, so when you copy text in tmux copy-mode, it actually goes to your system clipboard.
Better Keybinds
# Change prefix from Ctrl-b to Ctrl-a
unbind C-b
set -g prefix C-a
bind-key C-a send-prefix
# Vim-style pane navigation
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
# Split windows (opens in same directory)
unbind %
bind | split-window -h -c "#{pane_current_path}"
unbind '"'
bind - split-window -v -c "#{pane_current_path}"
# Reload config
unbind r
bind r source-file $HOME/.config/tmux/tmux.conf
# Alt+hjkl to switch panes without prefix
bind -n M-h select-pane -L
bind -n M-j select-pane -D
bind -n M-k select-pane -U
bind -n M-l select-pane -R
# Alt+number to select window
bind -n M-1 select-window -t 1
bind -n M-2 select-window -t 2
bind -n M-3 select-window -t 3
bind -n M-4 select-window -t 4
bind -n M-5 select-window -t 5
bind -n M-6 select-window -t 6
bind -n M-7 select-window -t 7
bind -n M-8 select-window -t 8
bind -n M-9 select-window -t 9
Let me explain the key concepts here:
unbind C-bremoves the default Ctrl-b prefix because it’s awkward to reach.set -g prefix C-achanges it to Ctrl-a, which is way more ergonomic since your pinky is already on Ctrl.bind-key C-a send-prefixallows you to send the actual Ctrl-a to the terminal (useful in nested tmux sessions or when an app needs Ctrl-a).- The vim-style
hjklbinds are essential if you’re a vim user - they let you navigate panes with prefix+h/j/k/l instead of the default arrow keys. split-window -h -c "#{pane_current_path}"is crucial - the-cflag makes new panes open in the same directory as your current pane. Without this, splits would open in your home directory, which is super annoying.unbind %andunbind '"'remove the default split bindings so we can use|and-instead, which are way more intuitive (vertical bar for vertical split, dash for horizontal split).bind -nmeans “bind without prefix”. Sobind -n M-hlets you use Alt+h to switch panes instantly, without hitting prefix first. This is a MASSIVE quality of life improvement once you get used to it.- The Alt+number binds (M-1 through M-9) let you jump directly to windows without prefix, similar to how browser tabs work with Ctrl+1-9.
Theme Colors
Now here’s where we make it look good. I’m using Tokyo Night Moon colors, but you can swap these out for any color scheme.
# Tokyo Night Moon theme colors
thm_bg="#222436"
thm_fg="#c8d3f5"
thm_cyan="#86e1fc"
thm_black="#1b1d2b"
thm_gray="#3a3f5a"
thm_magenta="#c099ff"
thm_pink="#ff757f"
thm_red="#ff757f"
thm_green="#c3e88d"
thm_yellow="#ffc777"
thm_blue="#82aaff"
thm_orange="#ff9e64"
thm_black4="#444a73"
# Status bar settings
set -g status "on"
set -g status-bg "${thm_bg}"
set -g status-justify "left"
set -g status-left-length "100"
set -g status-right-length "100"
# Messages
set -g message-style "fg=${thm_cyan},bg=${thm_gray},align=centre"
set -g message-command-style "fg=${thm_cyan},bg=${thm_gray},align=centre"
# Panes
set -g pane-border-style "fg=${thm_gray}"
set -g pane-active-border-style "fg=${thm_blue}"
# Windows
set -g window-status-activity-style "fg=${thm_fg},bg=${thm_bg},none"
set -g window-status-separator ""
set -g window-status-style "fg=${thm_fg},bg=${thm_bg},none"
Status Bar Customization
This is where it gets interesting. The status bar shows your current windows and session info.
# Statusline - current window
set -g window-status-current-format "#[fg=${thm_blue},bg=${thm_bg}] #I: #[fg=${thm_magenta},bg=${thm_bg}](✓) #[fg=${thm_cyan},bg=${thm_bg}]#(echo '#{pane_current_path}' | rev | cut -d'/' -f-2 | rev) #[fg=${thm_magenta},bg=${thm_bg}]"
# Statusline - other windows
set -g window-status-format "#[fg=${thm_blue},bg=${thm_bg}] #I: #[fg=${thm_fg},bg=${thm_bg}]#W"
# Statusline - right side
set -g status-right "#[fg=${thm_blue},bg=${thm_bg},nobold,nounderscore,noitalics]#[fg=${thm_bg},bg=${thm_blue},nobold,nounderscore,noitalics] #[fg=${thm_fg},bg=${thm_gray}] #W #{?client_prefix,#[fg=${thm_magenta}],#[fg=${thm_cyan}]}#[bg=${thm_gray}]#{?client_prefix,#[bg=${thm_magenta}],#[bg=${thm_cyan}]}#[fg=${thm_bg}] #[fg=${thm_fg},bg=${thm_gray}] #S "
# Statusline - left side (empty)
set -g status-left ""
# Modes
set -g clock-mode-colour "${thm_blue}"
set -g mode-style "fg=${thm_blue} bg=${thm_black4} bold"
This is where things get interesting. Let me break down what’s happening:
window-status-current-formatdefines how the active window looks in the status bar. It shows the window index (#I), a checkmark, and the last two parts of the current path.- The
#(echo '#{pane_current_path}' | rev | cut -d'/' -f-2 | rev)command runs a shell command every time the status bar updates. It reverses the path, takes the last 2 parts, then reverses again. So/home/tony/projects/dotfilesbecomesprojects/dotfiles. window-status-formatis for inactive windows - just shows the index and window name.status-rightshows the window name (#W), a visual indicator that changes from cyan to magenta when prefix is pressed using#{?client_prefix,...}conditional, and the session name (#S).#Iis the window index (number),#Wis the window name,#Sis the session name - these are tmux’s format variables.
The #{?client_prefix,...} syntax is tmux’s conditional - it means “if prefix is pressed, use magenta, otherwise use cyan”. This gives you a visual indicator when you’re in prefix mode.
Extra Binds & Tweaks
Here are some nice-to-haves that should be placed earlier in the config (after the basic settings):
# Change from 0 based to 1 based because keyboard layout
set -g base-index 1
set -g pane-base-index 1
set-window-option -g pane-base-index 1
set-option -g renumber-windows on
# Vim-like copy/paste
set-window-option -g mode-keys vi
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle
bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel
unbind -T copy-mode-vi MouseDragEnd1Pane
Here’s what these do:
base-index 1makes windows start counting from 1 instead of 0. This is way more ergonomic because window 1 is on the left of your keyboard (the 1 key), not the right (0 is to the right of 9). It’s a small thing but it makes a huge difference.pane-base-index 1does the same for panes.renumber-windows onautomatically renumbers your windows when you close one. So if you have windows 1, 2, 3, 4 and you close window 2, the remaining windows become 1, 2, 3. Without this, you’d have gaps like 1, 3, 4.mode-keys vienables vim keybindings in copy mode. This is essential if you’re a vim user - it means you can use j/k to navigate, v to start visual selection, etc.- The
copy-mode-vibindings makevstart a selection (like visual mode in vim) andyyank (copy) the selection. C-vlets you do rectangle selection (block visual mode in vim).unbind -T copy-mode-vi MouseDragEnd1Paneprevents mouse selection from automatically exiting copy mode, so you can still useyto copy after selecting with the mouse.- You enter copy mode with
prefix + [, navigate with vim keys,vto select,yto copy.
Final Thoughts
You’re now ready to use Neovim as a modern, fast, and extensible code editor.
Thanks so much for checking out this tutorial. If you got value from it, and you want to find more tutorials like this, check out my youtube channel here: YouTube, or my website here: tony,btw
You can support me here: kofi