Dev Terminal Setup with Ghostty + Tmux + Neovim
If you're a developer who lives in the terminal, having a fast, clean, and efficient setup can make a world of difference. In this post, I’ll walk you through my current terminal stack: Ghostty as the terminal emulator, Tmux for session and window management, and Neovim as the code editor. This trio creates a powerful, minimal, and highly customizable development environment.
Why this stack?
- Ghostty: A modern GPU-accelerated terminal emulator with a clean aesthetic and blazing performance.
- Tmux: Terminal multiplexer that lets you split windows, manage sessions, and persist your work.
- Neovim: A modern, extensible Vim-based text editor with built-in Lua scripting and native LSP support.
Looking for Neovim?
Neovim is a core part of my workflow, but I've separated it into its own post to keep things focused. (Coming soon!)
Step-by-Step Setup
This guide walks you through setting up my terminal environment—from installing the emulator to customizing the appearance and behavior. I’ll explain not just how everything is configured, but also why I use it this way—focusing on speed, clarity, and a workflow that feels intuitive and minimal.
Setting up Ghostty
Ghostty is a newer terminal emulator, designed for speed and simplicity.
My Ghostty Config
Ghostty works great out of the box, but I tweak a few things for aesthetics and comfort. Below is the configuration I use.
# Use zsh as the default shell
shell-integration = zsh
# Font setup for icons and readability
font-family = "MesloLGS NF"
# Best theme ever
theme = catppuccin-macchiato
# Cursor preferences
cursor-style = block
cursor-style-blink = true
shell-integration-features = no-cursor # (1)
# Window size and padding
window-width = 115
window-height = 45
window-padding-y = 25,1
window-padding-x = 1,1
# Minimal macOS titlebar for cleaner appearance
macos-titlebar-style = hidden
macos-titlebar-proxy-icon = hidden
# Keybindings
keybind = cmd+r=reload_config # (2)
Hide cursor during shell integration animations
Reload Ghostty config on the fly
MesloLGS Font
The font must be installed via Nerd Fonts. It's patched to include icons and symbols used by many terminal tools (like lsd, starship, and fzf). I use MesloLGS NF because it's clean, readable, and works well with powerline-style prompts.
You can install it using Homebrew:
Setting up Tmux
I rely on tmux daily to manage terminal sessions, windows, and panes
efficiently. In this section, I’ll walk through my .tmux.conf
, explaining each
key setting and plugin I use to streamline my workflow. You can install tmux via
Homebrew:
Enable True Color and Focus Events
True color support makes themes like Catppuccin shine with accurate colors. Focus events help tmux detect when a pane gains or loses focus — useful for plugins or scripts reacting to activity.
Custom Prefix Key: Ctrl+Space
I swapped the default prefix Ctrl+B to Ctrl+Space — it’s easier on my fingers and less likely to conflict with other tools.
What's a Prefix Key?
The prefix key is a special key or key combination that acts as a trigger before executing a command. Instead of executing immediately, commands are grouped behind this prefix to avoid conflicts and keep key mappings organized.
For example, in tmux, the default prefix is Ctrl+B, so you'd press Ctrl+B followed by another key (like C to create a new window). Similarly, in Neovim, plugins often use a leader key (commonly Space) as a prefix to access custom mappings, like Space+F+F to find files or Space+G+S to open Git status.
Reload Config with <prefix> + r
Quickly reload your tmux config without restarting your sessions.
super handy when tweaking your configs.
Mouse Support and Indexing
Mouse support lets you resize panes and select text intuitively. Starting window and pane numbering at 1 feels more natural to me. Setting both base-index and pane-base-index to 1 makes tmux start counting windows and panes from 1 instead of the default 0.
I prefer this because it aligns better with how we naturally count (starting at 1), and it avoids confusion when jumping between windows and panes—especially when scripting or switching frequently. It also matches how most tools (like Vim line numbers or shell history) index things.
Vi-style Key Bindings
Enables Vim-like movements inside copy mode - use H, J, K, L instead of arrow keys.
Pane Resizing with hjkl
This allows me to quickly resize panes using prefix + Vim keys (h, j, k, l).
bind-key -r h resize-pane -L 5
bind-key -r j resize-pane -D 5
bind-key -r k resize-pane -U 5
bind-key -r l resize-pane -R 5
The -r flag makes the key repeatable, so I can hold down the key to continuously resize in that direction.
Vim-like Copy-Yank
Visual mode (v
), yank (y
) and (p
) to paste just like Vim. Using pbcopy
ensures it goes to the system clipboard (macOS)
# previous window rebind to prefix + b (we'll use prefix + p for pasting later)
unbind-key b
bind-key b previous-window
# vim copy yank
bind-key -T copy-mode-vi 'v' send -X begin-selection
bind-key -T copy-mode-vi 'y' send -X copy-selection
unbind -T copy-mode-vi MouseDragEnd1Pane
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "pbcopy"
# vim paste
unbind-key p
bind-key p run-shell "pbpaste | tmux load-buffer - && tmux paste-buffer"
Window Management (prefix + w + ?
)
Custom keybinds to help manage windows and panes more efficiently.
This binds
prefix + w
to switch to a custom key table namedprefix-w
, which acts like a submenu of keybindings (a container for sub-keys).
bind-key -T prefix-w x confirm kill-window
bind-key -T prefix-w c new-window -c "#{pane_current_path}"
bind-key -T prefix-w v split-window -h -c "#{pane_current_path}"
bind-key -T prefix-w s split-window -v -c "#{pane_current_path}"
bind-key -T prefix-w m resize-pane -Z
bind-key -T prefix-w w choose-tree -w
bind-key -T prefix-w Escape switch-client -T root
From here, you can press other keys to run window-related commands, such as:
x
to close a window (with confirmation)c
to create a new window in the current pane’s directoryv
ands
to split panes vertically or horizontallym
to toggle maximizing the current panew
to list windows across all sessionsYou can also press Escape to exit this mode without triggering any command. For example, pressing
<prefix> + w + c
creates a new window.
Rebind Show Session
I don’t like the default key binding for showing sessions, so I remapped it to
<prefix> + Space
.
This matches my Neovim setup where
<prefix> + Space
shows all current buffers, making it easier to remember across tools.
Tmux Default Keybinds
Default Key Bindings to Remember
<prefix> + s
: Show sessions<prefix> + $
: Rename session<prefix> + ,
: Rename windowctrl + h/j/k/l
: Move between panes
Tmux Plugin Setup
To use plugins in Tmux, you first need to install TPM (Tmux Plugin Manager). It makes managing plugins easier — installation, updates, and removal can all be done from within Tmux.
Then add the following to your ~/.tmux.conf
After reloading (
ctrl + r
) your Tmux config
Check Plugin Status
- Run
<prefix> + I
to install plugins. - Run
<prefix> + U
to check for plugin updates.
Theme
Use the Catppuccin Tmux theme for a visually cohesive and modern look that matches other Catppuccin-themed tools (like Neovim or your terminal).
I follow the recommended default configuration and tweak it to my liking. You can find my full setup at the end of this post.
Session Persistence
Keep your Tmux sessions alive across reboots or accidental closures.
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @resurrect-capture-pane-contents 'on'
set -g @continuum-restore 'on'
- tmux-resurrect: Saves and restores your Tmux environment (windows, panes, working directories, even some program states).
- tmux-continuum: Automatically saves your Tmux state at regular intervals and can restore it when you restart Tmux.
Vim-Tmux Navigation
Seamlessly navigate between Tmux panes and Neovim splits using the same keys
(<Ctrl-h/j/k/l>
).
TPM Initialization
Finally, make sure to include this line at the end of your ~/.tmux.conf
to
activate TPM and load the plugins:
Reminder + Full Config
- Install plugins:
<prefix> + I
- Update plugins:
<prefix> + U
TPM fetches plugins via Git. Run these commands whenever you add, remove, or want to update plugins.
As promised, you can find my full configuration here.
Let me know if you’d like a post on my Neovim or shell setup next — or if you have any suggestions to improve this workflow!