钩子创建器Skill hook-creator

钩子创建器技能用于为Claude Code框架创建和注册钩子(hooks),支持多代理编排,包括工具执行前后的验证、内存管理、会话生命周期和路由执行。它自动化钩子创建流程,确保安全合规性,适用于软件开发中的自动化、验证和安全场景。关键词:钩子创建、验证、安全、自动化、多代理编排、Claude Code、软件开发工具。

DevOps 0 次安装 0 次浏览 更新于 3/10/2026

名称: 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: 存在性检查和更新器委托(强制 - 第一步)

在创建任何钩子文件之前,检查是否已存在:

  1. 检查钩子是否已存在:

    test -f .claude/hooks/<category>/<hook-name>.cjs && echo "存在" || echo "新建"
    
  2. 如果钩子存在:

    • 不要继续创建

    • 改为调用artifact-updater工作流:

      Skill({
        skill: 'artifact-updater',
        args: '--type hook --path .claude/hooks/<category>/<hook-name>.cjs --changes "<请求更改的描述>"',
      });
      
    • 返回更新器结果并停止

  3. 如果钩子是新建:

    • 继续步骤0.5

步骤0.5: 伴随检查

在继续创建之前,运行生态系统伴随检查:

  1. 使用 .claude/lib/creators/companion-check.cjs 中的 companion-check.cjs
  2. 调用 checkCompanions("hook", "{hook-name}") 以识别伴随工件
  3. 查看伴随清单 — 注意缺少哪些必需/推荐的伴随
  4. 计划在此工件完成后创建或验证缺少的伴随
  5. 在创建后集成笔记中包含伴随发现

此步骤是信息性的(不阻止创建),但确保考虑完整的工件生态系统。


参考钩子

使用 .claude/lib/routing/routing-table.cjs 作为规范路由参考。

在最终确定任何钩子之前,与路由表结构比较:

  • [ ] 具有正确的CommonJS导出(module.exports)
  • [ ] 导出钩子类型所需的函数(validate、main等)
  • [ ] 具有全面的测试文件(.test.cjs)
  • [ ] 具有正确的错误处理(try/catch、优雅回退)
  • [ ] 返回钩子类型的正确响应格式

步骤1: 收集钩子需求

创建钩子之前,收集:

  1. 目的: 此钩子应做什么?
  2. 触发器: 应在何时运行?(工具前、工具后、会话事件)
  3. 目标工具: 适用于哪些工具?(Bash、Write、Edit、Read)
  4. 行为: 阻止操作或仅警告?
  5. 退出码: 指示成功/失败的是什么?
// 需求收集示例
{
  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.cjs
  • enforce-tdd-workflow.cjs
  • extract-workflow-learnings.cjs
  • memory-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: 系统影响分析(强制)

此分析是强制的。没有它,钩子创建不完整。

创建钩子后:

  1. 设置注册(阻止)

    • 添加到.claude/settings.json中的PreToolUse/PostToolUse等。
    • 验证:grep "hook-name" .claude/settings.json
  2. 测试覆盖(阻止)

    • 创建.test.cjs文件,最少10个测试用例
    • 运行测试:node .claude/hooks/<category>/<name>.test.cjs
  3. 文档

    • 如果钩子添加新功能,更新.claude/docs/
    • 添加使用示例
  4. 相关钩子

    • 检查钩子是否影响同一触发类别中的其他钩子
    • 记录交互模式

完整清单:

[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: 创建后钩子注册(第一阶段集成)

**此步骤是关键。**创建钩子工件后,必须在钩子发现系统中注册它。

第一阶段上下文: 第一阶段负责工具和钩子验证/发现。未注册的钩子对系统不可见,启动时不会加载。

钩子文件写入和测试后:

  1. 在适当位置创建/更新钩子注册条目:

    如果注册表不存在,创建 .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"
        }
      ]
    }
    
  2. 根据架构验证钩子:

    确保钩子根据 .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()');
    "
    
  3. 在加载器中注册钩子:

    更新 .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'
      }
    };
    
  4. 在配置中注册钩子:

    用于工具前/后钩子 - 更新 .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
    
  5. .claude/hooks/README.md 中记录:

    在适当类别下添加条目:

    #### {钩子名称} (`{hook-name}.cjs`)
    
    {钩子做什么的详细描述。}
    
    **运行时机:** {触发条件 - 例如,“在每次Bash命令前”、“任务完成后”}
    
    **检查/做什么:**
    
    - {检查/动作1}
    - {检查/动作2}
    - {检查/动作3}
    
    **执行模式:** `process.env.{HOOK_NAME}_MODE` (默认: `warn`)
    
    **测试文件:** `.claude/hooks/{category}/{hook-name}.test.cjs`
    
    **相关钩子:** {列出与此交互的任何钩子}
    
  6. 更新内存:

    追加到 .claude/context/memory/learnings.md

    ## 钩子: {hook-name}
    
    - **类型:** {pre-tool|post-tool|event}
    - **类别:** {safety|routing|memory|session|validation}
    - **目的:** {详细目的}
    - **触发器:** {运行时机}
    - **执行:** {默认阻止/警告/关闭}
    - **集成笔记:** {任何特殊考虑}
    

为什么重要: 没有钩子注册:

  • 启动时钩子未加载
  • 钩子验证不发生
  • 系统无法发现可用钩子
  • 安全验证器被绕过
  • 出现“不可见工件”模式

第一阶段集成: 钩子注册表是第一阶段的发现机制,使系统能够根据架构验证钩子、启动时加载它们,并一致地执行安全规则。

步骤9: 集成验证(阻止 - 不要跳过)

此步骤验证工件是否正确集成到生态系统中。

在调用 TaskUpdate({ status: "completed" }) 之前,必须运行创建后验证工作流:

  1. 运行10项集成清单:

    node .claude/tools/cli/validate-integration.cjs .claude/hooks/<category>/<hook-name>.cjs
    
  2. 验证退出码为0(所有检查通过)

  3. 如果退出码为1(一个或多个检查失败):

    • 阅读错误输出以了解具体失败
    • 修复每个失败:
      • 缺少钩子注册 -> 创建注册条目(步骤8)
      • 缺少settings.json条目 -> 注册钩子(步骤8)
      • 缺少文档 -> 添加到hooks/README.md
      • 缺少内存更新 -> 更新learnings.md
      • 缺少测试文件 -> 创建.test.cjs文件
    • 重新运行验证,直到退出码为0
  4. 仅当验证通过时继续

此步骤是阻止的。 在验证通过之前,不要标记任务完成。

为什么重要: 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-creatorsemgrep-rule-creator 用于策略和静态检查
  • template-creator 用于标准化脚手架
  • workflow-creator 用于编排和阶段门控
  • command-creator 用于用户/操作员命令UX

跨创建者握手(必需)

完成前,验证所有相关握手:

  1. 工件路由存在于 .claude/CLAUDE.md 和相关路由文档中。
  2. 发现/注册条目已更新(目录/索引/注册表,如适用)。
  3. 伴随工件已创建或明确豁免并注明原因。
  4. validate-integration.cjs 为创建的工件通过。
  5. 技能元数据更改时,技能索引重新生成。

研究门(Exa优先,arXiv后备)

对于新模式、模板或工作流,研究是强制性的:

  1. 首先使用Exa进行实现和生态系统模式研究。
  2. 如果Exa不足,使用 WebFetch 加arXiv参考。
  3. 在工件参考/文档中记录决策、约束和非目标。
  4. 保持更新最小化,避免过度工程。

回归安全交付

  • 遵循严格的RED -> GREEN -> REFACTOR进行行为更改。
  • 对更改的模块运行针对性测试。
  • 对更改的文件运行lint/format。
  • 保持提交按关注点范围化(逻辑/文档/生成的工件)。