每天都在用 tmux,时间久了就积累了一套让 session 管理变得几乎零摩擦的 shell 辅助函数和快捷键。本地机器和远程机器都能用。

核心理念很简单:每个项目一个 tmux session,目录名就是 session 名。cd 进 code/myapp,输入 tm,你就在一个叫 myapp 的 session 里了。点号自动变成下划线(my.projectmy_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 选择远程 session
  • tms deploy — attach/create 远程 deploy session

终端标题带 🔗 前缀,一眼分辨远程 vs 本地 tab。

worktree 集成

用 git worktree 保持多个分支同时 checkout:

  • tw <name> — 创建 worktree + 对应 tmux session
  • twd — 同时删除 worktree 和 session
  • tmux-resurrect — 关机/重启后恢复 session
  • tmux-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 就完事。