Skip to content

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.

brew install ghostty

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.

~/.config/ghostty/config
# 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)
  1. ❓ Hide cursor during shell integration animations
  2. ❓ 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:

brew tap homebrew/cask-fonts
brew install --cask font-meslo-lg-nerd-font

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:

brew install tmux

Enable True Color and Focus Events

~/.tmux.conf
set -g default-terminal "screen-256color"
set-option -g focus-events on

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

~/.tmux.conf
set-option -g prefix C-Space
unbind-key C-b
bind-key C-Space send-prefix

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.

~/.tmux.conf
unbind r
bind r source-file ~/.tmux.conf \; display-message "Config reloaded!"

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.

~/.tmux.conf
set -g mouse on
set -g base-index 1
setw -g pane-base-index 1

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.

~/.tmux.conf
setw -g mode-keys vi

Pane Resizing with hjkl

This allows me to quickly resize panes using prefix + Vim keys (h, j, k, l).

~/.tmux.conf
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)

~/.tmux.conf
# 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.

~/.tmux.conf
bind-key w switch-client -T prefix-w

This binds prefix + w to switch to a custom key table named prefix-w, which acts like a submenu of keybindings (a container for sub-keys).

~/.tmux.conf
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 directory
  • v and s to split panes vertically or horizontally
  • m to toggle maximizing the current pane
  • w to list windows across all sessions

You 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.

~/.tmux.conf
bind-key Space choose-tree -s

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 window
  • ctrl + 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.

git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm

Then add the following to your ~/.tmux.conf

~/.tmux.conf
set -g @plugin 'tmux-plugins/tpm'

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).

set -g @plugin 'catppuccin/tmux#v1.0.0'
set -g @catppuccin_flavor 'macchiato'

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>).

set -g @plugin 'christoomey/vim-tmux-navigator'

TPM Initialization

Finally, make sure to include this line at the end of your ~/.tmux.conf to activate TPM and load the plugins:

run '~/.tmux/plugins/tpm/tpm'

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!