Terminal multiplexer. [Ghostty](/terminal/ghostty) runs nothing but tmux, and Ghostty's `ctrl+shift` chords are tmux bindings. tmux is also used through the kitty tmux host and remotely on goliath.
tpm is a `git-repo` external in `.chezmoiexternal.toml`, cloned to `~/.config/tmux/plugins/tpm` when missing. `tmux.conf` ends with `run '~/.config/tmux/plugins/tpm/tpm'`. Plugins installed by tpm (`prefix I`) land next to it and are ignored by chezmoi. `dot_config/tmux-palette/` (→ `~/.config/tmux-palette/`) holds the [palette](#command-palette) config.
| `set-titles` | `on`, `#S`: the terminal window title is the session name, so compositor window groups list sessions (one per Ghostty window) instead of `host:window` |
| `detach-on-destroy` | `no-detached` (killing a session switches only to a detached session, else detaches, so a Ghostty window never lands on another window's session) |
These settings are what [yazi](/tools/yazi) needs inside tmux. `allow-passthrough` carries image previews through to the terminal, `set-clipboard` copies paths via OSC 52, and the two environment variables let yazi detect the outer terminal's graphics support. Nothing binds `M-[`: tmux would read the `ESC [` that starts yazi's terminal-query replies as that key and break yazi's capability detection.
| `prefix t` | Project Tasks palette ([`pj-palette`](/shell/scripts#pj-palette)): install/dev/sync/make quick actions plus every `pj` task, each run in a full-width bottom split (25% of the window) |
| `C-h` / `C-j` / `C-k` / `C-l` (no prefix) | Vim-aware pane focus. In an nvim/vim/fzf pane (`@pane-is-vim`, set by smart-splits, or the pane's command), the key goes to nvim. nvim's `config.pane_nav` moves between its own splits and, at its outer edge, runs `tmux select-pane -t $TMUX_PANE`. Elsewhere tmux moves directly. Also bound in copy mode |
The status line copies kitty's tab bar (`tab_bar_style powerline`, `tab_powerline_style angled`). The current window is an accent-tinted plate with accent text. The other windows use `bg=default` and muted text, so the terminal's transparency shows through them, as with kitty's `tab_bar_background none`. That only works while every `window-status-*-style` stays `default`: inside a tab format, `bg=default` means that style's background, not the terminal's. `tmux.conf` therefore sets all of them explicitly, because a reload never clears a value a removed plugin left behind. As in kitty, a solid arrow leads into the current window and a thin one sits between two inactive windows. The arrow into the current window is a plain `U+E0B0` in `@tab-bg`, the window background. Ghostty draws that glyph as a built-in sprite that fills the whole cell even with `adjust-cell-height`. The session name is an accent pill on the far left (`status-justify left`); its arrow points straight into the first tab, so the pill and tabs read as one chain of arrows. The right side shows `COPY`/`PREFIX`/`ZOOM` flags and the hostname.
Colors are the user options `@tab-bg` (window background: the notch arrow and the session pill's text), `@tab-fg`, `@tab-active-bg`, and `@tab-active-fg`. They are a fixed cyberdream palette, the same one Ghostty, nvim, yazi, and television use, so the bar looks identical on every machine and does not depend on Omarchy. Active background = accent mixed 20% into background, the same derivation as the kitty tab bar.
Each window reads `<index> <icon> <label>`, updating as you work, the same rule as kitty's `tab_bar.py`:
| Pane runs | Label | Source |
| --- | --- | --- |
| `nvim`/`vim`/`hx`/`helix`, editing a file | The file name | The title nvim sets (`<file> \| <org/repo>`, astrocore `custom_title`), read from `#{pane_title}` by the format itself, so a buffer switch relabels the tab immediately |
| Anything else, or an editor with no file | Repo the cwd belongs to (walks up for `.git`); the directory name outside a repo; `~` at home | `tab-label.sh`, run as an async `#()` job. When its output differs from the current name, it re-arms `automatic-rename` so tmux relabels right after a `cd` instead of on the next keystroke |
Labels longer than 27 characters end in `…`. The icon comes from tmux-nerd-font-window-name.
| `omerxx/tmux-sessionx` | `@sessionx-bind o`; `@sessionx-zoxide-mode on` (a query that matches no session is resolved through zoxide into a new session); `@sessionx-fzf-builtin-tmux on` (`fzf --tmux` popup; needs fzf ≥ 0.53, bat for previews) |
| `eduwass/tmux-palette` | `@palette-key C-Space` (root table, no prefix). Needs [Bun](https://bun.sh); tpm runs `bun install` on first load |
### Command palette
`ctrl+space` opens tmux-palette, a fuzzy command list in a popup. Its user config lives in `~/.config/tmux-palette/` (source `dot_config/tmux-palette/`):
| `commands.json` | The kitty launchers ported as palette items: **Lazygit** (90% popup in the pane's cwd; kitty `ctrl+shift+g`), **Yazi** (new window; kitty `ctrl+shift+f`), **Neovim Split** (nvim in a split to the left, 60% of the pane; alias `nv`; kitty `ctrl+shift+e`), **Shell History (atuin)** (`atuin-pick` in a 25% split below; kitty `ctrl+shift+p`). Also **btop** (80% popup; aliases `top`, `htop`), **mandible** (80% popup running [`mandible-pick`](/shell/scripts#mandible-pick); alias `man`), **television** (`tv channels`, the [channel picker](/tools/television), in a new window in the pane's cwd; alias `tv`), **gitframe** (git diff viewer in a new window in the pane's cwd; alias `gf`), **omp** (the omp agent in a full-height split on the right, 33% of the window; aliases `agent`, `ai`), **Project Tasks** (opens the tasks palette), **Sessions (sessionx)**, **Save Sessions**, and **Restore Sessions** (resurrect). Programs are started with `exec`, so the tab icon is the program's, not the shell's |
| `palettes/tasks.json` | The **Project Tasks** palette (`prefix t`, Ghostty `ctrl+shift+space`), fed by [`pj-palette`](/shell/scripts#pj-palette): `bun install`, `bun run dev`, `uv sync`, `uv run python`, `make`, `go run .`, `cargo run` as Quick items when the project has them, then every task `pj` finds, grouped by tool. Each runs in a full-width split along the bottom (25% of the window) in its directory. `ctrl-c` stops a running task; once it has exited, `enter` or `ctrl-c` closes the pane |
| `hidden.json` | Hides the built-in **Switch Theme...** item, and with it the Appearance section: the palette stays on the fixed cyberdream `theme.json` |
resurrect saves sessions, windows, panes, cwds, pane contents, and a default set of programs (nvim, less, man, …). Keys: `prefix C-s` saves, `prefix C-r` restores. continuum saves automatically every 10 minutes. When a tmux server starts and no other tmux server is running, continuum restores the last save. In practice that means the first Ghostty window after login or a reboot.
`show-name: false`, because `automatic-rename-format` supplies the label. The icon sits on the left, with a fallback icon and a blank multi-pane icon. Icons are defined for `mprocs`, `mm`, `macmon`, `make`, `zsh`, `nvim`, `devbox`, `psql`, `yazi`, `lazygit`, `gh`, `tv`, `docker`, `bun`, `node`, `npm`, `pnpm`, `go`, `bunx`, `claude`, `omp`, and `gitframe`. The plugin parses the YAML with awk and does not interpret `\U` escapes, so the glyphs are literal characters.
Installed only on Linux `desktop`/`laptop` roles (gated in `.chezmoiignore.tmpl`). Given the pane command, path, tty, and title, it prints a context segment for the window title read by [Niri](/desktop/niri). It picks the first match: