hook-skill

from maxoreric/sop-engine

No description

0 stars0 forksUpdated Jan 20, 2026
npx skills add https://github.com/maxoreric/sop-engine --skill hook-skill

SKILL.md

Hook 开发

创建和配置 Claude Code Hooks,用于在特定事件时执行自定义逻辑。

Hook 基础

什么是 Hook?

Hook 是在 Claude Code 执行过程中特定时机自动触发的脚本或命令。可以用于:

  • 验证和拦截工具调用
  • 自动批准特定操作
  • 添加上下文信息
  • 实现循环执行
  • 通知和日志记录

10 种 Hook 事件

事件触发时机常见用途
PreToolUse工具执行前验证、拦截、修改输入
PostToolUse工具执行后验证结果、触发后续
PermissionRequest权限对话框显示时自动批准/拒绝
UserPromptSubmit用户提交 prompt 时添加上下文、验证
StopClaude 完成响应时实现循环、强制继续
SubagentStopSubagent 完成时链式触发、验证完成
PreCompact压缩操作前保存状态
SessionStart会话开始时加载上下文、初始化
SessionEnd会话结束时清理、保存状态
Notification通知时自定义通知

Exit Code 含义

Exit Code含义效果
0成功继续执行,stdout 可返回 JSON
2阻止阻止操作,stderr 反馈给 Claude
其他非阻止错误显示警告,继续执行

配置结构

hooks.json 格式

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here",
            "timeout": 60
          }
        ]
      }
    ]
  }
}

字段说明

  • matcher:工具名匹配模式(仅 PreToolUse、PostToolUse、PermissionRequest)
    • 精确匹配:Write
    • 正则匹配:Edit|WriteNotebook.*
    • 匹配所有:* 或省略
  • typecommand(bash 命令)或 prompt(LLM 评估)
  • command:要执行的命令
  • timeout:超时时间(秒),默认 60

环境变量

  • $CLAUDE_PROJECT_DIR:项目根目录
  • $CLAUDE_PLUGIN_ROOT:插件根目录(插件 Hook 专用)
  • $CLAUDE_ENV_FILE:环境变量文件(仅 SessionStart)

Hook 输入(stdin JSON)

通用字段

{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.jsonl",
  "cwd": "/current/directory",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse"
}

PreToolUse 输入

{
  "hook_event_name": "PreToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_use_id": "toolu_01ABC123..."
}

Stop 输入

{
  "hook_event_name": "Stop",
  "stop_hook_active": true  // 是否已被 Stop hook 继续过
}

UserPromptSubmit 输入

{
  "hook_event_name": "UserPromptSubmit",
  "prompt": "用户的 prompt 内容"
}

SessionStart 输入

{
  "hook_event_name": "SessionStart",
  "source": "startup"  // startup | resume | clear | compact
}

Hook 输出(JSON)

PreToolUse 控制

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",  // allow | deny | ask
    "permissionDecisionReason": "原因",
    "updatedInput": { }  // 可选:修改输入
  }
}

Stop 控制

{
  "decision": "block",  // block = 阻止停止,继续执行
  "reason": "告诉 Claude 为什么要继续"
}

UserPromptSubmit 控制

{
  "decision": "block",  // 可选:阻止 prompt
  "reason": "阻止原因",
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "添加的上下文"
  }
}

SessionStart 控制

{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "启动时添加的上下文"
  }
}

常用模式

1. 实现循环执行(Stop Hook)

#!/bin/bash
# stop-loop.sh - 阻止停止,让 Claude 继续

HOOK_INPUT=$(cat)
STOP_ACTIVE=$(echo "$HOOK_INPUT" | jq -r '.stop_hook_active // false')

# 检查状态文件
if [ -f ".loop-status.json" ]; then
    CURRENT=$(jq -r '.current // 0' .loop-status.json)
    MAX=$(jq -r '.max // 5' .loop-status.json)
    
    if [ "$CURRENT" -lt "$MAX" ]; then
        # 更新计数
        jq ".current = $((CURRENT + 1))" .loop-status.json > .tmp && mv .tmp .loop-status.json
        # 阻止停止
        echo "继续执行 ($((CURRENT + 1))/$MAX)" >&2
        exit 2
    fi
fi

exit 0

2. 自动批准文档文件读取

#!/usr/bin/env python3
import json
import sys

input_data = json.load(sys.stdin)
tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})

if tool_name == "Read":
    file_path = tool_input.get("file_path", "")
    if file_path.endswith((".md", ".txt", ".json")):
        output = {
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "allow",
                "permissionDecisionReason": "文档文件自动批准"
            }
        }
        print(json.dumps(output))
        sys.exit(0)

sys.exit(0)

3. 添加时间上下文(SessionStart)

#!/bin/bash
# session-start.sh

echo "当前时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "项目目录: $CLAUDE_PROJECT_DIR"

# 如果有 CLAUDE_ENV_FILE,设置环境变量
if [ -n "$CLAUDE_ENV_FILE" ]; then
    echo "export PROJECT_START_TIME=$(date +%s)" >> "$CLAUDE_ENV_FILE"
fi

exit 0

4. 验证 Bash 命令(PreToolUse)

#!/usr/bin/env python3
import json
import sys
import re

input_data = json.load(sys.stdin)
tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})

if tool_name != "Bash":
    sys.exit(0)

command = tool_input.get("command", "")

# 危险命令检查
dangerous_patterns = [
    (r"\brm\s+-rf\s+/", "禁止删除根目录"),
    (r"\bsudo\b", "禁止使用 sudo"),
]

for pattern, message in dangerous_patterns:
    if re.search(pattern, comman

...
Read full content

Repository Stats

Stars0
Forks0