一、目标:把记忆命令变成可重复工作流
本文组合 tmux、fzf、ripgrep、zoxide 和 Taskfile,构建可恢复会话、快速搜索、智能跳转和项目级自动化。原则是:交互探索用小工具,团队关键操作沉淀为可审计任务;不要把只有作者理解的 alias 当作自动化。
terminal
|-- tmux: session/window/pane recovery
|-- rg: fast content search
|-- fzf: interactive selection
|-- zoxide: frecency directory jump
`-- Taskfile: documented, repeatable project commands
二、安装、版本与配置备份
通过系统包管理器安装并记录版本。修改 shell 配置前先备份,避免一次粘贴破坏登录 shell。
tmux -V
fzf --version
rg --version
zoxide --version
task --version
cp -a ~/.zshrc ~/.zshrc.backup.$(date +%Y%m%d%H%M%S)
mkdir -p ~/.config/tmux ~/.config/fzf
在团队文档写明最低版本与安装来源;生产跳板机应遵循软件白名单。
三、tmux 会话模型
项目、窗口与 Pane 的职责
一个项目一个 session,窗口按职责划分,pane 只做并行观察。使用可预测名字,避免数字会话堆积。
tmux new-session -d -s catalog -n editor
tmux new-window -t catalog -n server
tmux new-window -t catalog -n logs
tmux split-window -h -t catalog:server
tmux send-keys -t catalog:server.0 'task dev' C-m
tmux send-keys -t catalog:server.1 'task logs' C-m
tmux attach -t catalog
.tmux.conf 保持最小:
set -g mouse on
set -g history-limit 100000
set -g base-index 1
setw -g pane-base-index 1
set -g renumber-windows on
set -g escape-time 10
bind r source-file ~/.tmux.conf \; display-message "config reloaded"
bind | split-window -h -c '#{pane_current_path}'
bind - split-window -v -c '#{pane_current_path}'
tmux source-file ~/.tmux.conf
tmux list-sessions
tmux list-panes -a -F '#S:#I.#P #{pane_current_path} #{pane_current_command}'
四、会话恢复与安全边界
tmux 保留进程,不等于持久化业务状态。电脑重启后会话消失,数据库事务也不应依赖 tmux。需要恢复布局可使用受控脚本或插件,但不要自动重放危险命令。
#!/usr/bin/env bash
set -euo pipefail
session=catalog
tmux has-session -t "$session" 2>/dev/null && exec tmux attach -t "$session"
tmux new-session -d -s "$session" -n shell -c "$PWD"
tmux new-window -t "$session" -n tests -c "$PWD"
exec tmux attach -t "$session"
脚本只恢复布局,不自动执行迁移、发布或删除任务。
五、ripgrep 建立可控搜索
rg 默认尊重 .gitignore,适合代码搜索。先缩小文件类型与目录,再增加上下文。
rg -n --hidden --glob '!.git/**' 'TODO|FIXME'
rg -n -tphp 'DB::raw|selectRaw' app tests
rg -n -C 3 'timeout|retry' config app
rg --files -g '*.yaml' -g '*.yml' | sort
团队可以提交 .rgignore 排除构建产物,但不要排除可能含运行逻辑的目录。
vendor/
node_modules/
storage/logs/
public/build/
coverage/
六、fzf 把列表变成交互选择
安全处理文件名
fzf 不负责产生数据,它对 stdin 候选排序并输出选择。始终对文件名使用空字符分隔,避免空格和换行破坏。
selected=$(rg --files -0 | fzf --read0 --print0 --preview 'sed -n "1,200p" {}')
[ -n "$selected" ] && printf '%s' "$selected" | xargs -0 ${EDITOR:-vi}
搜索代码并预览上下文:
rg --line-number --no-heading --color=always 'TODO|FIXME' \
| fzf --ansi --delimiter : \
--preview 'sed -n "$(( {2} > 5 ? {2}-5 : 1 )), $(( {2}+5 ))p" {1}'
不要把未经确认的 fzf 多选直接传给 rm。破坏性操作先打印精确目标,再二次确认。
七、zoxide 基于频率和最近访问跳转
在 shell 初始化 zoxide,让 z keyword 按 frecency 选择目录。自动生成的 init 必须放在 shell 插件之后的合适位置。
eval "$(zoxide init zsh)"
z catalog
zoxide query catalog
zoxide query -l | head -20
zi
共享终端或敏感目录环境要评估历史记录。离职、项目删除或路径变更后清理陈旧条目。
八、组合搜索文件、进程和 Git 分支
fvim() {
local file
file=$(rg --files | fzf --preview 'bat --style=numbers --color=always {} 2>/dev/null || sed -n "1,200p" {}') || return
${EDITOR:-vi} "$file"
}
fkill() {
local pid
pid=$(ps -u "$USER" -o pid=,stat=,command= | fzf -m | awk '{print $1}') || return
printf 'selected pid(s): %s\n' "$pid"
kill -TERM $pid
}
fkill 只选择当前用户进程并先发送 TERM;不要默认 sudo 或 KILL。
git branch --format='%(refname:short)' \
| fzf --preview 'git log --oneline --decorate -20 {}' \
| xargs -r git switch
九、用 Taskfile 沉淀团队命令
交互函数适合个人导航,构建、测试、日志和发布前检查应写入仓库 Taskfile。任务要有描述、依赖、前置条件和明确变量。
version: '3'
vars:
COMPOSE: docker compose
tasks:
doctor:
desc: 检查本地依赖与容器状态
cmds:
- docker version
- '{{.COMPOSE}} config --quiet'
- '{{.COMPOSE}} ps'
test:
desc: 运行应用测试
deps: [doctor]
cmds:
- '{{.COMPOSE}} exec -T app php artisan test'
logs:
desc: 跟随应用日志
cmds:
- '{{.COMPOSE}} logs -f --tail=200 app'
task --list
task doctor
task test
十、任务参数与危险操作保护
Plan 与 Apply 分离
使用 required 变量,避免环境变量为空时扩大范围。破坏性操作分成 plan/apply 两步。
tasks:
deploy:plan:
requires:
vars: [ENV, IMAGE]
cmds:
- ./scripts/deploy-plan --env '{{.ENV}}' --image '{{.IMAGE}}'
deploy:apply:
requires:
vars: [ENV, IMAGE, CHANGE_ID]
preconditions:
- sh: test '{{.ENV}}' != production || test -n '{{.CHANGE_ID}}'
msg: production requires CHANGE_ID
cmds:
- ./scripts/deploy --env '{{.ENV}}' --image '{{.IMAGE}}' --change '{{.CHANGE_ID}}'
task deploy:plan ENV=staging IMAGE=registry.example/app:abc123
task deploy:apply ENV=staging IMAGE=registry.example/app:abc123 CHANGE_ID=CHG-2026-0928
十一、统一项目启动体验
项目根目录提供 task setup、task dev、task test、task lint、task logs 和 task clean:plan。README 只解释入口,不重复维护所有底层命令。
tasks:
setup:
cmds:
- cp -n .env.example .env || true
- docker compose build
- docker compose run --rm app php artisan key:generate
dev:
cmds:
- docker compose up -d
- docker compose ps
clean:plan:
cmds:
- docker compose ps -a
- docker volume ls --filter label=com.docker.compose.project={{.PROJECT}}
清理 apply 不应默认删除数据库卷;确需删除时打印精确卷名并要求单独确认。
十二、性能和可维护性检查
Shell 启动过慢会抵消效率工具收益。测量交互 shell 启动,按需延迟加载重插件。
for i in {1..10}; do /usr/bin/time -p zsh -i -c exit; done 2>&1 | awk '/real/{sum+=$2;n++} END{print sum/n}'
zsh -xlic exit 2> /tmp/zsh-startup.trace
配置放 dotfiles 仓库但排除历史、凭据和机器私有路径。修改后在新 shell 验证,不要只在当前进程 source。
十三、故障排查
tmux 键失效:检查终端 $TERM、prefix 和配置是否加载;fzf 预览异常:检查占位符与文件名 quoting;rg 搜不到:检查 ignore 与 --hidden;zoxide 跳错:查看数据库并清理;Task 变量为空:使用 requires 和 set -u。
tmux show-options -g
rg --debug PATTERN path 2>&1 | head -80
zoxide query -l
task --summary test
十四、验收与维护
验收:新终端 300ms 左右可交互(按机器设阈值);项目会话可一条命令恢复;文件名含空格也能安全选择;搜索尊重 ignore;危险操作有 plan/apply;新成员只看 task --list 即可发现常用流程;所有项目任务在 CI 复用。
每季度删除无人使用的 alias 和任务。效率系统的目标是降低认知负担,不是收集更多快捷键。