钩子
通过响应生命周期事件来自定义Claude Code行为
什么是钩子?
钩子是响应Claude Code中特定事件而执行的JavaScript函数。它们允许您自定义行为、执行策略、集成外部工具和自动化工作流。
事件驱动
自动响应特定的生命周期事件
完全可自定义
编写JavaScript来自定义任何行为
策略执行
执行团队标准和安全策略
外部集成
连接到外部服务和工具
可用的钩子事件
PreToolUse
在Claude使用任何工具之前触发。验证、修改或阻止工具使用。
PostToolUse
工具完成后触发。处理结果、触发通知或记录操作。
UserPromptSubmit
用户提交提示时触发。修改提示、添加上下文或触发工作流。
Notification
Claude发送通知时触发。自定义通知行为。
SessionStart
Claude会话开始时触发。初始化资源或加载上下文。
SessionEnd
会话结束时触发。清理资源或保存会话数据。
Setup
通过 --init、--init-only 或 --maintenance 标志触发。适用于仓库设置和维护任务。
SubagentStop
子代理完成工作时触发。处理结果或触发后续操作。
SubagentStart
子代理即将启动时触发。监控子代理启动或注入上下文。
PermissionRequest
请求权限时触发。自动批准/拒绝或记录权限请求。
PreCompact
上下文压缩发生前触发。在上下文被压缩之前保存重要信息。
基于提示的钩子
在钩子中使用LLM驱动的决策。无需编写JavaScript逻辑,而是用自然语言描述您想要的内容。
{
"hooks": {
"PreToolUse": [
{
"type": "prompt",
"matcher": { "tool": "Write" },
"prompt": "Review this file write operation. Check if it follows
our coding standards. Respond with 'allow' or 'deny'
and explain why."
}
]
}
}何时使用
- +难以用代码编写的复杂决策逻辑
- +代码审查和质量检查
- +上下文感知验证
响应格式
{
"decision": "allow" | "deny" | "skip",
"reason": "Optional explanation",
"modifiedInput": { /* optional */ }
}实践示例
编辑后自动格式化代码
在Claude编辑文件后自动运行Prettier
// Auto-format files after Edit tool
export async function postToolUse({ tool, result }) {
if (tool.name === 'Edit' && result.success) {
const { execSync } = require('child_process');
try {
execSync(`prettier --write "${tool.params.file_path}"`);
console.log('✓ Formatted', tool.params.file_path);
} catch (error) {
console.error('Format failed:', error.message);
}
}
}保护敏感文件
防止Claude编辑关键配置文件
// Protect sensitive files
export async function preToolUse({ tool }) {
const protectedFiles = [
'.env',
'credentials.json',
'package-lock.json'
];
if (['Edit', 'Write'].includes(tool.name)) {
const filePath = tool.params.file_path;
if (protectedFiles.some(f => filePath.includes(f))) {
return {
allow: false,
reason: `Cannot modify protected file: ${filePath}`
};
}
}
return { allow: true };
}发送Slack通知
部署发生时通知团队
// Notify team on deployment
export async function postToolUse({ tool, result }) {
if (tool.name === 'Bash' &&
tool.params.command.includes('deploy')) {
const webhook = process.env.SLACK_WEBHOOK;
await fetch(webhook, {
method: 'POST',
body: JSON.stringify({
text: `🚀 Deployment completed!
Success: ${result.success}
Command: ${tool.params.command}`
})
});
}
}安全注意事项
钩子执行任意JavaScript代码。遵循以下安全最佳实践:
永远不要在钩子文件中存储密钥 - 使用环境变量
在执行外部命令之前验证所有输入
在使用来自外部源的钩子之前先审查它们
使用try-catch块优雅地处理错误
最佳实践
保持钩子简单
每个钩子应该只做好一件事。复杂的逻辑会降低Claude的速度。
优雅地处理错误
始终使用try-catch块并提供有意义的错误消息。
使用Async/Await
钩子支持用于外部API调用和文件操作的异步函数。
测试您的钩子
在部署之前彻底测试钩子,以避免中断工作流。