我是怎么用 WezTerm + Herdr 放一群 agent 的
agent 多了以后,最稀缺的不是算力,是你的注意力。
最近在干活的时候,同时跑四五个 coding agent 已经是常态:一个在重构,一个在写测试,一个在查文档,还有一个在陪我聊方案。
一开始我用 tmux 管它们。结果就是不停地 ctrl+b 加数字,一个窗口一个窗口地巡场:这个跑完了吗?那个是不是卡在等我确认?注意力全耗在”检查”上,而不是”决策”上。
后来换成了 WezTerm + Herdr 的组合,折腾了一阵,沉淀下来一些用法。这篇聊聊我觉得真正提效的几件事,以及踩过的坑。
Herdr 是什么
一句话:一个为 coding agent 生的终端复用器。看起来像 tmux——有 workspace、tab、pane,prefix 键也是 ctrl+b——但它多了一样关键的东西:它知道每个 pane 里的 agent 现在是什么状态。
blocked(在等你确认)、working(在干活)、done(干完了)、idle(闲着),实时显示在侧边栏里。而且状态会向上冒泡:一个 blocked 的 pane,会让它所在的 tab 和 workspace 都亮起来。
最重要的一条:只看 blocked,别巡场
这是换工具之后最大的习惯改变。
以前的循环是:切到每个窗口,看一眼,切走。现在的循环是:瞄一眼侧边栏,只有”变红”的地方才点进去。done 的看一眼结果,working 的随它跑。
听起来是小事,但它把”并行跑 N 个 agent”从一件心智负担很大的事,变成了一件很松的事。你的角色从监工变成了评审——只在 agent 需要你的时候出现。
状态别靠猜,装 integration
没有装 integration 的时候,Herdr 是靠”进程名 + 屏幕内容启发式”来判断状态的。大部分时候准,但 agent 的 UI 一变,它就可能把”等你确认”误判成”闲着”。
官方给主流 agent 都做了 integration(Pi、Claude Code、Codex、Kimi Code 都有),装上之后状态由 agent 的生命周期 hook 直接上报,是权威来源:
herdr integration install pi # 换成你用的 agent
herdr integration status # 确认生效
哪天状态显示不对,别猜,跑 herdr agent explain 看它命中的规则。
把通知打开,人就可以离开了
配合上面两条,最后一块拼图是通知。在 ~/.config/herdr/config.toml 里:
[ui.toast]
delivery = "system" # 直接弹 macOS 系统通知
agent 干完了、或者需要你拍板了,系统通知直接弹出来。你完全可以切去写文档、回消息,甚至去泡杯咖啡。它对当前聚焦的 tab 会自动静默,不会打断你正在做的事。
到这里,工作流就闭环了:agent 们各自跑,系统叫你你才出现。
WezTerm 和 Herdr,各管一层,别套娃
这是踩坑最多的地方,值得展开说。
WezTerm 和 Herdr 都是”复用器”,职责必须切干净:WezTerm 管 OS 窗口,Herdr 管里面的会话。持久化由 Herdr 的后台 server 提供,ctrl+b q detach 之后 agent 照跑,再敲 herdr 就接回来——所以 tmux 那套”保活”的心思可以完全放下。
几个具体的坑:
- 别在 Herdr 里再开 tmux。 Herdr 会把
tmux当成 pane 的前台进程,看不到后面的 agent,状态检测直接瞎掉。如果你的 shell 配置会自动 attach tmux,在 Herdr 里记得禁掉。 - macOS 上 Option 键默认不是 Alt。 Herdr 的直跳快捷键(比如
prefix+alt+1..9直接跳到第 N 个 agent)依赖终端把 Option 当 Meta 发。WezTerm 里要加两行:
config.send_composed_key_when_left_alt_is_pressed = false
config.send_composed_key_when_right_alt_is_pressed = false
代价是左 Option 不能输特殊字符了,可以只改一边。如果你全程走 ctrl+b prefix,不改也行。
- scrollback 调大。 agent 的输出又长又密,WezTerm 默认 3500 行经常不够翻,
config.scrollback_lines = 10000起步。
顺手安利一个组合技:WezTerm 开一个 tab 跑完整的 Herdr 总控,再开一个 tab 跑 herdr agent attach <名字>,全屏钉住某个正在做关键任务的 agent。总控负责调度,钉子负责盯梢。(名字哪来的?herdr agent rename,给每个 agent 按角色起名,比如 reviewer、docs-bot。)
几个值得早知道的小功能
- 侧边栏直接开 worktree。 Git workspace 那一行上有
New worktree,自动建 checkout、开成新 workspace 挂在原仓库下面。多个 agent 各改各的 worktree,永远不踩同一个目录。 prefix+?是看当前键位表的地方,忘了就按。- 远程机器用
herdr --remote,agent 跑在远端 server 上,本地断线重连无损。别在本地 tmux 里 SSH 过去,又回到套娃了。 - 永远别敲
herdr server stop,除非你真想把所有 agent 一锅端。
奇技淫巧:把配置调成自己的形状
上面那些是”会用”,下面这些才是”顺手”。入口先给你:
herdr --default-config > ~/.config/herdr/config.toml
这会把完整默认配置倒出来,所有能改的都在里面。改完 herdr server reload-config 热加载,不用重启任何 pane。接下来是我觉得值回票价的几个。
一键直跳 agent。 默认跳 agent 要进导航模式再选,加了 indexed 绑定之后一步到位:
[keys]
focus_agent = "prefix+alt+1..9" # 直跳第 N 个 agent
switch_tab = "prefix+1..9" # 直跳第 N 个 tab
一个动作想要多个快捷键也行,写成数组:next_tab = ["prefix+n", "ctrl+alt+]"]。
把高频工具绑成弹窗。 lazygit 这种每天要开十几次的东西,没必要占一个 pane:
[[keys.command]]
key = "prefix+alt+g"
type = "popup"
command = "lazygit"
description = "run lazygit"
width = "80%"
height = "80%"
prefix+alt+g 一按,弹窗浮在当前布局上,退出即消失,pane 布局纹丝不动。同一个机制还能开一个随手的 scratch terminal(command = "exec \"${SHELL:-sh}\""),算个 quick look 之类的东西特别合适。
让侧边栏显示 agent「正在干什么」。 状态图标只告诉你”在忙”,但我想知道”在忙什么”。侧边栏的行布局是可以自定义的,还能塞自定义 token:
[ui.sidebar.agents]
rows = [
["state_icon", "agent"],
["$summary"],
["workspace", "tab"],
]
然后在脚本或 hook 里随手上报:
herdr pane report-metadata w1:p1 --source my-hook --token summary="在重构登录模块"
侧边栏立刻多一行人话。偷懒的办法也有:很多 agent 会把当前任务写进终端标题,布局里加一个 terminal_title_stripped token,零成本把那句话捞上来。
给不同 agent 配不同的提示音。 done_path 和 request_path 区分”干完了”和”需要你”,再按 agent 单独开关:
[ui.sound.agents]
droid = "off" # 话多的关掉
claude = "on"
到最后基本靠耳朵调度:叮一声是有人交活,咚咚两声是有人举手。
主题跟着系统明暗走。 白天黑夜自动切换,不用手动:
[theme]
name = "catppuccin"
auto_switch = true
light_name = "catppuccin-latte"
dark_name = "catppuccin"
中文用户必开的两个 macOS 开关。 这俩藏在 experimental 里,但对中文输入的人是质变:
[experimental]
switch_ascii_input_source_in_prefix = true
reveal_hidden_cursor_for_cjk_ime = true
cjk_ime_agents = ["claude", "pi", "codex"]
第一个:按下 prefix 的瞬间自动切到英文输入法,回到输入时再切回来。再也没有「按了一串快捷键,发现全变成了中文」的脑溢血时刻。第二个:agent 的 TUI 经常把系统光标藏起来,导致输入法候选框不知道往哪儿跟,这个开关给它一个人工锚点。
WezTerm 侧:把「钉子」也做成一键。 前面说的 herdr agent attach 盯梢 tab,可以直接绑进 WezTerm 键位:
{
key = 'a',
mods = 'CMD|SHIFT',
action = wezterm.action.SpawnCommandInNewTab {
args = { 'herdr', 'agent', 'attach', 'reviewer' },
},
},
Cmd+Shift+A,新 tab 直接挂上 reviewer 的实时输出,连命令都不用敲。
写在最后
回头看,这套组合真正改变的不是”能开多少个窗口”,而是注意力的分配方式:从”轮流盯着每个 agent”,变成”agent 排队来找我”。
我一直觉得,工具的价值不在于它有多少功能,而在于它能不能让你忘掉它。tmux 我忘不了,因为我得一直想着它;Herdr 这套跑顺之后,我想的只剩一件事——这个决策,我同意还是不同意。
毕竟,agent 可以并行,你的注意力不行。