让编码智能体合并一个分支、清理一下工作树,它跑了49分钟。一次合并花这么久,作者想知道时间到底去哪了:是模型慢?是改动太难?还是智能体卡进了循环?Claude Code 和 Codex 都给不出答案——两者都在磁盘上留了详细日志,却没有一个能展示"什么真正占用了时间"的时间线。

打开网易新闻 查看精彩图片

于是他做了一个。结论很直接:49分钟里有47分钟是单次完整测试套件的运行。不是模型,不是编辑,就是一条命令。

这个工具叫 session-profiler,读取 Claude Code 和 Codex 已经存在本机的会话日志,打开一份本地报告。它把每个智能体画成一条泳道,主会话、子智能体和它启动的旁路会话共享同一条时间线,能看出哪些在并行、哪些在互相阻塞。每一次工具调用和后台任务都是一根可悬停、可点击的条,点开能看到具体命令。

时间被拆成三部分,加起来正好是总时长:智能体在工作、只有后台任务在跑、什么都没跑(通常是等你)。最慢的步骤会单独排名,那条吃掉整场会话的命令一眼就能跳出来。你不需要自己运行它,它作为插件和技能装进两个工具,你只要对智能体说一句"profile this session",它会跑辅助程序、打开报告,并告诉你时间花在哪。

合并那次的意外之后,作者统计了自己最近150个 Claude Code 会话,看每个提示词的时间有多大比例花在它最长的单步上,结果反复出现同一种形状:

  • 49分钟里的47分钟:合并后的一次完整测试套件运行(96%)。
  • 35分钟里的33分钟:一个抓取移动端截图的后台任务。
  • 31分钟里的23分钟:一条"跑完整检查套件"的命令。
  • 10分钟里接近8分钟:一次前台"跑完整检查"的调用。

每一次,他心目中"任务本身"只花了一两分钟,剩下全被一条命令吃掉,通常是测试套件或构建,智能体启动它然后干等。这比任何提示词微调都更改变了他的工作方式:迭代时只要相关的那部分测试,完整套件留到最后跑一次;完整运行躲不掉时,给智能体安排点别的事做,而不是让它等;在假设智能体"正在思考"之前,先看看后台还有什么在跑。

读日志是简单的部分,从日志里得出诚实的数字才是大部分工作量。一轮对话不等于在工作:一轮从你的提示词开始,到下一个提示词结束,按这个口径会把等你回答问题、等旁路会话回报的空转全算进去。分析器把应用注入的消息(旁路会话结束、另一个会话发来的消息)当作唤醒,这些消息之前的空档就显示为等待,而不是智能体在工作。

后台任务的结束时间也比它的调用晚。智能体在后台启动命令时,工具调用立刻返回,真正的结束是之后单独到达的完成通知。麻烦的是应用在清理时把任务杀掉的情况:作者有一个任务显示成了75小时。现在由通知的措辞决定——"被用户停止"或"达到时间上限"算真实结束;"会话结束前未完成",或会话安静很久之后一次没有理由的杀进程,则记为未知结束,而不是编一个。

Codex 的日志对很多命令只记录启动时间。在作者的 Codex 历史里,约64%的命令被记成耗时不到一毫秒,因为日志只捕获了启动花了多久。把它们显示成"0毫秒"会掩盖时间去向:当一条命令是它所在 exec 脚本唯一运行的东西时,分析器按那次脚本调用计时;当它和其他调用共享脚本时,时长显示为未知。

旁路会话在转录记录里没有链接。Claude 桌面应用启动旁路会话时,两份转录都没说哪个会话启动了哪个,链接只存在于应用自己的会话记录里,所以分析器读那些记录,把旁路会话嵌到父会话下面,记录格式变了就退回到分开显示。

安装方式:Claude Code 里先 /plugin marketplace add draconnn/session-profiler,再 /plugin install session-profiler@session-profiler;Codex 里先 codex plugin marketplace add draconnn/session-profiler,再 codex plugin add session-profiler@session-profiler。然后让智能体"profile this session"即可。

它是只读的,从不改动日志;报告在 127.0.0.1 上提供,不上传任何东西。只需要 Python 3.11+,没有其他依赖,跑在 macOS 和 Linux 上,MIT 许可。一个提醒:它读的日志格式没有文档,未来的应用更新可能弄坏其中部分功能,仓库里有针对合成会话的测试来尽早发现。