关于 hook-creator
hook-creator 是用于 Claude Code 多 Agent 编排框架的技能,帮助创建、验证和登记 Hook。它覆盖安全、记忆、路由与会话生命周期等用途,并要求配套测试及文档和系统注册。
主要功能
- 01创建安全、记忆、路由和会话 Hook
- 02按触发类型选择 Hook 位置
- 03为每个 Hook 编写测试
- 04登记 Hook 并更新文档
适用场景
- 01在命令执行前验证或拦截操作
- 02在任务完成后记录信息或更新记忆
- 03在提示提交或会话启停时执行逻辑
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ oimiragieo/ agent-studio --skill hook-creator安装后在 Claude Code 中输入/hook-creator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
commands/hook-creator.mdhooks/post-execute.cjspre-execute.cjsreferences/research-requirements.mdrules/hook-creator.mdschemas/input.schema.jsonoutput.schema.jsonscripts/main.cjstemplates/implementation-template.md详细介绍
钩子创建器技能
为多 Agent 编排框架创建、验证和注册钩子。
必须更新路由器(关键——不得跳过)
创建任何钩子后,必须更新文档:
1. Add to .claude/hooks/README.md under appropriate category
2. Register in config.yaml or settings.json if required
3. Update learnings.md with hook summary
验证:
grep "<hook-name>" .claude/hooks/README.md || echo "ERROR: hooks/README.md NOT UPDATED!"
原因:未记录的钩子不可见,也难以维护。
概述
此技能为 Claude Code 框架创建钩子:
- 工具执行前——在命令运行前进行安全验证
- 工具执行后——记录日志、更新记忆、收集遥测数据
- 会话生命周期——初始化上下文,在退出时清理
- 记忆管理——自动提取经验,整理记忆文件格式
- 路由规则执行——确保符合 Router-First 协议
钩子类型
| 类型 | 位置 | 用途 | 触发时机 |
|---|---|---|---|
| 安全 | .claude/hooks/safety/ | 验证命令,阻止危险操作 | Bash/Write/Edit 执行前 |
| 记忆 | .claude/hooks/memory/ | 自动更新经验,提取见解 | 任务完成后 |
| 路由 | .claude/hooks/routing/ | 强制执行路由器优先协议 | UserPromptSubmit 时 |
| 会话 | .claude/hooks/session/ | 初始化/清理会话 | 会话开始/结束时 |
钩子与 Agent 原型参考
创建钩子时,请确定新钩子将约束哪些 Agent 原型。参见 .claude/docs/@HOOK_AGENT_MAP.md,其中包括:
- 第 1 节:完整的钩子与 Agent 矩阵
- 第 2 节:原型钩子集(Router、Implementer、Reviewer、Documenter、Orchestrator、Researcher)
创建钩子后,必须将其添加到矩阵中,并更新受影响 Agent 的 ## Enforcement Hooks 部分。
Claude Code 钩子类型
| 钩子事件 | 触发时机 | 用途 |
|---|---|---|
PreToolUse | 工具执行前 | 验证、拦截、权限检查 |
PostToolUse | 工具执行后 | 日志记录、清理、通知 |
UserPromptSubmit | 模型接收消息前 | 路由、意图分析、过滤 |
工作流步骤
步骤 0:检查是否已存在并委派更新器(必须——第一步)
创建任何钩子文件之前,请先检查文件是否已存在:
-
检查钩子是否已存在:
test -f .claude/hooks/<category>/<hook-name>.cjs && echo "EXISTS" || echo "NEW" -
如果钩子已存在:
-
不要继续创建
-
改为调用 artifact-updater 工作流:
Skill({ skill: 'artifact-updater', args: '--type hook --path .claude/hooks/<category>/<hook-name>.cjs --changes "<description of requested changes>"', }); -
返回更新器结果并停止
-
-
如果钩子是新的:
- 继续执行下面的步骤 0.5
步骤 0.1:智能重复项检测(必须)
继续创建之前,运行 3 层重复项检查:
const { checkDuplicate } = require('.claude/lib/creation/duplicate-detector.cjs');
const result = checkDuplicate({
artifactType: 'hook',
name: proposedName,
description: proposedDescription,
keywords: proposedKeywords || [],
});
处理结果:
EXACT_MATCH:停止创建,改用hook-updater技能:Skill({ skill: 'hook-updater' })REGISTRY_MATCH:警告用户——该项目已注册,但文件可能缺失。创建前先调查,并请用户确认。SIMILAR_FOUND:显示带分数的候选项。询问用户:“存在相似项目。是继续创建新项目,还是更新现有项目?”NO_MATCH:继续执行步骤 0.5(配套项检查)。
覆盖选项:如果用户明确传入 --force,则完全跳过此检查。
步骤 0.5:配套项检查
在继续创建之前,运行生态系统配套项检查:
- 使用
.claude/lib/creators/companion-check.cjs中的companion-check.cjs - 调用
checkCompanions("hook", "{hook-name}"),识别配套产物 - 查看配套项清单,记录缺少哪些必需/推荐的配套项
- 计划在此产物完成后创建或核验缺少的配套项
- 在创建后的集成说明中包含配套项检查结果
此步骤仅供参考(不会阻止创建),但可确保充分考虑完整的产物生态系统。
参考 Hook
使用 .claude/lib/routing/routing-table.cjs 作为标准路由参考。
定稿任何 Hook 之前,请对照路由表结构进行检查:
- 具有正确的 CommonJS 导出(module.exports)
- 导出 Hook 类型所需的函数(validate、main 等)
- 具有完整的测试文件(.test.cjs)
- 具有适当的错误处理(try/catch、优雅的回退机制)
- 返回符合 Hook 类型要求的响应格式
步骤 1:收集 Hook 需求
创建 Hook 之前,请收集以下信息:
- 用途:此 Hook 应执行什么操作?
- 触发条件:何时运行?(工具调用前、工具调用后、会话事件)
- 目标工具:适用于哪些工具?(Bash、Write、Edit、Read)
- 行为:阻止操作还是仅发出警告?
- 退出代码:哪些代码表示成功/失败?
// Example requirements gathering
{
purpose: "Validate git push commands to prevent force push",
trigger: "pre-tool (Bash)",
target_tools: ["Bash"],
behavior: "block if force push detected",
exit_codes: { 0: "allow", 1: "block" }
}
步骤 2:确定 Hook 类型和位置
| 如果 Hook 执行…… | 类型 | 位置 |
|---|---|---|
| 验证命令 | Safety | .claude/hooks/safety/ |
| 修改路由 | Routing | .claude/hooks/routing/ |
| 更新记忆 | Memory | .claude/hooks/memory/ |
| 会话初始化/清理 | Session | .claude/hooks/session/ |
命名约定: <action>-<target>.cjs
示例:
validate-git-force-push.cjsenforce-tdd-workflow.cjsextract-workflow-learnings.cjsmemory-reminder.cjs
步骤 3:生成 Hook 代码(CJS 格式)
所有 Hook 均采用 CommonJS 格式,并遵循此模板:
'use strict';
/**
* {Hook Name}
*
* Type: {pre|post}-{tool} | session-{start|end} | user-prompt
* Purpose: {One line description}
* Trigger: {When this hook runs}
*
* Exit codes:
* - 0: Allow operation (with optional warning)
* - 1: Block operation (when in blocking mode)
*
* Environment:
* {HOOK_NAME}_MODE=block|warn|off (default: warn unless explicitly required)
*/
const fs = require('fs');
const path = require('path');
// Find project root by looking for .claude directory
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';
/**
* Parse hook input from Claude Code
* Claude Code passes JSON via process.argv[2] for hooks
* @returns {Object|null} Parsed hook input or null
*/
function parseHookInput() {
try {
if (process.argv[2]) {
return JSON.parse(process.argv[2]);
}
} catch (e) {
// Fallback for testing or invalid input
}
return null;
}
/**
* Validate hook - called by Claude Code or programmatically
* @param {Object} context - Hook context with tool info
* @param {string} context.tool - Tool name (Bash, Write, Edit, Read)
* @param {Object} context.parameters - Tool parameters
* @returns {Object} Validation result with valid (boolean), error (string), and optional warning (string)
*/
function validate(context) {
const { tool, parameters } = context;
// YOUR VALIDATION LOGIC HERE
// Return validation result
return { valid: true, error: '' };
}
/**
* Main execution for CLI hook usage
*/
function main() {
// Skip if enforcement is off
if (ENFORCEMENT_MODE === 'off') {
process.exit(0);
}
const hookInput = parseHookInput();
if (!hookInput) {
process.exit(0);
}
// Get tool name and input
const toolName = hookInput.tool_name || hookInput.tool;
const toolInput = hookInput.tool_input || hookInput.input || {};
// Run validation
const result = validate({ tool: toolName, parameters: toolInput });
if (!result.valid) {
if (ENFORCEMENT_MODE === 'block') {
console.error(`BLOCKED: ${result.error}`);
process.exit(1);
} else {
console.warn(`WARNING: ${result.error}`);
process.exit(0);
}
}
if (result.warning) {
console.warn(`WARNING: ${result.warning}`);
}
process.exit(0);
}
// Run main if executed directly
if (require.main === module) {
main();
}
// Export for programmatic use and testing
module.exports = {
validate,
findProjectRoot,
PROJECT_ROOT,
};
步骤 4:创建测试文件
每个 Hook 都必须有对应的测试文件:
'use strict';
const { validate } = require('./hook-name.cjs');
describe('Hook Name', () => {
test('allows valid operations', () => {
const result = validate({
tool: 'Bash',
parameters: { command: 'git status' },
});
expect(result.valid).toBe(true);
expect(result.error).toBe('');
});
test('blocks dangerous operations', () => {
const result = validate({
tool: 'Bash',
parameters: { command: 'git push --force' },
});
expect(result.valid).toBe(false);
expect(result.error).toContain('force push');
});
test('handles missing parameters gracefully', () => {
const result = validate({
tool: 'Bash',
parameters: {},
});
expect(result.valid).toBe(true);
});
});
步骤 5:注册 Hook(如有需要)
部分 Hook 需要在配置文件中注册:
对于工具调用前/后的 Hook(settings.json):
{
"hooks": {
"pre-tool": [".claude/hooks/safety/hook-name.cjs"],
"post-tool": [".claude/hooks/memory/hook-name.cjs"]
}
}
对于事件 Hook(config.yaml):
hooks:
UserPromptSubmit:
- path: .claude/hooks/routing/hook-name.cjs
type: command
SessionStart:
- path: .claude/hooks/session/hook-name.cjs
type: command
步骤 6:更新文档(强制 - 阻断性)
创建 Hook 后,更新 .claude/hooks/README.md:
#### {Hook Name} (`hook-name.cjs`)
{Description of what the hook does}
**When it runs:** {Trigger condition}
**What it checks/does:** {Detailed behavior}
通过以下方式验证:
grep "hook-name" .claude/hooks/README.md || echo "ERROR: Not documented!"
步骤 7:系统影响分析(强制)
此分析为强制要求。未完成此分析,Hook 创建流程即未完成。
创建 Hook 后:
-
设置注册(阻断性)
- 将其添加到 .claude/settings.json 的 PreToolUse/PostToolUse 等配置中。
- 使用以下命令验证:
grep "hook-name" .claude/settings.json
-
测试覆盖(阻断性)
- 创建 .test.cjs 文件,至少包含 10 个测试用例
- 运行测试:
node .claude/hooks/<category>/<name>.test.cjs
-
文档
- 如果 Hook 增添了新功能,请更新 .claude/docs/。
- 添加用法示例
-
相关 Hook
- 检查此 Hook 是否会影响同一触发类别中的其他 Hook
- 记录交互模式
完整清单:
[HOOK-CREATOR] System Impact Analysis for: <hook-name>
1. HOOK FILE CREATED
[ ] Created at .claude/hooks/<type>/<hook-name>.cjs
[ ] Follows CJS format with validate() export
[ ] Has main() function for CLI execution
[ ] Handles graceful degradation (warn by default)
2. TEST FILE CREATED (minimum 10 test cases)
[ ] Created at .claude/hooks/<type>/<hook-name>.test.cjs
[ ] Tests valid operations (3+ cases)
[ ] Tests blocked operations (3+ cases)
[ ] Tests edge cases (3+ cases)
[ ] Tests error handling (1+ cases)
3. DOCUMENTATION UPDATED
[ ] Added to .claude/hooks/README.md
[ ] Documented trigger conditions
[ ] Documented exit codes
4. REGISTRATION (BLOCKING)
[ ] Added to settings.json (pre/post-tool hooks)
[ ] Added to config.yaml (event hooks)
[ ] Verified: grep "<hook-name>" .claude/settings.json
5. MEMORY UPDATED
[ ] Added to learnings.md with hook summary
6. HOOK-AGENT MAP UPDATED (MANDATORY)
[ ] Added new hook to @HOOK_AGENT_MAP.md Section 1 matrix
[ ] Determined which agent archetypes are affected (based on hook trigger/tool target)
[ ] Updated affected agents' `## Enforcement Hooks` sections
[ ] Verified: `grep "<hook-name>" .claude/docs/@HOOK_AGENT_MAP.md || echo "ERROR: Hook not in agent map!"`
阻断性要求:如果上述任一项缺失,Hook 创建流程即未完成。
第 8 步:创建后钩子注册(第一阶段集成)
此步骤至关重要。 创建钩子产物后,必须将其注册到钩子发现系统中。
第一阶段背景: 第一阶段负责工具和钩子的验证与发现。未注册的钩子对系统不可见,启动时也不会加载。
写入并测试钩子文件后:
-
创建/更新钩子注册表条目,放在相应位置:
如果注册表不存在,请创建
.claude/context/artifacts/hook-registry.json:{ "hooks": [ { "name": "{hook-name}", "id": "{hook-name}", "description": "{Brief description from hook}", "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的验证要求(如果存在):# Validate hook structure node -e " const hook = require('./.claude/hooks/{category}/{hook-name}.cjs'); if (hook.validate) console.log('✓ Has validate() export'); if (hook.PROJECT_ROOT) console.log('✓ Has PROJECT_ROOT'); if (hook.findProjectRoot) console.log('✓ Has 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}', // Optional 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} (`{hook-name}.cjs`) {Detailed description of what the hook does.} **When it runs:** {Trigger condition - e.g., "Before every Bash command", "After task completion"} **What it checks/does:** - {Check/action 1} - {Check/action 2} - {Check/action 3} **Enforcement mode:** `process.env.{HOOK_NAME}_MODE` (default: `warn`) **Test file:** `.claude/hooks/{category}/{hook-name}.test.cjs` **Related hooks:** {List any hooks that interact with this one} -
更新记忆:
追加到
.claude/context/memory/learnings.md:## Hook: {hook-name} - **Type:** {pre-tool|post-tool|event} - **Category:** {safety|routing|memory|session|validation} - **Purpose:** {Detailed purpose} - **Trigger:** {When it runs} - **Enforcement:** {Block/warn/off by default} - **Integration Notes:** {Any special considerations}
重要性: 未注册钩子会导致:
- 启动时不会加载钩子
- 不会进行钩子验证
- 系统无法发现可用钩子
- 安全验证器被绕过
- 出现“不可见产物”模式
第一阶段集成: 钩子注册表是第一阶段的发现机制,使系统能够根据架构验证钩子、在启动时加载钩子,并一致地执行安全规则。
第 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 事件表明,如果遗漏集成步骤,即使产物已完全实现,Router 也可能无法发现它。此验证可确保不会出现“不可见产物”模式。
参考: .claude/workflows/core/post-creation-validation.md
CLI 参考
# Create hook using CLI tool
node .claude/tools/hook-creator/create-hook.mjs \
--name "hook-name" \
--type "PreToolUse|PostToolUse|UserPromptSubmit" \
--purpose "Description of what the hook does" \
--category "safety|routing|memory|audit|security|validation|custom" \
--matcher "Edit|Write|Bash" # Optional: tool matcher regex
# List all hooks
node .claude/tools/hook-creator/create-hook.mjs --list
# Validate hook structure
node .claude/tools/hook-creator/create-hook.mjs --validate "<path>"
# Assign to agents
node .claude/tools/hook-creator/create-hook.mjs --assign "name" --agents "agent1,agent2"
# Unregister hook
node .claude/tools/hook-creator/create-hook.mjs --unregister "<path>"
# Test with sample input
echo '{"tool_name":"Edit","tool_input":{"file_path":"test.js"} }' | node .claude/hooks/<category>/<hook-name>.cjs
钩子模式参考
模式 1:安全验证器(工具调用前)
用于在执行前验证命令:
'use strict';
/**
* Validate Git Force Push
* Prevents accidental force pushes to protected branches
*/
const PROTECTED_BRANCHES = ['main', 'master', 'production'];
function validate(context) {
const { tool, parameters } = context;
if (tool !== 'Bash') {
return { valid: true, error: '' };
}
const command = parameters?.command || '';
// Check for force push
if (command.includes('git push') && (command.includes('--force') || command.includes('-f'))) {
// Check if pushing to protected branch
for (const branch of PROTECTED_BRANCHES) {
if (command.includes(branch)) {
return {
valid: false,
error: `Force push to ${branch} blocked. Use --force-with-lease instead.`,
};
}
}
return {
valid: true,
error: '',
warning: 'Force push detected. Ensure you know what you are doing.',
};
}
return { valid: true, error: '' };
}
module.exports = { validate };
模式 2:记忆提取器(工具调用后)
用于在任务完成后提取经验:
'use strict';
/**
* Extract Workflow Learnings
* Automatically captures patterns from completed workflows
*/
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;
// Only process completed tasks
if (!result || result.status !== 'completed') {
return { extracted: false };
}
// Extract patterns from result
const learnings = [];
if (result.patterns) {
learnings.push(...result.patterns);
}
if (result.decisions) {
learnings.push(...result.decisions);
}
if (learnings.length === 0) {
return { extracted: false };
}
// Append to learnings file
const entry = `\n## [${new Date().toISOString().split('T')[0]}] ${context.taskName || 'Task'}\n\n`;
const content = learnings.map(l => `- ${l}`).join('\n');
fs.appendFileSync(LEARNINGS_PATH, entry + content + '\n');
return { extracted: true, count: learnings.length };
}
module.exports = { extractLearnings };
模式 3:路由强制器(用户提示词)
用于强制执行路由协议:
'use strict';
/**
* Router First Enforcer
* Ensures all requests go through the Router agent
*/
function validate(context) {
const { prompt, currentAgent } = context;
// Skip if already routed
if (currentAgent === 'router') {
return { valid: true, error: '' };
}
// Skip slash commands (handled by skill system)
if (prompt && prompt.trim().startsWith('/')) {
return { valid: true, error: '' };
}
// Suggest routing
return {
valid: true,
error: '',
warning: 'Consider using Router to spawn appropriate agent via Task tool.',
};
}
module.exports = { validate };
模式 4:会话初始化器
用于管理会话生命周期:
'use strict';
/**
* Session Memory Initializer
* Reminds agents to read memory files at session start
*/
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('\n' + '='.repeat(50));
console.log(' SESSION MEMORY REMINDER');
console.log('='.repeat(50));
console.log('\n Before starting work, read these memory files:');
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} (updated: ${modified})`);
}
}
console.log('\n' + '='.repeat(50) + '\n');
return { initialized: true };
}
// Run on direct execution
if (require.main === module) {
initialize();
}
module.exports = { initialize };
示例
安全验证钩子
node .claude/tools/hook-creator/create-hook.mjs \
--name "secret-detector" \
--type "PreToolUse" \
--purpose "Blocks commits containing secrets or credentials" \
--category "security" \
--matcher "Bash"
审计日志钩子
node .claude/tools/hook-creator/create-hook.mjs \
--name "operation-logger" \
--type "PostToolUse" \
--purpose "Logs all file modifications to audit trail" \
--category "audit"
意图分析钩子
node .claude/tools/hook-creator/create-hook.mjs \
--name "intent-classifier" \
--type "UserPromptSubmit" \
--purpose "Classifies user intent for intelligent routing" \
--category "routing"
工作流集成
此技能属于统一的工件生命周期。有关完整的多 Agent 编排,请参阅:
路由器决策: .claude/workflows/core/router-decision.md
- 路由器如何发现并调用此技能的工件
工件生命周期: .claude/workflows/core/skill-lifecycle.md
- 发现、创建、更新和弃用阶段
- 版本管理和注册表更新
- CLAUDE.md 集成要求
外部集成: .claude/workflows/core/external-integration.md
- 安全集成外部工件
- 安全审查和验证阶段
交叉引用:Creator 生态系统
此技能属于 Creator 生态系统。创建 hook 后,请考虑是否需要配套工件:
| 发现的缺口 | 所需工件 | 要调用的 Creator | 适用时机 |
|---|---|---|---|
| 领域知识需要可复用的技能 | skill | Skill({ skill: 'skill-creator' }) | 缺口涵盖完整的技能领域 |
| 现有技能的覆盖范围不完整 | skill 更新 | Skill({ skill: 'skill-updater' }) | 存在相近技能,但覆盖不完整 |
| 某项能力需要专属 Agent | agent | Skill({ skill: 'agent-creator' }) | 需要由 Agent 负责该能力 |
| 现有 Agent 需要更新能力 | agent 更新 | Skill({ skill: 'agent-updater' }) | 存在相近 Agent,但覆盖不完整 |
| 领域需要代码/项目脚手架 | template | Skill({ skill: 'template-creator' }) | 需要可复用的代码模式 |
| 行为需要执行前/后防护措施 | hook | Skill({ skill: 'hook-creator' }) | 需要强制执行行为 |
| 流程需要多阶段编排 | workflow | Skill({ skill: 'workflow-creator' }) | 需要多步骤协调 |
| 工件需要结构化 I/O 验证 | schema | Skill({ skill: 'schema-creator' }) | 需要用于工件 I/O 的 JSON schema |
| 用户交互需要斜杠命令 | command | Skill({ skill: 'command-creator' }) | 需要面向用户的快捷方式 |
| 重复逻辑需要可复用的 CLI 工具 | tool | Skill({ skill: 'tool-creator' }) | 需要 CLI 实用工具 |
| 仅限狭窄/单一工件的能力 | inline | 仅在此工件中记录 | 过于具体,不适合泛化 |
集成工作流
创建需要额外能力的 hook 后:
// 1. Hook created but needs dedicated skill
Skill({ skill: 'skill-creator' });
// Create skill that encapsulates hook logic
// 2. Hook needs to be assigned to agent
// Update agent's workflow to include hook awareness
// 3. Hook needs workflow for testing
// Create workflow in .claude/workflows/<hook-name>-test-workflow.md
生态系统集成的创建后检查清单
hook 完全创建并通过验证后:
[ ] Does hook need a skill wrapper? -> Use skill-creator
[ ] Does hook need dedicated agent? -> Use agent-creator
[ ] Does hook need testing workflow? -> Create workflow
[ ] Should hook be enabled by default? -> Update config.yaml
[ ] Does hook interact with other hooks? -> Document in README.md
[ ] Run post-creation validation -> node .claude/tools/cli/validate-integration.cjs .claude/hooks/<category>/<hook-name>.cjs
Hook 创建的铁律
这些规则绝不可违反。违反会导致静默故障。
1. NO HOOK WITHOUT validate() EXPORT
- Every hook MUST export validate() function
- Hooks without validate() cannot be called programmatically
2. NO HOOK WITHOUT main() FOR CLI
- Every hook MUST have main() for CLI execution
- Run only when require.main === module
3. NO HOOK WITHOUT ENFORCEMENT CONTROLS
- Support 'block|warn|off' via environment variable
- Default to 'warn' unless explicitly required to block
- Never crash on malformed input
4. NO HOOK WITHOUT ERROR HANDLING
- Wrap JSON.parse in try/catch
- Handle missing parameters gracefully
- Return valid: true when unsure (fail open, not closed)
5. NO HOOK WITHOUT TEST FILE
- Every hook needs <hook-name>.test.cjs
- Test valid, invalid, and edge cases
6. NO HOOK WITHOUT DOCUMENTATION
- Add to .claude/hooks/README.md
- Document trigger, behavior, exit codes
7. CROSS-PLATFORM PATHS
- Use path.join() not string concatenation
- Handle both / and \ path separators
- Use path.normalize() for comparison
8. NO CREATION WITHOUT SYSTEM IMPACT ANALYSIS
- Check if hook requires settings.json registration
- Check if hook requires config.yaml registration
- Update @HOOK_AGENT_MAP.md with new hook row (MANDATORY)
- Update affected agents' Enforcement Hooks sections (MANDATORY)
- Check if related hooks need updating
- Document all system changes made
9. IRON LAW I: PRE-TOOL HOOKS MUST VALIDATE AGAINST JSON SCHEMA
- PreToolUse hooks MUST compile and validate input against the companion
schemas/input.schema.json using AJV or equivalent before allowing execution
- Pattern: compile(schema) → validate(input) → exit 2 on schema failure
- Never block (exit 2) on schema-load errors — fail open, not closed
- Search: site:github.com "preToolUse" "ajv" "validate" filetype:cjs
10. IRON LAW III: POST-TOOL HOOKS MUST EMIT OBSERVABILITY EVENTS
- PostToolUse hooks MUST append a structured JSON line to
.claude/context/runtime/tool-events.jsonl via the centralized emitter:
const { sendEvent } = require('.claude/tools/observability/send-event.cjs')
- Required fields: tool_name, agent_id, session_id, outcome, timestamp
- Never crash on emit failure (try/catch, fail open)
- Inspect events: node .claude/tools/observability/send-event.cjs --tail 20
集成点
- 生态系统评估器:Hook 创建器集成生态系统评估,以进行反向查找
- Agent 创建器:Agent 可在其 frontmatter 中引用 hooks
- 技能创建器:技能可在其 hooks/ 目录中定义 hooks
- Settings.json:Hooks 会根据相应的触发器和匹配器自动注册
- Config.yaml:为 UserPromptSubmit、SessionStart 等事件注册 hooks
架构合规性
文件放置(ADR-076)
- Hooks:
.claude/hooks/{category}/(safety、routing、memory、session、validation、audit) - Hook 测试:
.claude/hooks/{category}/{name}.test.cjs(与 hooks 放在同一目录) - 测试:
tests/(hooks 的集成测试) - 相关文档:
.claude/docs/ - Hook 注册表:
.claude/hooks/README.md
文档引用(CLAUDE.md v3.1.0)
- 引用文件使用 @notation:@ENFORCEMENT_HOOKS.md、@TOOL_REFERENCE.md
- 位置:
.claude/docs/@*.md - 参见:CLAUDE.md 第 1.3 节(ENFORCEMENT HOOKS 引用)
Shell 安全性(ADR-077)
- 新增安全钩子: bash-cwd-validator.cjs、shell-injection-validator.cjs、variable-quoting-validator.cjs(ADR-077 第 2 阶段)
- 第 3 阶段钩子: shellcheck-validator.cjs、command-allowlist-validator.cjs(参考实现)
- 钩子测试必须验证 Shell 安全模式
- 参见:.claude/docs/SHELL-SECURITY-GUIDE.md
- 适用于:所有安全钩子、工具调用前钩子、验证钩子
近期 ADR
- 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:负责用户/操作员命令体验
创建者间握手(必需)
完成之前,验证所有相关握手:
- 制品路由已存在于
.claude/CLAUDE.md和相关路由文档中。 - 发现/注册表条目已更新(视情况更新目录/索引/注册表)。
- 已创建配套制品,或明确说明豁免及其原因。
- 针对此制品运行
validate-integration.cjs并通过验证。 - 技能元数据发生变化时,重新生成技能索引。
研究门槛(Exa + arXiv——两者均为强制要求)
对于新模式、模板或工作流,必须进行研究:
- 使用 Exa 研究实现和生态系统模式:
mcp__Exa__web_search_exa({ query: '<topic> 2025 best practices' })mcp__Exa__get_code_context_exa({ query: '<topic> implementation examples' })
- 搜索 arXiv 上的学术研究(AI/ML、Agent、评估、编排、记忆/RAG、安全性相关内容必须进行):
- 通过 Exa:
mcp__Exa__web_search_exa({ query: 'site:arxiv.org <topic> 2024 2025' }) - 直接调用 API:
WebFetch({ url: 'https://arxiv.org/search/?query=<topic>&searchtype=all&start=0' })
- 通过 Exa:
- 在制品参考资料/文档中记录决策、约束和非目标。
- 尽量减少更新,避免过度设计。
主题涉及以下内容时,arXiv 搜索为强制要求(不可作为备选): AI Agent、大模型评估、编排、记忆/RAG、安全性、静态分析或任何新兴方法论。
确保交付不引入回归
- 行为变更严格遵循 RED -> GREEN -> REFACTOR。
- 对已更改的模块运行针对性测试。
- 对已更改的文件运行 lint/format。
- 按关注点划分提交(逻辑/文档/生成的工件)。
可选:评估质量门禁
运行共享评估框架,验证钩子质量:
node .claude/skills/skill-creator/scripts/eval-runner.cjs --skill hook-creator
钩子工件的评分器断言:
- 退出码正确:钩子仅以
0(允许)或2(阻止)退出;绝不使用退出码1(根据 SE-03,该退出码会被视为错误,而非阻止) - 100ms 性能预算:钩子主体在 100ms 内完成;热路径中不得进行网络调用、阻塞式 I/O 或耗时计算
- 故障开放与故障关闭策略:安全钩子(routing、creator、write)采用故障关闭策略(出错时执行
process.exit(2));建议性钩子和 PostToolUse 钩子采用故障开放策略(出错时执行process.exit(0)) - 错误处理完善:钩子主体由
try/catch包裹;意外错误以0(非关键)或2(安全关键)退出——绝不在没有退出码的情况下崩溃 - 注册完整:钩子已在
.claude/settings.json中注册,并在@ENFORCEMENT_HOOKS.md中记录
完整评估流程以及评分器/分析器 Agent 的使用方法,请参阅 .claude/skills/skill-creator/EVAL_WORKFLOW.md。