Skip to content

--debug 更会说话了:子代理 frontmatter 拼错、慢钩子一眼看出 ​

自己写子代理、配钩子,最烦的往往不是写,而是「它为什么没生效」「为什么每轮都卡一下」。CLI 2.1.296 对 --debug 输出做了两处改进,正好对着这两个问题:

  1. 自定义子代理文件里不认识的 frontmatter 字段会被点名,并附上可能拼错的提示;
  2. 命令钩子跑完会留下一行,写明命令、来源插件、结果和耗时,慢钩子一查就知道。

先把调试日志打开 ​

两种方式(按 CLI 参考文档):

bash
# 写到默认位置:~/.claude/debug/<session-id>.txt
claude --debug

# 写到你指定的文件,同时隐式开启调试模式
claude --debug-file /tmp/claude-debug.log

注意 --debug 不会把日志打印到终端,要去日志文件里看。还可以按类别过滤,比如 --debug='mcp,startup'——过滤只在 = 写法下生效,用空格隔开会变成「开调试但不过滤」。

改进一:子代理 frontmatter 拼错会被点名 ​

子代理就是 .claude/agents/ 或 ~/.claude/agents/ 里的 Markdown 文件,靠开头的 YAML frontmatter 声明 name、description、tools、model 等。字段名拼错,比如把 tools 写成 tool,过去往往没有任何提示——那一项设置就悄悄不生效,你只觉得子代理「不太听话」。

2.1.296 起,--debug 会列出自定义 agent 文件里无法识别的 frontmatter 字段,并对疑似拼写错误给出提示。排查子代理行为异常时,先开调试跑一次,搜一下这个文件名,往往就能找到原因。

顺带记一下官方文档列出的「子代理文件被跳过」的几种情况,它们同样只在调试日志里能看到:

  • 没有 name:被当成放在旁边的说明文档;
  • 开头的 --- 不在第一行:被视为没有 frontmatter;
  • name 以 - 开头、包含 :,或超过 256 个字符:跳过并在调试日志写错误;
  • 有 name 但没有 description:跳过并写明原因;
  • YAML 解析失败:整份文件不读,跳过并记录解析错误。

想在开会话之前检查,可以对目录跑 claude plugin validate .claude/agents(2.1.233 起),它会找出 frontmatter 解析不了的文件;但只检查你指定的目录,也不会标出「能解析但没 name」的文件。

子代理还有不少新字段,比如前两天介绍的 autoCompactWindow,新字段写错也能靠这个功能尽早发现。

改进二:每个命令钩子都留下耗时 ​

钩子多了以后,偶尔会有一个特别慢:每次提交提示、每次工具调用都要等它。以前想找出是谁,得自己往脚本里加计时。

2.1.296 起,工具事件、UserPromptSubmit、SessionStart、Stop 等事件上的命令钩子结束时,无论它输出了什么,都会在调试日志里留下一行 Hooks:。按官方文档的例子,格式大致是:

text
Hooks: PostToolUse:Write [.claude/hooks/log-write.sh] finished with status 0 (31ms)

拆开看:

  • PostToolUse:Write:事件名,冒号后是匹配到的工具名或其他匹配值;
  • 方括号里:钩子执行的命令;来自插件的还会写明插件;
  • finished with status 0:怎么结束的;
  • (31ms):耗时。

结束方式除了正常退出,还可能是 timed out after <N>ms、cancelled、moved to the background 或 failed to start。Notification、SessionEnd、PreCompact 等少数事件上的命令钩子,会留下不带耗时的 completed with status 行。

找慢钩子的办法很直接:

bash
grep "Hooks:" /tmp/claude-debug.log

扫一眼括号里的毫秒数,最大的那个就是元凶。看到 failed to start 或 timed out,也可以结合 onFailure: "block" 想清楚:这个钩子失败时,是该放行还是该拦截。

需要更细的匹配信息(比如每个 matcher 命中多少钩子),可以再设 CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose。

小结 ​

  • 2.1.296 起,--debug 会点名子代理文件里不认识的 frontmatter 字段,并提示可能的拼写错误。
  • 命令钩子结束时会记录事件、命令、插件、结果和耗时,grep "Hooks:" 就能定位慢钩子或启动失败的钩子。
  • 调试日志不打印到终端:用 --debug 看 ~/.claude/debug/<session-id>.txt,或用 --debug-file 指定路径。

升级后用 claude --version 确认 ≥ 2.1.296。

Claude-cn.org,专注于 Claude Code 中文教程