本站截圖背後那份 ~/.tmux.conf:為小螢幕、程式助手,以及手機和電腦同時掛著的情境調過。
撰寫於
tmux 的預設值是為桌上型電腦寫的:只掛一個用戶端,鍵盤上有一整排修飾鍵,執行的程式只輸出文字。放到手機上,這幾條沒有一條成立,螢幕小,往往還有一台手提電腦同時掛著,而裏面跑的越來越多是程式助手,它講的是顏色、圖片和 Shift+Enter,這些在原裝 tmux 下都活不下來。
這就是我們真正在用的那份檔案,不是入門範本:本站所有 tmux 截圖都是透過它拍的。整份拷走,或者只挑你要的部分,每一行都帶註解說明它換來了甚麼,下面幾節則解釋那些不太顯然的取捨。
##### 終端機能力 ##### # 終端機類型 + 24 位真彩色:沒有 RGB,漸變會有色帶 set -g default-terminal "tmux-256color" set -as terminal-features ",*:RGB" # RGB 告訴的是 tmux:外層終端機支援真彩色;裏面的程式(nvim、bat、fzf、 # delta)要不要送 24 位色,看的是 COLORTERM。tmux 自己從不把這個變數 # 傳進去,所以把它釘死 set-environment -g COLORTERM truecolor # 內嵌圖片(sixel、kitty、imgcat):否則會被 tmux 丟掉 set -g allow-passthrough on set -as terminal-features ",*:sixel" # 在 tmux 裏複製,直接進手機剪貼簿(OSC 52) set -g set-clipboard on # ……走 mosh 時也一樣。tmux 發這條 OSC 52 時不填目標,發出來是 52;;, # 而 mosh 只轉發 52;c;,所以沒有這一行,在 tmux 裏複製的內容只會進 # tmux 自己的貼上緩衝區,根本出不了伺服器。%p1 一定要留着:跳過它 # 直接寫 %p2 的寫法能正常載入,然後甚麼都不發 set -ag terminal-overrides ',*:Ms=\E]52;%p1%sc;%p2%s\a' # 讓 Ctrl+Shift+…、Shift+Enter 之類以 CSI u 形式穿過 tmux # (Claude Code 靠這個來實現 Shift+Enter 換行) set -s extended-keys on set -as terminal-features ",*:extkeys" set -g extended-keys-format csi-u # 別在 Esc 上等:預設那 500ms 會毀掉 Alt 組合鍵 set -sg escape-time 10 # 焦點事件和滑鼠(在終端機裏按住 Shift 可以本機選取) set -g focus-events on set -g mouse on # 把視窗標題轉發出來,終端機 App 才能為分頁命名 set -g set-titles on set -g set-titles-string "tmux · #{pane_title}" # 捲動回看行數:程式助手輸出很多,給它留夠 set -g history-limit 100000 ##### 手機 / 同時掛著多個用戶端 ##### # 視窗大小跟著「最近活動」的用戶端走:手機和電腦同時掛著時, # 誰在打字就按誰的螢幕來;小螢幕不會把版面鎖死 set -g window-size latest setw -g aggressive-resize on # 視窗和窗格從 1 開始編號,關掉後自動補號:手機鍵盤上 1 比 0 好按 set -g base-index 1 setw -g pane-base-index 1 set -g renumber-windows on # 關掉目前工作階段時跳到下一個,而不是直接 detach: # 從手機上重新連線很麻煩 set -g detach-on-destroy off # 提示訊息多留一會兒,小螢幕上才來得及看 set -g display-time 2000 set -g display-panes-time 2000 ##### 程式助手提醒 ##### # Claude Code 這類工具做完會響鈴:不要閃螢幕, # 只在狀態列那個視窗名上加一個粗體的 ! set -g bell-action any set -g visual-bell off setw -g monitor-bell on # 背景視窗有新輸出 -> 狀態列出現 # 標記, # 一眼就能看出哪個程式助手還在跑、哪個已經停了 setw -g monitor-activity on set -g visual-activity off ##### 配色 ##### # bg=default 讓終端機自己的背景透過來,點綴色(工作階段名稱、前綴提示、 # 活動標記)取自終端機的調色盤。凡是必須在每個掛著的用戶端上都看得清的 # 部分,改用固定的 256 色,它們在任何主題下都長一個樣 # 狀態列放在頂部,避開底部 Claude Code 的輸入框 set -g status-position top set -g status-interval 5 set -g status-style "bg=default,fg=default" # 左邊顯示工作階段名稱;右邊只在按住前綴鍵時顯示 ^B 提示 set -g status-left "#[fg=colour5,bold] #S #[default]" set -g status-left-length 20 set -g status-right "#{?client_prefix,#[fg=colour3 bold]^B ,}" set -g status-right-length 20 # 視窗列表:目前視窗是一塊自帶白字的藍底(任何主題下對比度都是 5.8:1), # 其它視窗用中灰;響鈴(!)紅色,有活動(#)黃色 setw -g window-status-format " #I #W#{?window_flags,#{window_flags}, } " setw -g window-status-style "fg=colour245" setw -g window-status-current-format " #I #W " setw -g window-status-current-style "bg=colour26,fg=colour231,bold" setw -g window-status-bell-style "fg=colour203,bold" setw -g window-status-activity-style "fg=colour3" # 窗格邊框、訊息、複製模式的選取樣式:一種灰,一種藍 set -g pane-border-style "fg=colour243" set -g pane-active-border-style "fg=colour32" set -g message-style "fg=colour32,bold,bg=default" # tmux 自己的指令提示符是一條不透明的黑條:讓它和訊息一個樣 set -g message-command-style "fg=colour32,bold,bg=default" set -g mode-style "bg=colour26,fg=colour231" set -g display-panes-colour colour243 set -g display-panes-active-colour colour32 setw -g clock-mode-colour colour32 ##### 快捷鍵 ##### setw -g mode-keys vi # 分割和新增視窗都繼承目前目錄:不用再 cd 回程式助手做事的地方 bind | split-window -h -c "#{pane_current_path}" bind - split-window -v -c "#{pane_current_path}" bind c new-window -c "#{pane_current_path}" # Alt+數字直接跳視窗,不用按前綴鍵:手機上少按一次組合鍵 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 # 前綴鍵 + hjkl 在窗格之間移動 bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R ##### 複製與貼上 ##### # 前綴鍵 + v 也能進複製模式(比 [ 好記) bind v copy-mode # 複製模式:v 開始選取,y 複製(經 OSC 52 送到手機/本機剪貼簿), # Y 複製整行,Ctrl+v 切換矩形選取 bind -T copy-mode-vi v send -X begin-selection bind -T copy-mode-vi y send -X copy-selection-and-cancel bind -T copy-mode-vi Y send -X copy-line-and-cancel bind -T copy-mode-vi C-v send -X rectangle-toggle # 滑鼠拖選即複製,但留在複製模式的原位:不會跳回底部, # 可以接著看程式助手的捲動輸出;按 q 退出 bind -T copy-mode-vi MouseDragEnd1Pane send -X copy-selection # 雙擊複製一個詞,三擊複製一整行。詞的邊界只算空格, # 所以雙擊就能從程式助手的輸出裏一次拿到完整的檔案路徑或 URL set -g word-separators " " # 那個 `run -d0.3` 要留着:進複製模式和複製放在同一條指令裏, # tmux 的緩衝區有了內容,卻不送 OSC 52,剪貼簿裏甚麼都沒有。 # 用 -H 而不是 -M:-M 會把這次點擊繼續傳下去,選取範圍會越過這個詞 bind -n DoubleClick1Pane copy-mode -H \; send -X select-word \; run -d0.3 \; send -X copy-selection-and-cancel bind -n TripleClick1Pane copy-mode -H \; send -X select-line \; run -d0.3 \; send -X copy-selection-and-cancel bind -T copy-mode-vi DoubleClick1Pane send -X select-word \; send -X copy-selection-and-cancel bind -T copy-mode-vi TripleClick1Pane send -X select-line \; send -X copy-selection-and-cancel # 前綴鍵 + ] 貼上最近一次複製(tmux 預設);前綴鍵 + P 打開緩衝區清單, # 貼上更早複製的內容 bind P choose-buffer # 前綴鍵 + t:彈出一個小終端機跑一次性指令,不打亂程式助手的版面; # exit 就關 bind t display-popup -E -w 80% -h 75% -d "#{pane_current_path}" # 前綴鍵 + r:重新載入設定 bind r source-file ~/.tmux.conf \; display "已重新載入 ~/.tmux.conf"
多工器夾在程式和 Term 之間,而原裝的它對「放甚麼過去」相當保守。allow-passthrough on 才能讓內嵌圖片顯示出來:sixel、kitty graphics 和 imgcat 都是以逸出序列送達的,否則會被 tmux 吞掉。terminal-features ",*:RGB" 恢復24 位色,沒有它,TUI 裏的漸變全是色帶。而 set-clipboard on 才讓複製模式裏按 y 直接進手機剪貼簿,走 OSC 52,伺服器上不用裝任何輔助程式。
RGB 只是告訴 tmux 自己:Term 能畫 24 位色。裏面的程式要自己判斷,看的是 COLORTERM,而 tmux 從不把這個變數傳進去:從普通 shell 啟動的伺服端,會讓 nvim、bat、delta 退回 256 色,看起來只是主題發灰,不像出了錯。set-environment -g COLORTERM truecolor 把它釘給之後開的每一個窗格。Term 連上時也會替正在執行的 tmux 伺服端設上它;這一行讓這份設定從任何終端機連過去都一樣對。
三行 extended-keys 是這組裏最新、也最容易漏掉的。它讓 Ctrl+Shift+…、Shift+Enter 這類按鍵以 CSI u 形式穿過去,而不是被壓扁成普通按鍵。Claude Code 用 Shift+Enter 在提示詞裏換行;少了這幾行,這一下會變成普通 Enter,把寫到一半的提示詞直接送出。
set-clipboard 下面那行 terminal-overrides 只為一種組合而存在:在 mosh 工作階段裏跑 tmux。一條 OSC 52 要寫明它指的是哪個剪貼簿,而 tmux 把這個名字留空,發出來是 52;;;mosh 按字面只認 52;c;,於是一條都不轉發,你在 tmux 裏複製的內容落進 tmux 自己的貼上緩衝區就到頭了。這一行把名字釘成 c。格式裏的 %p1 即使取值被丟掉也必須留着:跳過它直接寫 %p2 的版本能正常載入,然後一個位元組都不發。
掛兩個用戶端時,原裝 tmux 會把每個視窗縮到最小的那個用戶端,手機一連上,200 欄的手提電腦就被壓到 56 欄,而且一直保持。window-size latest 改成按最近活動的用戶端來:在手提電腦上打字就用它的螢幕,拿起手機就為手機重排。aggressive-resize 對個別視窗做同樣的事。
detach-on-destroy off 也是同一個道理。關掉工作階段的最後一個窗格,原裝 tmux 會把你丟回對端的 shell:在手機上,這意味著你剛花二十秒建起來的那條連線。跳到下一個工作階段,人就還在裏面。
程式助手做完一輪會響鈴。monitor-bell 開、visual-bell 關,這一下就變成狀態列裏那個視窗名旁邊一個粗體的紅色 !,而不是在你正在看的螢幕上閃一下;monitor-activity 則替任何有輸出的視窗加一個黃色的 #。手機上同一時間只看得見一個視窗,狀態列是唯一能讓你分辨四個 agent 裏誰還在想、誰在等你的地方。
bg=default 讓 Term 自己的背景透過狀態列,點綴色(工作階段名稱、^B 提示、活動標記)都是調色盤裏的顏色,會跟著 Term 一起換主題。但跟著調色盤走,不等於看得清。調色盤裏的顏色保留的是它的角色,不是亮度:colour8 在每個主題裏都是「亮黑」,在深色主題上就是一片暗灰。目前視窗原來用的 reverse 更是把對比度變成了抽獎:黑底的調色盤上只有 2.2:1,粉彩系的調色盤上又沒問題。手機和電腦同時掛著時,兩邊的調色盤甚至都不一樣。
所以凡是要讀的部分,都改用固定的 256 色,它們在每個終端機裏畫出來都一樣。目前視窗是一塊自帶白字的藍底(colour26 底、colour231 字,任何主題下都是 5.8:1);其它視窗名用一種淺色深色都看得清的中灰;邊框、訊息、指令提示符和時鐘共用一種藍。tmux 3.7 能分辨用戶端是淺色還是深色(#{client_theme}),但前提是終端機回報,而走 mosh 時這份回報永遠到不了,所以這裏沒有任何東西依賴它。
這裏每一條綁定都在省掉一次組合鍵或一次跨鍵盤的移動。| 和 - 按它們長的樣子分割。前綴鍵 + hjkl 在窗格間移動,完全不用碰方向鍵。前綴鍵 + t 在目前窗格上彈出一個臨時小終端機(這是手機上對「我要跑一條指令,但不想打亂程式助手的版面」的答案),exit 就關。
切視窗是 tmux 裏最頻繁的操作,在手機上也最貴:前綴鍵再加一個數字,是兩層組合。bind -n 把前綴鍵整個去掉,而 Term 的按鍵列有一個黏滯 alt,於是它就變成兩次點擊。
分割和新增視窗那幾條綁定上的 -c "#{pane_current_path}",讓新窗格開在你已經在的那個目錄裏。沒有它,每次分割都從 $HOME 開始,而你在手機鍵盤上要打的第一樣東西就是一長串 cd。
複製相關的綁定是為了從程式助手印出的東西裏挑內容而調的。雙擊複製一個詞,而 word-separators 只算空格,所以一個「詞」就是一整條檔案路徑或 URL:點一下,不用小心翼翼地拖。三擊拿整行。滑鼠拖選會複製,並且留在複製模式的原位,不會彈回底部,你可以接著往回看捲動輸出;按 q 離開。前綴鍵 + P 打開之前複製過的內容清單。
雙擊和三擊那兩條綁定裏的 run -d0.3 要留着。進複製模式和複製放在同一條指令裏,tmux 的貼上緩衝區有了內容,卻不送 OSC 52,於是複製的東西到不了剪貼簿,不管走哪種連線都一樣。這點延遲讓模式切換先落定,tmux 內建的預設綁定裏也有它,就是這個原因。
~/.tmux.conf:不是手機上。tmux 在工作階段執行的那一端讀它。前綴鍵 + r 重新載入即可。tmux source-file ~/.tmux.conf中間那步看著和重新載入的綁定重複,其實不是:前綴鍵 + r 沒法完成第一次載入。這個綁定要等檔案被讀過才存在,而 tmux 伺服端是在啟動時讀設定的,第一次的時候,那還早於檔案存在。於是唯一不能用快捷鍵完成的重新載入,恰恰是把這個快捷鍵裝上的那一次。另外注意 source-file 是 tmux 的指令而不是 shell 的:所以在這裏要在前面加 tmux,而在設定檔裏則不用。
還有兩件事得先確認,否則怎麼改都不生效:這份設定需要 tmux 3.5 或更新的版本,更舊的版本啟動時只會報一句「unknown option」,那條設定就靜默失效了,用 tmux -V 看一下你裝的是哪個。另外在 Debian 與 Ubuntu 上,第一行選用的 tmux-256color 這條 terminfo 描述並不隨 tmux 一起裝,而是在 ncurses-term 套件裏,記得一併裝上。
延伸閱讀: 在手機上用 tmux · SSH 自動恢復 · 常見問題