名称: hook-creator 描述: ‘为Claude Code框架创建和注册钩子。处理工具执行前后的验证、内存管理和会话钩子。当需要新验证、安全或自动化钩子时使用。’ 版本: 2.1.0 模型: sonnet 调用者: both 用户可调用: true 工具: [Read, Write, Edit, Bash, Glob, Grep]
第一阶段集成: 钩子验证参考 .claude/config/tool-manifest.json
钩子可以验证工具可用性,并使用清单中的备用工具
单一真相来源: .claude/config/tool-manifest.json
最佳实践:
- 始终在适当配置中注册钩子
- 部署前测试钩子
- 在所有钩子中包含错误处理
- 记录钩子触发器和行为
- 使用显式执行模式(block|warn|off)并支持环境变量覆盖;默认warn,除非规范要求block 错误处理: graceful 流式处理: supported 输出位置: .claude/hooks/ 已验证: false 最后验证时间: 2026-02-19T05:29:09.098Z
钩子创建器技能
为多代理编排框架创建、验证和注册钩子。
路由器更新要求(关键 - 不要跳过)
创建任何钩子后,必须更新文档:
1. 在 .claude/hooks/README.md 的适当类别下添加
2. 如果需要,在 config.yaml 或 settings.json 中注册
3. 使用钩子摘要更新 learnings.md
验证:
grep "<hook-name>" .claude/hooks/README.md || echo "错误:hooks/README.md 未更新!"
为什么:未记录的钩子不可见且不可维护。
概述
此技能为Claude Code框架创建钩子:
- 工具执行前 - 命令运行前的安全验证
- 工具执行后 - 日志记录、内存更新、遥测
- 会话生命周期 - 初始化上下文,退出时清理
- 内存管理 - 自动提取学习内容,格式化内存文件
- 路由执行 - 确保路由器优先协议合规性
钩子类型
| 类型 | 位置 | 用途 | 触发时机 |
|---|---|---|---|
| 安全 | .claude/hooks/safety/ |
验证命令,阻止危险操作 | 在Bash/Write/Edit之前 |
| 内存 | .claude/hooks/memory/ |
自动更新学习内容,提取见解 | 任务完成后 |
| 路由 | .claude/hooks/routing/ |
执行路由器优先协议 | 在UserPromptSubmit时 |
| 会话 | .claude/hooks/session/ |
初始化/清理会话 | 会话开始/结束 |
钩子-代理原型参考
创建钩子时,确定新钩子将管理哪些代理原型。参见 .claude/docs/@HOOK_AGENT_MAP.md 以了解:
- 第一部分: 完整钩子-代理矩阵
- 第二部分: 原型钩子集(路由器、实施者、审查者、文档者、编排者、研究者)
创建钩子后,必须将其添加到矩阵中,并更新受影响代理的 ## 执行钩子 部分。
Claude Code钩子类型
| 钩子事件 | 触发时机 | 用例 |
|---|---|---|
PreToolUse |
工具执行前 | 验证、阻止、权限检查 |
PostToolUse |
工具完成后 | 日志记录、清理、通知 |
UserPromptSubmit |
模型看到消息前 | 路由、意图分析、过滤 |
工作流步骤
步骤0: 存在性检查和更新器委托(强制 - 第一步)
在创建任何钩子文件之前,检查是否已存在:
-
检查钩子是否已存在:
test -f .claude/hooks/<category>/<hook-name>.cjs && echo "存在" || echo "新建" -
如果钩子存在:
-
不要继续创建
-
改为调用artifact-updater工作流:
Skill({ skill: 'artifact-updater', args: '--type hook --path .claude/hooks/<category>/<hook-name>.cjs --changes "<请求更改的描述>"', }); -
返回更新器结果并停止
-
-
如果钩子是新建:
- 继续步骤0.5
步骤0.5: 伴随检查
在继续创建之前,运行生态系统伴随检查:
- 使用
.claude/lib/creators/companion-check.cjs中的companion-check.cjs - 调用
checkCompanions("hook", "{hook-name}")以识别伴随工件 - 查看伴随清单 — 注意缺少哪些必需/推荐的伴随
- 计划在此工件完成后创建或验证缺少的伴随
- 在创建后集成笔记中包含伴随发现
此步骤是信息性的(不阻止创建),但确保考虑完整的工件生态系统。
参考钩子
使用 .claude/lib/routing/routing-table.cjs 作为规范路由参考。
在最终确定任何钩子之前,与路由表结构比较:
- [ ] 具有正确的CommonJS导出(module.exports)
- [ ] 导出钩子类型所需的函数(validate、main等)
- [ ] 具有全面的测试文件(.test.cjs)
- [ ] 具有正确的错误处理(try/catch、优雅回退)
- [ ] 返回钩子类型的正确响应格式
步骤1: 收集钩子需求
创建钩子之前,收集:
- 目的: 此钩子应做什么?
- 触发器: 应在何时运行?(工具前、工具后、会话事件)
- 目标工具: 适用于哪些工具?(Bash、Write、Edit、Read)
- 行为: 阻止操作或仅警告?
- 退出码: 指示成功/失败的是什么?
// 需求收集示例
{
purpose: "验证git push命令以防止强制推送",
trigger: "工具前(Bash)",
target_tools: ["Bash"],
behavior: "检测到强制推送时阻止",
exit_codes: { 0: "允许", 1: "阻止" }
}
步骤2: 确定钩子类型和位置
| 如果钩子做… | 类型 | 位置 |
|---|---|---|
| 验证命令 | 安全 | .claude/hooks/safety/ |
| 修改路由 | 路由 | .claude/hooks/routing/ |
| 更新内存 | 内存 | .claude/hooks/memory/ |
| 会话初始化/清理 | 会话 | .claude/hooks/session/ |
命名约定: <action>-<target>.cjs
示例:
validate-git-force-push.cjsenforce-tdd-workflow.cjsextract-workflow-learnings.cjsmemory-reminder.cjs
步骤3: 生成钩子代码(CJS格式)
所有钩子使用CommonJS格式并遵循此模板:
'use strict';
/**
* {钩子名称}
*
* 类型: {pre|post}-{tool} | session-{start|end} | user-prompt
* 目的: {一行描述}
* 触发器: {此钩子运行时机}
*
* 退出码:
* - 0: 允许操作(带可选警告)
* - 1: 阻止操作(在阻止模式下)
*
* 环境:
* {HOOK_NAME}_MODE=block|warn|off (默认: warn,除非明确要求)
*/
const fs = require('fs');
const path = require('path');
// 通过查找.claude目录找到项目根目录
function findProjectRoot() {
let dir = __dirname;
while (dir !== path.parse(dir).root) {
if (fs.existsSync(path.join(dir, '.claude'))) {
return dir;
}
dir = path.dirname(dir);
}
return process.cwd();
}
const PROJECT_ROOT = findProjectRoot();
const ENFORCEMENT_MODE = process.env.HOOK_NAME_MODE || 'warn';
/**
* 从Claude Code解析钩子输入
* Claude Code通过process.argv[2]传递JSON给钩子
* @returns {Object|null} 解析的钩子输入或null
*/
function parseHookInput() {
try {
if (process.argv[2]) {
return JSON.parse(process.argv[2]);
}
} catch (e) {
// 测试或无效输入的回退
}
return null;
}
/**
* 验证钩子 - 由Claude Code或编程方式调用
* @param {Object} context - 带工具信息的钩子上下文
* @param {string} context.tool - 工具名称(Bash、Write、Edit、Read)
* @param {Object} context.parameters - 工具参数
* @returns {{ valid: boolean, error: string, warning?: string }}
*/
function validate(context) {
const { tool, parameters } = context;
// 您的验证逻辑在此处
// 返回验证结果
return { valid: true, error: '' };
}
/**
* 用于CLI钩子使用的主要执行
*/
function main() {
// 如果执行关闭则跳过
if (ENFORCEMENT_MODE === 'off') {
process.exit(0);
}
const hookInput = parseHookInput();
if (!hookInput) {
process.exit(0);
}
// 获取工具名称和输入
const toolName = hookInput.tool_name || hookInput.tool;
const toolInput = hookInput.tool_input || hookInput.input || {};
// 运行验证
const result = validate({ tool: toolName, parameters: toolInput });
if (!result.valid) {
if (ENFORCEMENT_MODE === 'block') {
console.error(`阻止: ${result.error}`);
process.exit(1);
} else {
console.warn(`警告: ${result.error}`);
process.exit(0);
}
}
if (result.warning) {
console.warn(`警告: ${result.warning}`);
}
process.exit(0);
}
// 如果直接执行则运行main
if (require.main === module) {
main();
}
// 导出以用于编程使用和测试
module.exports = {
validate,
findProjectRoot,
PROJECT_ROOT,
};
步骤4: 创建测试文件
每个钩子必须有相应的测试文件:
'use strict';
const { validate } = require('./hook-name.cjs');
describe('钩子名称', () => {
test('允许有效操作', () => {
const result = validate({
tool: 'Bash',
parameters: { command: 'git status' },
});
expect(result.valid).toBe(true);
expect(result.error).toBe('');
});
test('阻止危险操作', () => {
const result = validate({
tool: 'Bash',
parameters: { command: 'git push --force' },
});
expect(result.valid).toBe(false);
expect(result.error).toContain('强制推送');
});
test('优雅处理缺失参数', () => {
const result = validate({
tool: 'Bash',
parameters: {},
});
expect(result.valid).toBe(true);
});
});
步骤5: 注册钩子(如果需要)
一些钩子需要在配置文件中注册:
用于工具前/后钩子(settings.json):
{
"hooks": {
"pre-tool": [".claude/hooks/safety/hook-name.cjs"],
"post-tool": [".claude/hooks/memory/hook-name.cjs"]
}
}
用于事件钩子(config.yaml):
hooks:
UserPromptSubmit:
- path: .claude/hooks/routing/hook-name.cjs
type: command
SessionStart:
- path: .claude/hooks/session/hook-name.cjs
type: command
步骤6: 更新文档(强制 - 阻止)
创建钩子后,更新 .claude/hooks/README.md:
#### {钩子名称} (`hook-name.cjs`)
{钩子做什么的描述}
**运行时机:** {触发条件}
**检查/做什么:** {详细行为}
验证:
grep "hook-name" .claude/hooks/README.md || echo "错误:未记录!"
步骤7: 系统影响分析(强制)
此分析是强制的。没有它,钩子创建不完整。
创建钩子后:
-
设置注册(阻止)
- 添加到.claude/settings.json中的PreToolUse/PostToolUse等。
- 验证:
grep "hook-name" .claude/settings.json
-
测试覆盖(阻止)
- 创建.test.cjs文件,最少10个测试用例
- 运行测试:
node .claude/hooks/<category>/<name>.test.cjs
-
文档
- 如果钩子添加新功能,更新.claude/docs/
- 添加使用示例
-
相关钩子
- 检查钩子是否影响同一触发类别中的其他钩子
- 记录交互模式
完整清单:
[HOOK-CREATOR] 系统影响分析:<hook-name>
1. 钩子文件已创建
[ ] 创建于 .claude/hooks/<type>/<hook-name>.cjs
[ ] 遵循CJS格式,带有validate()导出
[ ] 具有main()函数用于CLI执行
[ ] 处理优雅降级(默认警告)
2. 测试文件已创建(最少10个测试用例)
[ ] 创建于 .claude/hooks/<type>/<hook-name>.test.cjs
[ ] 测试有效操作(3+案例)
[ ] 测试阻止操作(3+案例)
[ ] 测试边缘情况(3+案例)
[ ] 测试错误处理(1+案例)
3. 文档已更新
[ ] 添加到 .claude/hooks/README.md
[ ] 记录了触发条件
[ ] 记录了退出码
4. 注册(阻止)
[ ] 添加到settings.json(工具前/后钩子)
[ ] 添加到config.yaml(事件钩子)
[ ] 验证:grep "<hook-name>" .claude/settings.json
5. 内存已更新
[ ] 使用钩子摘要添加到learnings.md
6. 钩子-代理地图已更新(强制)
[ ] 在@HOOK_AGENT_MAP.md第一部分矩阵中添加新钩子
[ ] 确定哪些代理原型受影响(基于钩子触发/工具目标)
[ ] 更新受影响代理的`## 执行钩子`部分
[ ] 验证:`grep "<hook-name>" .claude/docs/@HOOK_AGENT_MAP.md || echo "错误:钩子不在代理地图中!"`
阻止: 如果以上任何项目缺失,钩子创建不完整。
步骤8: 创建后钩子注册(第一阶段集成)
**此步骤是关键。**创建钩子工件后,必须在钩子发现系统中注册它。
第一阶段上下文: 第一阶段负责工具和钩子验证/发现。未注册的钩子对系统不可见,启动时不会加载。
钩子文件写入和测试后:
-
在适当位置创建/更新钩子注册条目:
如果注册表不存在,创建
.claude/context/artifacts/hook-registry.json:{ "hooks": [ { "name": "{hook-name}", "id": "{hook-name}", "description": "{钩子简要描述}", "category": "{safety|routing|memory|session|validation|audit}", "type": "{pre-tool|post-tool|user-prompt|session-start|session-end}", "version": "1.0.0", "targetTools": ["{Tool1}", "{Tool2}"], "enforcementMode": "{block|warn|off}", "defaultEnabled": true, "filePath": ".claude/hooks/{category}/{hook-name}.cjs", "testFilePath": ".claude/hooks/{category}/{hook-name}.test.cjs", "environmentVariable": "{HOOK_NAME}_MODE" } ] } -
根据架构验证钩子:
确保钩子根据
.claude/schemas/hook-schema.json验证(如果存在):# 验证钩子结构 node -e " const hook = require('./.claude/hooks/{category}/{hook-name}.cjs'); if (hook.validate) console.log('✓ 有validate()导出'); if (hook.PROJECT_ROOT) console.log('✓ 有PROJECT_ROOT'); if (hook.findProjectRoot) console.log('✓ 有findProjectRoot()'); " -
在加载器中注册钩子:
更新
.claude/lib/hooks/hook-loader.cjs(如果存在)以包含新钩子:const HOOKS_MANIFEST = { '{hook-name}': { path: './.claude/hooks/{category}/{hook-name}.cjs', type: '{pre-tool|post-tool}', matcher: '{Bash|Write|Edit|Read}', // 可选 enabled: true, enforcementMode: process.env.{HOOK_NAME}_MODE || 'warn' } }; -
在配置中注册钩子:
用于工具前/后钩子 - 更新
.claude/settings.json:{ "hooks": { "pre-tool": ["./.claude/hooks/safety/{hook-name}.cjs"], "post-tool": ["./.claude/hooks/memory/{hook-name}.cjs"] } }用于事件钩子 - 更新
.claude/config.yaml:hooks: UserPromptSubmit: - path: ./.claude/hooks/routing/{hook-name}.cjs type: command SessionStart: - path: ./.claude/hooks/session/{hook-name}.cjs type: command -
在
.claude/hooks/README.md中记录:在适当类别下添加条目:
#### {钩子名称} (`{hook-name}.cjs`) {钩子做什么的详细描述。} **运行时机:** {触发条件 - 例如,“在每次Bash命令前”、“任务完成后”} **检查/做什么:** - {检查/动作1} - {检查/动作2} - {检查/动作3} **执行模式:** `process.env.{HOOK_NAME}_MODE` (默认: `warn`) **测试文件:** `.claude/hooks/{category}/{hook-name}.test.cjs` **相关钩子:** {列出与此交互的任何钩子} -
更新内存:
追加到
.claude/context/memory/learnings.md:## 钩子: {hook-name} - **类型:** {pre-tool|post-tool|event} - **类别:** {safety|routing|memory|session|validation} - **目的:** {详细目的} - **触发器:** {运行时机} - **执行:** {默认阻止/警告/关闭} - **集成笔记:** {任何特殊考虑}
为什么重要: 没有钩子注册:
- 启动时钩子未加载
- 钩子验证不发生
- 系统无法发现可用钩子
- 安全验证器被绕过
- 出现“不可见工件”模式
第一阶段集成: 钩子注册表是第一阶段的发现机制,使系统能够根据架构验证钩子、启动时加载它们,并一致地执行安全规则。
步骤9: 集成验证(阻止 - 不要跳过)
此步骤验证工件是否正确集成到生态系统中。
在调用 TaskUpdate({ status: "completed" }) 之前,必须运行创建后验证工作流:
-
运行10项集成清单:
node .claude/tools/cli/validate-integration.cjs .claude/hooks/<category>/<hook-name>.cjs -
验证退出码为0(所有检查通过)
-
如果退出码为1(一个或多个检查失败):
- 阅读错误输出以了解具体失败
- 修复每个失败:
- 缺少钩子注册 -> 创建注册条目(步骤8)
- 缺少settings.json条目 -> 注册钩子(步骤8)
- 缺少文档 -> 添加到hooks/README.md
- 缺少内存更新 -> 更新learnings.md
- 缺少测试文件 -> 创建.test.cjs文件
- 重新运行验证,直到退出码为0
-
仅当验证通过时继续
此步骤是阻止的。 在验证通过之前,不要标记任务完成。
为什么重要: Party Mode事件表明,如果集成步骤遗漏,完全实现的工件可能对路由器不可见。此验证确保没有“不可见工件”模式。
参考: .claude/workflows/core/post-creation-validation.md
CLI参考
# 使用CLI工具创建钩子
node .claude/tools/hook-creator/create-hook.mjs \
--name "hook-name" \
--type "PreToolUse|PostToolUse|UserPromptSubmit" \
--purpose "钩子做什么的描述" \
--category "safety|routing|memory|audit|security|validation|custom" \
--matcher "Edit|Write|Bash" # 可选: 工具匹配器正则表达式
# 列出所有钩子
node .claude/tools/hook-creator/create-hook.mjs --list
# 验证钩子结构
node .claude/tools/hook-creator/create-hook.mjs --validate "<路径>"
# 分配给代理
node .claude/tools/hook-creator/create-hook.mjs --assign "名称" --agents "agent1,agent2"
# 取消注册钩子
node .claude/tools/hook-creator/create-hook.mjs --unregister "<路径>"
# 使用示例输入测试
node .claude/hooks/<category>/<hook-name>.cjs '{"tool_name":"Edit","tool_input":{"file_path":"test.js"}}'
钩子模式参考
模式1: 安全验证器(工具前)
用于执行前验证命令:
'use strict';
/**
* 验证Git强制推送
* 防止意外强制推送到受保护分支
*/
const PROTECTED_BRANCHES = ['main', 'master', 'production'];
function validate(context) {
const { tool, parameters } = context;
if (tool !== 'Bash') {
return { valid: true, error: '' };
}
const command = parameters?.command || '';
// 检查强制推送
if (command.includes('git push') && (command.includes('--force') || command.includes('-f'))) {
// 检查是否推送到受保护分支
for (const branch of PROTECTED_BRANCHES) {
if (command.includes(branch)) {
return {
valid: false,
error: `阻止强制推送到${branch}。请改用--force-with-lease。`,
};
}
}
return {
valid: true,
error: '',
warning: '检测到强制推送。请确保您知道自己在做什么。',
};
}
return { valid: true, error: '' };
}
module.exports = { validate };
模式2: 内存提取器(工具后)
用于任务完成后提取学习内容:
'use strict';
/**
* 提取工作流学习内容
* 自动从完成的工作流中捕获模式
*/
const fs = require('fs');
const path = require('path');
function findProjectRoot() {
let dir = __dirname;
while (dir !== path.parse(dir).root) {
if (fs.existsSync(path.join(dir, '.claude'))) return dir;
dir = path.dirname(dir);
}
return process.cwd();
}
const LEARNINGS_PATH = path.join(findProjectRoot(), '.claude/context/memory/learnings.md');
function extractLearnings(context) {
const { tool, parameters, result } = context;
// 仅处理完成的任务
if (!result || result.status !== 'completed') {
return { extracted: false };
}
// 从结果中提取模式
const learnings = [];
if (result.patterns) {
learnings.push(...result.patterns);
}
if (result.decisions) {
learnings.push(...result.decisions);
}
if (learnings.length === 0) {
return { extracted: false };
}
// 追加到学习内容文件
const entry = `
## [${new Date().toISOString().split('T')[0]}] ${context.taskName || '任务'}
`;
const content = learnings.map(l => `- ${l}`).join('
');
fs.appendFileSync(LEARNINGS_PATH, entry + content + '
');
return { extracted: true, count: learnings.length };
}
module.exports = { extractLearnings };
模式3: 路由执行器(用户提示)
用于执行路由协议:
'use strict';
/**
* 路由器优先执行器
* 确保所有请求通过路由器代理
*/
function validate(context) {
const { prompt, currentAgent } = context;
// 如果已路由则跳过
if (currentAgent === 'router') {
return { valid: true, error: '' };
}
// 跳过斜杠命令(由技能系统处理)
if (prompt && prompt.trim().startsWith('/')) {
return { valid: true, error: '' };
}
// 建议路由
return {
valid: true,
error: '',
warning: '考虑使用路由器通过Task工具生成适当代理。',
};
}
module.exports = { validate };
模式4: 会话初始化器
用于会话生命周期管理:
'use strict';
/**
* 会话内存初始化器
* 在会话开始时提醒代理读取内存文件
*/
const fs = require('fs');
const path = require('path');
function findProjectRoot() {
let dir = __dirname;
while (dir !== path.parse(dir).root) {
if (fs.existsSync(path.join(dir, '.claude'))) return dir;
dir = path.dirname(dir);
}
return process.cwd();
}
const MEMORY_FILES = [
'.claude/context/memory/learnings.md',
'.claude/context/memory/issues.md',
'.claude/context/memory/decisions.md',
];
function initialize() {
const root = findProjectRoot();
console.log('
' + '='.repeat(50));
console.log(' 会话内存提醒');
console.log('='.repeat(50));
console.log('
开始工作前,请阅读这些内存文件:');
for (const file of MEMORY_FILES) {
const fullPath = path.join(root, file);
if (fs.existsSync(fullPath)) {
const stats = fs.statSync(fullPath);
const modified = stats.mtime.toISOString().split('T')[0];
console.log(` - ${file} (更新于: ${modified})`);
}
}
console.log('
' + '='.repeat(50) + '
');
return { initialized: true };
}
// 直接执行时运行
if (require.main === module) {
initialize();
}
module.exports = { initialize };
示例
安全验证钩子
node .claude/tools/hook-creator/create-hook.mjs \
--name "secret-detector" \
--type "PreToolUse" \
--purpose "阻止包含秘密或凭据的提交" \
--category "security" \
--matcher "Bash"
审计日志钩子
node .claude/tools/hook-creator/create-hook.mjs \
--name "operation-logger" \
--type "PostToolUse" \
--purpose "将所有文件修改记录到审计追踪" \
--category "audit"
意图分析钩子
node .claude/tools/hook-creator/create-hook.mjs \
--name "intent-classifier" \
--type "UserPromptSubmit" \
--purpose "为用户意图分类以进行智能路由" \
--category "routing"
工作流集成
此技能是统一工件生命周期的一部分。对于完整的多代理编排:
路由器决策: .claude/workflows/core/router-decision.md
- 路由器如何发现和调用此技能的工件
工件生命周期: .claude/workflows/core/skill-lifecycle.md
- 发现、创建、更新、弃用阶段
- 版本管理和注册表更新
- CLAUDE.md集成要求
外部集成: .claude/workflows/core/external-integration.md
- 外部工件的安全集成
- 安全审查和验证阶段
交叉参考: 创建者生态系统
此技能是创建者生态系统的一部分。创建钩子后,考虑是否需要伴随工件:
| 需求 | 调用的创建者 | 命令 |
|---|---|---|
| 钩子逻辑的专用技能 | skill-creator |
Skill({ skill: 'skill-creator' }) |
| 使用此钩子的代理 | agent-creator |
Skill({ skill: 'agent-creator' }) |
| 钩子测试的工作流 | workflow-creator |
在 .claude/workflows/ 中创建 |
| 钩子配置的架构 | schema-creator |
在 .claude/schemas/ 中创建 |
| 钩子脚手架的模板 | template-creator |
在 .claude/templates/ 中创建 |
集成工作流
创建需要额外功能的钩子后:
// 1. 钩子已创建,但需要专用技能
Skill({ skill: 'skill-creator' });
// 创建封装钩子逻辑的技能
// 2. 钩子需要分配给代理
// 更新代理的工作流以包含钩子意识
// 3. 钩子需要测试工作流
// 在.claude/workflows/<hook-name>-test-workflow.md中创建工作流
创建后生态系统集成清单
钩子完全创建和验证后:
[ ] 钩子是否需要技能包装? -> 使用skill-creator
[ ] 钩子是否需要专用代理? -> 使用agent-creator
[ ] 钩子是否需要测试工作流? -> 创建工作流
[ ] 钩子应默认启用吗? -> 更新config.yaml
[ ] 钩子是否与其他钩子交互? -> 在README.md中记录
[ ] 运行创建后验证 -> node .claude/tools/cli/validate-integration.cjs .claude/hooks/<category>/<hook-name>.cjs
钩子创建的钢铁法则
这些规则不可违反。违反它们会导致静默失败。
1. 没有validate()导出的钩子
- 每个钩子必须导出validate()函数
- 没有validate()的钩子无法以编程方式调用
2. 没有main()用于CLI的钩子
- 每个钩子必须有main()用于CLI执行
- 仅当require.main === module时运行
3. 没有执行控制的钩子
- 通过环境变量支持'block|warn|off'
- 默认'warn',除非明确要求阻止
- 永不因格式错误的输入而崩溃
4. 没有错误处理的钩子
- 在try/catch中包装JSON.parse
- 优雅处理缺失参数
- 不确定时返回valid: true(开放失败,不关闭)
5. 没有测试文件的钩子
- 每个钩子需要<hook-name>.test.cjs
- 测试有效、无效和边缘情况
6. 没有文档的钩子
- 添加到.claude/hooks/README.md
- 记录触发器、行为、退出码
7. 跨平台路径
- 使用path.join()而不是字符串连接
- 处理/和\路径分隔符
- 使用path.normalize()进行比较
8. 没有系统影响分析的创建
- 检查钩子是否需要settings.json注册
- 检查钩子是否需要config.yaml注册
- 使用新钩子行更新@HOOK_AGENT_MAP.md(强制)
- 更新受影响代理的执行钩子部分(强制)
- 检查是否需要更新相关钩子
- 记录所有系统更改
集成点
- 生态系统评估器: 钩子创建器与生态系统评估集成以进行反向查找
- 代理创建器: 代理可以在其前端中引用钩子
- 技能创建器: 技能可以在其hooks/目录中定义钩子
- Settings.json: 钩子自动注册,具有适当的触发器和匹配器
- Config.yaml: 事件钩子注册用于UserPromptSubmit、SessionStart等
架构合规性
文件放置(ADR-076)
- 钩子:
.claude/hooks/{category}/(安全、路由、内存、会话、验证、审计) - 钩子测试:
.claude/hooks/{category}/{name}.test.cjs(与钩子同位置) - 测试:
tests/(钩子的集成测试) - 相关文档:
.claude/docs/ - 钩子注册表:
.claude/hooks/README.md
文档参考(CLAUDE.md v2.2.1)
- 参考文件使用@符号: @ENFORCEMENT_HOOKS.md, @TOOL_REFERENCE.md
- 位于:
.claude/docs/@*.md - 参见: CLAUDE.md 第1.3节(执行钩子参考)
Shell安全(ADR-077)
- 新安全钩子: bash-cwd-validator.cjs, shell-injection-validator.cjs, variable-quoting-validator.cjs (ADR-077 第二阶段)
- 第三阶段钩子: shellcheck-validator.cjs, command-allowlist-validator.cjs (参考实现)
- 钩子测试必须验证shell安全模式
- 参见: .claude/docs/SHELL-SECURITY-GUIDE.md
- 应用于: 所有安全钩子、工具前钩子、验证钩子
最近ADRs
- ADR-075: 路由器配置感知模型选择
- ADR-076: 文件放置架构重新设计
- ADR-077: Shell命令安全架构
文件放置与标准
输出位置规则
此技能输出到: .claude/hooks/<category>/
类别:
safety/- 安全验证器(命令验证、安全检查、shell安全)routing/- 路由器执行钩子memory/- 内存管理钩子session/- 会话生命周期钩子validation/- 输入/输出验证钩子
强制参考
- 文件放置: 参见
.claude/docs/FILE_PLACEMENT_RULES.md - 开发者工作流: 参见
.claude/docs/DEVELOPER_WORKFLOW.md - 工件命名: 参见
.claude/docs/ARTIFACT_NAMING.md
执行
文件放置由 file-placement-guard.cjs 钩子执行。
无效放置将在生产模式下被阻止。
内存协议(强制)
创建钩子前:
cat .claude/context/memory/learnings.md
检查:
- 先前创建的钩子
- 已知钩子模式
- 用户对钩子行为的偏好
完成后:
- 新钩子创建 -> 追加到
.claude/context/memory/learnings.md - 钩子问题 -> 追加到
.claude/context/memory/issues.md - 钩子设计决策 -> 追加到
.claude/context/memory/decisions.md
假设中断: 您的上下文可能重置。如果不在内存中,则未发生。
生态系统对齐合同(强制)
此创建者技能是协调创建者生态系统的一部分。这里创建的任何工件必须与相关创建者对齐并验证:
agent-creator用于所有权和执行路径skill-creator用于能力打包和分配tool-creator用于可执行自动化表面hook-creator用于执行和护栏rule-creator和semgrep-rule-creator用于策略和静态检查template-creator用于标准化脚手架workflow-creator用于编排和阶段门控command-creator用于用户/操作员命令UX
跨创建者握手(必需)
完成前,验证所有相关握手:
- 工件路由存在于
.claude/CLAUDE.md和相关路由文档中。 - 发现/注册条目已更新(目录/索引/注册表,如适用)。
- 伴随工件已创建或明确豁免并注明原因。
validate-integration.cjs为创建的工件通过。- 技能元数据更改时,技能索引重新生成。
研究门(Exa优先,arXiv后备)
对于新模式、模板或工作流,研究是强制性的:
- 首先使用Exa进行实现和生态系统模式研究。
- 如果Exa不足,使用
WebFetch加arXiv参考。 - 在工件参考/文档中记录决策、约束和非目标。
- 保持更新最小化,避免过度工程。
回归安全交付
- 遵循严格的RED -> GREEN -> REFACTOR进行行为更改。
- 对更改的模块运行针对性测试。
- 对更改的文件运行lint/format。
- 保持提交按关注点范围化(逻辑/文档/生成的工件)。