同时跑多个 Claude Code 和 Codex 任务,怎么知道哪个 Agent 需要你?Baton 在菜单栏里给你答案
用 AI 编码 Agent 越多,问题就越从「这个 Agent 能不能完成任务」变成「我的 N 个 Agent 哪个正在等我决策」。Claude Code 开几个终端 Tab,Codex 又开几个线程,你切回来看一圈,可能哪个都不需要你——但你不知道哪个不需要你。
Baton 是一个开源 macOS 菜单栏工具,帮你一眼看清所有正在运行的 AI 编码 Agent 会话状态:哪个在工作、哪个在等你、哪个已经结束。点击就能直接跳转到对应的终端窗口或 Codex 线程,不需要在窗口间来回翻找。
痛点:Agent 越来越多,注意力越来越散
以前写代码是自己一个人敲键盘,现在是你同时给几个 Agent 派活:
- Claude Code 正在重构一个模块
- Codex 在写测试用例
- 另一个 Claude Code 在分析代码库
你每隔几分钟切回来看一眼——「写完了吗?」没有,还在工作。再过几分钟回来看——「需要我确认吗?」没有,还在工作。真正需要你决策的那个 Agent 可能已经等你 10 分钟了,只是你切换窗口时没有第一个看到它。
Baton 解决的就是这个「注意力分配」问题。它不做 Agent 调度,不控制 Agent 行为,只做一件事:告诉你哪个 Agent 此刻需要你。
安装和基本使用
Baton 是 Python 写的,依赖极轻(只有 rumps 菜单栏框架和 FSEvents 文件监听),安装一条命令:
curl -fsSL https://raw.githubusercontent.com/neilkpatel/baton/main/install.sh | bash
这条命令会把 Baton 克隆到 ~/.baton,创建独立的 Python 虚拟环境,安装 LaunchAgent 实现开机自启。几秒后菜单栏就会出现一个 🎽 图标,旁边显示正在等你的 Agent 数量。
它也支持手动安装和 --no-autostart 选项:
git clone https://github.com/neilkpatel/baton.git && cd baton bash install.sh --no-autostart
不想要了?一条命令卸载:
bash install.sh --uninstall
系统要求:macOS(利用 FSEvents 文件监听和 AppleScript 窗口跳转),Python 3.9+(Codex 自动化跟踪需要 3.11+)。支持的 Agent 包括 Claude Code 和 Codex,只装其中一个也能正常工作。
功能亮点
菜单栏一目了然
🎽 图标旁边显示的数字,就是正在等你的会话数量。它使用 FSEvents 监听会话文件变化——不是轮询,文件一变立刻更新,几乎零耗电。
点击菜单栏展开下拉列表,按工具(Claude Code / Codex)分组显示每个会话的状态:Working(工作中)、Waiting(等你)、Done(已完成)。每个会话都显示 Claude Code 自己的 ai-title 摘要,一看就知道这个会话在做什么。
点击直接跳转
这是最实用的功能。点击一个 Claude Code 会话,对应的 Terminal.app Tab 自动跳到最前面;点击一个 Codex 线程,用 codex:// 深度链接直接打开。不用再在 8 个终端窗口里找”刚刚那个跑测试的 Agent 是哪个 Tab”。
如果使用 iTerm 或 Ghostty 等其他终端,Claude Code 的点击跳转会打开仪表板页面而不是直接跳转 Tab(Codex 的跳转不受终端影响,因为用的是深度链接)。
准确的「等你」判断
Baton 对两种 Agent 的「等你」判断方式不同,设计得很合理:
- Claude Code:会话空闲且最后一条消息是 Agent 的回答 → 标记为「等你」。你点击跳转或手动查看后清除标记,直到 Agent 产生新的回答才会重新标记。
- Codex:直接镜像 Codex 自己的「未读(蓝点)」状态。已经打开看过的线程不会重复提示。
可选的推送通知
默认菜单栏是安静通道——只在图标上显示数量变化,不弹通知。但如果你需要,可以开启通知开关:Agent 把接力棒交回到你手上那一刻,系统推送一条横幅通知。
HTML 仪表板
除了菜单栏,Baton 还自带一个完整的 HTML 仪表板(server.py + index.html),从菜单栏下拉列表点击”Open full dashboard”即可打开,或者在终端启动:
bash start.sh
默认运行在 http://127.0.0.1:8787,只绑定本地地址,不会暴露到网络。
原理解析
Baton 的设计很简洁,核心是两个概念:
- Collector 采集器:每种 Agent 对应一个采集器,读取各自的会话文件,统一输出为
track记录格式:
{ id, source, title, project, status, lastActive, detail, alive, extras }
status ∈ waiting | working | done | idle | scheduled
- 事件驱动:不轮询。用 FSEvents 监听
~/.claude/sessions/和~/.codex/目录的变化,文件一变立刻更新状态。备用的安全网轮询仅在极端情况下触发。
数据来源完全本地只读:
| 来源 | 读取路径 | 信号判断 |
|---|---|---|
| Claude Code | ~/.claude/sessions/{pid}.json + transcripts | busy/idle + 最后对话轮次 |
| Codex 线程 | ~/.codex/session_index.jsonl + .codex-global-state.json | 未读(蓝点)状态 |
| Codex 自动化 | ~/.codex/automations/*/automation.toml | 定时任务排期 |
隐私与安全
Baton 完全本地运行,对 ~/.claude 和 ~/.codex 严格只读——不会修改任何会话状态,没有任何数据离开你的机器。由于实时数据包含你的实际 Prompt 和工作目录,仪表板服务器绑定 127.0.0.1 而非 0.0.0.0,不会暴露到局域网。
适合谁用
- 同时跑多个 Claude Code 会话的开发者:比如你给不同项目各开一个 Agent,Baton 帮你统一管理
- Claude Code + Codex 双修用户:两种 Agent 的状态在一个地方看,不用切来切去
- 做 Agent 编排实验的人:当你并行启动多个 Agent 执行不同子任务时,Baton 帮你跟踪每个的等待状态
目前限制是 macOS only(依赖 FSEvents 和菜单栏 API),且跳转 Claude Code 会话仅支持 Terminal.app。但对于 macOS 上日常使用 Claude Code 和 Codex 的开发者来说,Baton 是一个很实用的小工具——它不做多 fancy 的事情,但把”哪个 Agent 需要我”这件事做到了一目了然。