hooks ã§ã¯ãŒã¯ãããŒãèªååãã
Claude Code ããã¡ã€ã«ãç·šéããããã¿ã¹ã¯ãå®äºããããå ¥åãå¿ èŠã«ãªã£ãããããšãã«ãã·ã§ã«ã³ãã³ããèªåçã«å®è¡ããŸããã³ãŒãããã©ãŒãããããéç¥ãéä¿¡ããã³ãã³ããæ€èšŒãããããžã§ã¯ãã«ãŒã«ãé©çšããŸãã
Hooks 㯠Claude Code ã®ã©ã€ããµã€ã¯ã«ã®ç¹å®ã®ãã€ã³ãã§å®è¡ããããŠãŒã¶ãŒå®çŸ©ã®ã·ã§ã«ã³ãã³ãã§ããããã㯠Claude Code ã®åäœã«å¯ŸããŠæ±ºå®è«çãªå¶åŸ¡ãæäŸããLLM ãå®è¡ãéžæããã®ã«äŸåããã®ã§ã¯ãªããç¹å®ã®ã¢ã¯ã·ã§ã³ãåžžã«çºçããããšãä¿èšŒããŸããHooks ã䜿çšããŠããããžã§ã¯ãã«ãŒã«ãé©çšããå埩çãªã¿ã¹ã¯ãèªååããClaude Code ãæ¢åã®ããŒã«ãšçµ±åããŸãã
倿ãå¿ èŠãªæ±ºå®ã«ã€ããŠã¯ã決å®è«çãªã«ãŒã«ã§ã¯ãªããClaude ã¢ãã«ã䜿çšããŠæ¡ä»¶ãè©äŸ¡ãã ããã³ããããŒã¹ã® hooks ãŸã㯠ãšãŒãžã§ã³ãããŒã¹ã® hooks ã䜿çšããããšãã§ããŸãã
Claude Code ãæ¡åŒµããä»ã®æ¹æ³ã«ã€ããŠã¯ãClaude ã«è¿œå ã®æç€ºãšå®è¡å¯èœãªã³ãã³ããäžããããã® skillsãåé¢ãããã³ã³ããã¹ãã§ã¿ã¹ã¯ãå®è¡ããããã® subagentsããããžã§ã¯ãå šäœã§å ±æããæ¡åŒµæ©èœãããã±ãŒãžåããããã® plugins ãåç §ããŠãã ããã
ãã®ã¬ã€ãã§ã¯äžè¬çãªãŠãŒã¹ã±ãŒã¹ãšå§ãæ¹ãã«ããŒããŠããŸããå®å šãªã€ãã³ãã¹ããŒããJSON å ¥å/åºå圢åŒãéåæ hooks ã MCP ããŒã« hooks ãªã©ã®é«åºŠãªæ©èœã«ã€ããŠã¯ãHooks ãªãã¡ã¬ã³ã¹ ãåç §ããŠãã ããã
æåã® hook ãã»ããã¢ãããã
Hook ãäœæããã«ã¯ãèšå®ãã¡ã€ã« ã« hooks ãããã¯ã远å ããŸãããã®ãã¥ãŒããªã¢ã«ã§ã¯ãã¹ã¯ãããéç¥ hook ãäœæãããããClaude ãããªãã®å
¥åãåŸ
ã£ãŠãããšãã«ã¢ã©ãŒããåãåãããšãã§ããŸããã¿ãŒããã«ãç£èŠãã代ããã«ã
hook ãèšå®ã«è¿œå ãã
~/.claude/settings.json ãéããNotification hook ã远å ããŸãã以äžã®äŸã¯ macOS çšã« osascript ã䜿çšããŠããŸããLinux ãš Windows ã®ã³ãã³ãã«ã€ããŠã¯ãClaude ãå
¥åãå¿
èŠãšãããšãã«éç¥ãåãåã ãåç
§ããŠãã ããã
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}
èšå®ãã¡ã€ã«ã«æ¢ã« hooks ããŒãããå Žåã¯ããªããžã§ã¯ãå
šäœã眮ãæããã®ã§ã¯ãªããNotification ãæ¢åã®ã€ãã³ãããŒã®å
åŒãšããŠè¿œå ããŸããåã€ãã³ãåã¯åäžã® hooks ãªããžã§ã¯ãå
ã®ããŒã§ãïŒ
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }]
}
],
"Notification": [
{
"matcher": "",
"hooks": [{ "type": "command", "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'" }]
}
]
}
}
CLI ã§èª¬æããããšã§ãClaude ã« hook ãæžããŠãããããšãã§ããŸãã
èšå®ã確èªãã
/hooks ãšå
¥åã㊠hooks ãã©ãŠã¶ãéããŸããå©çšå¯èœãªãã¹ãŠã® hook ã€ãã³ãã®ãªã¹ãã衚瀺ãããhooks ãèšå®ãããŠããã€ãã³ãã®æšªã«æ°ã衚瀺ãããŸããNotification ãéžæããŠãæ°ãã hook ããªã¹ãã«è¡šç€ºãããããšã確èªããŸããHook ãéžæãããšããã®è©³çްã衚瀺ãããŸãïŒã€ãã³ãããããã£ãŒãã¿ã€ãããœãŒã¹ãã¡ã€ã«ãããã³ã³ãã³ãã
hook ããã¹ããã
Esc ãæŒã㊠CLI ã«æ»ããŸããClaude ã«èš±å¯ãå¿
èŠãªäœããããããäŸé Œããã¿ãŒããã«ããåãæ¿ããŸãããã¹ã¯ãããéç¥ãåãåãã¯ãã§ãã
/hooks ã¡ãã¥ãŒã¯èªã¿åãå°çšã§ããHooks ã远å ã倿ŽããŸãã¯åé€ããã«ã¯ãèšå® JSON ãçŽæ¥ç·šéããããClaude ã«å€æŽãäŸé ŒããŸãã
èªååã§ãããã®
Hooks ã䜿çšãããšãClaude Code ã®ã©ã€ããµã€ã¯ã«ã®äž»èŠãªãã€ã³ãã§ã³ãŒããå®è¡ã§ããŸãïŒç·šéåŸã«ãã¡ã€ã«ããã©ãŒãããããå®è¡åã«ã³ãã³ãããããã¯ããClaude ãå ¥åãå¿ èŠãšãããšãã«éç¥ãéä¿¡ããã»ãã·ã§ã³éå§æã«ã³ã³ããã¹ããæ³šå ¥ãããªã©ãHook ã€ãã³ãã®å®å šãªãªã¹ãã«ã€ããŠã¯ãHooks ãªãã¡ã¬ã³ã¹ ãåç §ããŠãã ããã
åäŸã«ã¯ãèšå®ãã¡ã€ã« ã«è¿œå ããæºåãã§ããèšå®ãããã¯ãå«ãŸããŠããŸããæãäžè¬çãªãã¿ãŒã³ïŒ
- Claude ãå ¥åãå¿ èŠãšãããšãã«éç¥ãåãåã
- ç·šéåŸã«ã³ãŒããèªåãã©ãŒããããã
- ä¿è·ããããã¡ã€ã«ãžã®ç·šéããããã¯ãã
- å§çž®åŸã«ã³ã³ããã¹ããåæ³šå ¥ãã
- èšå®å€æŽãç£æ»ãã
- ãã£ã¬ã¯ããªãŸãã¯ãã¡ã€ã«ã倿Žããããšãã«ç°å¢ããªããŒããã
- ç¹å®ã®èš±å¯ããã³ãããèªåæ¿èªãã
Claude ãå ¥åãå¿ èŠãšãããšãã«éç¥ãåãåã
Claude ãäœæ¥ãå®äºããŠå ¥åãå¿ èŠãšãããšãã¯ãã€ã§ããã¹ã¯ãããéç¥ãååŸããã¿ãŒããã«ããã§ãã¯ããã«ä»ã®ã¿ã¹ã¯ã«åãæ¿ããããšãã§ããŸãã
ãã® hook 㯠Notification ã€ãã³ãã䜿çšããŸãããã㯠Claude ãå
¥åãŸãã¯èš±å¯ãåŸ
ã£ãŠãããšãã«çºç«ããŸãã以äžã®åã¿ãã¯ãã©ãããã©ãŒã ã®ãã€ãã£ãéç¥ã³ãã³ãã䜿çšããŸããããã ~/.claude/settings.json ã«è¿œå ããŸãïŒ
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}
éç¥ã衚瀺ãããªãå Žå
osascript ã¯çµã¿èŸŒã¿ã® Script Editor ã¢ããªãéããŠéç¥ãã«ãŒãã£ã³ã°ããŸããScript Editor ã«éç¥æš©éããªãå Žåãã³ãã³ãã¯éãã«å€±æããmacOS ã¯ãããä»äžããããæ±ããŸãããTerminal ã§ããã 1 åå®è¡ããŠãScript Editor ãéç¥èšå®ã«è¡šç€ºãããŸãïŒ
osascript -e 'display notification "test"'
ãŸã äœã衚瀺ãããŸãããSystem Settings > Notifications ãéãããªã¹ãã§ Script Editor ãèŠã€ããŠãAllow Notifications ããªã³ã«ããŸããã³ãã³ããå床å®è¡ããŠããã¹ãéç¥ã衚瀺ãããããšã確èªããŸãã
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude Code' 'Claude Code needs your attention'"
}
]
}
]
}
}
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')\""
}
]
}
]
}
}
空㮠matcher ã¯ãã¹ãŠã®éç¥ã¿ã€ãã§çºç«ããŸããç¹å®ã®ã€ãã³ãã§ã®ã¿çºç«ãããã«ã¯ã次ã®ããããã®å€ã«èšå®ããŸãïŒ
| Matcher | çºç«ããã¿ã€ãã³ã° |
|---|---|
permission_prompt |
Claude ãããŒã«äœ¿çšãæ¿èªããå¿ èŠããããšã |
idle_prompt |
Claude ãå®äºããæ¬¡ã®ããã³ãããåŸ ã£ãŠãããšã |
auth_success |
èªèšŒãå®äºãããšã |
elicitation_dialog |
MCP ãµãŒããŒãåŒãåºããã©ãŒã ãéããšã |
elicitation_complete |
MCP åŒãåºããã©ãŒã ãéä¿¡ãŸãã¯åŽäžããããšã |
elicitation_response |
MCP åŒãåºãå¿çããµãŒããŒã«éãè¿ããããšã |
/hooks ãšå
¥åã㊠Notification ãéžæããhook ãç»é²ãããŠããããšã確èªããŸããå®å
šãªã€ãã³ãã¹ããŒãã«ã€ããŠã¯ãNotification ãªãã¡ã¬ã³ã¹ ãåç
§ããŠãã ããã
ç·šéåŸã«ã³ãŒããèªåãã©ãŒããããã
Claude ãç·šéãããã¹ãŠã®ãã¡ã€ã«ã§ Prettier ãèªåçã«å®è¡ããæåæäœãªãã§ãã©ãŒãããã®äžè²«æ§ãä¿ã¡ãŸãã
ãã® hook 㯠PostToolUse ã€ãã³ãã Edit|Write ãããã£ãŒã§äœ¿çšããããããã¡ã€ã«ç·šéããŒã«ã®åŸã«ã®ã¿å®è¡ãããŸããã³ãã³ã㯠jq ã§ç·šéããããã¡ã€ã«ãã¹ãæœåºããPrettier ã«æž¡ããŸããããããããžã§ã¯ãã«ãŒãã® .claude/settings.json ã«è¿œå ããŸãïŒ
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
ãã®ããŒãžã® Bash ã®äŸã¯ JSON è§£æã« jq ã䜿çšããŸããbrew install jqïŒmacOSïŒãapt-get install jqïŒDebian/UbuntuïŒã§ã€ã³ã¹ããŒã«ããããjq ããŠã³ããŒã ãåç
§ããŠãã ããã
ä¿è·ããããã¡ã€ã«ãžã®ç·šéããããã¯ãã
Claude ã .envãpackage-lock.jsonã.git/ å
ã®ãã®ãªã©ã®æ©å¯ãã¡ã€ã«ã倿Žããã®ãé²ããŸããClaude ã¯ç·šéããããã¯ãããçç±ã説æãããã£ãŒãããã¯ãåãåããããã¢ãããŒãã調æŽã§ããŸãã
ãã®äŸã¯ hook ãåŒã³åºãå¥ã®ã¹ã¯ãªãããã¡ã€ã«ã䜿çšããŸããã¹ã¯ãªããã¯ã¿ãŒã²ãããã¡ã€ã«ãã¹ãä¿è·ããããã¿ãŒã³ã®ãªã¹ãã«å¯ŸããŠãã§ãã¯ããçµäºã³ãŒã 2 ã§ç·šéããããã¯ããŸãã
hook ã¹ã¯ãªãããäœæãã
ããã .claude/hooks/protect-files.sh ã«ä¿åããŸãïŒ
#!/bin/bash
# protect-files.sh
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")
for pattern in "${PROTECTED_PATTERNS[@]}"; do
if [[ "$FILE_PATH" == *"$pattern"* ]]; then
echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
exit 2
fi
done
exit 0
ã¹ã¯ãªãããå®è¡å¯èœã«ããïŒmacOS/LinuxïŒ
Claude Code ã hook ã¹ã¯ãªãããå®è¡ããã«ã¯ãå®è¡å¯èœã§ããå¿ èŠããããŸãïŒ
chmod +x .claude/hooks/protect-files.sh
hook ãç»é²ãã
.claude/settings.json ã« PreToolUse hook ã远å ããŠãEdit ãŸã㯠Write ããŒã«åŒã³åºãã®åã«ã¹ã¯ãªãããå®è¡ããŸãïŒ
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
}
]
}
]
}
}
å§çž®åŸã«ã³ã³ããã¹ããåæ³šå ¥ãã
Claude ã®ã³ã³ããã¹ããŠã£ã³ããŠããã£ã±ãã«ãªããšãå§çž®ã¯äŒè©±ãèŠçŽããŠã¹ããŒã¹ãè§£æŸããŸããããã¯éèŠãªè©³çްã倱ãå¯èœæ§ããããŸããcompact ãããã£ãŒã§ SessionStart hook ã䜿çšããŠããã¹ãŠã®å§çž®åŸã«éèŠãªã³ã³ããã¹ããåæ³šå
¥ããŸãã
ã³ãã³ãã stdout ã«æžã蟌ãããã¹ã㯠Claude ã®ã³ã³ããã¹ãã«è¿œå ãããŸãããã®äŸã¯ãããžã§ã¯ãèŠçŽãšæè¿ã®äœæ¥ã Claude ã«æãåºãããŸããããããããžã§ã¯ãã«ãŒãã® .claude/settings.json ã«è¿œå ããŸãïŒ
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "echo 'Reminder: use Bun, not npm. Run bun test before committing. Current sprint: auth refactor.'"
}
]
}
]
}
}
echo ã git log --oneline -5 ãªã©ã®åçåºåãçæããã³ãã³ãã«çœ®ãæããŠãæè¿ã®ã³ãããã衚瀺ã§ããŸãããã¹ãŠã®ã»ãã·ã§ã³éå§æã«ã³ã³ããã¹ããæ³šå
¥ããå Žåã¯ã代ããã« CLAUDE.md ã䜿çšããããšãæ€èšããŠãã ãããç°å¢å€æ°ã«ã€ããŠã¯ããªãã¡ã¬ã³ã¹ã® CLAUDE_ENV_FILE ãåç
§ããŠãã ããã
èšå®å€æŽãç£æ»ãã
ã»ãã·ã§ã³äžã«èšå®ãŸãã¯ã¹ãã«ãã¡ã€ã«ã倿Žããããšãã远跡ããŸããConfigChange ã€ãã³ãã¯å€éšããã»ã¹ãŸãã¯ãšãã£ã¿ãèšå®ãã¡ã€ã«ã倿Žãããšãã«çºç«ãããããã³ã³ãã©ã€ã¢ã³ã¹ã®ããã«å€æŽããã°ã«èšé²ããããäžæ£ãªå€æŽããããã¯ãããã§ããŸãã
ãã®äŸã¯å倿Žãç£æ»ãã°ã«è¿œå ããŸããããã ~/.claude/settings.json ã«è¿œå ããŸãïŒ
{
"hooks": {
"ConfigChange": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "jq -c '{timestamp: now | todate, source: .source, file: .file_path}' >> ~/claude-config-audit.log"
}
]
}
]
}
}
ãããã£ãŒã¯èšå®ã¿ã€ãã§ãã£ã«ã¿ãªã³ã°ããŸãïŒuser_settingsãproject_settingsãlocal_settingsãpolicy_settingsããŸã㯠skillsã倿Žãæå¹ã«ãªãã®ããããã¯ããã«ã¯ãçµäºã³ãŒã 2 ã§çµäºãããã{"decision": "block"} ãè¿ããŸããå®å
šãªå
¥åã¹ããŒãã«ã€ããŠã¯ãConfigChange ãªãã¡ã¬ã³ã¹ ãåç
§ããŠãã ããã
ãã£ã¬ã¯ããªãŸãã¯ãã¡ã€ã«ã倿Žããããšãã«ç°å¢ããªããŒããã
äžéšã®ãããžã§ã¯ãã¯ãã©ã®ãã£ã¬ã¯ããªã«ãããã«å¿ããŠç°ãªãç°å¢å€æ°ãèšå®ããŸããdirenv ãªã©ã®ããŒã«ã¯ã·ã§ã«ã§èªåçã«ãããè¡ããŸãããClaude ã® Bash ããŒã«ã¯ãããã®å€æŽãèªåçã«ååŸããŸããã
SessionStart hook ã CwdChanged hook ãšãã¢ãªã³ã°ããããšã§ãããä¿®æ£ããŸããSessionStart ã¯èµ·åãããã£ã¬ã¯ããªã®å€æ°ãããŒãããCwdChanged 㯠Claude ããã£ã¬ã¯ããªã倿Žãããã³ã«ãããããªããŒãããŸããã©ã¡ãã CLAUDE_ENV_FILE ã«æžã蟌ã¿ãClaude Code ã¯å Bash ã³ãã³ãã®åã«ã¹ã¯ãªããããªã¢ã³ãã«ãšããŠå®è¡ããŸããããã ~/.claude/settings.json ã«è¿œå ããŸãïŒ
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
}
]
}
],
"CwdChanged": [
{
"hooks": [
{
"type": "command",
"command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
}
]
}
]
}
}
direnv allow ããã¹ãŠã®ãã£ã¬ã¯ããªã§ 1 åå®è¡ããŠãdirenv ã .envrc ãããŒãããããšãèš±å¯ãããããã«ããŸããdirenv ã®ä»£ããã« devbox ãŸã㯠nix ã䜿çšããå Žåãåããã¿ãŒã³ã¯ direnv export bash ã®ä»£ããã« devbox shellenv ãŸã㯠devbox global shellenv ã§æ©èœããŸãã
ãã¹ãŠã®ãã£ã¬ã¯ããªå€æŽã§ã¯ãªããç¹å®ã®ãã¡ã€ã«ã«åå¿ããã«ã¯ãFileChanged ã matcher ã§äœ¿çšããŠãç£èŠãããã¡ã€ã«åããªã¹ãããŸãïŒãã€ãã§åºåãããŠããŸãïŒããŠã©ãããªã¹ããæ§ç¯ããããã«ããã®å€ã¯æ£èŠè¡šçŸãšããŠè©äŸ¡ãããã®ã§ã¯ãªãããªãã©ã«ãã¡ã€ã«åã«åå²ãããŸããFileChanged ãåç
§ããŠãåãå€ããã¡ã€ã«ã倿Žããããšãã«ã©ã® hook ã°ã«ãŒããå®è¡ããããããã£ã«ã¿ãªã³ã°ããæ¹æ³ã確èªããŠãã ããããã®äŸã¯çŸåšã®ãã£ã¬ã¯ããªã® .envrc ãš .env ãç£èŠããŸãïŒ
{
"hooks": {
"FileChanged": [
{
"matcher": ".envrc|.env",
"hooks": [
{
"type": "command",
"command": "direnv export bash > \"$CLAUDE_ENV_FILE\""
}
]
}
]
}
}
å
¥åã¹ããŒããwatchPaths åºåãããã³ CLAUDE_ENV_FILE ã®è©³çްã«ã€ããŠã¯ãCwdChanged ããã³ FileChanged ãªãã¡ã¬ã³ã¹ãšã³ããªãåç
§ããŠãã ããã
ç¹å®ã®èš±å¯ããã³ãããèªåæ¿èªãã
åžžã«èš±å¯ããããŒã«åŒã³åºãã®æ¿èªãã€ã¢ãã°ãã¹ãããããŸãããã®äŸã¯ ExitPlanMode ãèªåæ¿èªããŸãããã㯠Claude ããã©ã³ã®æç€ºãçµäºããŠç¶è¡ããããæ±ãããšãã«åŒã³åºãããŒã«ã§ãããã©ã³ãæºåã§ãããã³ã«ããã³ããã衚瀺ãããããšã¯ãããŸããã
äžèšã®çµäºã³ãŒãäŸãšã¯ç°ãªããèªåæ¿èªã«ã¯ hook ã JSON 決å®ã stdout ã«æžã蟌ãå¿
èŠããããŸããPermissionRequest hook 㯠Claude Code ãèš±å¯ãã€ã¢ãã°ã衚瀺ããããšãããšãã«çºç«ãã"behavior": "allow" ãè¿ããšããªãã®ä»£ããã«ããã«çããŸãã
ãããã£ãŒã¯ hook ã ExitPlanMode ã®ã¿ã«ã¹ã³ãŒããããããä»ã®ããã³ããã¯åœ±é¿ãåããŸãããããã ~/.claude/settings.json ã«è¿œå ããŸãïŒ
{
"hooks": {
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"
}
]
}
]
}
}
Hook ãæ¿èªãããšãClaude Code 㯠Plan Mode ãçµäºããPlan Mode ã«å ¥ãåã«ã¢ã¯ãã£ãã ã£ãèš±å¯ã¢ãŒãã埩å ããŸãããã©ã³ã¹ã¯ãªããã¯ããã€ã¢ãã°ã衚瀺ãããã¯ãã®å Žæã«ãAllowed by PermissionRequest hookããšè¡šç€ºãããŸããHook ãã¹ã¯åžžã«çŸåšã®äŒè©±ãä¿æããŸãïŒãã€ã¢ãã°ãã§ããããã«ãã³ã³ããã¹ããã¯ãªã¢ããŠæ°ããå®è£ ã»ãã·ã§ã³ãéå§ããããšã¯ã§ããŸããã
ç¹å®ã®èš±å¯ã¢ãŒããèšå®ãã代ããã«ãhook ã®åºåã« setMode ãšã³ããªãå«ã updatedPermissions é
åãå«ããããšãã§ããŸããmode å€ã¯ defaultãacceptEditsããŸã㯠bypassPermissions ãªã©ã®ä»»æã®èš±å¯ã¢ãŒãã§ãããdestination: "session" ã¯çŸåšã®ã»ãã·ã§ã³ã®ã¿ã«é©çšããŸãã
bypassPermissions ã¯ãã»ãã·ã§ã³ãæ¢ã«ãã€ãã¹ã¢ãŒãã§èµ·åãããå Žåã«ã®ã¿é©çšãããŸãïŒ--dangerously-skip-permissionsã--permission-mode bypassPermissionsã--allow-dangerously-skip-permissionsããŸãã¯èšå®ã® permissions.defaultMode: "bypassPermissions"ãããã³ permissions.disableBypassPermissionsMode ã§ç¡å¹åãããŠããªãå ŽåãdefaultMode ãšããŠæ°žç¶åãããããšã¯ãããŸããã
ã»ãã·ã§ã³ã acceptEdits ã«åãæ¿ããã«ã¯ãhook 㯠stdout ã«æ¬¡ã® JSON ãæžã蟌ã¿ãŸãïŒ
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "allow",
"updatedPermissions": [
{ "type": "setMode", "mode": "acceptEdits", "destination": "session" }
]
}
}
}
ãããã£ãŒãã§ããã ãçãä¿ã¡ãŸãã.* ã§ãããã³ã°ãããããããã£ãŒã空ã®ãŸãŸã«ãããšããã¡ã€ã«æžã蟌ã¿ãã·ã§ã«ã³ãã³ããå«ããã¹ãŠã®èš±å¯ããã³ãããèªåæ¿èªãããŸããæ±ºå®ãã£ãŒã«ãã®å®å
šãªã»ããã«ã€ããŠã¯ãPermissionRequest ãªãã¡ã¬ã³ã¹ ãåç
§ããŠãã ããã
hooks ã®ä»çµã¿
Hook ã€ãã³ã㯠Claude Code ã®ã©ã€ããµã€ã¯ã«ã®ç¹å®ã®ãã€ã³ãã§çºç«ããŸããã€ãã³ããçºç«ãããšããã¹ãŠã®ãããã³ã°ãã hooks ã䞊åã§å®è¡ãããåäžã® hook ã³ãã³ãã¯èªåçã«éè€æé€ãããŸãã以äžã®è¡šã¯åã€ãã³ããšãããããªã¬ãŒããããšãã瀺ããŠããŸãïŒ
| Event | When it fires |
|---|---|
SessionStart |
When a session begins or resumes |
Setup |
When you start Claude Code with --init-only, or with --init or --maintenance in -p mode. For one-time preparation in CI or scripts |
UserPromptSubmit |
When you submit a prompt, before Claude processes it |
UserPromptExpansion |
When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |
PreToolUse |
Before a tool call executes. Can block it |
PermissionRequest |
When a permission dialog appears |
PermissionDenied |
When a tool call is denied by the auto mode classifier. Return {retry: true} to tell the model it may retry the denied tool call |
PostToolUse |
After a tool call succeeds |
PostToolUseFailure |
After a tool call fails |
PostToolBatch |
After a full batch of parallel tool calls resolves, before the next model call |
Notification |
When Claude Code sends a notification |
SubagentStart |
When a subagent is spawned |
SubagentStop |
When a subagent finishes |
TaskCreated |
When a task is being created via TaskCreate |
TaskCompleted |
When a task is being marked as completed |
Stop |
When Claude finishes responding |
StopFailure |
When the turn ends due to an API error. Output and exit code are ignored |
TeammateIdle |
When an agent team teammate is about to go idle |
InstructionsLoaded |
When a CLAUDE.md or .claude/rules/*.md file is loaded into context. Fires at session start and when files are lazily loaded during a session |
ConfigChange |
When a configuration file changes during a session |
CwdChanged |
When the working directory changes, for example when Claude executes a cd command. Useful for reactive environment management with tools like direnv |
FileChanged |
When a watched file changes on disk. The matcher field specifies which filenames to watch |
WorktreeCreate |
When a worktree is being created via --worktree or isolation: "worktree". Replaces default git behavior |
WorktreeRemove |
When a worktree is being removed, either at session exit or when a subagent finishes |
PreCompact |
Before context compaction |
PostCompact |
After context compaction completes |
Elicitation |
When an MCP server requests user input during a tool call |
ElicitationResult |
After a user responds to an MCP elicitation, before the response is sent back to the server |
SessionEnd |
When a session terminates |
è€æ°ã® hooks ããããããå Žåããããããç¬èªã®çµæãè¿ããŸããæ±ºå®ã«ã€ããŠã¯ãClaude Code ã¯æãå¶éçãªçããéžæããŸããPreToolUse hook ã deny ãè¿ããšãä»ãäœãè¿ããã«é¢ããããããŒã«åŒã³åºãããã£ã³ã»ã«ãããŸãã1 ã€ã® hook ã ask ãè¿ããšãæ®ãã allow ãè¿ããŠããèš±å¯ããã³ããã匷å¶ãããŸããadditionalContext ããã®ããã¹ãã¯ãã¹ãŠã® hook ããä¿æãããClaude ã«äžç·ã«æž¡ãããŸãã
å hook ã«ã¯ããããã©ã®ããã«å®è¡ãããããæ±ºå®ãã type ããããŸããã»ãšãã©ã® hooks 㯠"type": "command" ã䜿çšããã·ã§ã«ã³ãã³ããå®è¡ããŸããä»ã® 4 ã€ã®ã¿ã€ããå©çšå¯èœã§ãïŒ
"type": "http"ïŒã€ãã³ãããŒã¿ã URL ã« POST ããŸããHTTP hooks ãåç §ããŠãã ããã"type": "mcp_tool"ïŒæ¢ã«æ¥ç¶ãããŠãã MCP ãµãŒããŒäžã®ããŒã«ãåŒã³åºããŸããMCP tool hooks ãåç §ããŠãã ããã"type": "prompt"ïŒã·ã³ã°ã«ã¿ãŒã³ LLM è©äŸ¡ãããã³ããããŒã¹ã® hooks ãåç §ããŠãã ããã"type": "agent"ïŒããŒã«ã¢ã¯ã»ã¹ä»ããã«ãã¿ãŒã³æ€èšŒããšãŒãžã§ã³ã hooks ã¯å®éšçã§ããã倿Žãããå¯èœæ§ããããŸãããšãŒãžã§ã³ãããŒã¹ã® hooks ãåç §ããŠãã ããã
å ¥åãèªã¿åããåºåãè¿ã
Hooks 㯠stdinãstdoutãstderrãããã³çµäºã³ãŒããéã㊠Claude Code ãšéä¿¡ããŸããã€ãã³ããçºç«ãããšãClaude Code ã¯ã€ãã³ãåºæã®ããŒã¿ã JSON ãšããŠã¹ã¯ãªããã® stdin ã«æž¡ããŸããã¹ã¯ãªããã¯ãã®ããŒã¿ãèªã¿åããäœæ¥ãè¡ããçµäºã³ãŒããéã㊠Claude Code ã«æ¬¡ã«äœãããããäŒããŸãã
Hook å ¥å
ãã¹ãŠã®ã€ãã³ãã«ã¯ session_id ãš cwd ãªã©ã®å
±éãã£ãŒã«ããå«ãŸããŠããŸãããåã€ãã³ãã¿ã€ãã¯ç°ãªãããŒã¿ã远å ããŸããããšãã°ãClaude ã Bash ã³ãã³ããå®è¡ãããšããPreToolUse hook 㯠stdin ã§æ¬¡ã®ãããªãã®ãåãåããŸãïŒ
{
"session_id": "abc123", // ãã®ã»ãã·ã§ã³ã®äžæã® ID
"cwd": "/Users/sarah/myproject", // ã€ãã³ããçºç«ãããšãã®äœæ¥ãã£ã¬ã¯ããª
"hook_event_name": "PreToolUse", // ãã® hook ãããªã¬ãŒããã€ãã³ã
"tool_name": "Bash", // Claude ã䜿çšããããšããŠããããŒã«
"tool_input": { // Claude ãããŒã«ã«æž¡ããåŒæ°
"command": "npm test" // Bash ã®å Žåãããã¯ã·ã§ã«ã³ãã³ã
}
}
ã¹ã¯ãªããã¯ãã® JSON ãè§£æãããããã®ãã£ãŒã«ãã®ããããã«åºã¥ããŠåäœã§ããŸããUserPromptSubmit hooks ã¯ä»£ããã« prompt ããã¹ããååŸããSessionStart hooks 㯠sourceïŒstartupãresumeãclearãcompactïŒãååŸãããªã©ããªãã¡ã¬ã³ã¹ã® å
±éå
¥åãã£ãŒã«ã ã§å
±æãã£ãŒã«ããåç
§ããåã€ãã³ãã®ã»ã¯ã·ã§ã³ã§ã€ãã³ãåºæã®ã¹ããŒããåç
§ããŠãã ããã
Hook åºå
ã¹ã¯ãªãã㯠stdout ãŸã㯠stderr ã«æžã蟌ã¿ãç¹å®ã®ã³ãŒãã§çµäºããããšã§ãClaude Code ã«æ¬¡ã«äœãããããäŒããŸããããšãã°ãã³ãã³ãããããã¯ããã PreToolUse hookïŒ
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
if echo "$COMMAND" | grep -q "drop table"; then
echo "Blocked: dropping tables is not allowed" >&2 # stderr 㯠Claude ã®ãã£ãŒãããã¯ã«ãªããŸã
exit 2 # exit 2 = ã¢ã¯ã·ã§ã³ããããã¯
fi
exit 0 # exit 0 = ç¶è¡ããã
çµäºã³ãŒãã¯æ¬¡ã«äœãèµ·ããããæ±ºå®ããŸãïŒ
- çµäº 0ïŒã¢ã¯ã·ã§ã³ãç¶è¡ãããŸãã
UserPromptSubmitãUserPromptExpansionãããã³SessionStarthooks ã®å Žåãstdout ã«æžã蟌ããã¹ãŠã®ãã®ã Claude ã®ã³ã³ããã¹ãã«è¿œå ãããŸãã - çµäº 2ïŒã¢ã¯ã·ã§ã³ããããã¯ãããŸããstderr ã«çç±ãæžã蟌ã¿ãClaude ã¯ããããã£ãŒãããã¯ãšããŠåãåãããã調æŽã§ããŸããäžéšã®ã€ãã³ãã¯ãããã¯ã§ããŸããïŒ
SessionStartãSetupãNotificationãªã©ã®å Žåãçµäº 2 㯠stderr ããŠãŒã¶ãŒã«è¡šç€ºããå®è¡ã¯ç¶è¡ãããŸããã€ãã³ãããšã®çµäºã³ãŒã 2 ã®åäœ ã§å®å šãªãªã¹ããåç §ããŠãã ããã - ãã®ä»ã®çµäºã³ãŒãïŒã¢ã¯ã·ã§ã³ãç¶è¡ãããŸãããã©ã³ã¹ã¯ãªããã¯
<hook name> hook erroréç¥ã衚瀺ãããã®åŸ stderr ã®æåã®è¡ãç¶ããŸããå®å šãª stderr 㯠ãããã°ãã° ã«èšé²ãããŸãã
æ§é å JSON åºå
çµäºã³ãŒã㯠2 ã€ã®ãªãã·ã§ã³ãæäŸããŸãïŒèš±å¯ãŸãã¯ãããã¯ãããå€ãã®å¶åŸ¡ã®ããã«ãçµäº 0 ã㊠stdout ã« JSON ãªããžã§ã¯ããåºåããŸãã
çµäº 2 ã§ stderr ã¡ãã»ãŒãžã§ãããã¯ããããçµäº 0 ã§ JSON ã§æ§é åå¶åŸ¡ã䜿çšããŸããæ··åšãããªãã§ãã ããïŒClaude Code ã¯çµäº 2 ã®ãšãã« JSON ãç¡èŠããŸãã
ããšãã°ãPreToolUse hook ã¯ããŒã«åŒã³åºããæåŠããŠçç±ã Claude ã«äŒãããããŠãŒã¶ãŒã®æ¿èªã®ããã«ãšã¹ã«ã¬ãŒããããã§ããŸãïŒ
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Use rg instead of grep for better performance"
}
}
"deny" ã䜿çšãããšãClaude Code ã¯ããŒã«åŒã³åºãããã£ã³ã»ã«ããpermissionDecisionReason ã Claude ã«ãã£ãŒãããã¯ãšããŠè¿ããŸãããããã® permissionDecision å€ã¯ PreToolUse ã«åºæã§ãïŒ
"allow"ïŒã€ã³ã¿ã©ã¯ãã£ããªèš±å¯ããã³ãããã¹ãããããŸããDeny ããã³ ask ã«ãŒã«ïŒãšã³ã¿ãŒãã©ã€ãºç®¡ç deny ãªã¹ããå«ãïŒã¯åŒãç¶ãé©çšãããŸã"deny"ïŒããŒã«åŒã³åºãããã£ã³ã»ã«ããçç±ã Claude ã«éä¿¡ããŸã"ask"ïŒéåžžã©ãããŠãŒã¶ãŒã«èš±å¯ããã³ããã衚瀺ããŸã
4 çªç®ã®å€ "defer" ã¯ã-p ãã©ã°ä»ãã® éã€ã³ã¿ã©ã¯ãã£ãã¢ãŒã ã§å©çšå¯èœã§ããããã»ã¹ãçµäºããããŒã«åŒã³åºããä¿æããŠãAgent SDK ã©ãããŒãå
¥åãåéããŠåéã§ããããã«ããŸãããªãã¡ã¬ã³ã¹ã® ããŒã«åŒã³åºããåŸã§å»¶æãã ãåç
§ããŠãã ããã
"allow" ãè¿ããšã€ã³ã¿ã©ã¯ãã£ãããã³ãããã¹ãããããŸãããèš±å¯ã«ãŒã« ããªãŒããŒã©ã€ãããŸãããDeny ã«ãŒã«ãããŒã«åŒã³åºãã«ãããããå Žåãhook ã "allow" ãè¿ããŠãåŒã³åºãã¯ãããã¯ãããŸããAsk ã«ãŒã«ããããããå ŽåããŠãŒã¶ãŒã¯ãŸã ããã³ããã衚瀺ãããŸããããã¯ã管çèšå® ãå«ããã¹ãŠã®èšå®ã¹ã³ãŒãããã® deny ã«ãŒã«ããhook æ¿èªãããåžžã«åªå
ãããããšãæå³ããŸãã
ä»ã®ã€ãã³ãã¯ç°ãªã決å®ãã¿ãŒã³ã䜿çšããŸããããšãã°ãPostToolUse ããã³ Stop hooks ã¯ãããã¬ãã«ã® decision: "block" ãã£ãŒã«ãã䜿çšããPermissionRequest 㯠hookSpecificOutput.decision.behavior ã䜿çšããŸãããªãã¡ã¬ã³ã¹ã® ãµããªãŒããŒãã« ã§ã€ãã³ãå¥ã®å®å
šãªå
èš³ãåç
§ããŠãã ããã
UserPromptSubmit hooks ã®å Žåã代ããã« additionalContext ã䜿çšã㊠Claude ã®ã³ã³ããã¹ãã«ããã¹ããæ³šå
¥ããŸããããã³ããããŒã¹ã® hooksïŒtype: "prompt"ïŒã¯åºåãç°ãªãæ¹æ³ã§åŠçããŸãïŒããã³ããããŒã¹ã® hooks ãåç
§ããŠãã ããã
ãããã£ãŒã§ hooks ããã£ã«ã¿ãªã³ã°ãã
ãããã£ãŒãªãã§ã¯ãhook ã¯ãã®ã€ãã³ãã®ãã¹ãŠã®çºçã§çºç«ããŸãããããã£ãŒã䜿çšãããšããããçµã蟌ãããšãã§ããŸããããšãã°ããã¡ã€ã«ç·šéåŸã«ã®ã¿ãã©ãŒããã¿ãŒãå®è¡ãããå ŽåïŒãã¹ãŠã®ããŒã«åŒã³åºãã®åŸã§ã¯ãªãïŒãPostToolUse hook ã«ãããã£ãŒã远å ããŸãïŒ
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "prettier --write ..." }
]
}
]
}
}
"Edit|Write" ãããã£ãŒã¯ Edit ãŸã㯠Write ããŒã«åŒã³åºãã§ã®ã¿çºç«ããBashãReadããŸãã¯ä»ã®ããŒã«ã§ã¯çºç«ããŸããããããã£ãŒãã¿ãŒã³ ãåç
§ããŠããã¬ãŒã³åãšæ£èŠè¡šçŸãã©ã®ããã«è©äŸ¡ããããã確èªããŠãã ããã
Claude ã¯ãŸããBash ããŒã«ãéããŠã·ã§ã«ã³ãã³ããå®è¡ããããšã§ãã¡ã€ã«ãäœæãŸãã¯å€æŽã§ããŸããã³ã³ãã©ã€ã¢ã³ã¹ã¹ãã£ã³ãŸãã¯ç£æ»ãã°ãªã©ãhook ããã¹ãŠã®ãã¡ã€ã«å€æŽã確èªããå¿
èŠãããå Žåã¯ãã¿ãŒã³ããšã« 1 åäœæ¥ããªãŒãã¹ãã£ã³ãã Stop hook ã远å ããŠãã ãããåŒã³åºãããšã®ã«ãã¬ããžã®å Žåã¯ãBash ãããããããã¹ã¯ãªããã§ git status --porcelain ã䜿çšããŠå€æŽããããã¡ã€ã«ãšè¿œè·¡ãããŠããªããã¡ã€ã«ããªã¹ãã¢ããããŠãã ããã
åã€ãã³ãã¿ã€ãã¯ç¹å®ã®ãã£ãŒã«ãã§ãããããŸãïŒ
| ã€ãã³ã | ãããã£ãŒããã£ã«ã¿ãªã³ã°ãããã® | ãããã£ãŒå€ã®äŸ |
|---|---|---|
PreToolUseãPostToolUseãPostToolUseFailureãPermissionRequestãPermissionDenied |
ããŒã«å | BashãEdit|Writeãmcp__.* |
SessionStart |
ã»ãã·ã§ã³ãã©ã®ããã«éå§ãããã | startupãresumeãclearãcompact |
Setup |
ã©ã® CLI ãã©ã°ãã»ããã¢ãããããªã¬ãŒããã | initãmaintenance |
SessionEnd |
ã»ãã·ã§ã³ãçµäºããçç± | clearãresumeãlogoutãprompt_input_exitãbypass_permissions_disabledãother |
Notification |
éç¥ã¿ã€ã | permission_promptãidle_promptãauth_successãelicitation_dialogãelicitation_completeãelicitation_response |
SubagentStart |
ãšãŒãžã§ã³ãã¿ã€ã | general-purposeãExploreãPlanããŸãã¯ã«ã¹ã¿ã ãšãŒãžã§ã³ãå |
PreCompactãPostCompact |
å§çž®ãããªã¬ãŒãããã® | manualãauto |
SubagentStop |
ãšãŒãžã§ã³ãã¿ã€ã | SubagentStart ãšåãå€ |
ConfigChange |
èšå®ãœãŒã¹ | user_settingsãproject_settingsãlocal_settingsãpolicy_settingsãskills |
StopFailure |
ãšã©ãŒã¿ã€ã | rate_limitãauthentication_failedãoauth_org_not_allowedãbilling_errorãinvalid_requestãserver_errorãmax_output_tokensãunknown |
InstructionsLoaded |
ããŒãçç± | session_startãnested_traversalãpath_glob_matchãincludeãcompact |
Elicitation |
MCP ãµãŒããŒå | èšå®ãã MCP ãµãŒããŒå |
ElicitationResult |
MCP ãµãŒããŒå | Elicitation ãšåãå€ |
FileChanged |
ãªãã©ã«ãã¡ã€ã«åãç£èŠïŒFileChanged ãåç §ïŒ | .envrc|.env |
UserPromptExpansion |
ã³ãã³ãå | ã¹ãã«ãŸãã¯ã³ãã³ãå |
UserPromptSubmitãPostToolBatchãStopãTeammateIdleãTaskCreatedãTaskCompletedãWorktreeCreateãWorktreeRemoveãCwdChanged |
ãããã£ãŒãµããŒããªã | ãã¹ãŠã®çºçã§åžžã«çºç« |
ç°ãªãã€ãã³ãã¿ã€ãã®ãããã£ãŒã瀺ãããã€ãã®äŸïŒ
Bash ããŒã«åŒã³åºãã®ã¿ããããããåã³ãã³ãããã¡ã€ã«ã«ãã°ã«èšé²ããŸããPostToolUse ã€ãã³ãã¯ã³ãã³ããå®äºããåŸã«çºç«ãããããtool_input.command ã¯å®è¡ããããã®ãå«ã¿ãŸããHook 㯠stdin ã§ JSON ãšããŠã€ãã³ãããŒã¿ãåãåããjq -r '.tool_input.command' ã¯ã³ãã³ãæååã®ã¿ãæœåºãã>> ã¯ãã°ãã¡ã€ã«ã«è¿œå ããŸãïŒ
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
}
]
}
]
}
}
MCP ããŒã«ã¯çµã¿èŸŒã¿ããŒã«ãšã¯ç°ãªãåœåèŠåã䜿çšããŸãïŒmcp__<server>__<tool>ãããã§ <server> 㯠MCP ãµãŒããŒåã§ã<tool> ã¯ãããæäŸããããŒã«ã§ããããšãã°ãmcp__github__search_repositories ãŸã㯠mcp__filesystem__read_fileãç¹å®ã®ãµãŒããŒãããã¹ãŠã®ããŒã«ãã¿ãŒã²ããããããã«æ£èŠè¡šçŸãããã£ãŒã䜿çšããããmcp__.*__write.* ã®ãããªãã¿ãŒã³ã§ãµãŒããŒå
šäœã§ãããããŸãããªãã¡ã¬ã³ã¹ã® MCP ããŒã«ããããããã ãåç
§ããŠãå®å
šãªäŸã®ãªã¹ãã確èªããŠãã ããã
以äžã®ã³ãã³ã㯠hook ã® JSON å
¥åããããŒã«åã jq ã§æœåºããstderr ã«æžã蟌ã¿ãŸããstderr ã«æžã蟌ãããšã§ stdout ãã¯ãªãŒã³ã«ä¿ã¡ãã¡ãã»ãŒãžã ãããã°ãã° ã«éä¿¡ããŸãïŒ
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__github__.*",
"hooks": [
{
"type": "command",
"command": "echo \"GitHub tool called: $(jq -r '.tool_name')\" >&2"
}
]
}
]
}
}
SessionEnd ã€ãã³ãã¯ã»ãã·ã§ã³ãçµäºããçç±ã®ãããã£ãŒããµããŒãããŸãããã® hook 㯠clearïŒ/clear ãå®è¡ãããšãïŒã§ã®ã¿çºç«ããéåžžã®çµäºã§ã¯çºç«ããŸããïŒ
{
"hooks": {
"SessionEnd": [
{
"matcher": "clear",
"hooks": [
{
"type": "command",
"command": "rm -f /tmp/claude-scratch-*.txt"
}
]
}
]
}
}
å®å šãªãããã£ãŒæ§æã«ã€ããŠã¯ãHooks ãªãã¡ã¬ã³ã¹ ãåç §ããŠãã ããã
if ãã£ãŒã«ãã§ããŒã«åãšåŒæ°ã§ãã£ã«ã¿ãªã³ã°ãã
if ãã£ãŒã«ãã«ã¯ Claude Code v2.1.85 以éãå¿
èŠã§ãã以åã®ããŒãžã§ã³ã¯ãããç¡èŠããããããããã¹ãŠã®åŒã³åºãã§ hook ãå®è¡ããŸãã
if ãã£ãŒã«ã㯠蚱å¯ã«ãŒã«æ§æ ã䜿çšããŠãããŒã«åãšåŒæ°ã®äž¡æ¹ã§ hooks ããã£ã«ã¿ãªã³ã°ãããããhook ããã»ã¹ã¯ããŒã«åŒã³åºããããããããšãã«ã®ã¿çæãããŸãããã㯠matcher ãè¶
ããŠãããããŒã«åã®ã¿ã§ã°ã«ãŒãã¬ãã«ã§ãã£ã«ã¿ãªã³ã°ããŸãã
ããšãã°ããã¹ãŠã® Bash ã³ãã³ãã§ã¯ãªããClaude ã git ã³ãã³ãã䜿çšãããšãã«ã®ã¿ hook ãå®è¡ããã«ã¯ïŒ
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(git *)",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-git-policy.sh"
}
]
}
]
}
}
Hook ããã»ã¹ã¯ Bash ã³ãã³ãã git * ã«ããããããšãã«ã®ã¿çæãããŸãããŸãã¯ãã³ãã³ããè§£æããã«ã¯è€éããããšãã§ããnpm test && git push ã®ãããªè€åã³ãã³ãã®å ŽåãClaude Code ã¯åãµãã³ãã³ããè©äŸ¡ããgit push ãããããããã hook ãçºç«ãããŸããif ãã£ãŒã«ãã¯èš±å¯ã«ãŒã«ãšåããã¿ãŒã³ãåãå
¥ããŸãïŒ"Bash(git *)"ã"Edit(*.ts)" ãªã©ãè€æ°ã®ããŒã«åãããããããã«ã¯ãããããç¬èªã® if å€ãæã€å¥ã®ãã³ãã©ãŒã䜿çšãããããã€ã亀æ¿ããµããŒããããŠãã matcher ã¬ãã«ã§ãããããŸãã
if ã¯ããŒã«ã€ãã³ãã§ã®ã¿æ©èœããŸãïŒPreToolUseãPostToolUseãPostToolUseFailureãPermissionRequestãããã³ PermissionDeniedãä»ã®ã€ãã³ãã«è¿œå ãããšãhook ãå®è¡ãããã®ãé²ããŸãã
hook ã®å Žæãèšå®ãã
Hook ã远å ããå Žæããã®ã¹ã³ãŒããæ±ºå®ããŸãïŒ
| å Žæ | ã¹ã³ãŒã | å ±æå¯èœ |
|---|---|---|
~/.claude/settings.json |
ãã¹ãŠã®ãããžã§ã¯ã | ãããããã·ã³ã«ããŒã«ã« |
.claude/settings.json |
åäžãããžã§ã¯ã | ã¯ãããªããžããªã«ã³ãããå¯èœ |
.claude/settings.local.json |
åäžãããžã§ã¯ã | ããããgitignored |
| 管çããªã·ãŒèšå® | çµç¹å šäœ | ã¯ãã管çè å¶åŸ¡ |
Plugin hooks/hooks.json |
ãã©ã°ã€ã³ãæå¹ãªãšã | ã¯ãããã©ã°ã€ã³ã«ãã³ãã« |
| Skill ãŸã㯠agent frontmatter | ã¹ãã«ãŸãã¯ãšãŒãžã§ã³ããã¢ã¯ãã£ããªãšã | ã¯ããã³ã³ããŒãã³ããã¡ã€ã«ã§å®çŸ© |
Claude Code ã§ /hooks ãå®è¡ããŠãã€ãã³ãå¥ã«ã°ã«ãŒãåããããã¹ãŠã®èšå®æžã¿ hooks ãåç
§ããŸãããã¹ãŠã® hooks ãäžåºŠã«ç¡å¹ã«ããã«ã¯ãèšå®ãã¡ã€ã«ã§ "disableAllHooks": true ãèšå®ããŸãã
Claude Code ãå®è¡äžã«èšå®ãã¡ã€ã«ãçŽæ¥ç·šéããå Žåããã¡ã€ã«ãŠã©ããã£ãŒã¯éåžžãhook ã®å€æŽãèªåçã«ååŸããŸãã
ããã³ããããŒã¹ã® hooks
決å®è«çãªã«ãŒã«ã§ã¯ãªã倿ãå¿
èŠãªæ±ºå®ã«ã€ããŠã¯ãtype: "prompt" hooks ã䜿çšããŸããã·ã§ã«ã³ãã³ããå®è¡ãã代ããã«ãClaude Code ã¯ããã³ãããš hook ã®å
¥åããŒã¿ã Claude ã¢ãã«ïŒããã©ã«ãã§ã¯ HaikuïŒã«éä¿¡ããŠæ±ºå®ãäžããŸããããå€ãã®æ©èœãå¿
èŠãªå Žåã¯ãmodel ãã£ãŒã«ãã§ç°ãªãã¢ãã«ãæå®ã§ããŸãã
ã¢ãã«ã®å¯äžã®ä»äºã¯ãyes/no 決å®ã JSON ãšããŠè¿ãããšã§ãïŒ
"ok": trueïŒã¢ã¯ã·ã§ã³ãç¶è¡ãããŸã"ok": falseïŒäœãèµ·ãããã¯ã€ãã³ãã«ãã£ãŠç°ãªããŸãïŒStopããã³SubagentStopïŒreason㯠Claude ã«ãã£ãŒãããã¯ãšããŠè¿ããããããäœæ¥ãç¶ããŸãPreToolUseïŒããŒã«åŒã³åºããæåŠãããreasonã¯ããŒã«ãšã©ãŒãšã㊠Claude ã«è¿ãããããã調æŽããŠç¶è¡ã§ããŸãPostToolUseãPostToolBatchãUserPromptSubmitãããã³UserPromptExpansionïŒã¿ãŒã³ãçµäºããreasonã¯èŠåè¡ãšããŠãã£ããã«è¡šç€ºãããŸã
ãã®äŸã¯ Stop hook ã䜿çšããŠãèŠæ±ããããã¹ãŠã®ã¿ã¹ã¯ãå®äºããŠãããã©ãããã¢ãã«ã«å°ããŸããã¢ãã«ã "ok": false ãè¿ãå ŽåãClaude ã¯äœæ¥ãç¶ããreason ãæ¬¡ã®æç€ºãšããŠäœ¿çšããŸãïŒ
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Check if all tasks are complete. If not, respond with {\"ok\": false, \"reason\": \"what remains to be done\"}."
}
]
}
]
}
}
å®å šãªèšå®ãªãã·ã§ã³ã«ã€ããŠã¯ããªãã¡ã¬ã³ã¹ã® ããã³ããããŒã¹ã® hooks ãåç §ããŠãã ããã
ãšãŒãžã§ã³ãããŒã¹ã® hooks
ãšãŒãžã§ã³ã hooks ã¯å®éšçã§ããåäœãšèšå®ã¯å°æ¥ã®ãªãªãŒã¹ã§å€æŽãããå¯èœæ§ããããŸããæ¬çªã¯ãŒã¯ãããŒã«ã€ããŠã¯ãã³ãã³ã hooks ãåªå ããŠãã ããã
æ€èšŒããã¡ã€ã«ã®æ€æ»ãŸãã¯ã³ãã³ãã®å®è¡ãå¿
èŠãšããå Žåãtype: "agent" hooks ã䜿çšããŸããããã³ãã hooks ã¯åäžã® LLM åŒã³åºããè¡ããŸããããšãŒãžã§ã³ã hooks ã¯æ¡ä»¶ãè¿ãåã«ãã¡ã€ã«ãèªã¿åããã³ãŒããæ€çŽ¢ããä»ã®ããŒã«ã䜿çšã§ãã subagent ãçæããŸãã
ãšãŒãžã§ã³ã hooks ã¯ããã³ãã hooks ãšåã "ok" / "reason" å¿ç圢åŒã䜿çšããŸãããããã©ã«ãã®ã¿ã€ã ã¢ãŠãã 60 ç§ã§ãæå€§ 50 ããŒã«äœ¿çšã¿ãŒã³ã§ãã
ãã®äŸã¯ Claude ã忢ããããšãèš±å¯ããåã«ãã¹ããåæ Œããããšãæ€èšŒããŸãïŒ
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "agent",
"prompt": "Verify that all unit tests pass. Run the test suite and check the results. $ARGUMENTS",
"timeout": 120
}
]
}
]
}
}
Hook å ¥åããŒã¿ã ãã§æ±ºå®ãäžãã®ã«ååãªå Žåã¯ããã³ãã hooks ã䜿çšããŸããã³ãŒãããŒã¹ã®å®éã®ç¶æ ã«å¯ŸããŠäœããæ€èšŒããå¿ èŠãããå Žåã¯ãšãŒãžã§ã³ã hooks ã䜿çšããŸãã
å®å šãªèšå®ãªãã·ã§ã³ã«ã€ããŠã¯ããªãã¡ã¬ã³ã¹ã® ãšãŒãžã§ã³ãããŒã¹ã® hooks ãåç §ããŠãã ããã
HTTP hooks
type: "http" hooks ã䜿çšããŠãã·ã§ã«ã³ãã³ããå®è¡ãã代ããã«ãã€ãã³ãããŒã¿ã HTTP ãšã³ããã€ã³ãã« POST ããŸãããšã³ããã€ã³ãã¯ã³ãã³ã hook ã stdin ã§åãåãã®ãšåã JSON ãåãåããHTTP ã¬ã¹ãã³ã¹ããã£ã䜿çšããŠåã JSON 圢åŒã§çµæãè¿ããŸãã
HTTP hooks ã¯ãWeb ãµãŒããŒãã¯ã©ãŠã颿°ããŸãã¯å€éšãµãŒãã¹ã« hook ããžãã¯ãåŠçããããå Žåã«äŸ¿å©ã§ããããšãã°ãããŒã å šäœã®ããŒã«äœ¿çšã€ãã³ãããã°ã«èšé²ããå ±æç£æ»ãµãŒãã¹ã
ãã®äŸã¯ãã¹ãŠã®ããŒã«äœ¿çšãããŒã«ã«ãã°ãµãŒãã¹ã« POST ããŸãïŒ
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "http",
"url": "http://localhost:8080/hooks/tool-use",
"headers": {
"Authorization": "Bearer $MY_TOKEN"
},
"allowedEnvVars": ["MY_TOKEN"]
}
]
}
]
}
}
ãšã³ããã€ã³ãã¯ãã³ãã³ã hooks ãšåã åºååœ¢åŒ ã䜿çšã㊠JSON ã¬ã¹ãã³ã¹ããã£ãè¿ãå¿
èŠããããŸããããŒã«åŒã³åºãããããã¯ããã«ã¯ãé©å㪠hookSpecificOutput ãã£ãŒã«ãã§ 2xx ã¬ã¹ãã³ã¹ãè¿ããŸããHTTP ã¹ããŒã¿ã¹ã³ãŒãã ãã§ã¯ã¢ã¯ã·ã§ã³ããããã¯ã§ããŸããã
ããããŒå€ã¯ $VAR_NAME ãŸã㯠${VAR_NAME} æ§æã䜿çšããç°å¢å€æ°è£éããµããŒãããŸããallowedEnvVars é
åã«ãªã¹ããããŠãã倿°ã®ã¿ã解決ãããŸããä»ã®ãã¹ãŠã® $VAR åç
§ã¯ç©ºã®ãŸãŸã§ãã
å®å šãªèšå®ãªãã·ã§ã³ãšã¬ã¹ãã³ã¹åŠçã«ã€ããŠã¯ããªãã¡ã¬ã³ã¹ã® HTTP hooks ãåç §ããŠãã ããã
å¶éãšãã©ãã«ã·ã¥ãŒãã£ã³ã°
å¶é
- ã³ãã³ã hooks 㯠stdoutãstderrãããã³çµäºã³ãŒããéããŠã®ã¿éä¿¡ããŸãããããã¯
/ã³ãã³ããŸãã¯ããŒã«åŒã³åºããããªã¬ãŒã§ããŸãããadditionalContextãéããŠè¿ãããããã¹ãã¯ãClaude ãå¹³æãšããŠèªãã·ã¹ãã ãªãã€ã³ããŒãšããŠæ³šå ¥ãããŸããHTTP hooks ã¯ã¬ã¹ãã³ã¹ããã£ãéããŠéä¿¡ããŸãã - Hook ã¿ã€ã ã¢ãŠãã¯ããã©ã«ãã§ 10 åã§ãhook ããšã«
timeoutãã£ãŒã«ãïŒç§åäœïŒã§èšå®å¯èœã§ãã PostToolUsehooks ã¯ããŒã«ãæ¢ã«å®è¡ãããŠãããããã¢ã¯ã·ã§ã³ãå ã«æ»ãããšã¯ã§ããŸãããPermissionRequesthooks 㯠éã€ã³ã¿ã©ã¯ãã£ãã¢ãŒãïŒ-pïŒã§ã¯çºç«ããŸãããèªååãããèš±å¯æ±ºå®ã«ã¯PreToolUsehooks ã䜿çšããŸããStophooks ã¯ã¿ã¹ã¯å®äºæã ãã§ãªããClaude ãå¿çãçµäºãããã³ã«çºç«ããŸãããŠãŒã¶ãŒã®å²ã蟌ã¿ã§ã¯çºç«ããŸãããAPI ãšã©ãŒã¯ä»£ããã« StopFailure ãçºç«ãããŸãã- è€æ°ã® PreToolUse hooks ã
updatedInputãè¿ããŠããŒã«ã®åŒæ°ãæžãçŽãå ŽåãæåŸã«å®äºãããã®ãåã¡ãŸããHooks ã¯äžŠåã§å®è¡ããããããé åºã¯é決å®çã§ããåãããŒã«ã®å ¥åã倿Žããè€æ°ã® hooks ãæã€ããšãé¿ããŠãã ããã
Hooks ãšèš±å¯ã¢ãŒã
PreToolUse hooks ã¯ä»»æã®èš±å¯ã¢ãŒããã§ãã¯ã®åã«çºç«ããŸããpermissionDecision: "deny" ãè¿ã hook ã¯ãbypassPermissions ã¢ãŒããŸã㯠--dangerously-skip-permissions ã§ãããŒã«ããããã¯ããŸããããã«ããããŠãŒã¶ãŒãèš±å¯ã¢ãŒãã倿ŽããŠãã€ãã¹ã§ããªãããªã·ãŒãé©çšã§ããŸãã
éã¯çã§ã¯ãããŸããïŒ"allow" ãè¿ã hook ã¯ãèšå®ããã® deny ã«ãŒã«ããã€ãã¹ããŸãããHooks ã¯å¶éãå³ããã§ããŸãããèš±å¯ã«ãŒã«ãèš±å¯ããç¯å²ãè¶
ããŠç·©åããããšã¯ã§ããŸããã
Hook ãçºç«ããªã
Hook ã¯èšå®ãããŠããŸãããå®è¡ãããŸããã
/hooksãå®è¡ããhook ãæ£ããã€ãã³ãã®äžã«è¡šç€ºãããããšã確èªããŸã- ãããã£ãŒãã¿ãŒã³ãããŒã«åãšæ£ç¢ºã«ãããããããšã確èªããŸãïŒãããã£ãŒã¯å€§æåå°æåãåºå¥ããŸãïŒ
- æ£ããã€ãã³ãã¿ã€ããããªã¬ãŒããŠããããšã確èªããŸãïŒäŸïŒ
PreToolUseã¯ããŒã«å®è¡åã«çºç«ããPostToolUseã¯åŸã«çºç«ããŸãïŒ - éã€ã³ã¿ã©ã¯ãã£ãã¢ãŒãïŒ
-pïŒã§PermissionRequesthooks ã䜿çšããŠããå Žåã¯ã代ããã«PreToolUseã«åãæ¿ããŸã
Hook ãšã©ãŒãåºåã«è¡šç€ºããã
ãã©ã³ã¹ã¯ãªããã«ãPreToolUse hook error: ...ããšããã¡ãã»ãŒãžã衚瀺ãããŸãã
- ã¹ã¯ãªãããäºæãããŒã以å€ã®ã³ãŒãã§çµäºããŸããããµã³ãã« JSON ããã€ãããŠæåã§ãã¹ãããŸãïŒ
echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh echo $? # çµäºã³ãŒããç¢ºèª - ãcommand not foundãã衚瀺ãããå Žåã¯ã絶察ãã¹ã䜿çšããããã¹ã¯ãªãããåç
§ããããã«
$CLAUDE_PROJECT_DIRã䜿çšããŸã - ãjq: command not foundãã衚瀺ãããå Žåã¯ã
jqãã€ã³ã¹ããŒã«ããããJSON è§£æã« Python/Node.js ã䜿çšããŸã - ã¹ã¯ãªããããŸã£ããå®è¡ãããŠããªãå Žåã¯ãå®è¡å¯èœã«ããŸãïŒ
chmod +x ./my-hook.sh
/hooks ã«èšå®ããã hooks ã衚瀺ãããªã
èšå®ãã¡ã€ã«ãç·šéããŸããããhooks ãã¡ãã¥ãŒã«è¡šç€ºãããŸããã
- ãã¡ã€ã«ç·šéã¯éåžžèªåçã«ååŸãããŸããæ°ç§åŸã«è¡šç€ºãããŠããªãå Žåããã¡ã€ã«ãŠã©ããã£ãŒã倿ŽãèŠéããå¯èœæ§ããããŸãïŒã»ãã·ã§ã³ãåéããŠåŒ·å¶çã«ãªããŒãããŸãã
- JSON ãæå¹ã§ããããšã確èªããŸãïŒæ«å°Ÿã®ã³ã³ããšã³ã¡ã³ãã¯èš±å¯ãããŠããŸããïŒ
- èšå®ãã¡ã€ã«ãæ£ããå Žæã«ããããšã確èªããŸãïŒãããžã§ã¯ã hooks ã®å Žåã¯
.claude/settings.jsonãã°ããŒãã« hooks ã®å Žåã¯~/.claude/settings.json
Stop hook ãæ°žé ã«å®è¡ããã
Claude ã¯ç¡éã«ãŒãã§äœæ¥ãç¶ããŸãã忢ãã代ããã«ã
Stop hook ã¹ã¯ãªããã¯ããããæ¢ã«ããªã¬ãŒããããã©ããããã§ãã¯ããå¿
èŠããããŸããJSON å
¥åãã stop_hook_active ãã£ãŒã«ããè§£æããtrue ã®å Žåã¯æ©æã«çµäºããŸãïŒ
#!/bin/bash
INPUT=$(cat)
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
exit 0 # Claude ã忢ããããšãèš±å¯
fi
# ... hook ããžãã¯ã®æ®ã
JSON æ€èšŒã«å€±æããŸãã
Claude Code 㯠hook ã¹ã¯ãªãããæå¹ãª JSON ãåºåããŠããã«ãããããããJSON è§£æãšã©ãŒã衚瀺ããŸãã
Claude Code ã hook ãå®è¡ãããšãããããã¡ã€ã«ïŒ~/.zshrc ãŸã㯠~/.bashrcïŒããœãŒã¹ããã·ã§ã«ãçæããŸãããããã¡ã€ã«ã«ç¡æ¡ä»¶ã® echo ã¹ããŒãã¡ã³ããå«ãŸããŠããå Žåããã®åºå㯠hook ã® JSON ã«å眮ãããŸãïŒ
Shell ready on arm64
{"decision": "block", "reason": "Not allowed"}
Claude Code ã¯ããã JSON ãšããŠè§£æããããšããŠå€±æããŸãããããä¿®æ£ããã«ã¯ãã·ã§ã«ãããã¡ã€ã«ã® echo ã¹ããŒãã¡ã³ããã©ããããŠãã€ã³ã¿ã©ã¯ãã£ãã·ã§ã«ã§ã®ã¿å®è¡ããããã«ããŸãïŒ
# ~/.zshrc ãŸã㯠~/.bashrc å
if [[ $- == *i* ]]; then
echo "Shell ready"
fi
$- 倿°ã¯ã·ã§ã«ãã©ã°ãå«ã¿ãi ã¯ã€ã³ã¿ã©ã¯ãã£ããæå³ããŸããHooks ã¯éã€ã³ã¿ã©ã¯ãã£ãã·ã§ã«ã§å®è¡ããããããecho ã¯ã¹ããããããŸãã
ãããã°æè¡
ãã©ã³ã¹ã¯ãªãããã¥ãŒïŒCtrl+O ã§åãæ¿ãïŒã¯ãçºç«ããå hook ã® 1 è¡ã®ãµããªãŒã衚瀺ããŸãïŒæåã¯ç¡é³ãããããã³ã°ãšã©ãŒã¯ stderr ã衚瀺ããéããããã³ã°ãšã©ãŒã¯ <hook name> hook error éç¥ã衚瀺ãããã®åŸ stderr ã®æåã®è¡ãç¶ããŸãã
å®å
šãªå®è¡è©³çްïŒã©ã® hooks ãããããããããããã®çµäºã³ãŒããstdoutãstderr ãªã©ïŒã«ã€ããŠã¯ããããã°ãã°ãèªã¿ãŸããclaude --debug-file /tmp/claude.log ã§ Claude Code ãéå§ããŠæ¢ç¥ã®ãã¹ã«æžã蟌ã¿ãå¥ã®ã¿ãŒããã«ã§ tail -f /tmp/claude.log ãå®è¡ããŸãããã®ãã©ã°ãªãã§éå§ããå Žåã¯ãã»ãã·ã§ã³äžã« /debug ãå®è¡ããŠãã°ãæå¹ã«ãããã°ãã¹ãèŠã€ããŸãã
詳现ãåŠã¶
- Hooks ãªãã¡ã¬ã³ã¹ïŒå®å šãªã€ãã³ãã¹ããŒããJSON åºå圢åŒãéåæ hooksãããã³ MCP ããŒã« hooks
- ã»ãã¥ãªãã£ã«é¢ããèæ ®äºé ïŒå ±æãŸãã¯æ¬çªç°å¢ã« hooks ããããã€ããåã«ç¢ºèªããŠãã ãã
- Bash ã³ãã³ãããªããŒã¿ãŒäŸïŒå®å šãªãªãã¡ã¬ã³ã¹å®è£