mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
feat: update usage recommendations across multiple workflow commands to require user confirmation and improve clarity
This commit is contained in:
@@ -837,15 +837,28 @@ Selected items call: `/issue:new "{issue summary} - {dimension}"`
|
||||
|
||||
---
|
||||
|
||||
## Usage Recommendations
|
||||
## Usage Recommendations (Requires User Confirmation)
|
||||
|
||||
1. **First Time**: Use default mode (debug-first), observe workflow
|
||||
2. **Quick Decision**: Use CLI Quick (--mode cli) for immediate recommendations
|
||||
3. **Quick Fix**: Use `--hotfix --yes` for minimal diagnostics (debug mode)
|
||||
4. **Learning**: Use debug-first, read `understanding.md`
|
||||
5. **Complete Validation**: Use bidirectional for multi-dimensional insights
|
||||
6. **Auto Repair**: Use test-first for automatic iteration
|
||||
7. **Escalation**: Start with CLI Quick, escalate to other modes as needed
|
||||
**Use `Skill(skill="ccw-debug", args="\"bug description\"")` when:**
|
||||
- First time: Use default mode (debug-first), observe workflow
|
||||
|
||||
**Use `Skill(skill="ccw-debug", args="--mode cli \"issue\"")` when:**
|
||||
- Quick Decision: Immediate recommendations without full workflow
|
||||
|
||||
**Use `Skill(skill="ccw-debug", args="--hotfix --yes \"issue\"")` when:**
|
||||
- Quick Fix: Minimal diagnostics for production issues
|
||||
|
||||
**Use `Skill(skill="ccw-debug", args="--mode debug \"issue\"")` when:**
|
||||
- Learning: Read `understanding.md` for debugging insights
|
||||
|
||||
**Use `Skill(skill="ccw-debug", args="--mode bidirectional \"issue\"")` when:**
|
||||
- Complete Validation: Multi-dimensional insights from parallel workflows
|
||||
|
||||
**Use `Skill(skill="ccw-debug", args="--mode test \"issue\"")` when:**
|
||||
- Auto Repair: Automatic iteration with test-first approach
|
||||
|
||||
**Use `Skill(skill="ccw-debug", args="--mode cli \"issue\"")` when:**
|
||||
- Escalation: Start with CLI Quick, then escalate to other modes as needed
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -515,29 +515,35 @@ User agrees with current direction, wants deeper code analysis
|
||||
- Current design allows horizontal scaling without session affinity
|
||||
```
|
||||
|
||||
## Usage Recommendations
|
||||
## Usage Recommendations (Requires User Confirmation)
|
||||
|
||||
**Use `/workflow:analyze-with-file` when:**
|
||||
**Use `Skill(skill="workflow:analyze-with-file", args="\"topic\"")` when:**
|
||||
- Exploring a complex topic collaboratively
|
||||
- Need documented discussion trail
|
||||
- Decision-making requires multiple perspectives
|
||||
- Want to iterate on understanding with user input
|
||||
- Building shared understanding before implementation
|
||||
|
||||
**Use `/workflow:debug-with-file` when:**
|
||||
**Use `Skill(skill="workflow:debug-with-file", args="\"bug description\"")` when:**
|
||||
- Diagnosing specific bugs
|
||||
- Need hypothesis-driven investigation
|
||||
- Focus on evidence and verification
|
||||
|
||||
**Use `/workflow:brainstorm-with-file` when:**
|
||||
**Use `Skill(skill="workflow:brainstorm-with-file", args="\"topic or question\"")` when:**
|
||||
- Generating new ideas or solutions
|
||||
- Need creative exploration
|
||||
- Want divergent thinking before convergence
|
||||
|
||||
**Use `/workflow:lite-plan` when:**
|
||||
**Use `Skill(skill="workflow:collaborative-plan-with-file", args="\"task description\"")` when:**
|
||||
- Complex planning requiring multiple perspectives
|
||||
- Large scope needing parallel sub-domain analysis
|
||||
- Want shared collaborative planning document
|
||||
- Need structured task breakdown with agent coordination
|
||||
|
||||
**Use `Skill(skill="workflow:lite-plan", args="\"task description\"")` when:**
|
||||
- Ready to implement (past analysis phase)
|
||||
- Need structured task breakdown
|
||||
- Focus on execution planning
|
||||
- Need simple task breakdown
|
||||
- Focus on quick execution planning
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -745,25 +745,31 @@ Dimensions matched against topic keywords to identify focus areas:
|
||||
|
||||
See full markdown template in original file (lines 955-1161).
|
||||
|
||||
## Usage Recommendations
|
||||
## Usage Recommendations (Requires User Confirmation)
|
||||
|
||||
**Use `/workflow:brainstorm-with-file` when:**
|
||||
**Use `Skill(skill="workflow:brainstorm-with-file", args="\"topic or question\"")` when:**
|
||||
- Starting a new feature/product without clear direction
|
||||
- Facing a complex problem with multiple possible solutions
|
||||
- Need to explore alternatives before committing
|
||||
- Want documented thinking process for team review
|
||||
- Combining multiple stakeholder perspectives
|
||||
|
||||
**Use `/workflow:analyze-with-file` when:**
|
||||
**Use `Skill(skill="workflow:analyze-with-file", args="\"topic\"")` when:**
|
||||
- Investigating existing code/system
|
||||
- Need factual analysis over ideation
|
||||
- Debugging or troubleshooting
|
||||
- Understanding current state
|
||||
|
||||
**Use `/workflow:plan` when:**
|
||||
**Use `Skill(skill="workflow:collaborative-plan-with-file", args="\"task description\"")` when:**
|
||||
- Complex planning requiring multiple perspectives
|
||||
- Large scope needing parallel sub-domain analysis
|
||||
- Want shared collaborative planning document
|
||||
- Need structured task breakdown with agent coordination
|
||||
|
||||
**Use `Skill(skill="workflow:lite-plan", args="\"task description\"")` when:**
|
||||
- Direction is already clear
|
||||
- Ready to move from ideas to execution
|
||||
- Need implementation breakdown
|
||||
- Need simple implementation breakdown
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -658,15 +658,15 @@ Why is config value None during update?
|
||||
| Hypothesis history | ❌ | ✅ hypotheses.json |
|
||||
| Gemini validation | ❌ | ✅ At key decision points |
|
||||
|
||||
## Usage Recommendations
|
||||
## Usage Recommendations (Requires User Confirmation)
|
||||
|
||||
Use `/workflow:debug-with-file` when:
|
||||
**Use `Skill(skill="workflow:debug-with-file", args="\"bug description\"")` when:**
|
||||
- Complex bugs requiring multiple investigation rounds
|
||||
- Learning from debugging process is valuable
|
||||
- Team needs to understand debugging rationale
|
||||
- Bug might recur, documentation helps prevention
|
||||
|
||||
Use `/workflow:debug` when:
|
||||
**Use `Skill(skill="ccw-debug", args="--mode cli \"issue\"")` when:**
|
||||
- Simple, quick bugs
|
||||
- One-off issues
|
||||
- Documentation overhead not needed
|
||||
|
||||
453
.claude/docs/HOOKS_ANALYSIS_REPORT.md
Normal file
453
.claude/docs/HOOKS_ANALYSIS_REPORT.md
Normal file
@@ -0,0 +1,453 @@
|
||||
# Claude Code Hooks - 当前实现 vs 官方标准对比报告
|
||||
|
||||
## 执行摘要
|
||||
|
||||
当前 CCW 代码库中的钩子实现**不符合 Claude Code 官方标准**。存在以下主要问题:
|
||||
|
||||
1. ❌ **钩子事件名称不符合官方标准** - 使用了错误的事件名称
|
||||
2. ❌ **配置结构不同** - 自定义了配置格式,不符合官方规范
|
||||
3. ❌ **使用了不存在的事件类型** - 某些事件在官方钩子系统中不存在
|
||||
4. ❌ **文档与实现不一致** - 代码中的注释引用的是自定义实现,而非官方标准
|
||||
|
||||
---
|
||||
|
||||
## 详细对比
|
||||
|
||||
### 1. 钩子事件名称对比
|
||||
|
||||
#### ❌ 当前实现(错误)
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"session-start": [], // ❌ 错误:应为 SessionStart
|
||||
"session-end": [], // ❌ 错误:应为 SessionEnd
|
||||
"file-modified": [], // ❌ 错误:官方不支持此事件
|
||||
"context-request": [], // ❌ 错误:官方不支持此事件
|
||||
"PostToolUse": [] // ✅ 正确
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### ✅ 官方标准(正确)
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [], // ✅ 当会话开始或恢复时触发
|
||||
"UserPromptSubmit": [], // ✅ 当用户提交提示词时触发
|
||||
"PreToolUse": [], // ✅ 工具调用前触发,可以阻止
|
||||
"PermissionRequest": [], // ✅ 权限对话出现时触发
|
||||
"PostToolUse": [], // ✅ 工具调用成功后触发
|
||||
"PostToolUseFailure": [], // ✅ 工具调用失败时触发
|
||||
"Notification": [], // ✅ 通知发送时触发
|
||||
"SubagentStart": [], // ✅ 子代理生成时触发
|
||||
"SubagentStop": [], // ✅ 子代理完成时触发
|
||||
"Stop": [], // ✅ Claude 完成响应时触发
|
||||
"PreCompact": [], // ✅ 上下文压缩前触发
|
||||
"SessionEnd": [] // ✅ 会话终止时触发
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 配置结构对比
|
||||
|
||||
#### ❌ 当前实现(自定义结构)
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"session-start": [
|
||||
{
|
||||
"name": "Progressive Disclosure",
|
||||
"description": "Injects progressive disclosure index",
|
||||
"enabled": true,
|
||||
"handler": "internal:context",
|
||||
"timeout": 5000,
|
||||
"failMode": "silent"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hookSettings": {
|
||||
"globalTimeout": 60000,
|
||||
"defaultFailMode": "silent",
|
||||
"allowAsync": true,
|
||||
"enableLogging": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**问题:**
|
||||
- 使用了非标准字段:`name`, `description`, `enabled`, `handler`, `failMode`
|
||||
- 使用了自定义的 `hookSettings` 配置
|
||||
- 结构过度复杂化
|
||||
|
||||
#### ✅ 官方标准(简洁标准)
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "startup|resume|clear|compact",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash /path/to/script.sh",
|
||||
"timeout": 600,
|
||||
"async": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**优点:**
|
||||
- 简洁明了的三层结构:事件 → 匹配器 → 处理器
|
||||
- 标准的字段集:`type`, `command`, `timeout`, `async`
|
||||
- 支持三种处理器类型:`command`, `prompt`, `agent`
|
||||
|
||||
### 3. 官方支持的钩子事件及其触发时机
|
||||
|
||||
| 事件名称 | 触发时机 | 可阻止 | 匹配器支持 |
|
||||
|---------|---------|--------|-----------|
|
||||
| `SessionStart` | 会话开始或恢复 | ❌ | startup, resume, clear, compact |
|
||||
| `UserPromptSubmit` | 用户提交提示词前 | ✅ | ❌ |
|
||||
| `PreToolUse` | 工具调用前 | ✅ | 工具名称 |
|
||||
| `PermissionRequest` | 权限对话出现时 | ✅ | 工具名称 |
|
||||
| `PostToolUse` | 工具调用成功后 | ❌ | 工具名称 |
|
||||
| `PostToolUseFailure` | 工具调用失败时 | ❌ | 工具名称 |
|
||||
| `Notification` | 通知发送时 | ❌ | 通知类型 |
|
||||
| `SubagentStart` | 子代理生成时 | ❌ | 代理类型 |
|
||||
| `SubagentStop` | 子代理完成时 | ✅ | 代理类型 |
|
||||
| `Stop` | Claude 完成响应时 | ✅ | ❌ |
|
||||
| `PreCompact` | 上下文压缩前 | ❌ | manual, auto |
|
||||
| `SessionEnd` | 会话终止时 | ❌ | 终止原因 |
|
||||
|
||||
**当前实现不支持的事件:**
|
||||
- ❌ `file-modified` - 官方系统中不存在
|
||||
- ❌ `context-request` - 官方系统中不存在
|
||||
|
||||
### 4. 处理器类型对比
|
||||
|
||||
#### ❌ 当前实现
|
||||
|
||||
仅支持一种:`handler: "internal:context"`(自定义内部处理器)
|
||||
|
||||
#### ✅ 官方标准
|
||||
|
||||
支持三种标准类型:
|
||||
|
||||
1. **Command hooks** (`type: "command"`)
|
||||
```json
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash /path/to/script.sh",
|
||||
"timeout": 600,
|
||||
"async": false
|
||||
}
|
||||
```
|
||||
|
||||
2. **Prompt hooks** (`type: "prompt"`)
|
||||
```json
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Evaluate if this is safe to execute: $ARGUMENTS",
|
||||
"model": "haiku",
|
||||
"timeout": 30
|
||||
}
|
||||
```
|
||||
|
||||
3. **Agent hooks** (`type: "agent"`)
|
||||
```json
|
||||
{
|
||||
"type": "agent",
|
||||
"prompt": "Verify tests pass: $ARGUMENTS",
|
||||
"model": "haiku",
|
||||
"timeout": 60
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 匹配器对比
|
||||
|
||||
#### ❌ 当前实现
|
||||
|
||||
没有明确的匹配器概念,而是使用:
|
||||
- `handler: "internal:context"` - 内部处理
|
||||
- 没有工具级别的过滤
|
||||
|
||||
#### ✅ 官方标准
|
||||
|
||||
完整的匹配器系统:
|
||||
|
||||
```json
|
||||
{
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write", // 仅在 Edit 或 Write 工具时触发
|
||||
"hooks": [ ... ]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**支持的匹配器:**
|
||||
- **工具事件**:`Bash`, `Edit`, `Write`, `Read`, `Glob`, `Grep`, `Task`, `WebFetch`, `WebSearch`
|
||||
- **MCP工具**:`mcp__memory__.*`, `mcp__.*__write.*`
|
||||
- **会话事件**:`startup`, `resume`, `clear`, `compact`
|
||||
- **通知类型**:`permission_prompt`, `idle_prompt`, `auth_success`
|
||||
- **代理类型**:`Bash`, `Explore`, `Plan`
|
||||
|
||||
### 6. 输入/输出机制对比
|
||||
|
||||
#### ❌ 当前实现
|
||||
|
||||
- 未定义标准的 stdin/stdout 通信协议
|
||||
- 使用了自定义的环境变量:`$SESSION_ID`, `$FILE_PATH`, `$PROJECT_PATH`
|
||||
|
||||
#### ✅ 官方标准
|
||||
|
||||
**标准 JSON stdin 输入:**
|
||||
```json
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "/path/to/transcript.jsonl",
|
||||
"cwd": "/current/dir",
|
||||
"permission_mode": "default",
|
||||
"hook_event_name": "PreToolUse",
|
||||
"tool_name": "Bash",
|
||||
"tool_input": {
|
||||
"command": "npm test"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**标准 exit code 输出:**
|
||||
- **exit 0**: 成功,解析 stdout 的 JSON 决策
|
||||
- **exit 2**: 阻止性错误,stderr 成为 Claude 的反馈
|
||||
- **其他码**: 非阻止性错误,stderr 显示在详细模式
|
||||
|
||||
**标准 JSON stdout 输出:**
|
||||
```json
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "allow|deny|ask",
|
||||
"permissionDecisionReason": "explanation"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. 文件位置对比
|
||||
|
||||
#### 当前实现
|
||||
|
||||
示例配置文件位置:
|
||||
- `ccw/src/templates/hooks-config-example.json`
|
||||
|
||||
#### ✅ 官方标准
|
||||
|
||||
标准配置位置(优先级顺序):
|
||||
1. `~/.claude/settings.json` - 全局用户配置
|
||||
2. `.claude/settings.json` - 项目配置(可提交)
|
||||
3. `.claude/settings.local.json` - 项目本地配置(gitignored)
|
||||
4. 插件 `hooks/hooks.json` - 插件内部
|
||||
5. Skill/Agent frontmatter - 技能或代理
|
||||
|
||||
---
|
||||
|
||||
## 代码库中的具体问题位置
|
||||
|
||||
### 1. 错误的配置示例
|
||||
|
||||
**文件:** `ccw/src/templates/hooks-config-example.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"session-start": [ ... ], // ❌ 应为 SessionStart
|
||||
"session-end": [ ... ], // ❌ 应为 SessionEnd
|
||||
"file-modified": [ ... ], // ❌ 不存在的事件
|
||||
"context-request": [ ... ] // ❌ 不存在的事件
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**应改为:**
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "startup|resume",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "echo 'Session started'"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "prettier --write $FILE_PATH"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"SessionEnd": [
|
||||
{
|
||||
"matcher": "clear",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "echo 'Session ended'"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 错误的命令注释
|
||||
|
||||
**文件:** `ccw/src/commands/hook.ts`
|
||||
|
||||
当前代码引用了自定义的钩子处理逻辑,但不符合官方标准。
|
||||
|
||||
---
|
||||
|
||||
## 修复建议
|
||||
|
||||
### 优先级 1:关键修复
|
||||
|
||||
- [ ] 更新 `hooks-config-example.json` 使用官方事件名称
|
||||
- [ ] 更新配置结构以符合官方三层标准
|
||||
- [ ] 移除不支持的事件类型:`file-modified`, `context-request`
|
||||
- [ ] 文档化官方支持的事件列表
|
||||
|
||||
### 优先级 2:功能对齐
|
||||
|
||||
- [ ] 实现官方的标准 JSON stdin/stdout 通信
|
||||
- [ ] 实现标准的 exit code 处理
|
||||
- [ ] 支持标准的匹配器系统
|
||||
|
||||
### 优先级 3:增强
|
||||
|
||||
- [ ] 添加对 `prompt` 和 `agent` 处理器类型的支持
|
||||
- [ ] 实现标准的异步钩子支持(`async: true`)
|
||||
- [ ] 添加对环境变量持久化的支持(`CLAUDE_ENV_FILE`)
|
||||
|
||||
---
|
||||
|
||||
## 官方示例
|
||||
|
||||
### 例1:格式化代码后自动执行
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 例2:阻止编辑受保护文件
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 例3:会话开始时重新注入上下文
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "compact",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "echo 'Use Bun, not npm. Run bun test before committing.'"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 例4:基于条件的权限决策
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Is this a safe command to run? $ARGUMENTS"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 参考资源
|
||||
|
||||
- 官方指南:https://code.claude.com/docs/en/hooks-guide
|
||||
- 官方参考:https://code.claude.com/docs/en/hooks
|
||||
- 官方示例:https://github.com/anthropics/claude-code/tree/main/examples/hooks
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
当前 CCW 的钩子实现是基于自定义规范的,**完全不兼容** Claude Code 官方钩子系统。为了与官方标准对齐,需要进行彻底的重构,包括:
|
||||
|
||||
1. ✅ 采用官方的事件名称(已在 `.claude/docs/` 文件中提供)
|
||||
2. ✅ 采用官方的三层配置结构
|
||||
3. ✅ 实现官方的 JSON stdin/stdout 通信协议
|
||||
4. ✅ 移除不存在的自定义事件
|
||||
5. ✅ 支持官方的三种处理器类型
|
||||
|
||||
这样才能确保当用户将 CCW 的配置迁移到真实的 Claude Code CLI 时,能够正常工作。
|
||||
224
.claude/docs/HOOKS_DOCUMENTATION_INDEX.md
Normal file
224
.claude/docs/HOOKS_DOCUMENTATION_INDEX.md
Normal file
@@ -0,0 +1,224 @@
|
||||
# Claude Code Hooks - 文档索引
|
||||
|
||||
本目录包含 Claude Code 官方钩子系统的完整文档和分析报告。
|
||||
|
||||
---
|
||||
|
||||
## 📚 官方文档(已下载)
|
||||
|
||||
### 1. HOOKS_OFFICIAL_GUIDE.md
|
||||
- **来源**: https://code.claude.com/docs/en/hooks-guide
|
||||
- **内容**: 官方钩子指南,包含快速入门、常见用例、配置教程
|
||||
- **适用**: 初次使用钩子系统的开发者
|
||||
|
||||
### 2. HOOKS_OFFICIAL_REFERENCE.md
|
||||
- **来源**: https://code.claude.com/docs/en/hooks
|
||||
- **内容**: 完整的技术参考,包含所有事件的 schema、输入输出格式、配置选项
|
||||
- **适用**: 需要查阅具体事件参数和配置细节的开发者
|
||||
|
||||
### 3. HOOKS_QUICK_REFERENCE.md
|
||||
- **内容**: 快速查阅指南,包含所有事件列表、配置模板、常见用例
|
||||
- **适用**: 需要快速查找特定配置或事件信息的开发者
|
||||
|
||||
---
|
||||
|
||||
## 📊 分析报告
|
||||
|
||||
### 4. HOOKS_ANALYSIS_REPORT.md
|
||||
- **内容**: 当前 CCW 钩子实现 vs 官方标准对比分析
|
||||
- **包含**:
|
||||
- 当前实现存在的问题
|
||||
- 事件名称对比
|
||||
- 配置结构对比
|
||||
- 修复建议和优先级
|
||||
- **适用**: 需要了解当前实现与官方标准差异的开发者
|
||||
|
||||
---
|
||||
|
||||
## 💻 示例代码
|
||||
|
||||
### 5. ../examples/hooks_bash_command_validator.py
|
||||
- **来源**: https://github.com/anthropics/claude-code/blob/main/examples/hooks/bash_command_validator_example.py
|
||||
- **内容**: 官方示例 - Bash 命令验证器
|
||||
- **功能**: 拦截 Bash 命令,建议使用 ripgrep 替代 grep
|
||||
- **适用**: 学习如何编写 PreToolUse 钩子的开发者
|
||||
|
||||
---
|
||||
|
||||
## 🎯 官方钩子事件列表
|
||||
|
||||
### 官方支持的 12 个钩子事件
|
||||
|
||||
| # | 事件名称 | 触发时机 | 可阻止 |
|
||||
|---|---------|---------|--------|
|
||||
| 1 | `SessionStart` | 会话开始或恢复 | ❌ |
|
||||
| 2 | `UserPromptSubmit` | 用户提交提示词前 | ✅ |
|
||||
| 3 | `PreToolUse` | 工具调用前 | ✅ |
|
||||
| 4 | `PermissionRequest` | 权限对话出现时 | ✅ |
|
||||
| 5 | `PostToolUse` | 工具调用成功后 | ❌ |
|
||||
| 6 | `PostToolUseFailure` | 工具调用失败后 | ❌ |
|
||||
| 7 | `Notification` | 通知发送时 | ❌ |
|
||||
| 8 | `SubagentStart` | 子代理生成时 | ❌ |
|
||||
| 9 | `SubagentStop` | 子代理完成时 | ✅ |
|
||||
| 10 | `Stop` | Claude完成响应时 | ✅ |
|
||||
| 11 | `PreCompact` | 上下文压缩前 | ❌ |
|
||||
| 12 | `SessionEnd` | 会话终止时 | ❌ |
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 当前实现的主要问题
|
||||
|
||||
### 问题 1: 事件名称不符合官方标准
|
||||
|
||||
❌ **当前使用(错误):**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"session-start": [], // 错误
|
||||
"session-end": [], // 错误
|
||||
"file-modified": [], // 不存在
|
||||
"context-request": [] // 不存在
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
✅ **官方标准(正确):**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [], // 正确
|
||||
"SessionEnd": [], // 正确
|
||||
"PostToolUse": [], // 使用其他官方事件
|
||||
"PreToolUse": [] // 替代自定义事件
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 问题 2: 配置结构不符合官方标准
|
||||
|
||||
❌ **当前结构(自定义):**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"session-start": [
|
||||
{
|
||||
"name": "...",
|
||||
"enabled": true,
|
||||
"handler": "internal:context",
|
||||
"failMode": "silent"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
✅ **官方结构(标准):**
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "startup|resume",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash script.sh",
|
||||
"timeout": 600
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔗 外部资源
|
||||
|
||||
### 官方资源
|
||||
- **官方指南**: https://code.claude.com/docs/en/hooks-guide
|
||||
- **官方参考**: https://code.claude.com/docs/en/hooks
|
||||
- **GitHub 示例**: https://github.com/anthropics/claude-code/tree/main/examples/hooks
|
||||
- **配置博客**: https://claude.com/blog/how-to-configure-hooks
|
||||
|
||||
### 社区资源
|
||||
- [Claude Code Hooks 从入门到实战 - 知乎](https://zhuanlan.zhihu.com/p/1969164730326324920)
|
||||
- [GitHub: claude-code-best-practices](https://github.com/xiaobei930/claude-code-best-practices)
|
||||
- [Claude Code power user customization](https://claude.com/blog/how-to-configure-hooks)
|
||||
|
||||
---
|
||||
|
||||
## 📖 推荐阅读顺序
|
||||
|
||||
### 对于初学者
|
||||
1. `HOOKS_QUICK_REFERENCE.md` - 快速了解钩子概念
|
||||
2. `HOOKS_OFFICIAL_GUIDE.md` - 学习如何配置和使用
|
||||
3. `hooks_bash_command_validator.py` - 查看示例代码
|
||||
|
||||
### 对于开发者(修复当前实现)
|
||||
1. `HOOKS_ANALYSIS_REPORT.md` - 了解问题和修复方案
|
||||
2. `HOOKS_OFFICIAL_REFERENCE.md` - 查阅技术细节
|
||||
3. `HOOKS_OFFICIAL_GUIDE.md` - 学习最佳实践
|
||||
|
||||
### 对于高级用户
|
||||
1. `HOOKS_OFFICIAL_REFERENCE.md` - 完整技术参考
|
||||
2. 官方 GitHub 仓库 - 更多示例
|
||||
3. `HOOKS_QUICK_REFERENCE.md` - 快速查阅
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 快速开始
|
||||
|
||||
### 查看当前配置
|
||||
```bash
|
||||
# 在 Claude Code CLI 中
|
||||
/hooks
|
||||
```
|
||||
|
||||
### 创建第一个钩子(格式化代码)
|
||||
`.claude/settings.json`:
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "jq -r '.tool_input.file_path' | xargs prettier --write"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 调试钩子
|
||||
```bash
|
||||
claude --debug # 查看详细执行日志
|
||||
```
|
||||
|
||||
在 CLI 中按 `Ctrl+O` 切换详细模式
|
||||
|
||||
---
|
||||
|
||||
## 📝 文档更新
|
||||
|
||||
- **创建时间**: 2026-02-01
|
||||
- **官方文档版本**: 最新(截至 2026-02-01)
|
||||
- **下次更新建议**: 当 Claude Code 发布新版本时
|
||||
|
||||
---
|
||||
|
||||
## 🔍 搜索关键词
|
||||
|
||||
钩子、Hooks、事件、Events、SessionStart、PreToolUse、PostToolUse、配置、Configuration、命令、Command、Prompt、Agent、阻止、Block、通知、Notification
|
||||
|
||||
---
|
||||
|
||||
**需要帮助?**
|
||||
|
||||
参考 `HOOKS_QUICK_REFERENCE.md` 获取快速答案,或查阅 `HOOKS_OFFICIAL_REFERENCE.md` 获取完整技术细节。
|
||||
124
.claude/docs/HOOKS_OFFICIAL_GUIDE.md
Normal file
124
.claude/docs/HOOKS_OFFICIAL_GUIDE.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Claude Code Hooks - Official Guide
|
||||
|
||||
> Complete official documentation from https://code.claude.com/docs/en/hooks-guide
|
||||
|
||||
## Automate workflows with hooks
|
||||
|
||||
Run shell commands automatically when Claude Code edits files, finishes tasks, or needs input. Format code, send notifications, validate commands, and enforce project rules.
|
||||
|
||||
### Hook lifecycle
|
||||
|
||||
Hooks fire at specific points during a Claude Code session. The official hook events are:
|
||||
|
||||
| Event | When it fires |
|
||||
| :------------------- | :--------------------------------------------------- |
|
||||
| `SessionStart` | When a session begins or resumes |
|
||||
| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |
|
||||
| `PreToolUse` | Before a tool call executes. Can block it |
|
||||
| `PermissionRequest` | When a permission dialog appears |
|
||||
| `PostToolUse` | After a tool call succeeds |
|
||||
| `PostToolUseFailure` | After a tool call fails |
|
||||
| `Notification` | When Claude Code sends a notification |
|
||||
| `SubagentStart` | When a subagent is spawned |
|
||||
| `SubagentStop` | When a subagent finishes |
|
||||
| `Stop` | When Claude finishes responding |
|
||||
| `PreCompact` | Before context compaction |
|
||||
| `SessionEnd` | When a session terminates |
|
||||
|
||||
### Hook handler types
|
||||
|
||||
There are three types of hook handlers:
|
||||
|
||||
1. **Command hooks** (`type: "command"`): Run a shell command
|
||||
2. **Prompt hooks** (`type: "prompt"`): Use Claude model for single-turn evaluation
|
||||
3. **Agent hooks** (`type: "agent"`): Spawn subagent with tool access
|
||||
|
||||
### Configuration structure
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"EventName": [
|
||||
{
|
||||
"matcher": "ToolName|AnotherTool",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash /path/to/script.sh",
|
||||
"timeout": 600,
|
||||
"async": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Hook input (stdin)
|
||||
|
||||
Common fields for all events:
|
||||
- `session_id`: Current session ID
|
||||
- `transcript_path`: Path to conversation JSON
|
||||
- `cwd`: Current working directory
|
||||
- `permission_mode`: Current permission mode
|
||||
- `hook_event_name`: Name of the event that fired
|
||||
|
||||
Event-specific fields depend on the event type.
|
||||
|
||||
### Hook output (exit codes and stdout)
|
||||
|
||||
- **Exit 0**: Success. Parse stdout for JSON decision
|
||||
- **Exit 2**: Blocking error. stderr text becomes Claude's feedback
|
||||
- **Any other code**: Non-blocking error
|
||||
|
||||
### Tool matchers
|
||||
|
||||
Available for: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`
|
||||
|
||||
Tool names:
|
||||
- Built-in: `Bash`, `Edit`, `Write`, `Read`, `Glob`, `Grep`, `Task`, `WebFetch`, `WebSearch`
|
||||
- MCP tools: `mcp__<server>__<tool>` (e.g., `mcp__github__search_repositories`)
|
||||
|
||||
### Event matchers
|
||||
|
||||
Different events match on different fields:
|
||||
- `SessionStart`: `startup`, `resume`, `clear`, `compact`
|
||||
- `SessionEnd`: `clear`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other`
|
||||
- `Notification`: `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`
|
||||
- `SubagentStart`/`SubagentStop`: agent type (e.g., `Bash`, `Explore`, `Plan`)
|
||||
- `PreCompact`: `manual`, `auto`
|
||||
|
||||
### Hook configuration locations
|
||||
|
||||
| Location | Scope |
|
||||
|----------|-------|
|
||||
| `~/.claude/settings.json` | All your projects |
|
||||
| `.claude/settings.json` | Single project |
|
||||
| `.claude/settings.local.json` | Single project (gitignored) |
|
||||
| Plugin `hooks/hooks.json` | When plugin enabled |
|
||||
| Skill/Agent frontmatter | While component active |
|
||||
|
||||
### Best practices
|
||||
|
||||
✅ **DO:**
|
||||
- Use command hooks for deterministic actions
|
||||
- Use prompt hooks for judgment-based decisions
|
||||
- Use agent hooks when verification requires file inspection
|
||||
- Quote all shell variables: `"$VAR"`
|
||||
- Use absolute paths with `$CLAUDE_PROJECT_DIR`
|
||||
- Set appropriate timeouts
|
||||
- Use async hooks for long-running operations
|
||||
- Keep hooks fast (< 10 seconds by default)
|
||||
|
||||
❌ **DON'T:**
|
||||
- Trust input data blindly
|
||||
- Use relative paths
|
||||
- Put sensitive data in hook output
|
||||
- Create infinite loops in Stop hooks
|
||||
- Run blocking operations without async
|
||||
|
||||
---
|
||||
|
||||
See https://code.claude.com/docs/en/hooks-guide for complete guide
|
||||
See https://code.claude.com/docs/en/hooks for reference documentation
|
||||
268
.claude/docs/HOOKS_OFFICIAL_REFERENCE.md
Normal file
268
.claude/docs/HOOKS_OFFICIAL_REFERENCE.md
Normal file
@@ -0,0 +1,268 @@
|
||||
# Claude Code Hooks - Official Reference
|
||||
|
||||
> Complete official reference from https://code.claude.com/docs/en/hooks
|
||||
|
||||
## Hooks reference
|
||||
|
||||
This is the complete technical reference for Claude Code hooks.
|
||||
|
||||
### Hook events reference
|
||||
|
||||
#### SessionStart
|
||||
|
||||
**When it fires:** When a session begins or resumes
|
||||
|
||||
**Matchers:**
|
||||
- `startup` - New session
|
||||
- `resume` - `--resume`, `--continue`, or `/resume`
|
||||
- `clear` - `/clear`
|
||||
- `compact` - Auto or manual compaction
|
||||
|
||||
**Input schema:**
|
||||
```json
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "/path/to/transcript.jsonl",
|
||||
"cwd": "/current/working/dir",
|
||||
"permission_mode": "default",
|
||||
"hook_event_name": "SessionStart",
|
||||
"source": "startup|resume|clear|compact",
|
||||
"model": "claude-sonnet-4-5-20250929"
|
||||
}
|
||||
```
|
||||
|
||||
**Output control:**
|
||||
- Exit 0: Text written to stdout is added to Claude's context
|
||||
- Can use `additionalContext` in JSON output
|
||||
- Cannot block session start
|
||||
|
||||
**Special variables:**
|
||||
- `CLAUDE_ENV_FILE`: Write `export` statements to persist environment variables
|
||||
|
||||
#### UserPromptSubmit
|
||||
|
||||
**When it fires:** When user submits a prompt, before Claude processes it
|
||||
|
||||
**Input schema:**
|
||||
```json
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"hook_event_name": "UserPromptSubmit",
|
||||
"prompt": "User's prompt text here"
|
||||
}
|
||||
```
|
||||
|
||||
**Output control:**
|
||||
- Exit 0: Plain text stdout is added as context
|
||||
- `decision: "block"` prevents prompt processing
|
||||
- `additionalContext` adds context to Claude
|
||||
|
||||
#### PreToolUse
|
||||
|
||||
**When it fires:** Before a tool call executes
|
||||
|
||||
**Matchers:** Tool names (Bash, Edit, Write, Read, etc.)
|
||||
|
||||
**Tool input schemas:**
|
||||
- `Bash`: `command`, `description`, `timeout`, `run_in_background`
|
||||
- `Write`: `file_path`, `content`
|
||||
- `Edit`: `file_path`, `old_string`, `new_string`, `replace_all`
|
||||
- `Read`: `file_path`, `offset`, `limit`
|
||||
- `Glob`: `pattern`, `path`
|
||||
- `Grep`: `pattern`, `path`, `glob`, `output_mode`, `-i`, `multiline`
|
||||
- `WebFetch`: `url`, `prompt`
|
||||
- `WebSearch`: `query`, `allowed_domains`, `blocked_domains`
|
||||
- `Task`: `prompt`, `description`, `subagent_type`, `model`
|
||||
|
||||
**Output control:**
|
||||
- `permissionDecision`: `"allow"`, `"deny"`, `"ask"`
|
||||
- `permissionDecisionReason`: Explanation
|
||||
- `updatedInput`: Modify tool input before execution
|
||||
- `additionalContext`: Add context to Claude
|
||||
|
||||
#### PermissionRequest
|
||||
|
||||
**When it fires:** When permission dialog appears
|
||||
|
||||
**Input schema:** Similar to PreToolUse but fires when permission needed
|
||||
|
||||
**Output control:**
|
||||
- `decision.behavior`: `"allow"` or `"deny"`
|
||||
- `decision.updatedInput`: Modify input before execution
|
||||
- `decision.message`: For deny, tells Claude why
|
||||
|
||||
#### PostToolUse
|
||||
|
||||
**When it fires:** After a tool call succeeds
|
||||
|
||||
**Input schema:** Includes both `tool_input` and `tool_response`
|
||||
|
||||
**Output control:**
|
||||
- `decision: "block"` to flag issue to Claude
|
||||
- `additionalContext`: Add context
|
||||
- `updatedMCPToolOutput`: For MCP tools, replace output
|
||||
|
||||
#### PostToolUseFailure
|
||||
|
||||
**When it fires:** After a tool call fails
|
||||
|
||||
**Input schema:** Includes `error` and `is_interrupt` fields
|
||||
|
||||
**Output control:**
|
||||
- `additionalContext`: Provide context about the failure
|
||||
|
||||
#### Notification
|
||||
|
||||
**When it fires:** When Claude Code sends a notification
|
||||
|
||||
**Matchers:**
|
||||
- `permission_prompt` - Permission needed
|
||||
- `idle_prompt` - Claude idle
|
||||
- `auth_success` - Auth successful
|
||||
- `elicitation_dialog` - Dialog shown
|
||||
|
||||
**Input schema:**
|
||||
```json
|
||||
{
|
||||
"hook_event_name": "Notification",
|
||||
"message": "Notification text",
|
||||
"title": "Title",
|
||||
"notification_type": "permission_prompt|idle_prompt|..."
|
||||
}
|
||||
```
|
||||
|
||||
#### SubagentStart
|
||||
|
||||
**When it fires:** When subagent is spawned
|
||||
|
||||
**Matchers:** Agent types (Bash, Explore, Plan, or custom)
|
||||
|
||||
**Input schema:**
|
||||
```json
|
||||
{
|
||||
"hook_event_name": "SubagentStart",
|
||||
"agent_id": "agent-abc123",
|
||||
"agent_type": "Explore"
|
||||
}
|
||||
```
|
||||
|
||||
**Output control:**
|
||||
- `additionalContext`: Add context to subagent
|
||||
|
||||
#### SubagentStop
|
||||
|
||||
**When it fires:** When subagent finishes
|
||||
|
||||
**Input schema:** Similar to SubagentStart with `stop_hook_active` field
|
||||
|
||||
#### Stop
|
||||
|
||||
**When it fires:** When Claude finishes responding
|
||||
|
||||
**Input schema:**
|
||||
```json
|
||||
{
|
||||
"hook_event_name": "Stop",
|
||||
"stop_hook_active": false|true
|
||||
}
|
||||
```
|
||||
|
||||
**Output control:**
|
||||
- `decision: "block"` prevents Claude from stopping
|
||||
- `reason`: Required when blocking, tells Claude why to continue
|
||||
- Check `stop_hook_active` to prevent infinite loops
|
||||
|
||||
#### PreCompact
|
||||
|
||||
**When it fires:** Before context compaction
|
||||
|
||||
**Matchers:**
|
||||
- `manual` - `/compact`
|
||||
- `auto` - Auto-compact when context full
|
||||
|
||||
**Input schema:**
|
||||
```json
|
||||
{
|
||||
"hook_event_name": "PreCompact",
|
||||
"trigger": "manual|auto",
|
||||
"custom_instructions": ""
|
||||
}
|
||||
```
|
||||
|
||||
#### SessionEnd
|
||||
|
||||
**When it fires:** When session terminates
|
||||
|
||||
**Matchers:**
|
||||
- `clear` - `/clear`
|
||||
- `logout` - User logged out
|
||||
- `prompt_input_exit` - User exited during prompt
|
||||
- `bypass_permissions_disabled` - Bypass disabled
|
||||
- `other` - Other reasons
|
||||
|
||||
**Input schema:**
|
||||
```json
|
||||
{
|
||||
"hook_event_name": "SessionEnd",
|
||||
"reason": "clear|logout|..."
|
||||
}
|
||||
```
|
||||
|
||||
### Prompt-based hooks
|
||||
|
||||
**Type:** `"prompt"`
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Your prompt here. Use $ARGUMENTS for input JSON",
|
||||
"model": "haiku",
|
||||
"timeout": 30
|
||||
}
|
||||
```
|
||||
|
||||
**Response schema:**
|
||||
```json
|
||||
{
|
||||
"ok": true|false,
|
||||
"reason": "Explanation if ok is false"
|
||||
}
|
||||
```
|
||||
|
||||
### Agent-based hooks
|
||||
|
||||
**Type:** `"agent"`
|
||||
|
||||
**Configuration:**
|
||||
```json
|
||||
{
|
||||
"type": "agent",
|
||||
"prompt": "Your prompt here. Use $ARGUMENTS for input JSON",
|
||||
"model": "haiku",
|
||||
"timeout": 60
|
||||
}
|
||||
```
|
||||
|
||||
**Response schema:** Same as prompt hooks
|
||||
|
||||
### Async hooks
|
||||
|
||||
**For command hooks only:**
|
||||
```json
|
||||
{
|
||||
"type": "command",
|
||||
"command": "...",
|
||||
"async": true,
|
||||
"timeout": 300
|
||||
}
|
||||
```
|
||||
|
||||
- Doesn't block Claude's execution
|
||||
- Cannot return decisions
|
||||
- Output delivered on next conversation turn
|
||||
- Max 50 turns per session
|
||||
|
||||
---
|
||||
|
||||
See https://code.claude.com/docs/en/hooks for full reference
|
||||
390
.claude/docs/HOOKS_QUICK_REFERENCE.md
Normal file
390
.claude/docs/HOOKS_QUICK_REFERENCE.md
Normal file
@@ -0,0 +1,390 @@
|
||||
# Claude Code Hooks - 快速参考
|
||||
|
||||
## 12 个官方钩子事件
|
||||
|
||||
| # | 事件名称 | 触发时机 | 可阻止 | 匹配器 |
|
||||
|---|---------|---------|--------|--------|
|
||||
| 1 | `SessionStart` | 会话开始/恢复 | ❌ | startup, resume, clear, compact |
|
||||
| 2 | `UserPromptSubmit` | 用户提交提示词前 | ✅ | ❌ 不支持 |
|
||||
| 3 | `PreToolUse` | 工具调用前 | ✅ | 工具名称 |
|
||||
| 4 | `PermissionRequest` | 权限对话时 | ✅ | 工具名称 |
|
||||
| 5 | `PostToolUse` | 工具成功后 | ❌ | 工具名称 |
|
||||
| 6 | `PostToolUseFailure` | 工具失败后 | ❌ | 工具名称 |
|
||||
| 7 | `Notification` | 发送通知时 | ❌ | 通知类型 |
|
||||
| 8 | `SubagentStart` | 子代理开始 | ❌ | 代理类型 |
|
||||
| 9 | `SubagentStop` | 子代理完成 | ✅ | 代理类型 |
|
||||
| 10 | `Stop` | Claude完成响应 | ✅ | ❌ 不支持 |
|
||||
| 11 | `PreCompact` | 上下文压缩前 | ❌ | manual, auto |
|
||||
| 12 | `SessionEnd` | 会话终止 | ❌ | 终止原因 |
|
||||
|
||||
---
|
||||
|
||||
## 配置模板
|
||||
|
||||
### 基础结构
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"EventName": [
|
||||
{
|
||||
"matcher": "pattern",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command|prompt|agent",
|
||||
"command": "...",
|
||||
"timeout": 600,
|
||||
"async": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 工具名称(用于匹配器)
|
||||
|
||||
### 内置工具
|
||||
```
|
||||
Bash, Edit, Write, Read, Glob, Grep, Task, WebFetch, WebSearch
|
||||
```
|
||||
|
||||
### MCP 工具
|
||||
```
|
||||
mcp__<server>__<tool>
|
||||
mcp__memory__.*
|
||||
mcp__.*__write.*
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exit Codes
|
||||
|
||||
| Code | 含义 | Claude反馈 |
|
||||
|------|------|-----------|
|
||||
| 0 | 成功 | 解析 stdout JSON,允许操作 |
|
||||
| 2 | 阻止 | stderr 发送给 Claude,阻止操作 |
|
||||
| 其他 | 错误 | stderr 仅在详细模式显示 |
|
||||
|
||||
---
|
||||
|
||||
## 标准 JSON 输入(stdin)
|
||||
|
||||
```json
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "/path/to/transcript.jsonl",
|
||||
"cwd": "/current/dir",
|
||||
"permission_mode": "default",
|
||||
"hook_event_name": "PreToolUse",
|
||||
"tool_name": "Bash",
|
||||
"tool_input": {
|
||||
"command": "npm test"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 标准 JSON 输出(stdout, exit 0)
|
||||
|
||||
### PreToolUse
|
||||
```json
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "allow|deny|ask",
|
||||
"permissionDecisionReason": "explanation"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### UserPromptSubmit
|
||||
```json
|
||||
{
|
||||
"decision": "block",
|
||||
"reason": "explanation",
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "UserPromptSubmit",
|
||||
"additionalContext": "context string"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Stop
|
||||
```json
|
||||
{
|
||||
"decision": "block",
|
||||
"reason": "Must complete tasks X, Y, Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 处理器类型
|
||||
|
||||
### 1. Command Hook
|
||||
```json
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash /path/to/script.sh",
|
||||
"timeout": 600,
|
||||
"async": false
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Prompt Hook
|
||||
```json
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Evaluate: $ARGUMENTS",
|
||||
"model": "haiku",
|
||||
"timeout": 30
|
||||
}
|
||||
```
|
||||
|
||||
响应格式:
|
||||
```json
|
||||
{
|
||||
"ok": true|false,
|
||||
"reason": "explanation if ok is false"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Agent Hook
|
||||
```json
|
||||
{
|
||||
"type": "agent",
|
||||
"prompt": "Verify tests pass: $ARGUMENTS",
|
||||
"model": "haiku",
|
||||
"timeout": 60
|
||||
}
|
||||
```
|
||||
|
||||
响应格式:与 Prompt Hook 相同
|
||||
|
||||
---
|
||||
|
||||
## 环境变量
|
||||
|
||||
### 标准变量
|
||||
```bash
|
||||
$CLAUDE_PROJECT_DIR # 项目根目录
|
||||
$CLAUDE_PLUGIN_ROOT # 插件根目录(插件内部使用)
|
||||
$CLAUDE_CODE_REMOTE # "true" 在远程环境
|
||||
```
|
||||
|
||||
### SessionStart 特殊变量
|
||||
```bash
|
||||
$CLAUDE_ENV_FILE # 持久化环境变量的文件路径
|
||||
```
|
||||
|
||||
用法:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
if [ -n "$CLAUDE_ENV_FILE" ]; then
|
||||
echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
|
||||
fi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见用例
|
||||
|
||||
### 1. 格式化代码
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "jq -r '.tool_input.file_path' | xargs prettier --write"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 阻止危险命令
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rm.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
脚本 `block-rm.sh`:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
COMMAND=$(jq -r '.tool_input.command')
|
||||
if echo "$COMMAND" | grep -q 'rm -rf'; then
|
||||
echo "Blocked: rm -rf is not allowed" >&2
|
||||
exit 2
|
||||
fi
|
||||
exit 0
|
||||
```
|
||||
|
||||
### 3. 通知用户
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"Notification": [
|
||||
{
|
||||
"matcher": "permission_prompt",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "osascript -e 'display notification \"Claude needs your attention\"'"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 确认任务完成
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Check if all tasks complete: $ARGUMENTS"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 异步运行测试
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "/path/to/run-tests.sh",
|
||||
"async": true,
|
||||
"timeout": 120
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6. 会话开始注入上下文
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "compact",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "echo 'Reminder: use Bun, not npm'"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 配置位置
|
||||
|
||||
| 位置 | 作用域 | 可共享 |
|
||||
|------|--------|--------|
|
||||
| `~/.claude/settings.json` | 全局用户 | ❌ |
|
||||
| `.claude/settings.json` | 单个项目 | ✅ |
|
||||
| `.claude/settings.local.json` | 单个项目 | ❌ (gitignored) |
|
||||
| 插件 `hooks/hooks.json` | 插件启用时 | ✅ |
|
||||
| Skill/Agent frontmatter | 组件活动时 | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 1. 详细模式
|
||||
```bash
|
||||
claude --debug # 查看完整钩子执行细节
|
||||
Ctrl+O # 切换详细模式(实时)
|
||||
```
|
||||
|
||||
### 2. 测试钩子脚本
|
||||
```bash
|
||||
echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh
|
||||
echo $? # 检查退出码
|
||||
```
|
||||
|
||||
### 3. 检查钩子配置
|
||||
```
|
||||
/hooks # 交互式钩子管理器
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
✅ **推荐:**
|
||||
- 总是引用 shell 变量:`"$VAR"`
|
||||
- 使用绝对路径:`"$CLAUDE_PROJECT_DIR"/script.sh`
|
||||
- 设置合理的超时时间
|
||||
- 验证和清理输入数据
|
||||
- 在 Stop 钩子中检查 `stop_hook_active`
|
||||
- 使用 async 进行长时间运行的操作
|
||||
|
||||
❌ **避免:**
|
||||
- 直接信任输入数据
|
||||
- 使用相对路径
|
||||
- 在钩子输出中暴露敏感数据
|
||||
- 创建无限循环(尤其在 Stop 钩子)
|
||||
- 没有设置超时的阻塞操作
|
||||
|
||||
---
|
||||
|
||||
## 官方资源
|
||||
|
||||
- **指南**: https://code.claude.com/docs/en/hooks-guide
|
||||
- **参考**: https://code.claude.com/docs/en/hooks
|
||||
- **示例**: https://github.com/anthropics/claude-code/tree/main/examples/hooks
|
||||
|
||||
---
|
||||
|
||||
## 本地文档
|
||||
|
||||
- `HOOKS_OFFICIAL_GUIDE.md` - 官方指南中文版
|
||||
- `HOOKS_OFFICIAL_REFERENCE.md` - 官方参考中文版
|
||||
- `HOOKS_ANALYSIS_REPORT.md` - 当前实现对比分析
|
||||
- `hooks_bash_command_validator.py` - 官方示例脚本
|
||||
85
.claude/examples/hooks_bash_command_validator.py
Normal file
85
.claude/examples/hooks_bash_command_validator.py
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Claude Code Hook: Bash Command Validator
|
||||
=========================================
|
||||
This hook runs as a PreToolUse hook for the Bash tool.
|
||||
It validates bash commands against a set of rules before execution.
|
||||
In this case it changes grep calls to using rg.
|
||||
|
||||
Read more about hooks here: https://code.claude.com/docs/en/hooks
|
||||
|
||||
Make sure to change your path to your actual script.
|
||||
|
||||
Configuration for .claude/settings.json:
|
||||
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 /path/to/bash_command_validator.py"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
# Define validation rules as a list of (regex pattern, message) tuples
|
||||
_VALIDATION_RULES = [
|
||||
(
|
||||
r"^grep\b(?!.*\|)",
|
||||
"Use 'rg' (ripgrep) instead of 'grep' for better performance and features",
|
||||
),
|
||||
(
|
||||
r"^find\s+\S+\s+-name\b",
|
||||
"Use 'rg --files | rg pattern' or 'rg --files -g pattern' instead of 'find -name' for better performance",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def _validate_command(command: str) -> list[str]:
|
||||
issues = []
|
||||
for pattern, message in _VALIDATION_RULES:
|
||||
if re.search(pattern, command):
|
||||
issues.append(message)
|
||||
return issues
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
input_data = json.load(sys.stdin)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
|
||||
# Exit code 1 shows stderr to the user but not to Claude
|
||||
sys.exit(1)
|
||||
|
||||
tool_name = input_data.get("tool_name", "")
|
||||
if tool_name != "Bash":
|
||||
sys.exit(0)
|
||||
|
||||
tool_input = input_data.get("tool_input", {})
|
||||
command = tool_input.get("command", "")
|
||||
|
||||
if not command:
|
||||
sys.exit(0)
|
||||
|
||||
issues = _validate_command(command)
|
||||
if issues:
|
||||
for message in issues:
|
||||
print(f"• {message}", file=sys.stderr)
|
||||
# Exit code 2 blocks tool call and shows stderr to Claude
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user