资讯动态

Claude Code 技能自动激活核心揭秘:UserPromptSubmit 与 PreToolUse Hook 机制深度解析

发布时间:2026/10/9 2:11:07 来源:尧图企业网站定制
AI 技能AI 插件人工智能开发工具【免费下载链接】claude-code-infrastructure-showcaseExamples of my Claude Code infrastructure with skill auto-activation, hooks, and agents项目地址https://gitcode.com/gh_mirrors/cl/claude-code-infrastructure-showcase点击查看免费下载导读本文档是 claude-code-infrastructure-showcase 仓库中 skill-developer 技能的核心技术文档完整拆解了 Claude Code 中两个最关键的 HookUserPromptSubmit与PreToolUse从触发、执行、判定到阻断的完整链路。通过本文你将掌握Hook 的注册方式与执行序列、stdout/stderr 与退出码Exit Code三种通道各自的作用、会话状态Session State如何防止重复打扰以及如何通过配置调优让技能自动激活系统既灵敏又低延迟。文中所有机制均可在仓库源码 .claude/hooks/ 与 .claude/skills/skill-rules.json 中找到一一对应的实现依据。一、整体架构五个 Hook 如何协同工作在深入两个核心 Hook 之前先理解它们在完整架构中的位置。仓库的 .claude/settings.json 一共注册了五种 Hook形成一个提示前建议 → 工具前拦截 → 工具后追踪 → 会话结束归档的闭环Hook 事件触发时机脚本/实现职责UserPromptSubmitClaude 处理用户提示之前skill-activation-prompt.sh → skill-activation-prompt.ts基于关键词 意图正则可选 AI 分类推荐相关技能stdout 注入上下文PreToolUsematcher:Edit\|MultiEdit\|Write编辑类工具执行之前skill-verification-guard.sh → skill-verification-guard.ts强制执行必选技能two-try 模型与护栏guardrail文件/内容模式检查PostToolUseEdit/MultiEdit/Write编辑工具完成之后post-tool-use-tracker.sh追踪被编辑的文件与仓库PostToolUseSkillSkill 工具执行之后skill-activation-tracker.sh从 pending 列表清除已激活技能解除后续阻断StopClaude 回复结束session-doc-updater.sh为向量检索索引 dev 文档、清理过期会话状态其中UserPromptSubmit与PreToolUse是建议 强制的左右手也是本文的主角。二者的根本差异在于前者只看不动非阻塞建议后者该拦就拦退出码 2 阻断工具执行。二、UserPromptSubmit Hook技能建议的注入流程2.1 执行序列UserPromptSubmit是一个纯咨询advisory性质的 Hook其完整执行链路如下用户提交 prompt ↓ .claude/settings.json 注册该 Hook无 matcher对所有提示生效 ↓ skill-activation-prompt.sh 被调用 ↓ npx tsx skill-activation-prompt.ts源码入口 ↓ Hook 从 stdin 读取 JSON包含 prompt 字段 ↓ 加载 .claude/skills/skill-rules.json ↓ 匹配 keywords intentPatterns正则意图模式 ↓ 按优先级分组匹配结果critical → high → medium → low ↓ 向 stdout 输出格式化消息 ↓ stdout 内容成为 Claude 的上下文在 prompt 之前注入 ↓ Claude 最终看到[skill suggestion] 用户原始 prompt2.2 关键行为特征从源码 skill-activation-prompt.ts 的main()函数可以逐条印证退出码恒为 0允许即使加载skill-rules.json失败、AI 分类超时或出现任何异常都通过process.exit(0)优雅退出见第 898-906 行的兜底逻辑绝不阻塞用户提示stdout → Claude 的上下文console.log(generateTieredOutput(...))第 836 行输出的内容会被注入为系统级上下文置于用户 prompt 之前时机在 Claude 处理 prompt之前执行这意味着建议能影响 Claude 的第一步行动例如先调用 Skill 工具行为非阻塞、仅建议目的让 Claude 意识到当前任务相关的技能存在。需要特别说明的是skill-rules.json的settings.skill_activation_mode字段默认disabled即纯正则零成本模式决定分类来源而conservativenessstrict/balanced/aggressive控制建议的激进程度详见 skill-rules.json。2.3 输入格式Hook 从 stdin 收到的 JSONClaude Code 会自动把如下结构的 JSON 通过 stdin 传给 Hook{ session_id: abc-123, transcript_path: /path/to/transcript.json, cwd: /root/git/your-project, permission_mode: normal, hook_event_name: UserPromptSubmit, prompt: how does the layout system work? }源码中对应的类型定义HookInput见 skill-activation-prompt.ts只消费prompt、session_id、cwd等字段其中prompt是分类匹配的输入session_id用于读写会话状态。2.4 输出格式写到 stdout 的内容当命中推荐技能时Hook 向 stdout 输出如下格式的分隔块━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SKILL ACTIVATION CHECK ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ RECOMMENDED SKILLS: → project-catalog-developer ACTION: Use Skill tool BEFORE responding ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━Claude 会在处理用户 prompt 之前看到这段输出。源码中的generateTieredOutput()skill-activation-prompt.ts实际支持两种级别的输出有 MANDATORY 技能时输出⛔ MANDATORY SKILL ACTIVATION REQUIRED块明确提示EDITS WILL BE BLOCKED until mandatory skills are activated配合 PreToolUse 拦截生效仅有推荐技能时输出上述 SKILL ACTIVATION CHECK建议块。值得注意的是一个技能能否被标记为 MANDATORY 取决于其enforcement是否为block——suggest/warn技能无论匹配多强都只作为推荐出现这个过滤逻辑由fallbackToClassificationResult()与enforceMandatoryEligibility()实现见 skill-activation-prompt.ts。三、PreToolUse Hook编辑拦截的执行流程3.1 执行序列PreToolUse是技能自动激活系统中强制执行的关口。它在 Claude 调用Edit/Write/MultiEdit工具之前运行Claude 调用 Edit/Write 工具 ↓ .claude/settings.json 注册 Hookmatcher: Edit|MultiEdit|Write ↓ skill-verification-guard.sh 执行 ↓ npx tsx skill-verification-guard.ts源码入口 ↓ Hook 从 stdin 读取 JSON含 tool_name、tool_input ↓ 加载 .claude/skills/skill-rules.json ↓ 检查文件路径模式glob 匹配基于 minimatch ↓ 读取文件内容做内容模式匹配若文件存在 ↓ 检查会话状态该技能本次会话是否已用过 ↓ 检查跳过条件文件标记、环境变量覆盖 ↓ IF 命中且未跳过: 更新会话状态标记该技能已强制执行 向 stderr 输出阻断消息 以退出码 2 退出BLOCK ELSE: 以退出码 0 退出ALLOW ↓ IF BLOCKED: stderr 内容 → Claude 可见 Edit/Write 工具不执行 Claude 必须使用相应技能后重试 IF ALLOWED: 工具正常执行3.2 关键行为特征源码 skill-verification-guard.ts 印证了以下要点退出码 2 BLOCKstderr 内容反馈给 Claude退出码 0 ALLOW时机在工具执行之前运行会话跟踪同一会话内已执行过的技能不会反复阻断Fail Open失败即放行任何异常路径都process.exit(0)见第 537-541 行 catch 块保证 Hook 自身出错绝不中断正常开发流程目的强制关键护栏guardrail。settings.json中该 Hook 的 matcher 为Edit|MultiEdit|Write同时定义了 15 秒超时见 .claude/settings.json。3.3 输入格式Hook 从 stdin 收到的 JSON{ session_id: abc-123, transcript_path: /path/to/transcript.json, cwd: /root/git/your-project, permission_mode: normal, hook_event_name: PreToolUse, tool_name: Edit, tool_input: { file_path: /root/git/your-project/form/src/services/user.ts, old_string: ..., new_string: ... } }源码中HookInput类型skill-verification-guard.ts除上述字段外还包含tool_input.contentWrite 工具与edits数组MultiEdit 工具getEditContent()第 106-118 行会按工具类型提取待写入内容。3.4 输出格式阻断时写到 stderr原文档中的示例使用了一个假想的database-verification护栏技能来演示阻断流程并明确指出本仓库实际内置的block级护栏是frontend-dev-guidelines其完整blockMessage定义在 skill-rules.json。阻断消息示例⚠️ BLOCKED - Database Operation Detected REQUIRED ACTION: 1. Use Skill tool: database-verification 2. Verify ALL table and column names against schema 3. Check database structure with DESCRIBE commands 4. Then retry this edit Reason: Prevent column name errors in Prisma queries File: form/src/services/user.ts TIP: Add // skip-validation comment to skip future checksClaude 收到该消息后会明白必须先使用相应技能再重试编辑。实际仓库中frontend-dev-guidelines的阻断消息结构与此完全一致且包含 MUI v7 兼容性要求如Grid需使用size{{}}属性而非xs/sm与// skip-validation文件标记跳过机制。四、退出码行为关键机制4.1 退出码参考表退出码stdoutstderr工具执行Claude 可见内容0UserPromptSubmit→ 上下文→ 仅用户不适用stdout 内容0PreToolUse→ 仅用户→ 仅用户正常执行无2PreToolUse→ 仅用户→Claude被阻断stderr 内容其他→ 仅用户→ 仅用户被阻断无这张表揭示了 Hook 与 Claude 通信的全部秘密stdout 和 stderr 是两个独立的反馈通道。对UserPromptSubmit而言 stdout 会注入 Claude 上下文对PreToolUse而言只有退出码 2 时的 stderr 内容才会反馈给 Claude。4.2 为什么退出码 2 如此重要这是强制执行机制的唯一命门它是 PreToolUse 中唯一能把消息送达 Claude 的途径stderr 内容会被自动回喂给 ClaudeClaude 看到阻断消息后理解该做什么先调用技能工具执行被阻止因此它是护栏强制执行的基石。4.3 一次完整的对话流示例用户: Add a new user service with Prisma Claude: Ill create the user service... [尝试编辑 form/src/services/user.ts] PreToolUse Hook: [退出码 2] stderr: ⚠️ BLOCKED - Use database-verification Claude 看到错误后回应: I need to verify the database schema first. [使用 Skill 工具: database-verification] [验证列名] [重试编辑 - 放行依赖会话跟踪]从源码看这个流程还叠加了two-try 阻断模型mandatory_pending非空时第一次编辑会被阻断同时 Hook 立即把该技能写入skills_used并从mandatory_pending清除skill-verification-guard.ts因此第二次编辑必然放行——即使 Claude 并没有真的调用 Skill 工具也避免了无限循环阻断。五、会话状态管理Session State Management5.1 目的防止同一会话内重复打扰一旦 Claude 在本次会话中使用过某技能就不再针对该技能反复阻断。5.2 状态文件位置.claude/hooks/state/skills-used-{session_id}.json注意原文档示例中的database-verification/error-tracking为说明性示例本仓库实际会持久化的字段由 session-state.ts 的SessionState接口定义包括skills_used、mandatory_pending、files_verified、ai_suggested_skills、files_analyzed_by_ai、pretooluse_pending、last_updated七个字段。5.3 状态文件结构{ skills_used: [ database-verification, error-tracking ], files_verified: [] }5.4 工作原理会话内第一次编辑如触碰 Prisma 相关文件Hook 以退出码 2 阻断更新会话状态把database-verification加入skills_usedClaude 看到消息后使用该技能。同会话第二次编辑Hook 检查会话状态发现database-verification已在skills_used中以退出码 0 放行不再向 Claude 发送消息。不同会话新的会话 ID 新的状态文件Hook 会再次阻断。从实现层面看会话状态的读写都经由loadSessionState()/updateSessionState().claude/hooks/lib/session-state.ts。由于 Claude 可能并发发起多个工具调用状态写入采用**读最新 原子写**策略updateSessionState()在写入前重新读取磁盘最新状态再通过临时文件 rename原子落盘把读-改-写竞态窗口从整个 Hook 生命周期秒级含 AI 分析压缩到微秒级。5.5 已知局限Hook无法检测技能是否真的被调用——它只是每会话每技能阻断一次。这意味着若 Claude 未使用技能却改做其他编辑也不会再被阻断系统默认信任 Claude 会遵循指令未来增强方向检测实际的 Skill 工具调用事件仓库通过独立的 PostToolUseskill-activation-trackerHook 朝这个方向做了铺垫见 .claude/settings.json。六、性能考量与优化策略6.1 目标指标Hook目标耗时UserPromptSubmit 100msPreToolUse 200ms实际配置中settings.json为两类 Hook 分别设置了 15 秒超时.claude/settings.json 与第 21 行这是 Claude Code 层面的兜底上限而实现内部对 AI 分类与向量检索另行设置了 10 秒超时AI_TIMEOUT_MS 10000见 skill-activation-prompt.ts超时即静默回退到正则匹配。6.2 性能瓶颈每次执行都加载 skill-rules.json两个 Hook 均如此未来方向内存缓存监听文件变更仅在需要时重载。读取文件内容PreToolUse仅在配置了contentPatterns时发生仅在文件存在时发生大文件可能拖慢匹配。Glob 路径匹配PreToolUse每个模式都要编译正则未来方向一次编译后缓存。正则匹配两个 Hook 共用意图模式UserPromptSubmit 的intentPatterns内容模式PreToolUse 的contentPatterns未来方向惰性编译缓存已编译正则。6.3 优化策略减少模式数量使用更具体的模式减少待检查项尽可能合并相似模式。文件路径模式越具体 需要检查的文件越少示例form/src/services/**优于form/**。内容模式仅在确实必要时添加更简单的正则 更快的匹配。值得补充的是源码中已经内置了两道廉价闸门cheap gates来规避不必要的开销isHighSignalEdit()skill-verification-guard.ts先用纯正则快速判断编辑内容是否值得 AI 分析如是否含 import、函数/类定义、Prisma 调用等或内容超过 150 字符且同一文件在本次会话中已分析过则跳过——这样多数普通编辑根本不会触发昂贵的 AI 调用。七、相关文件导航SKILL.md —— 技能开发主指南含五个 Hook 的架构总览与 500 行规则TROUBLESHOOTING.md —— 调试 Hook 问题SKILL_RULES_REFERENCE.md —— 规则配置参考结语UserPromptSubmit与PreToolUse一柔一刚构成了 Claude Code 技能自动激活系统的核心骨架前者在每次对话开始前低成本地提醒Claude 该用什么技能后者在每次编辑前用退出码 2 stderr 通道强制Claude 遵循护栏。理解 stdout/stderr/退出码三条通道的语义差异、会话状态的持久化约定以及fail open two-try的防御性设计就能在自己的项目中安全地扩展这套机制——这套设计在 .claude/settings.json、.claude/hooks/ 与 .claude/skills/skill-rules.json 中均有完整可参考的实现。赞分享AI 技能AI 插件人工智能开发工具【免费下载链接】claude-code-infrastructure-showcaseExamples of my Claude Code infrastructure with skill auto-activation, hooks, and agents项目地址https://gitcode.com/gh_mirrors/cl/claude-code-infrastructure-showcase点击查看免费下载相关推荐Claude Code Hooks 机制深度剖析claude-code-infrastructure-showcase 中的 UserPromptSubmit 与 PreToolUse 实现Claude Code Hooks 机制深度剖析claude code infrastructure showcase 中的 UserPromptSubmitAI 技能AI 插件人工智能开发工具揭秘Claude Code三大核心引擎实时Steering机制深度解析揭秘Claude Code三大核心引擎实时Steering机制深度解析 Claude Code作为现代AI编程助手的杰出代表其核心引擎的3个关键组件构成了整示例工程AI Agent人工智能12行PythonH100上的TileLang GEMM打到cuBLAS同档12行PythonH100上的TileLang GEMM打到cuBLAS同档 一个1024×1024、带融合ReLU的FP16矩阵乘在H100上延迟与厂商库AI 技能AI 插件人工智能开发工具上一篇3 步讲清 US.KG 免费域名注册能做什么、不能做什么避开 90% 的坑下一篇Woodpecker UI 开发指南基于 Vue 3 Vite 的前端架构与本地开发调试全流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑