-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy path.tmux.conf
More file actions
270 lines (229 loc) · 11.1 KB
/
Copy path.tmux.conf
File metadata and controls
270 lines (229 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# tmux configuration
# Fixed version addressing configuration issues
# ===============
# Basic Settings
# ===============
# Set prefix to Ctrl-Space
unbind C-b
unbind C-Space
set -g prefix C-Space
bind C-Space send-prefix
# Performance and behavior settings
set -g history-limit 50000
set -s escape-time 0 # Fast escape (consistent setting)
set -g assume-paste-time 0
# status-interval + window-status-format overrides for tmux-agentbar live
# AT THE BOTTOM of this file (after TPM init), because Dracula's plugin
# clobbers these when it loads.
# Colors and display
set -g default-terminal "tmux-256color"
set -ag terminal-overrides ",xterm-ghostty:Tc,xterm-256color:Tc"
# Start windows and panes at 1, not 0
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
# Don't let programs rename windows via escape sequences
set-option -g allow-rename off
# Auto-name windows after the current directory. The "agent here" robot
# glyph is injected by tmux-agentbar's window-status script (process-tree
# detection catches claude, copilot, aider, codex, gemini, etc. — not just
# claude's version-string process title). Window name stays as bare dirname.
set-option -g automatic-rename on
set-option -g automatic-rename-format "#{b:pane_current_path}"
# Bell handling — tmux-agentbar fires \a on `waiting`/`done` via Claude Code hooks.
# `monitor-bell on` + `window-status-bell-style` flips only the originating tab
# into reverse video until you focus it, so a multi-window Claude session tells
# you WHICH window needs attention (vs visual-bell's one-shot whole-bar flash).
set -g visual-bell off
set -g monitor-bell on
set -g bell-action any
set -g activity-action none
set -g window-status-bell-style 'reverse,bold'
# Enable mouse control
set -g mouse on
# Allow passthrough escape sequences (for images, Claude Code notifications, progress bars)
set -g allow-passthrough on
# Let tmux distinguish Shift+Enter from Enter so Claude Code's newline works inside tmux
# (per https://code.claude.com/docs/en/terminal-config#configure-tmux)
set -s extended-keys always
set -as terminal-features 'xterm*:extkeys'
# ===============
# Key Bindings
# ===============
# Session management
bind-key N new-session
# Reload config file
bind r source-file ~/.tmux.conf \; display-message "Config reloaded..."
# Per-directory Claude Code popup — prefix + y
# Session name is derived from the MD5 of the current path, so the same directory
# always reattaches to the same Claude session across invocations.
bind -r y run-shell '\
SESSION="claude-$(echo #{pane_current_path} | md5 -q | cut -c1-8)"; \
tmux has-session -t "$SESSION" 2>/dev/null || \
tmux new-session -d -s "$SESSION" -c "#{pane_current_path}" "claude"; \
tmux display-popup -w80% -h80% -E "tmux attach-session -t $SESSION"'
# Lazygit popup — prefix + g. Scoped to current pane's cwd.
# Default prefix + g is "choose session by name", which I have prefix + s / o for.
bind -r g display-popup -E -w 90% -h 90% -d "#{pane_current_path}" "lazygit"
# Ephemeral shell peek — prefix + Enter.
# Quick shell at the current pane's cwd without creating a new window.
# Exits back when you `exit` or Ctrl-D.
bind Enter display-popup -E -w 80% -h 80% -d "#{pane_current_path}" "zsh"
# Personal cheat sheet — prefix + ? (overrides native "list-keys -N" which is too verbose).
# Rendered with glow (proper markdown: headings, tables, code blocks) when available,
# falls back to bat until `brew install glow` completes. Press q to exit.
bind '?' display-popup -E -w 90% -h 90% "if command -v glow >/dev/null 2>&1; then glow -p ~/projects/dotfiles/tmux-help.md; else bat --paging=always --style=plain --language=markdown ~/projects/dotfiles/tmux-help.md; fi"
# Local-LLM chat menu — prefix + a. Pops a model picker; each entry opens or
# reattaches a persistent ollama scratch session in a popup. Conversation
# history is per-model (each model gets its own tmux session), so you can
# park a coding thread in qwen3-coder while running quick Q&A in gemma3.
# Override default tmux `prefix + a` (last-pane, rarely used).
#
# Rebuilt 2026-08-11 from the compile-and-run bench, which grades by actually
# building and executing each model's output (bench-results/m1-max-64gb.md).
# Every entry below scored 3/3; nothing untested is offered.
#
# gemma4:26b 3/3 58.2 tok/s 17 GB default — MoE, ~4B active, so it
# runs at 7B latency despite size
# qwen3-coder:30b 3/3 74.0 tok/s 18 GB fastest; base for the agentic
# ctx64k variant used by OpenCode/Pi
# gpt-oss:20b 3/3 62.2 tok/s 13 GB 128K context, tunable reasoning
# gemma4:12b 3/3 27.8 tok/s 7.6 GB small footprint, slower
#
# Dropped from the menu: qwen2.5-coder:7b — it was the DEFAULT and scores 1/3,
# failing both Kotlin (unresolved reference) and Swift (@main misuse).
# mistral:7b and gemma3:4b are dropped as never benched on this suite; both are
# still installed, so pass them to ai-popup.sh directly if you want them.
#
# Note gpt-oss:20b was previously deleted here as an underperformer. It now
# scores 3/3 — that was an older build, so the old note no longer holds.
bind a display-menu -T "#[align=centre] AI chat — pick a model " -x C -y C \
"gemma4:26b (default, 3/3, 58 tok/s)" g "run-shell '~/projects/dotfiles/ai-popup.sh gemma4:26b'" \
"qwen3-coder:30b (3/3, fastest 74 tok/s)" c "run-shell '~/projects/dotfiles/ai-popup.sh qwen3-coder:30b'" \
"" \
"gpt-oss:20b (3/3, 128K ctx, reasoning)" o "run-shell '~/projects/dotfiles/ai-popup.sh gpt-oss:20b'" \
"gemma4:12b (3/3, small 7.6 GB)" l "run-shell '~/projects/dotfiles/ai-popup.sh gemma4:12b'"
# Pane management
unbind x
bind x resize-pane -Z # Zoom/maximize pane
# Split windows with intuitive keys
bind | split-window -h -c "#{pane_current_path}"
bind _ split-window -c "#{pane_current_path}"
# Resize panes
bind C-l resize-pane -R 10
bind C-j resize-pane -D 10
bind C-h resize-pane -L 10
# Note: Removed C-k binding to avoid conflicts
bind C-u resize-pane -U 10 # Changed from C-k to C-u
bind * resize-pane -x 80
# Swap panes
bind ) swap-pane -D
bind ( swap-pane -U
# Synchronize panes
bind = setw synchronize-panes
# Layout management
bind-key @ select-layout even-horizontal
bind-key ! select-layout even-vertical
bind l select-layout -n
bind L select-layout -p
# Pane navigation with Alt-arrow (no prefix needed)
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D
# Outer navigation with Shift+Alt+arrow (no prefix needed).
# Horizontal = windows (siblings), Vertical = sessions (cousins).
# Mnemonic parity with Alt+arrow for panes.
bind -n M-S-Left previous-window
bind -n M-S-Right next-window
bind -n M-S-Up switch-client -p
bind -n M-S-Down switch-client -n
# Double prefix toggles last window (`Ctrl-Space Ctrl-Space`). Restores the
# tmux default `prefix + l` behavior, which I lost when I remapped `l` to
# `select-layout -n`. Useful for ping-ponging between two windows.
bind C-Space last-window
# Cycle through panes with double prefix
unbind ^A
bind ^A select-pane -t :.+
# Clear pane (safer binding that doesn't conflict)
bind -n C-M-k send-keys -R \; clear-history
# Pane title management
bind-key t command-prompt -p "Rename pane:" "select-pane -T '%%'"
bind-key T if -F '#{?#{==:#{pane-border-status},off},0,1}' 'set pane-border-status off' 'set pane-border-status top'
# ===============
# Plugin Configuration
# ===============
# TPM Plugin list
#
# tmux-continuum MUST be last: it auto-saves by injecting a hook into
# status-right, and any plugin loaded after it that also sets status-right
# (Dracula does) silently wipes the hook → auto-save stops, restores serve
# whatever the last successful save was. See tmux-continuum README.
set -g @tpm_plugins ' \
tmux-plugins/tpm \
tmux-plugins/tmux-sensible \
tmux-plugins/tmux-resurrect \
dracula/tmux \
omerxx/tmux-sessionx \
tmux-plugins/tmux-continuum \
'
# sessionx — fuzzy session/window picker in a tmux popup.
# Bound to `prefix + o` (overrides default rotate-pane-forward, which I don't use).
# Complements `prefix + s` (native, kept as fallback) and the `s` shell function.
set -g @sessionx-bind 'o'
set -g @sessionx-zoxide-mode 'on'
set -g @sessionx-window-mode 'on'
set -g @sessionx-preview-enabled 'true'
set -g @sessionx-filter-current 'false'
set -g @sessionx-prompt ' ⚡ '
# Plugin settings
# Continuum auto-saves session/window/pane state and restores it on tmux start.
# combined with @continuum-boot below, this means: reboot → open iTerm →
# tmux launches → all sessions/windows/layouts/cwds back where you left them.
# Note: running processes in panes (claude, npm dev, etc.) are NOT auto-resumed —
# panes come back as fresh shells at the right cwd.
set -g @continuum-restore 'on'
set -g @continuum-save-interval '5'
set -g @continuum-boot 'on'
set -g @continuum-boot-options 'iterm,fullscreen'
set -g @resurrect-capture-pane-contents 'on'
set -g @resurrect-strategy-vim 'session'
# Dracula theme settings
set -g @dracula-show-powerline true
set -g @dracula-show-flags true
set -g @dracula-plugins "cpu-usage ram-usage time"
set -g @dracula-left-icon-padding 0
set -g @dracula-military-time true
# ===============
# macOS Compatibility
# ===============
# Modern macOS doesn't need reattach-to-user-namespace
# Only set if the utility exists (for older systems)
if-shell 'command -v reattach-to-user-namespace >/dev/null 2>&1' \
'set-option -g default-command "reattach-to-user-namespace -l $SHELL"' \
'set-option -g default-command "$SHELL"'
# ===============
# Plugin Manager Initialization
# ===============
# Initialize TPM (keep at bottom) - with error handling
if-shell 'test -f ~/.tmux/plugins/tpm/tpm' \
'run ~/.tmux/plugins/tpm/tpm' \
'display-message "TPM not installed. Run: git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm"'
# ===============
# Post-plugin overrides (must come AFTER TPM init)
# ===============
# Dracula's tmux plugin sets window-status-format and status-interval when it
# loads, so any values we set earlier get clobbered. Re-apply here so the
# tmux-agentbar icon shows up AND the spinner animates at 1s cadence.
#
# The format preserves Dracula's colors (#44475a bg, #f8f8f2 fg for normal;
# #6272a4 bg for current) and just injects the agent icon between #W and the
# window flags.
set -g status-interval 1
# The `` glyphs (U+E0B0) are Dracula's powerline chevrons that transition
# between the current tab's purple bg and the surrounding dark bg. Don't drop
# them — if your editor shows a box, make sure the terminal font is a Nerd
# Font (IosevkaTermNF here) and the file is UTF-8.
setw -g window-status-format "#[fg=#f8f8f2]#[bg=#44475a] #I #(~/projects/dotfiles/tmux-agentbar/scripts/agentbar-window-status.sh #I)#W#{?window_flags,#[fg=#6272a4]#{window_flags},}"
setw -g window-status-current-format "#[fg=#44475a,bg=#6272a4]#[fg=#f8f8f2,bg=#6272a4] #I #(~/projects/dotfiles/tmux-agentbar/scripts/agentbar-window-status.sh #I)#W#{?window_flags,#[fg=#bd93f9]#{window_flags},} #[fg=#6272a4,bg=#44475a]"