news 2026/10/2 2:54:53

Claude Code Hooks 完全指南:用事件机制打造自动化编码 Agent

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Claude Code Hooks 完全指南:用事件机制打造自动化编码 Agent

说实话,我把 Claude Code 从“命令行问答工具”升级成“真正能放手的编码 Agent”,靠的就是 Hooks。早期我用它改代码,每次都要手动补一句“记得跑一下格式化”或“检查下有没有 lint 报错”,改的文件一多,这种重复指令极其消耗耐心,而且容易漏。后来研究完 Hooks 机制,把“改完文件自动跑格式化和 lint”“危险命令自动拦截”“每次会话自动归档日志”这类事情全部交给事件触发,体验直接上了一个台阶。

这篇是 Claude Code 系列指南的第四篇,专门讲 Hooks。我会把事件类型、配置语法、匹配规则、四种 Hook 变体讲清楚,然后用真实场景演示怎么落地。适合两类人:一是已经会用 Claude Code 写代码、想把它接入工程化流程的人;二是准备在团队里推广 Claude Code、需要统一安全和规范的人。读完你就能在自己的 settings.json 里写出第一套能用的 Hooks。

1. Hooks 的核心机制与设计思路

1.1 Hooks 本质上是一组“事件回调”

用过前端的人对 addEventListener 不会陌生,Hooks 的原理和它一模一样:Claude Code 在运行过程中会触发各种生命周期事件,你在配置里给这些事件挂上 shell 命令,事件发生时系统就会执行对应脚本。

举个例子,Claude 要执行 Bash 工具之前,会触发 PreToolUse 事件;执行完文件编辑之后,会触发 PostToolUse 事件;你输入完 prompt 准备让 Claude 干活时,会触发 UserPromptSubmit 事件;Claude 回答完一轮、停下来等你输入时,会触发 Stop 事件。

每一个事件都会携带结构化 JSON 数据,通过标准输入(stdin)传给你的脚本。你的脚本处理完数据后,可以通过标准输出(stdout)和标准错误(stderr)反过来影响 Claude 的行为。比如 PreToolUse 事件的脚本发现命令里有危险操作,就往 stdout 输出一个 BLOCK 标记,Claude 的工具调用就会被拦住。

这套设计最值钱的地方在于:你不需要改 Claude Code 源码,不用维护一个常驻服务,只需要写一些可以被 shell 执行的脚本,然后用 JSON 配置把它们挂到对应事件上。脚本可以是 Python、Node.js、Shell、Ruby,甚至编译好的二进制,只要系统能执行就行。

1.2 事件模型完整拆解

我把常用事件整理成了表格,方便对照理解。

事件类型触发时机典型用途
PreToolUseClaude 调用任意工具之前危险命令拦截、权限审批、注入额外上下文
PostToolUse工具执行完成后自动格式化、 lint、跑测试、记录工具执行结果
UserPromptSubmit用户提交 prompt 之后、Claude 回复之前prompt 审计、敏感信息脱敏、团队规范校验
StopClaude 完成一轮回复、等待用户输入时会话日志归档、状态同步、发通知
SubagentStop子 Agent 完成任务返回时汇总子任务结果、检查子 Agent 产物
NotificationClaude 需要用户授权或切换模式时桌面通知、Webhook 提醒
PreCompact上下文压缩发生之前备份关键状态、导出摘要

这里我重点说三个最容易出效果的。

PreToolUse 是所有事件的“闸门”。因为它在工具真正执行之前触发,你可以做到:Bash 工具执行前检查命令内容,发现rm -rf /或git push --force直接拒绝;Read 工具读取敏感文件前做路径拦截;WebSearch 执行前确认搜索词是否合规。拦截逻辑写在脚本里,Claude 想绕都绕不过去,因为它没有“跳过 hook”的权限。

PostToolUse 是质量门禁。Claude 写完代码后,紧接着触发格式化、lint、单测,坏了就直接把报错信息反馈给 Claude 让它继续修。这样 AI 写代码和工程规范之间就有了闭环,而不是每次写完再手动提要求。

UserPromptSubmit 是最容易被忽略但收益极高的一个事件。它能在 Claude“看到”你的 prompt 之前先让你的脚本“看一眼”,适合做日志、脱敏和规范检查。我会在第三部分专门演示。

1.3 为什么不用手动脚本,非要用 Hooks

可能有人觉得:这些事我手动跑不也行吗?可以,但实际工程里手动执行有四个致命问题。

第一,记忆不可靠。你让 Claude 改十个文件,改到第五个的时候注意力早就分散了,很容易漏跑检查。Hooks 是系统级触发,只要配置好,每次工具调用都会走一遍逻辑,不会漏。

第二,策略不统一。团队里十个人用 Claude Code,有人跑 lint 有人不跑,代码风格很快会乱。Hooks 可以放进项目仓库的.claude/settings.json,所有人在这个仓库里开发都自动生效。

第三,安全不可控。让 AI 随心所欲执行命令是有风险的,手动监督在大规模并行编辑时会失灵。PreToolUse 拦截是最后一道防线,相当于给 AI 上了一道“行为护栏”,这比事后发现写坏了再回滚成本低得多。

第四,上下文碎片化。手动执行脚本的结果在终端里一闪而过,没法自动回流给 Claude。但 PostToolUse 的 stdout 可以被 Claude 看到,这意味着你可以在脚本里处理完数据后,把关键信息“喂”给 Claude,让它基于最新结果继续决策。

2. 配置方法与参数详解

2.1 配置文件的位置与优先级

Hooks 写在 settings.json 里。Claude Code 会加载多层配置:

  • 托管策略配置:由企业管理员统一下发,用户改不了,适合强制安全基线;
  • 用户级配置:~/.claude/settings.json,对你本机所有项目生效,适合放个人偏好和全局日志;
  • 项目级配置:.claude/settings.json,放在项目根目录下,会随 Git 仓库走,适合团队共享质量门禁和安全策略。

配置合并的优先级通常是:项目级 > 用户级 > 托管策略。具体值的覆盖关系不一定要死记,你只需要记住一个原则:和团队规范相关的放项目级,个人习惯相关的放用户级,强制底线放托管策略。

如果你在 VS Code 里装了 Claude Code 插件,Hooks 机制完全一样,因为插件底层还是同一个 CLI,读取的也是同一套 settings.json。所以不要去找什么 “VS Code 专用 Hooks 设置界面”,没有,直接改 JSON 就对了。

2.2 Hooks 配置结构详解

先看一个最基础的配置结构:

{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "python3 scripts/check_command.py", "timeout": 30 } ] } ] } }

最外层是hooks对象,key 是事件名。每个事件对应一个数组,数组里每个对象都包含matcher和hooks两部分。matcher决定这个配置组匹配哪些工具或输入,hooks是真正要执行的命令列表。

hooks数组里的每一项都有两个必填字段:

  • type:命令类型。默认写command,其他还有commandAsync、commandBlock、commandAllow,下一节细说。
  • command:要执行的 shell 命令字符串。

可选字段是timeout,单位秒,默认 60 秒。超过这个时间,hook 会被认为是失败或超时,行为取决于事件类型。

我个人强烈建议所有 hook 命令都写成“调用外部脚本文件”,而不是直接在 JSON 里写一长串内联脚本。原因很简单:JSON 里写复杂 shell 命令,转义和换行很容易出错;单独放一个scripts/目录,可以用 Python 或 Node.js 写完整逻辑,还能写单元测试。团队协作时,脚本也能走代码评审。

2.3 四种 Hook 变体:Block、Allow、Async 和普通模式

这是很多人一开始就绕晕的地方。同一个事件,能挂的命令类型其实有区别,关键在于这个事件是否需要“影响 Claude 的下一步行为”。

普通command是阻断式的:Claude Code 会等它执行完,stdout 和 stderr 怎么处理取决于事件类型。而带后缀的类型会改变行为逻辑:

type 写法行为说明主要使用场景
command普通阻塞执行,按事件默认规则处理输出大部分通用场景
commandBlock阻塞执行,可阻止工具调用(主要用于 PreToolUse)危险命令拦截、权限审批
commandAllow非阻塞执行,只记录和观察,不阻止工具调用审计、监控、指标采集
commandAsync异步执行,不等待结果,不阻塞主流程日志上报、通知、耗时任务

不同事件支持的类型还不一样。PreToolUse 支持command、commandBlock、commandAllow,但不支持commandAsync,因为它必须在工具执行前同步做出“允许还是阻止”的决策。PostToolUse 支持command、commandBlock、commandAsync,可以用 Block 模式把 stdout 内容追加给 Claude,也可以用 Async 模式异步做归档。UserPromptSubmit 支持command、commandBlock、commandAllow,适合 prompt 审计和拦截。Stop、SubagentStop、Notification、PreCompact 都支持command、commandBlock、commandAsync,通常用 Async 做收尾工作,避免拖慢对话。

这里的关键认知是:Block 不一定比 Allow 好。Block 会拖慢主流程,如果脚本写得慢,用户体感就是“每次操作都卡一下”。所以我的习惯是:需要拦截的就用 Block,纯记录类的尽量用 Allow,实在耗时的上报任务用 Async。

2.4 matcher 匹配规则:从全量匹配到精确匹配

不写matcher时,这个配置组会匹配该事件的所有触发场景。写matcher可以缩小范围,避免无关工具也触发脚本。

最简单的是工具名匹配。比如 PreToolUse 里只关心 Bash 工具,就写"matcher": "Bash"。注意工具名是大小写敏感的,Bash 的 B 是大写,Write、Edit、MultiEdit 同样首字母大写。

多个工具可以用正则,比如:

{ "matcher": "/^Edit$|^Write$|^MultiEdit$/", "hooks": [ { "type": "command", "command": "python3 scripts/format_file.py" } ] }

带/ /包裹的就是正则表达式,不包就是普通字符串匹配。更高级的用法是 JSONPath,直接从 hook 输入 JSON 里做条件匹配。比如你想只在读取/etc/passwd时才拦截,可以写:

{ "matcher": "$.tool_input.file_path", "hooks": [ { "type": "commandBlock", "command": "python3 scripts/check_path.py" } ] }

不过 JSONPath 对新手不友好,建议先从工具名匹配开始,等确实遇到“需要根据参数内容区分”的需求再升级。

2.5 Hook 脚本的输入输出约定

每次 hook 被触发时,系统会把事件 JSON 写入脚本的 stdin。不同事件的 JSON 结构不同,但最核心的 PreToolUse 结构长这样:

{ "tool_name": "Bash", "tool_input": { "command": "git status" }, "tool_response_id": "xxxx" }

PostToolUse 会在后面多一个tool_response字段,UserPromptSubmit 会带prompt字段。脚本要做的第一件事就是把 stdin 解析成 JSON,然后取你关心的字段。

输出约定需要特别注意:

  • 对 PreToolUse 的 Block 型 hook,如果脚本 stdout 以BLOCK开头,工具调用会被阻止。普通输出不会阻止,但脚本 stderr 的内容会被记录进会话,Claude 能看到。
  • 对 PostToolUse 的 Block 型 hook,脚本 stdout 的内容会随工具结果一起返回给 Claude 作为上下文。stderr 同样会传给 Claude。
  • 对 CommandAllow 这类观察型 hook,输出不会影响主流程。

这意味着脚本“话太多”会烧掉大量 token。PostToolUse 脚本如果每次编辑完都打印一屏日志,Claude 每轮都要为这些日志消耗上下文。正确做法是:成功时保持安静,只在失败或需要补充关键信息时才输出。

3. 核心场景实操:从安全拦截到质量门禁

3.1 实战一:拦截危险命令,给 Claude 上安全护栏

我在团队里落地 Hooks 的第一件事,就是拦住git push到主分支。因为 Claude 在自动修 bug 时,可能会顺手把代码推到 main,这在很多团队是不可接受的。

先写一个检查脚本,我放在.claude/scripts/guard_git_push.py:

import json import sys data = json.load(sys.stdin) tool_name = data.get("tool_name") tool_input = data.get("tool_input", {}) if tool_name != "Bash": sys.exit(0) cmd = tool_input.get("command", "") # 只关心 git push 相关命令 if "git push" not in cmd: sys.exit(0) # 判断是否推送到 main / master if any(branch in cmd for branch in ["main", "master"]): print("BLOCK: 禁止直接推送 main/master 分支,请使用 feature 分支并走 MR") print("已拦截对主分支的推送操作", file=sys.stderr)

然后在.claude/settings.json里挂载:

{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "commandBlock", "command": "python3 .claude/scripts/guard_git_push.py" } ] } ] } }

注意这里用commandBlock,因为我们需要在工具执行前把它拦截下来。脚本里优先用stdout输出BLOCK前缀,系统会识别并阻止工具调用;stderr里的解释会进入会话,让 Claude 知道为什么被拦,从而调整自己的行为。

这套逻辑还可以扩展。比如拦截rm -rf指向项目根目录的命令、拦截对.env文件的 Read 操作、拦截curl上传源码到外部服务的命令。规则写多了以后,Claude 在你这套环境里会自动学会避免触发这些警告,相当于用代码约束了 Agent 的行为边界。

3.2 实战二:文件编辑后自动格式化和 lint

PostToolUse 是我认为 Hooks 里“投产比”最高的事件。因为 Claude 改代码是高频操作,每次写完自动做质量检查,比事后统一跑一遍体验好得多。

配置如下:

{ "hooks": { "PostToolUse": [ { "matcher": "/^Edit$|^Write$|^MultiEdit$/", "hooks": [ { "type": "command", "command": "python3 .claude/scripts/quality_gate.py", "timeout": 30 } ] } ] } }

脚本核心逻辑:

import json import subprocess import sys data = json.load(sys.stdin) tool_input = data.get("tool_input", {}) file_path = tool_input.get("file_path") if not file_path: sys.exit(0) # 仅处理当前项目内的文件 if not file_path.startswith("src/"): sys.exit(0) # 先格式化,再 lint subprocess.run(["npx", "prettier", "--write", file_path], check=False) result = subprocess.run(["npx", "eslint", file_path], capture_output=True, text=True) if result.returncode != 0: # 输出 lint 错误,让 Claude 看到并修复 print(f"LINT_FAIL: {file_path}\n{result.stdout[:2000]}")

这里面有个关键细节:文件路径从tool_input.file_path取,不要自己在命令里拼接变量。因为直接往 settings.json 里写prettier --write ${FILE_PATH}这类模板变量,Claude Code 不会帮你展开,最后会变成一个空的或错误的路径。把所有逻辑放到脚本里解析 JSON,是最稳的做法。

lint 失败时,脚本输出LINT_FAIL前缀并附上错误摘要,PostToolUse 的 stdout 会回流给 Claude,Claude 会继续修复问题。这就形成了一个自动循环:写文件 → 触发质量检查 → 有问题反馈给 Claude → Claude 修复 → 再触发检查,直到通过。

3.3 实战三:UserPromptSubmit 做审计、脱敏和规范校验

我在多个项目里部署过这个模式:用户输入任何 prompt,先经过钩子脚本,写入本地日志,顺便检查有没有把密钥贴进去。

脚本如下:

import json import re import sys from datetime import datetime data = json.load(sys.stdin) prompt = data.get("prompt", "") # 1. 审计日志:记录每次 prompt with open(".claude/prompt_log.jsonl", "a") as f: f.write(json.dumps({ "time": datetime.now().isoformat(), "prompt": prompt[:500] }) + "\n") # 2. 敏感信息检测 secret_patterns = [ r"sk-[A-Za-z0-9]{20,}", r"ghp_[A-Za-z0-9]{20,}", r"AKIA[A-Z0-9]{16}", ] for pattern in secret_patterns: if re.search(pattern, prompt): print("BLOCK: 检测到疑似密钥内容,请输入经过脱敏的 prompt") print("请移除密钥后再发送", file=sys.stderr) sys.exit(0)

这个脚本的效果立竿见影。之前有同事在 prompt 里贴了线上数据库连接串,Claude 直接把连接串写进代码里再提交,差点出事。加了 UserPromptSubmit 拦截之后,密钥根本进不到 Claude 上下文里。

还有团队拿它做规范校验:要求 prompt 必须带上需求单号,没有就通过 stderr 提醒。这比人工 review 聊天记录靠谱多了,因为拦截发生在模型看到内容之前,属于前置约束。

3.4 实战四:Stop 事件做会话归档与异步通知

Stop 事件在 Claude 回复完之后触发,适合做“每一轮对话的落盘”。我个人的习惯是用commandAsync把归档任务丢到后台,不阻塞下一轮输入。

{ "hooks": { "Stop": [ { "hooks": [ { "type": "commandAsync", "command": "python3 .claude/scripts/archive_session.py" } ] } ] } }

归档脚本做的事情很简单:把当前会话的关键消息追加到session_archive.jsonl。这个文件的用途是之后做数据复盘,比如统计这个项目里 Claude 花了多少轮才解决问题、哪些类型的修改频繁触发 lint 错误、有没有反复修改同一个文件。

不要小看这个日志,有一次我排查“为什么某天 Claude 突然一直改错文件”,就是从 Stop hook 的归档日志里发现,上午我在 prompt 里给了一个过时的目录结构,Claude 后续所有判断都基于那个错误上下文。有了历史日志,这类问题就变成可追溯的了。

3.5 实战五:与本地服务和其他 CLI 工具联动

Hooks 本质就是执行 shell 命令,所以它能联动的对象远超 Claude Code 本身。你可以让它在文件更新后调用本地 Flutter/Django 的格式化工具,可以把工具调用记录推送给内部审计 API,也可以把 Claude 的修改摘要交给本地模型服务做二次校验或者生成变更说明。

一个比较实用的做法是:在 PostToolUse 里把“改动的文件列表”交给一个本地脚本,脚本自动生成 commit message 草案并追加到临时文件。这样当 Claude 准备提交代码时,它能直接引用一份结构化的变更说明,提交信息质量有明显提升。

再比如很多团队会写内部 CLI 来做代码规范校验,你可以直接把它作为 hook 挂在 PostToolUse 上,命令换成my-cli check $(jq -r '.tool_input.file_path' <<< "$HOOK_INPUT")。注意这里如果要用 jq,系统里必须有 jq,而且 Hook 执行环境和终端环境不一定完全相同,这在第四部分排查里我会重点提醒。

3.6 大型代码库中落地 Hooks 的三个原则

在超大仓库里用 Hooks,最重要的一点是:不要让钩子脚本变成性能瓶颈。PreToolUse 是同步阻塞的,如果脚本逻辑复杂,每次 Claude 调用工具都有明显延迟,整个体验会变得不可用。

我的三条实操原则:

第一,拦截逻辑保持轻量。PreToolUse 脚本只做模式匹配和判断,不要做深度分析。判断命令里有没有危险关键字用 Python 的in或正则就够,别在拦截脚本里做 AST 解析。

第二,重量操作异步化。格式化、日志归档这类任务,能挂 Async 就别用同步 Block。格式化可以放到 PostToolUse 的普通模式里,日志就放到 Stop 的commandAsync。

第三,用git diff限定范围。PostToolUse 触发时,不要对整个仓库跑 lint,只针对tool_input.file_path或者git diff --name-only输出的文件列表。很多团队在 CI 里已经这么做了,Hooks 里同理,否则改一个文件触发两分钟全仓扫描,谁也受不了。

4. 常见问题与排查技巧实录

4.1 Hook 没触发,先查这三件事

我遇到过最多的问题是:配置写了,脚本也挂了,但事件就是不触发。排查顺序如下:

第一,确认配置文件路径。你改了~/.claude/settings.json,但当前项目里存在.claude/settings.json,项目级配置覆盖或合并后把优先级顶掉了,导致你以为生效的规则其实没生效。建议检查时先claude里执行hooks相关的帮助命令,或者直接手动打开两个文件看有没有冲突。

第二,确认 matcher 有没有匹配上。写"matcher": "Bash"时,如果实际触发的是Bash(git status)这种带额外信息的工具名,就匹配不上。同理,正则写错了也会静默失败。最简单的验证方式是:在脚本第一行把收到的事件 JSON 写到一个临时文件,然后手动构造一次触发,看 JSON 长什么样。

第三,确认脚本本身能不能在 Claude Code 的环境里跑通。Claude Code 在 GUI 里启动时,PATH 环境变量可能和终端里不一样,python命令找不到 Python、node找不到 Node 就会静默失败。这时候不要用python,直接用绝对路径,比如/usr/bin/python3,或者用which python3查一下再写死。

4.2 Timeout 和异步执行的坑

默认情况下 hook 有 60 秒超时。看起来很长,但 PreToolUse 是阻塞式的,一旦脚本执行时间超过预期,Claude 的工具调用会被挂起,表现就是“卡住不动”。如果你的脚本里跑了npm install或全仓eslint,60 秒很容易超。

我踩过的坑是这样的:第一次写 PostToolUse 格式化脚本时,直接在命令里写了npx prettier --write,结果 npx 在第一次运行时要下载包,光下载就等了十几秒。更麻烦的是,这个下载消耗不是每次都有,于是脚本表现不稳定,有时快有时慢。

解决办法是:项目里固定依赖本地安装好的prettier/eslint,命令写node_modules/.bin/prettier而不是npx prettier。或者干脆在脚本开头对依赖做一次确定性检查,缺依赖直接返回,不要现场下载。

异步 hook 也有坑。commandAsync虽然不阻塞主流程,但它不会像同步 hook 那样捕获 stdout 回传,日志写在哪里需要你自己控制。而且异步脚本并发执行时,如果都往同一个文件追加内容,可能产生并发写问题。解决办法是在脚本里用追加模式打开文件,或者加一个简单的文件锁。

4.3 stdout 和 stderr 输出污染上下文

这个问题非常隐蔽。PostToolUse 的 Block 型 hook 会把 stdout 内容作为上下文发给 Claude,如果你的脚本习惯性打印了成功信息,比如Formatting complete.、Processed 12 files.,每一轮都会被塞进上下文。

测试跑下来你会觉得很奇怪:明明没干多少活,怎么上下文消耗这么快?查了半天发现是 hook 脚本刷屏。所以 PostToolUse 脚本的纪律是:正常情况不输出,异常情况才输出,而且输出要精炼。

对于 PreToolUse 的 stderr 也一样。Claude 能看到 stderr,如果你把脚本内部调试信息全打进去,Claude 可能会被干扰,以为发生了什么错误。建议脚本里不要用print做日志追踪,真要记录状态就写文件。

4.4 权限与路径问题

Hooks 是以当前用户的权限执行的,不会额外提权。如果你的脚本需要写/etc下的文件,或者需要访问某个只有 root 才能读的目录,它不会成功。

另一个典型问题是工作目录。Claude Code 的主进程通常以项目根目录作为 cwd,你写的脚本路径和相对路径都要基于这个理解。比如"command": "python3 .claude/scripts/check.py"里的.claude是相对于项目根目录的。但要是你在脚本里还写了open("log.txt", "w"),这个log.txt也会写到项目根目录下,而不是脚本所在目录。需要根据实际需求使用绝对路径,或通过环境变量判断当前目录。

Windows 环境下还要注意 shell 差异。settings.json 里的 command 在 Windows 上走的是 cmd 的语法,和 Linux/macOS 的 bash 语法有区别。跨平台团队的建议是:把脚本用 Python 写,命令统一成python3 .claude/scripts/xxx.py,尽量避免在 JSON 里直接写 shell 专属语法。

4.5 高频问题速查表

现象可能原因快速解法
Hook 完全不触发配置文件路径不对或 matcher 未匹配检查项目级和用户级 settings.json,临时把 matcher 删掉测试
工具调用经常卡住同步 hook 执行过慢优化脚本,改用绝对路径解释器,去掉 npx 下载逻辑
上下文消耗异常高PostToolUse 脚本 stdout 刷屏脚本只在异常时输出,成功保持静默
拦截不生效用了 command 而不是 commandBlock确认事件是否支持拦截,改成 commandBlock
异步日志丢失commandAsync 不捕获输出日志内容直接由脚本写文件,不要依赖 stdout
Windows 下脚本报错shell 语法不兼容统一用 Python 脚本,避免 bash 专属指令

4.6 调试 Hooks 的三个技巧

最后分享三个实战调试技巧。

第一,写一个 dump 脚本。把输入 JSON 原封不动写到文件。不确定某个事件携带什么数据结构时,就先用 dump 脚本跑一轮,看完输出再写正式逻辑。

import json, sys with open("/tmp/hook_input.json", "w") as f: json.dump(json.load(sys.stdin), f, ensure_ascii=False, indent=2)

第二,在命令里临时加个标记文件。有些 hook 执行太快,你不知道它到底有没有跑到。在脚本入口处写一个touch /tmp/hook_running.flag,然后手动触发工具调用,看这个文件有没有生成。没有生成就是脚本没被执行,生成就是脚本内部逻辑有问题。

第三,用 exit code 做故障隔离。脚本里捕获所有异常,异常时sys.exit(2)并往 stderr 写信息,正常路径sys.exit(0)。这样当你看到工具被莫名卡住或拦截时,可以快速判断是脚本抛异常还是业务规则触发。

我个人在实际操作中的体会是:Hooks 这个功能,真正拉开差距的不是“会用”,而是“克制”。你不需要在第一天上手就挂十个事件,那样只会让自己疲于调试。先把 UserPromptSubmit 的审计日志跑起来,再补一个 PreToolUse 危险命令拦截,最后把 PostToolUse 的格式化和 lint 加上,三步走完已经能覆盖绝大部分工程化需求。

踩过几次坑之后,我现在最推荐的第一次尝试,是从 UserPromptSubmit 日志开始。把每天的 prompt 落到一个 JSONL 文件里,第二天回看,你会很直观地发现自己在让 Claude 重复做哪些事,然后才能真正理解该用哪个事件去自动化掉它们。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 2:54:53

VS Code历史记录清理全攻略:从SQLite到工作区缓存

最近接手了同事的一台电脑&#xff0c;他抱怨VS Code越来越“卡”&#xff0c;我打开一看&#xff0c;好家伙&#xff0c;最近打开的文件夹和工作区列表攒了几百条&#xff0c;光找自己的项目就得翻半天。他问我能不能把这些历史记录清掉&#xff0c;我把几种方法都试了一遍&am…

作者头像 李华
网站建设 2026/10/2 2:54:36

Ultralytics YOLO模块自定义与替换:从原理到实战

Ultralytics YOLO模块自定义与替换&#xff0c;听起来像是算法工程师的进阶课程。实际上我这两年被问得最多的问题反而不是训练怎么跑&#xff0c;而是“我想把Backbone换了怎么办”“损失函数能不能自己改”“换了模块之后报错怎么查”。这篇文章就是把我在真实项目里动刀YOLO…

作者头像 李华
网站建设 2026/10/2 2:54:32

ASP.NET ERP电商进销存系统源码拆解与二次开发

简介&#xff1a;这是一套基于ASP.NET Web Forms开发模式的电商进销存管理系统源码&#xff0c;面向后端开发人员及ERP方向学习者&#xff0c;既适合初学者了解B/S架构基础&#xff0c;也为中级开发者提供扩展参考&#xff0c;可用于理解库存管理、订单处理、权限控制等核心业务…

作者头像 李华
网站建设 2026/10/2 2:54:09

用Claude Code构建多Agent协作系统:从架构设计到终端监控

这套多 Agent 协作系统是我在过去一段时间里折腾 Claude Code 时逐步搭起来的&#xff0c;最初只是想解决一个很实际的问题&#xff1a;单个 Claude Code 实例处理复杂任务时&#xff0c;上下文容易被塞满&#xff0c;工具调用链一长就容易迷失方向&#xff0c;最终产出的质量非…

作者头像 李华
网站建设 2026/10/2 2:54:08

卫星通信MATLAB仿真:链路预算与BER曲线的完整工作流

简介&#xff1a;卫星通信链路仿真与设计配套资源&#xff0c;面向电子信息、通信工程及数学等专业大学生和MATLAB开发者&#xff0c;适用于课程设计、期末大作业与毕业设计等场景。资源采用参数化编程思路实现卫星通信核心仿真模块&#xff0c;覆盖链路预算、调制解调、编码解…

作者头像 李华
网站建设 2026/10/2 2:53:31

KVM虚拟化快照管理:virsh命令从创建到回滚的完整指南

KVM虚拟化环境里&#xff0c;快照这个功能平时不起眼&#xff0c;等哪天真把一台虚拟机搞到起不来的时候&#xff0c;你才会意识到它有多救命。我用virsh这套命令行管理KVM快照好几年了&#xff0c;从最初给测试机打快照练手&#xff0c;到后来在生产环境升级内核、装补丁、调数…

作者头像 李华