每天都在用 tmux,时间久了就积累了一套让 session 管理变得几乎零摩擦的 shell 辅助函数和快捷键。本地机器和远程机器都能用。
核心理念很简单:每个项目一个 tmux session,目录名就是 session 名。cd 进 code/myapp,输入 tm,你就在一个叫 myapp 的 session 里了。点号自动变成下划线(my.project → my_project),避免 tmux 报错。
5 个核心命令
全部遵循同一个模式:session 存在就 attach,不存在就创建。
| 命令 | 功能 |
|---|---|
tm | 为当前目录创建/attach session |
tp | 用 fzf 模糊选择已有 session |
tv | 同 tm,但启动时带 neovim |
tn | 用显式名称创建 session |
zm | 同 tm,但面向 zellij |
Fish 版本:
function tm
set session_name (basename (pwd) | string replace '.' '_')
printf '\033]0;💻 %s\007' "$session_name"
if tmux has-session -t "$session_name"
tmux attach-session -t "$session_name"
else
tmux new-session -s "$session_name"
end
end
Bash/Zsh 版本:
tm() {
local session_name
session_name=$(basename "$PWD" | tr '.' '_')
printf '\033]0;💻 %s\007' "$session_name"
if tmux has-session -t "$session_name" 2>/dev/null; then
tmux attach-session -t "$session_name"
else
tmux new-session -s "$session_name"
fi
}
tp:无 args 时用 fzf 选,有 args 时 attach/create 指定 session
function tp
if test (count $argv) -eq 0
set selected_session (tmux list-sessions -F "#{session_attached} #{session_name}#{?session_attached, (attached),}" \
| sort -rn | string replace -r '^\d+ ' '' | fzf --height 40% --reverse \
| string replace -r ' \(attached\)$' '')
# attach 选中的 session...
else
# 直接 attach/create $argv[1] session
end
end
tv:带 neovim 启动的 session
function tv
set session_name (basename (pwd) | string replace '.' '_')
if test (count $argv) -gt 0
set file_to_edit $argv[1]
else
set file_to_edit ""
end
# 存在就 attach,不存在就新建并启动 nvim
end
支持传文件名:tv src/main.rs 直接打开。
前缀键:Ctrl-a(比 Ctrl-b 更顺手)
重映射后永远不需要往任何地方发送 Ctrl-s。
Vim 风格快捷键
prefix h/j/k/l — 面板导航
prefix H/J/K/L — 调整面板大小(可重复)
prefix d — 水平拆分
prefix s — 垂直拆分
prefix z — 放大/全屏面板
prefix x — 关闭面板
prefix - — 快速 detach
prefix i — 把上一个面板拉进来
prefix e — 在 neovim 里打开 scrollback
prefix o — fuzzy session 切换(sessionx)
prefix g — 重载配置
Alt-1..9 — 按编号切换窗口
Alt-k — 清除 screen + scrollback(类似 macOS Cmd-k)
Alt-k:让他特别满意的一个细节
普通 shell:清除 screen 和 scrollback(类似 Cmd-k)。 有程序在运行(neovim、dev server 等):发送 Ctrl-l,不打断正在做的事。
is_program="ps -o comm= -t '#{pane_tty}' | grep -vE '^-?(fish|bash|zsh|sh|ps|grep|awk|sed|cut|sort|uniq|head|cat|echo|printf)$' | grep -q ."
bind -n M-k if-shell "$is_program" "send-keys C-l" "send-keys -R; clear-history"
通过检查 ps 判断是不是 shell 之外的进程。
远程 session 管理
在 SSH config 里配置了一台远程 Mac(m3pro),tms 脚本做同样的 session 管理:
tms— fzf 选择远程 sessiontms deploy— attach/create 远程 deploy session
终端标题带 🔗 前缀,一眼分辨远程 vs 本地 tab。
worktree 集成
用 git worktree 保持多个分支同时 checkout:
tw <name>— 创建 worktree + 对应 tmux sessiontwd— 同时删除 worktree 和 sessiontmux-resurrect— 关机/重启后恢复 sessiontmux-continuum— 每 15 分钟自动保存
tmux 配置要点
# 前缀重映射
set -g prefix C-a
unbind C-b
# base index 从 1 开始
set -g base-index 1
setw -g pane-base-index 1
# 自动重命名关闭(名字由 session 脚本控制)
set -g automatic-rename off
# 新拆分保持当前目录
bind d split-window -h -c "#{pane_current_path}"
bind s split-window -v -c "#{pane_current_path}"
所有脚本和配置都在一个 Gist 里,丢进 ~/.config/fish/functions/ 然后 source 就完事。
这是一篇实用至上的 developer tooling 帖,没有新概念但执行得很干净。几个值得借鉴的地方:1) 目录→session 名的自动化映射消除了命名摩擦;2) scrollback 处理逻辑(检测进程类型决定发送 Ctrl-l 还是清屏)是少数人会想到但又特别影响体验的细节;3) worktree + tmux session 联动解决的是真实痛点。