mcpField
H
hook-creator

hook-creator

github.com/oimiragieoAgent 工作流4464 次安装17 周前更新
代码仓库

关于 hook-creator

hook-creator 是用于 Claude Code 多 Agent 编排框架的技能,帮助创建、验证和登记 Hook。它覆盖安全、记忆、路由与会话生命周期等用途,并要求配套测试及文档和系统注册。

主要功能

  1. 01创建安全、记忆、路由和会话 Hook
  2. 02按触发类型选择 Hook 位置
  3. 03为每个 Hook 编写测试
  4. 04登记 Hook 并更新文档

适用场景

  1. 01在命令执行前验证或拦截操作
  2. 02在任务完成后记录信息或更新记忆
  3. 03在提示提交或会话启停时执行逻辑

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/oimiragieo/agent-studio --skill hook-creator

安装后在 Claude Code 中输入/hook-creator确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

commands/
hook-creator.md
hooks/
post-execute.cjs
pre-execute.cjs
references/
research-requirements.md
rules/
hook-creator.md
schemas/
input.schema.json
output.schema.json
scripts/
main.cjs
templates/
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:检查是否已存在并委派更新器(必须——第一步)

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

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

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

    • 不要继续创建

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

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

  3. 如果钩子是新的:

    • 继续执行下面的步骤 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:配套项检查

在继续创建之前,运行生态系统配套项检查:

  1. 使用 .claude/lib/creators/companion-check.cjs 中的 companion-check.cjs
  2. 调用 checkCompanions("hook", "{hook-name}"),识别配套产物
  3. 查看配套项清单,记录缺少哪些必需/推荐的配套项
  4. 计划在此产物完成后创建或核验缺少的配套项
  5. 在创建后的集成说明中包含配套项检查结果

此步骤仅供参考(不会阻止创建),但可确保充分考虑完整的产物生态系统。


参考 Hook

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

定稿任何 Hook 之前,请对照路由表结构进行检查:

  • 具有正确的 CommonJS 导出(module.exports)
  • 导出 Hook 类型所需的函数(validate、main 等)
  • 具有完整的测试文件(.test.cjs)
  • 具有适当的错误处理(try/catch、优雅的回退机制)
  • 返回符合 Hook 类型要求的响应格式
步骤 1:收集 Hook 需求

创建 Hook 之前,请收集以下信息:

  1. 用途:此 Hook 应执行什么操作?
  2. 触发条件:何时运行?(工具调用前、工具调用后、会话事件)
  3. 目标工具:适用于哪些工具?(Bash、Write、Edit、Read)
  4. 行为:阻止操作还是仅发出警告?
  5. 退出代码:哪些代码表示成功/失败?
// 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.cjs
  • enforce-tdd-workflow.cjs
  • extract-workflow-learnings.cjs
  • memory-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 后:

  1. 设置注册(阻断性)

    • 将其添加到 .claude/settings.json 的 PreToolUse/PostToolUse 等配置中。
    • 使用以下命令验证:grep "hook-name" .claude/settings.json
  2. 测试覆盖(阻断性)

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

    • 如果 Hook 增添了新功能,请更新 .claude/docs/。
    • 添加用法示例
  4. 相关 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 步:创建后钩子注册(第一阶段集成)

此步骤至关重要。 创建钩子产物后,必须将其注册到钩子发现系统中。

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

写入并测试钩子文件后:

  1. 创建/更新钩子注册表条目,放在相应位置:

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

    确保钩子符合 .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()');
    "
    
  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}', // Optional
        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} (`{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}
    
  6. 更新记忆:

    追加到 .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" }) 前,必须运行创建后验证工作流:

  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 事件表明,如果遗漏集成步骤,即使产物已完全实现,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适用时机
领域知识需要可复用的技能skillSkill({ skill: 'skill-creator' })缺口涵盖完整的技能领域
现有技能的覆盖范围不完整skill 更新Skill({ skill: 'skill-updater' })存在相近技能,但覆盖不完整
某项能力需要专属 AgentagentSkill({ skill: 'agent-creator' })需要由 Agent 负责该能力
现有 Agent 需要更新能力agent 更新Skill({ skill: 'agent-updater' })存在相近 Agent,但覆盖不完整
领域需要代码/项目脚手架templateSkill({ skill: 'template-creator' })需要可复用的代码模式
行为需要执行前/后防护措施hookSkill({ skill: 'hook-creator' })需要强制执行行为
流程需要多阶段编排workflowSkill({ skill: 'workflow-creator' })需要多步骤协调
工件需要结构化 I/O 验证schemaSkill({ skill: 'schema-creator' })需要用于工件 I/O 的 JSON schema
用户交互需要斜杠命令commandSkill({ skill: 'command-creator' })需要面向用户的快捷方式
重复逻辑需要可复用的 CLI 工具toolSkill({ 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:负责用户/操作员命令体验
创建者间握手(必需)

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

  1. 制品路由已存在于 .claude/CLAUDE.md 和相关路由文档中。
  2. 发现/注册表条目已更新(视情况更新目录/索引/注册表)。
  3. 已创建配套制品,或明确说明豁免及其原因。
  4. 针对此制品运行 validate-integration.cjs 并通过验证。
  5. 技能元数据发生变化时,重新生成技能索引。
研究门槛(Exa + arXiv——两者均为强制要求)

对于新模式、模板或工作流,必须进行研究:

  1. 使用 Exa 研究实现和生态系统模式:
    • mcp__Exa__web_search_exa({ query: '<topic> 2025 best practices' })
    • mcp__Exa__get_code_context_exa({ query: '<topic> implementation examples' })
  2. 搜索 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' })
  3. 在制品参考资料/文档中记录决策、约束和非目标。
  4. 尽量减少更新,避免过度设计。

主题涉及以下内容时,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。

评论

支持 Markdown