Skip to main content

คู่มือ Hooks ของ Claude Code

รัน shell commands โดยอัตโนมัติเมื่อ Claude Code แก้ไขไฟล์, เสร็จงาน หรือต้องการ input จัดรูปแบบโค้ด, ส่งการแจ้งเตือน, ตรวจสอบคำสั่ง และ enforce project rules

Hooks คือ shell commands ที่ผู้ใช้กำหนด ซึ่งทำงาน ณ จุดเฉพาะใน lifecycle ของ Claude Code ให้การควบคุมแบบ deterministic เหนือพฤติกรรมของ Claude Code เพื่อให้มั่นใจว่า actions บางอย่างจะเกิดขึ้นเสมอ แทนที่จะพึ่งให้ LLM เลือกที่จะรัน

ตั้งค่า Hook แรกของคุณ

เพื่อสร้าง hook ให้เพิ่ม hooks block ใน settings file เดินตามขั้นตอนนี้เพื่อสร้าง desktop notification hook:

ขั้นตอนที่ 1: เพิ่ม hook ใน settings

เปิด ~/.claude/settings.json และเพิ่ม Notification hook:

{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}

ขั้นตอนที่ 2: ตรวจสอบ configuration

พิมพ์ /hooks เพื่อเปิด hooks browser คุณจะเห็นรายการ hook events ที่มีอยู่ทั้งหมด

ขั้นตอนที่ 3: ทดสอบ hook

กด Esc เพื่อกลับไปที่ CLI ขอให้ Claude ทำอะไรที่ต้องการสิทธิ์ แล้วสลับออกจาก terminal คุณควรได้รับ desktop notification

สิ่งที่สามารถทำ Automation ได้

รับการแจ้งเตือนเมื่อ Claude ต้องการ Input

รับ desktop notification เมื่อ Claude เสร็จงานและรอ input ของคุณ:

macOS:

{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}

Linux:

{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude Code' 'Claude Code needs your attention'"
}
]
}
]
}
}

Auto-format Code หลังการแก้ไข

รัน Prettier อัตโนมัติบนทุกไฟล์ที่ Claude แก้ไข:

{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}

บล็อคการแก้ไขไฟล์ที่ได้รับการป้องกัน

ป้องกัน Claude จากการแก้ไขไฟล์ sensitive เช่น .env, package-lock.json หรืออะไรก็ตามใน .git/:

สร้าง script ที่ .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

ลงทะเบียน hook:

{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
}
]
}
]
}
}

Re-inject Context หลัง Compaction

ใช้ SessionStart hook กับ compact matcher เพื่อ re-inject context สำคัญหลังจาก compaction:

{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "echo 'Reminder: use Bun, not npm. Run bun test before committing. Current sprint: auth refactor.'"
}
]
}
]
}
}

Auto-approve Permission Prompts ที่เฉพาะเจาะจง

ข้ามการ confirm dialog สำหรับ tool calls ที่คุณอนุญาตเสมอ:

{
"hooks": {
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"
}
]
}
]
}
}

วิธีการทำงานของ Hooks

Hook Events

Eventเมื่อไหร่ที่ทำงาน
SessionStartเมื่อ session เริ่มต้นหรือ resume
UserPromptSubmitเมื่อคุณส่ง prompt
PreToolUseก่อน tool call ทำงาน สามารถบล็อคได้
PermissionRequestเมื่อ permission dialog ปรากฏ
PostToolUseหลัง tool call สำเร็จ
Notificationเมื่อ Claude Code ส่งการแจ้งเตือน
Stopเมื่อ Claude เสร็จการตอบสนอง
ConfigChangeเมื่อ configuration file เปลี่ยนแปลง
CwdChangedเมื่อ working directory เปลี่ยน
FileChangedเมื่อไฟล์ที่ watch เปลี่ยนแปลง
SessionEndเมื่อ session สิ้นสุด

Hook Types

  • "type": "command" - รัน shell command
  • "type": "http" - POST event data ไปยัง URL
  • "type": "mcp_tool" - เรียก tool บน MCP server
  • "type": "prompt" - single-turn LLM evaluation
  • "type": "agent" - multi-turn verification พร้อม tool access

Exit Codes

  • Exit 0: ไม่มีการคัดค้าน การดำเนินการดำเนินต่อตามปกติ
  • Exit 2: การดำเนินการถูกบล็อค เขียน reason ไปที่ stderr
  • Exit อื่น ๆ: การดำเนินการดำเนินต่อ แต่แสดง error notice

Prompt-based Hooks

สำหรับ decisions ที่ต้องการการตัดสินใจแทน deterministic rules ใช้ type: "prompt" hooks:

{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Check if all tasks are complete. If not, respond with {\"ok\": false, \"reason\": \"what remains to be done\"}."
}
]
}
]
}
}

Agent-based Hooks

เมื่อการตรวจสอบต้องการการ inspect ไฟล์หรือรัน commands ใช้ type: "agent" hooks:

{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "agent",
"prompt": "Verify that all unit tests pass. Run the test suite and check the results.",
"timeout": 120
}
]
}
]
}
}

HTTP Hooks

POST event data ไปยัง HTTP endpoint:

{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "http",
"url": "http://localhost:8080/hooks/tool-use",
"headers": {
"Authorization": "Bearer $MY_TOKEN"
},
"allowedEnvVars": ["MY_TOKEN"]
}
]
}
]
}
}

ตำแหน่งของ Hook Configuration

ตำแหน่งขอบเขต
~/.claude/settings.jsonทุก projects ของคุณ
.claude/settings.jsonProject เดียว (commit ได้)
.claude/settings.local.jsonProject เดียว (gitignored)
Plugin hooks/hooks.jsonเมื่อ plugin เปิดใช้งาน

การแก้ไขปัญหา

Hook ไม่ทำงาน

  • รัน /hooks และยืนยันว่า hook ปรากฏภายใต้ event ที่ถูกต้อง
  • ตรวจสอบว่า matcher pattern ตรงกับ tool name
  • ตรวจสอบว่า script มีสิทธิ์ execute: chmod +x ./my-hook.sh

JSON Validation ล้มเหลว

ตรวจสอบว่า shell profile ไม่มี unconditional echo statements:

# ใน ~/.zshrc หรือ ~/.bashrc
if [[ $- == *i* ]]; then
echo "Shell ready"
fi

Debug Hooks

รัน Claude Code ด้วย debug flag:

claude --debug-file /tmp/claude.log

จากนั้น:

tail -f /tmp/claude.log

ดูเพิ่มเติม

  • Hooks reference: full event schemas, JSON output format, async hooks และ MCP tool hooks
  • Security considerations: review ก่อน deploy hooks ใน shared environments