Techsy
Liên hệ
Bắt đầu
Quay lại Blog
ai-machine-learning

Claude Code Hooks: Cẩm nang toàn diện cho lập trình viên với các ví dụ sẵn sàng cho production

Viết bởi Mert Batur Gürbüz
Apr 5, 2026
24 phút đọc
Mục lục
Claude Code Hooks: Cẩm nang toàn diện cho lập trình viên với các ví dụ sẵn sàng cho production

Claude Code Hooks: Cẩm nang toàn tập cho lập trình viên kèm ví dụ sẵn sàng cho production

Claude Code viết code rất giỏi, nhưng nó vẫn là một hệ thống xác suất. Bạn có thể yêu cầu nó chạy Prettier sau mỗi lần chỉnh sửa file. Bạn có thể đưa chỉ dẫn đó vào CLAUDE.md. Và đôi khi, nó sẽ cứ thế... quên mất. Claude Code hooks giải quyết vấn đề này bằng cách cho bạn quyền kiểm soát mang tính tất định, được đảm bảo chắc chắn đối với những gì diễn ra trước, trong và sau mỗi hành động mà Claude thực hiện.

Tôi đã cấu hình hooks cho hàng chục dự án trong vài tháng qua, và chúng đã âm thầm trở thành phần quan trọng nhất trong thiết lập Claude Code của tôi. Cẩm nang này bao quát mọi thứ từ những kiến thức cơ bản cho đến một bộ starter kit sẵn sàng cho production mà bạn có thể đưa ngay vào bất kỳ dự án nào hôm nay. Nếu bạn từng sử dụng Claude Code cùng với các công cụ như Cursor hay Copilot, hẳn bạn đã hiểu rõ giá trị của việc tùy biến, và hooks còn đưa điều đó tiến xa hơn một bước.

Claude Code Hooks là gì (và tại sao bạn nên quan tâm)?

Claude Code hooks là các lệnh shell, endpoint HTTP hoặc prompt LLM do người dùng định nghĩa, được thực thi tự động tại các thời điểm cụ thể trong vòng đời của Claude Code. Theo tài liệu chính thức của Anthropic, khác với các chỉ dẫn trong prompt mà Claude có thể bỏ qua, hooks luôn được kích hoạt một cách xác định mỗi lần, giúp bạn kiểm soát đảm bảo việc định dạng, bảo mật, thông báo và tự động hóa quy trình làm việc.

Vấn đề xác suất

Có một điều cần nói về các chỉ thị trong CLAUDE.md: chúng là gợi ý, chứ không phải hợp đồng ràng buộc. Bạn có thể viết "luôn chạy npx prettier --write sau khi chỉnh sửa các tệp TypeScript" trong ngữ cảnh dự án của mình, và Claude sẽ tuân theo phần lớn thời gian. Nhưng "phần lớn thời gian" là không đủ tốt khi bạn đang áp đặt việc định dạng mã trên toàn đội ngũ, hay chặn các lệnh đẩy lên môi trường production, hoặc ghi log mọi lệnh shell phục vụ kiểm toán bảo mật.

Đây chính là mâu thuẫn cốt lõi trong bất kỳ công cụ lập trình AI nào. Claude là một mô hình ngôn ngữ, nó hoạt động dựa trên xác suất. Kỹ thuật kỹ nghệ ngữ cảnh của bạn có thể điều hướng hành vi, nhưng không thể đảm bảo tuyệt đối.

Cách Hooks giải quyết vấn đề này

Hooks hoàn toàn bỏ qua LLM. Chúng là các shell script, lệnh gọi HTTP hoặc các đánh giá AI được kích hoạt tại những sự kiện vòng đời cụ thể: trước khi một công cụ chạy (PreToolUse), sau khi nó hoàn tất (PostToolUse), khi một thông báo xuất hiện, khi một phiên bắt đầu, hoặc khi Claude dừng lại. Hãy xem chúng như Git hooks, nhưng dành cho trợ lý lập trình AI của bạn.

Có bốn loại hook: command (shell script), HTTP (yêu cầu POST webhook), prompt (đánh giá có/không của Claude trong một lượt duy nhất) và agent (khởi tạo một subagent có quyền truy cập công cụ). Chúng ta sẽ phân tích từng loại ở phần sau, còn các command hook xử lý khoảng 90% những gì bạn cần.

Cách Claude Code Hooks hoạt động: Luồng vòng đời

Claude Code hooks thực thi theo một vòng đời được xác định rõ: một sự kiện được kích hoạt (ví dụ: PreToolUse), trình đối sánh (matcher) kiểm tra xem hook có áp dụng được không, script của hook chạy và nhận JSON qua stdin, sau đó mã thoát (exit code) sẽ quyết định điều gì xảy ra tiếp theo. Mã thoát 0 nghĩa là tiếp tục, mã thoát 2 nghĩa là chặn hành động đó. Luồng này giống nhau bất kể bạn đang sử dụng loại hook nào.

Sự kiện -> Matcher -> Hook -> Mã thoát (Luồng 4 bước)

Đây là cách mọi lần thực thi hook hoạt động:

text
1. EVENT FIRES          e.g., PreToolUse(Write)
       |
2. MATCHER CHECKS       Does "Write" match the hook's matcher pattern?
       |
3. HOOK EXECUTES        Shell script runs, receives JSON via stdin
       |
4. EXIT CODE DECIDES    0 = proceed | 2 = block | other = error

JSON được gửi đến qua stdin chứa mọi thông tin về sự kiện: tool_name, tool_input (đường dẫn tệp, nội dung, lệnh) và siêu dữ liệu phiên. Tập lệnh của bạn đọc JSON này, thực hiện bất kỳ logic nào cần thiết, rồi thoát với mã phù hợp.

Đối với các hook PreToolUse, mã thoát 2 là mã mạnh nhất — nó chặn hoàn toàn hành động đó và gửi thông báo trên stdout của bạn về cho Claude dưới dạng phản hồi. Claude sẽ nhìn thấy thông báo của bạn và có thể điều chỉnh cách tiếp cận của mình.

Phạm vi cấu hình: Người dùng, Dự án và Cục bộ

Hooks được đặt trong settings.json ở ba cấp độ:

Phạm viTệpCó commit vào Git?Trường hợp sử dụng
Người dùng~/.claude/settings.jsonKhôngMặc định cá nhân (thông báo, tùy chọn định dạng)
Dự án.claude/settings.jsonCóHooks dùng chung cho nhóm (bảo vệ tệp, trình chạy test, linting)
Cục bộ.claude/settings.local.jsonKhông (bỏ qua bởi gitignore)Ghi đè cá nhân cho dự án này

Cài đặt cấp dự án là hữu ích nhất cho các nhóm. Chỉ cần đặt hooks vào .claude/settings.json, commit lại, và mọi lập trình viên trong nhóm sẽ tự động có cùng các quy tắc bảo vệ.

Trường if: Lọc chi tiết

Kể từ Claude Code v2.1.85, hook đã hỗ trợ trường if, cho phép bạn lọc theo tham số của công cụ chứ không chỉ theo tên công cụ. Như được ghi trong tài liệu tham khảo về hook của Anthropic, điều này có nghĩa là bạn có thể viết một hook chỉ kích hoạt với các lệnh Bash khớp với git push, thay vì kích hoạt với mọi lệnh Bash.

json
{
  "matcher": "Bash",
  "if": "tool_input.command matches 'git push'",
  "hooks": [{ "type": "command", "command": "./scripts/check-branch.sh" }]
}

Đây là một cải tiến lớn. Trước khi có if, bạn sẽ khớp quá rộng (mọi lệnh Bash) hoặc phải thực hiện việc lọc bên trong script (rất lộn xộn).

Tất cả các sự kiện Hook của Claude Code: Bảng tham khảo nhanh

Claude Code cung cấp hơn 20 sự kiện hook xuyên suốt vòng đời của nó, như được ghi chép trong tài liệu tham khảo hooks chính thức và nhật ký thay đổi của Claude Code. Các sự kiện được sử dụng phổ biến nhất là PreToolUse, PostToolUse, Notification và Stop, nhưng các sự kiện mới hơn như ConfigChange và FileChanged mở ra những mẫu tự động hóa nâng cao.

Dưới đây là bảng tham khảo đầy đủ:

Sự kiệnThời điểm kích hoạtCó thể chặn?Trường hợp sử dụng phổ biến
PreToolUseTrước khi một công cụ thực thiCó (exit 2)Chặn các lệnh nguy hiểm, bảo vệ tệp
PostToolUseSau khi một công cụ hoàn tấtKhôngTự động định dạng, chạy kiểm thử, ghi nhật ký hành động
NotificationKhi Claude gửi một thông báoKhôngCảnh báo trên màn hình, tin nhắn Slack
StopKhi Claude hoàn thành một phản hồiKhôngDọn dẹp, tạo bản tóm tắt
SessionStartKhi khởi tạo phiênKhôngBơm ngữ cảnh, thiết lập môi trường
UserPromptSubmitKhi người dùng gửi một promptCó (exit 2)Xác thực đầu vào, lọc nội dung
PreCompactTrước khi nén ngữ cảnhKhôngLưu trạng thái trước khi bộ nhớ được cắt tỉa
PostCompactSau khi nén ngữ cảnhKhôngBơm lại ngữ cảnh quan trọng
ConfigChangeKhi cài đặt thay đổiKhôngTải nóng các biến môi trường
FileChangedKhi một tệp được theo dõi thay đổiKhôngKích hoạt build lại, vô hiệu hóa bộ nhớ đệm
TaskCreatedKhi một tác vụ mới được tạo raKhôngTheo dõi tác vụ, phân bổ tài nguyên
PermissionDeniedKhi một kiểm tra quyền bị từ chốiKhôngGhi nhật ký kiểm toán, cảnh báo về các hành động bị chặn
WorktreeCreateKhi một Git worktree mới được tạoKhôngKhởi tạo các cài đặt riêng cho worktree
SubagentStartKhi một subagent được khởi chạyKhôngGiám sát hoạt động của subagent
SubagentStopKhi một subagent hoàn tấtKhôngXác thực đầu ra của subagent

Mẹo chuyên nghiệp: Bạn sẽ sử dụng PreToolUse và PostToolUse cho 80% các hook của mình. SessionStart là sự kiện hữu ích tiếp theo, nó hoàn hảo để bơm ngữ cảnh dự án mà Claude cần vào lúc bắt đầu mỗi phiên.

4 loại Hook của Claude Code được giải thích

Claude Code hỗ trợ bốn loại hook handler: command hook chạy các shell script, HTTP hook gửi POST đến các URL, prompt hook đặt cho Claude một câu hỏi có/không, và agent hook khởi tạo một subagent có quyền truy cập công cụ. Theo kinh nghiệm của chúng tôi, command hook xử lý được 90% các trường hợp sử dụng. Hãy dùng HTTP cho các tích hợp bên ngoài, còn prompt hook và agent hook cho những quyết định tinh tế cần đến khả năng phán đoán của AI.

LoạiTốc độĐộ phức tạpPhù hợp nhất choVí dụ
CommandNhanhThấpĐịnh dạng, chặn, ghi logChạy Prettier sau khi chỉnh sửa file
HTTPTrung bìnhTrung bìnhDịch vụ bên ngoài, webhookGửi POST đến Slack khi hoàn tất
PromptChậmTrung bìnhCác quyết định mang tính chủ quan"Đoạn code này có an toàn để chạy không?"
AgentChậm nhấtCaoXác minh phức tạp có nhận biết về fileKiểm tra xem code mới có tuân theo các pattern của dự án không

Command Hooks (Công cụ đắc lực)

Command hooks thực thi một lệnh shell và sử dụng mã thoát để xác định kết quả. Chúng nhận dữ liệu JSON của sự kiện qua stdin.

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "jq -r '.tool_input.command' | grep -q 'rm -rf /' && exit 2 || exit 0"
      }]
    }]
  }
}

Đây là thứ bạn sẽ dùng cho việc định dạng, bảo vệ tệp, gửi thông báo và hầu hết các tác vụ tự động hóa. Nhanh chóng, đơn giản và dễ đoán.

HTTP Hook (Tích hợp bên ngoài)

HTTP hook gửi một yêu cầu POST đến một URL với JSON sự kiện làm phần nội dung. Mã trạng thái phản hồi sẽ quyết định kết quả (200 = tiếp tục, 403 = chặn).

json
{
  "hooks": {
    "Stop": [{
      "matcher": "",
      "hooks": [{
        "type": "http",
        "url": "https://your-api.com/claude-webhook"
      }]
    }]
  }
}

Rất phù hợp để gửi sự kiện đến Slack, Discord, PagerDuty hoặc một bảng điều khiển tùy chỉnh. Bạn cũng có thể dùng cách này để truy vấn một hệ thống chính sách bên ngoài trước khi cho phép thực thi một công cụ.

Prompt Hooks (Quyết định được hỗ trợ bởi AI)

Prompt hook chuyển dữ liệu sự kiện cho chính Claude để đánh giá có/không trong một lượt duy nhất. Claude trả về phản hồi JSON với "decision": "allow" hoặc "decision": "block" kèm theo lập luận.

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "prompt",
        "prompt": "Is this bash command safe to run in a production environment? Consider: does it modify system files, delete data, or access sensitive credentials?"
      }]
    }]
  }
}

Hãy sử dụng chúng một cách hạn chế. Chúng làm tăng độ trễ (một lần gọi LLM đầy đủ cho mỗi lần thực thi hook) và chi phí. Nhưng đối với những kiểm tra an toàn thực sự mang tính chủ quan, chẳng hạn như "bản di chuyển cơ sở dữ liệu này trông có vẻ mang tính phá hủy không?", thì chúng khó có gì sánh kịp. Nếu bạn tò mò về việc chuyển đổi mô hình Claude Code, mô hình được dùng cho prompt hook sẽ tuân theo mô hình phiên hiện tại của bạn.

Agent Hooks (Xác minh có công cụ hỗ trợ)

Agent hook khởi tạo một subagent có quyền truy cập vào các công cụ Read, Grep và Glob. Subagent có thể kiểm tra các tệp trước khi đưa ra quyết định.

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Write",
      "hooks": [{
        "type": "agent",
        "prompt": "Check if the file being written follows the project's naming conventions and import patterns. Read .claude/CONVENTIONS.md for the rules."
      }]
    }]
  }
}

Đây là loại hook mạnh mẽ nhất, nhưng cũng chậm nhất. Hãy dành nó cho các kiểm tra có mức độ quan trọng cao, nơi bạn cần ngữ cảnh từ tệp để đưa ra quyết định chính xác.

7 Ví dụ về Claude Code Hook sẵn sàng cho production (Copy-Paste dùng được ngay)

Các hook Claude Code hữu ích nhất bao gồm tự động định dạng bằng Prettier hoặc Black sau khi chỉnh sửa file, chặn ghi vào các file được bảo vệ, gửi thông báo desktop khi hoàn thành tác vụ, đưa ngữ cảnh dự án vào khi bắt đầu phiên làm việc, chạy test sau khi thay đổi code, thực thi bảo vệ branch và kiểm toán toàn bộ việc sử dụng công cụ. Tôi đã và đang chạy các biến thể của những hook này trên mọi dự án trong suốt ba tháng qua.

Mỗi ví dụ dưới đây là một đoạn settings.json hoàn chỉnh mà bạn có thể đưa thẳng vào .claude/settings.json của mình. Các bộ sưu tập từ cộng đồng như awesome-claude-code còn có thêm nhiều pattern khác.

1. Tự động định dạng khi lưu

json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Write|Edit",
      "hooks": [{
        "type": "command",
        "command": "FILE=$(jq -r '.tool_input.file_path // .tool_input.file' /dev/stdin); case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) black \"$FILE\" 2>/dev/null;; esac; exit 0"
      }]
    }]
  }
}

Đoạn hook này được kích hoạt sau mỗi lần Write hoặc Edit, trích xuất đường dẫn tệp từ JSON ở stdin và chạy trình định dạng tương ứng. Lệnh exit 0 ở cuối đảm bảo hook không bao giờ bị chặn — lỗi định dạng không được làm gián đoạn Claude.

Mẹo chuyên nghiệp: Hãy thêm *.go với gofmt và *.rs với rustfmt nếu bạn làm việc với nhiều ngôn ngữ.

2. Chặn ghi vào các tệp được bảo vệ

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Write|Edit",
      "if": "tool_input.file_path matches '(\\.env|\\.env\\.local|package-lock\\.json|yarn\\.lock|pnpm-lock\\.yaml)'",
      "hooks": [{
        "type": "command",
        "command": "echo '{\"message\": \"BLOCKED: This file is protected. Edit it manually.\"}' && exit 2"
      }]
    }]
  }
}

Mã thoát 2 sẽ chặn hành động và gửi thông báo JSON lại cho Claude. Claude sẽ nhận được phản hồi và tự điều chỉnh, thường thì nó sẽ cho bạn biết rằng nó muốn chỉnh sửa tệp và yêu cầu bạn thực hiện thủ công. Trường if giúp ngăn hook này kích hoạt ở mọi lần Ghi.

3. Thông báo trên màn hình khi hoàn tất

json
{
  "hooks": {
    "Notification": [{
      "matcher": "",
      "hooks": [{
        "type": "command",
        "command": "MSG=$(jq -r '.message // \"Claude Code task finished\"' /dev/stdin); if [ \"$(uname)\" = 'Darwin' ]; then osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\"; else notify-send 'Claude Code' \"$MSG\"; fi; exit 0"
      }]
    }]
  }
}

Hoạt động trên macOS (osascript) và Linux (notify-send). Bộ khớp rỗng có nghĩa là nó sẽ kích hoạt với mọi thông báo. Tính năng này thực sự hữu ích khi bạn khởi chạy một tác vụ dài rồi chuyển sang cửa sổ khác.

4. Tiêm ngữ cảnh khi bắt đầu phiên làm việc

json
{
  "hooks": {
    "SessionStart": [{
      "matcher": "",
      "hooks": [{
        "type": "command",
        "command": "echo '{\"message\": \"Project: '\"$(basename $(pwd))\"' | Branch: '\"$(git branch --show-current 2>/dev/null || echo none)\"' | Last commit: '\"$(git log --oneline -1 2>/dev/null || echo none)\"'\"}'; exit 0"
      }]
    }]
  }
}

Đoạn này sẽ tiêm tên dự án hiện tại, nhánh Git và commit gần nhất vào mỗi phiên làm việc. Claude sẽ tự động nhận được ngữ cảnh này, bạn không cần phải nói cho nó biết mình đang ở nhánh nào.

5. Tự động chạy kiểm thử sau khi thay đổi mã nguồn

json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Write|Edit",
      "if": "tool_input.file_path matches '\\.(ts|tsx|js|jsx|py)$'",
      "hooks": [{
        "type": "command",
        "command": "FILE=$(jq -r '.tool_input.file_path' /dev/stdin); TEST_FILE=$(echo \"$FILE\" | sed 's/\\.[^.]*$/.test&/'); if [ -f \"$TEST_FILE\" ]; then npx jest \"$TEST_FILE\" --no-coverage 2>&1 | tail -5; fi; exit 0",
        "timeout": 30000
      }]
    }]
  }
}

Nếu tồn tại tệp kiểm thử tương ứng, nó sẽ tự động chạy sau khi Claude chỉnh sửa mã nguồn. Lệnh tail -5 giúp giữ cho đầu ra ngắn gọn, và timeout ngăn các bộ kiểm thử chạy quá lâu. Tính năng này kết hợp rất tốt với quy trình đánh giá mã nguồn bằng AI.

6. Thực thi Bảo vệ Nhánh (Nâng cao)

json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "if": "tool_input.command matches 'git push.*(main|master|production)'",
      "hooks": [{
        "type": "command",
        "command": "echo '{\"message\": \"BLOCKED: Direct push to protected branch. Use a feature branch and open a PR.\"}' && exit 2"
      }]
    }]
  }
}

Thao tác này chặn mọi lệnh git push nhắm đến các nhánh main, master hoặc production. Claude sẽ nhận được phản hồi và đề xuất tạo một nhánh tính năng để thay thế.

7. Ghi log kiểm toán bảo mật (Nâng cao)

json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "INPUT=$(cat /dev/stdin); CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command'); echo \"[$(date -u +%Y-%m-%dT%H:%M:%SZ)] BASH: $CMD\" >> .claude/audit.log; exit 0"
      }]
    }]
  }
}

Ghi lại mọi lệnh Bash mà Claude thực thi vào một tệp kiểm toán kèm dấu thời gian UTC. Vô cùng hữu ích cho việc rà soát bảo mật và nắm rõ Claude thực sự đã làm gì trong suốt một phiên. Hãy thêm .claude/audit.log vào .gitignore của bạn.

Hooks vs MCP vs Skills vs CLAUDE.md: Khi nào dùng gì

Dùng hooks cho các tác vụ tự động hóa tất định, phải luôn chạy (định dạng code, chặn thao tác, gửi thông báo). Dùng MCP để cho Claude truy cập các công cụ và dữ liệu bên ngoài. Dùng Skills cho các gói prompt tái sử dụng. Dùng CLAUDE.md cho hướng dẫn hành vi và ngữ cảnh dự án. Hooks được đảm bảo thực thi; mọi thứ khác đều mang tính xác suất. Đây là điểm phân biệt quan trọng nhất, và tôi luôn quay lại nó mỗi khi tư vấn cho các đội ngũ.

Ma trận Quyết định

Cơ chếCó tất định?Thời điểm chạyPhù hợp nhất choVí dụ
HooksCóTự động theo các sự kiện vòng đờiThực thi, tự động hóa, thông báoTự động định dạng, chặn ghi tệp
MCPKhông (Claude quyết định)Khi Claude gọi công cụ MCPTính năng mới, truy cập dữ liệu bên ngoàiTruy vấn cơ sở dữ liệu, tìm kiếm trên Notion
SkillsKhông (người dùng kích hoạt)Khi người dùng gọi lệnh gạch chéoBộ hướng dẫn tái sử dụng/review cho quy trình đánh giá mã
CLAUDE.mdKhông (mang tính hướng dẫn)Được đọc khi bắt đầu phiênNgữ cảnh dự án, tiêu chuẩn viết mã"Sử dụng Tailwind, viết kiểm thử cho mọi mã mới"

Để tìm hiểu sâu về MCP, hãy xem hướng dẫn MCP của chúng tôi. Nếu bạn chuyển đến từ Cursor, hệ thống quy tắc của Cursor khá tương đồng với CLAUDE.md, nhưng Cursor không có gì giống như hooks.

Khi chúng chồng lấn (và cách lựa chọn)

Đây là lưu đồ mà tôi sử dụng:

  • "Điều này có CẦN phải xảy ra mỗi lần, không có ngoại lệ không?", Hook. Định dạng code, chặn các tệp được bảo vệ, gửi thông báo. Hoàn toàn không mơ hồ.
  • "Claude có cần một KHẢ NĂNG mới mà nó chưa có không?", máy chủ MCP. Truy cập cơ sở dữ liệu, gọi API, tìm kiếm tài liệu bên ngoài.
  • "Tôi có muốn các HƯỚNG DẪN có thể tái sử dụng cho một quy trình cụ thể không?", Skill (lệnh gạch chéo). Mẫu đánh giá code, danh sách kiểm tra triển khai.
  • "Tôi có muốn định hình HÀNH VI của Claude trong dự án này không?", CLAUDE.md. Tiêu chuẩn code, quyết định kiến trúc, thư viện ưa thích.

Những ví dụ thực tế giúp làm rõ ranh giới:

  • "Luôn định dạng bằng Prettier" = Hook (phải xảy ra mỗi lần)
  • "Sử dụng Prettier để định dạng" trong CLAUDE.md = Hướng dẫn (Claude có thể quên)
  • "Tìm kiếm tài liệu công ty của chúng tôi" = MCP (khả năng mới)
  • "Tuân thủ hướng dẫn phong cách của chúng tôi khi đánh giá code" = Skill hoặc CLAUDE.md

Như được mô tả trong thông báo về plugin của Anthropic, hook là một phần của hệ sinh thái plugin rộng lớn hơn, bao gồm cả MCP và Skill. Chúng được thiết kế để bổ sung cho nhau, chứ không phải để cạnh tranh.

Bộ Starter Kit: Cấu hình Claude Code Hooks dùng ngay cho mọi dự án

Một cấu hình hooks khởi đầu cho Claude Code nên bao gồm tự động định dạng khi chỉnh sửa tệp, thông báo khi hoàn thành tác vụ, bảo vệ các tệp nhạy cảm, nạp ngữ cảnh phiên và một stop hook để dọn dẹp. Đây chính là cấu hình mà tôi áp dụng cho mọi dự án mới, có điều chỉnh theo stack, nhưng cấu trúc thì luôn giữ nguyên.

Cấu hình

json
{
  "hooks": {
    "SessionStart": [{
      "matcher": "",
      "hooks": [{
        "type": "command",
        "command": "echo '{\"message\": \"Project: '\"$(basename $(pwd))\"' | Branch: '\"$(git branch --show-current 2>/dev/null)\"' | Node: '\"$(node -v 2>/dev/null)\"'\"}'; exit 0"
      }]
    }],
    "PreToolUse": [{
      "matcher": "Write|Edit",
      "if": "tool_input.file_path matches '(\\.env|\\.env\\..+|.*lock\\.json|.*lock\\.yaml)'",
      "hooks": [{
        "type": "command",
        "command": "echo '{\"message\": \"Protected file. Edit manually.\"}' && exit 2"
      }]
    }],
    "PostToolUse": [{
      "matcher": "Write|Edit",
      "hooks": [{
        "type": "command",
        "command": "FILE=$(jq -r '.tool_input.file_path // .tool_input.file' /dev/stdin); case \"$FILE\" in *.ts|*.tsx|*.js|*.jsx) npx prettier --write \"$FILE\" 2>/dev/null;; *.py) black \"$FILE\" 2>/dev/null;; *.go) gofmt -w \"$FILE\" 2>/dev/null;; esac; exit 0"
      }]
    }],
    "Notification": [{
      "matcher": "",
      "hooks": [{
        "type": "command",
        "command": "MSG=$(jq -r '.message // \"Done\"' /dev/stdin); osascript -e \"display notification \\\"$MSG\\\" with title \\\"Claude Code\\\"\" 2>/dev/null || notify-send 'Claude Code' \"$MSG\" 2>/dev/null; exit 0"
      }]
    }],
    "Stop": [{
      "matcher": "",
      "hooks": [{
        "type": "command",
        "command": "echo '[STOP] '\"$(date +%H:%M:%S)\"'' >> .claude/session.log; exit 0"
      }]
    }]
  }
}

Cách tùy chỉnh cho stack của bạn

StackLệnh định dạngLệnh kiểm thửPhần mở rộng theo dõi
Node/TypeScriptnpx prettier --writenpx jest --no-coverage.ts, .tsx, .js, .jsx
Pythonblackpytest -x.py
Gogofmt -wgo test ./....go
Rustrustfmtcargo test.rs

Hãy thay các lệnh định dạng và kiểm thử trong cấu hình ở trên cho phù hợp với stack của bạn. Cấu trúc vẫn giữ nguyên.

Xác minh Hook của bạn đang hoạt động

Có ba cách để xác nhận các hook đang hoạt động:

  1. Lệnh /hooks, Nhập /hooks trong Claude Code để xem tất cả các hook đã đăng ký, các matcher của chúng và trạng thái của chúng.
  2. Kiểm tra bản ghi (transcript), Sau khi một hook kích hoạt, hãy kiểm tra bản ghi phiên làm việc. Các lần thực thi hook sẽ xuất hiện cùng với đầu ra và mã thoát (exit code) của chúng.
  3. Chuyển đổi nhanh, Thêm "disableAllHooks": true vào settings.json của bạn để tạm thời vô hiệu hóa tất cả các hook mà không cần xóa cấu hình. Xóa nó đi (hoặc đặt thành false) để bật lại.

Tích hợp CI/CD: Claude Code Hooks ở chế độ Headless

Claude Code hooks hoạt động ở chế độ headless (claude -p) với một số điểm khác biệt: Các hook thông báo vẫn được kích hoạt nhưng bạn nên chuyển hướng sang ghi log thay vì hiển thị cảnh báo trên màn hình. Các hook PreToolUse với mã thoát 2 có thể tạm dừng phiên headless để con người xem xét. GitHub Actions sử dụng anthropics/claude-code-action@v1 kết hợp cùng các hook cho quy trình làm việc tự động.

Hành vi của Chế độ Headless

Sự kiện HookChế độ Tương tácChế độ Headless (-p)Khuyến nghị cho CI
PreToolUse (exit 2)Chặn và hiển thị thông báoTạm dừng để chờ --resumeDùng cho các phê duyệt bắt buộc từ con người
PostToolUseChạy bình thườngChạy bình thườngGiữ lại các formatter và logger
NotificationCảnh báo trên màn hìnhVẫn được kích hoạt (không có UI)Chuyển hướng đến tệp log hoặc Slack webhook
StopChạy dọn dẹpChạy dọn dẹpPhù hợp để thu thập artifact trong CI
SessionStartBơm ngữ cảnhBơm ngữ cảnhBơm các biến môi trường CI

Điều bất ngờ lớn nhất ở chế độ headless: các hook PreToolUse thoát với mã 2 không chỉ thất bại trong im lặng. Chúng tạm dừng phiên và cho phép bạn tiếp tục bằng --resume, tạo ra một mô hình có con người tham gia trong vòng lặp (human-in-the-loop) cho các pipeline CI.

Tích hợp GitHub Actions

Dưới đây là một workflow GitHub Actions tối giản sử dụng Claude Code kèm theo hooks. Như được ghi trong hướng dẫn GitHub Actions chính thức:

yaml
- name: Run Claude Code
  uses: anthropics/claude-code-action@v1
  with:
    prompt: "Review this PR and suggest improvements"
    allowed_tools: "Read,Grep,Glob"
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

Các hooks trong .claude/settings.json của bạn sẽ đi kèm với repo, vì vậy chúng sẽ kích hoạt trong CI giống hệt như khi chạy cục bộ. Chỉ cần đảm bảo rằng mọi hooks phụ thuộc vào các công cụ dành riêng cho máy tính để bàn (chẳng hạn như osascript) đều có phương án dự phòng hoặc điều kiện kiểm tra.

Quản lý Hook trong nhóm

Một mô hình hoạt động hiệu quả cho các nhóm:

  • .claude/settings.json (được commit), Hook dùng chung cho nhóm: bảo vệ tệp, trình định dạng, bảo vệ nhánh. Mọi người đều nhận được những hook này.
  • .claude/settings.local.json (bỏ qua bởi git), Hook cá nhân: tùy chọn thông báo, ghi log tùy chỉnh, hook thử nghiệm.
  • ~/.claude/settings.json (toàn cục cho người dùng), Các mặc định của bạn trên tất cả dự án: kiểu thông báo, tùy chọn định dạng cá nhân.

Điều này phản ánh cách .editorconfig (được commit) và cài đặt IDE cục bộ (cá nhân) hoạt động. Như hướng dẫn CI/CD của Angelo Lima đã đề cập, các nhóm chuẩn hóa trên các hook dùng chung sẽ gặp ít vấn đề "chạy được trên máy tôi" hơn với Claude Code.

Khắc phục sự cố Claude Code Hooks và các lỗi thường gặp

Các vấn đề phổ biến với Claude Code hooks bao gồm hooks không được kích hoạt (kiểm tra chính tả matcher và vị trí settings.json), hooks chạy nhưng không chặn được (sai exit code, hãy dùng 2 thay vì 1), vòng lặp vô hạn (Stop hook tự kích hoạt chính nó), và khởi động chậm (quá nhiều hooks đồng bộ). Lỗi phổ biến nhất mà tôi thường thấy là nhầm lẫn về exit code — các nhà phát triển dùng exit 1 trong khi ý họ là exit 2.

Hook không được kích hoạt

Triệu chứng: Bạn đã thêm một hook nhưng không có gì xảy ra khi sự kiện diễn ra.

Cách khắc phục:

  • Sai chính tả trong matcher, Các matcher có phân biệt chữ hoa chữ thường. \"write\" sẽ không khớp với công cụ Write. Hãy kiểm tra tên công cụ chính xác bằng /hooks.
  • Sai tệp cài đặt, Các hook trong ~/.claude/settings.json sẽ không xuất hiện trong kết quả /hooks của phạm vi dự án. Hãy thử dùng .claude/settings.json ở thư mục gốc của dự án.
  • Lỗi cú pháp JSON, Một dấu phẩy thừa hoặc thiếu dấu ngoặc sẽ vô hiệu hóa toàn bộ cấu hình hook một cách âm thầm. Hãy chạy settings.json của bạn qua jq . để kiểm tra tính hợp lệ.
  • disableAllHooks: true, Hãy kiểm tra xem có ai đó (hoặc một phiên gỡ lỗi trước đó) đã để bật cờ này hay không.

Hook chạy nhưng không chặn

Triệu chứng: Hook PreToolUse của bạn thực thi, nhưng hành động vẫn tiếp tục diễn ra.

Cách khắc phục:

  • Mã thoát (exit code) sai, Mã thoát 1 có nghĩa là "lỗi" (hook thất bại), chứ không phải "chặn." Hãy dùng exit 2 để chặn một hành động. Đây là lỗi mà hầu như ai cũng mắc phải, như được nêu trong tài liệu chính thức.
  • Thiếu JSON ở stdout, Đối với các hook chặn, hãy xuất ra một thông điệp JSON để Claude biết lý do hành động bị chặn: echo '{"message": "Blocked: reason"}'

Vòng lặp vô hạn

Triệu chứng: Claude liên tục thử lại cùng một hành động, hoặc máy của bạn nóng lên một cách đáng ngờ.

Cách khắc phục:

  • Stop hook kích hoạt hành động, Nếu Stop hook của bạn ghi một tệp hoặc chạy một lệnh khiến Claude phản hồi, bạn đã tạo ra một vòng lặp. Stop hook chỉ nên thực hiện những việc thụ động: ghi nhật ký, thông báo, dọn dẹp.
  • PostToolUse hook gây ra chỉnh sửa, Một PostToolUse hook sửa đổi tệp sẽ kích hoạt một sự kiện PostToolUse khác. Hãy phòng tránh điều này bằng các matcher cụ thể hoặc trường if.

Vấn đề về hiệu năng

Triệu chứng: Claude khởi động hoặc thực thi công cụ chậm hơn rõ rệt.

Cách khắc phục:

  • Quá nhiều hook SessionStart, Mỗi hook chạy đồng bộ khi khởi động. Hãy giữ chúng ở mức nhẹ (dưới 1 giây mỗi hook).
  • Script nặng trong các đường dẫn nóng, Các hook ở PreToolUse và PostToolUse kích hoạt thường xuyên. Nếu script của bạn thực hiện các yêu cầu mạng hoặc tính toán nặng, hãy thêm trường timeout (mili giây) và cân nhắc xem liệu nó có nên là một HTTP hook hay không.
  • Không có bộ nhớ đệm, Nếu bạn đang kiểm tra đi kiểm tra lại cùng một thứ (chẳng hạn "đây có phải là nhánh được bảo vệ không?"), hãy lưu kết quả vào một tệp tạm thay vì chạy các lệnh Git ở mỗi lần gọi hook.

Câu hỏi thường gặp

Hook của Claude Code là gì và chúng hoạt động như thế nào?

Hook của Claude Code là các tập lệnh tự động hóa do người dùng định nghĩa, được thực thi tại các sự kiện vòng đời cụ thể trong suốt một phiên làm việc của Claude Code. Bạn cấu hình chúng trong settings.json bằng một mẫu khớp (matcher pattern) và một trình xử lý (lệnh shell, endpoint HTTP, prompt hoặc agent). Khi sự kiện khớp được kích hoạt, hook sẽ tự động chạy và sử dụng các mã thoát (exit code) để kiểm soát kết quả.

Làm cách nào để cấu hình hooks trong settings.json của Claude Code?

Thêm một object "hooks" vào bất kỳ vị trí cấu hình nào trong ba vị trí sau: ~/.claude/settings.json (toàn cục cho người dùng), .claude/settings.json (dùng chung cho dự án), hoặc .claude/settings.local.json (cá nhân cho dự án). Mỗi loại sự kiện ánh xạ tới một mảng các định nghĩa hook với matcher, trường if tùy chọn, và một mảng hooks chứa các object xử lý với type và command hoặc url.

Sự khác biệt giữa hook PreToolUse và PostToolUse là gì?

PreToolUse kích hoạt trước khi một công cụ thực thi, cho phép bạn chặn nó bằng exit code 2. PostToolUse kích hoạt sau khi quá trình thực thi hoàn tất, hữu ích cho việc định dạng, kiểm thử hoặc ghi log. PreToolUse dùng để ngăn chặn và kiểm soát. PostToolUse dùng để xác thực và dọn dẹp. Cả hai đều nhận tên công cụ và đầu vào dưới dạng JSON trên stdin.

Hook của Claude Code có thể chặn các lệnh nguy hiểm không?

Có. Hook PreToolUse với mã thoát (exit code) 2 sẽ chặn mọi hành vi thực thi công cụ. Bạn có thể bảo vệ các tệp nhạy cảm khỏi bị ghi đè, chặn các lệnh shell khớp với những mẫu nguy hiểm như rm -rf hoặc git push main, và ngăn truy cập vào các cơ sở dữ liệu production. Thông báo chặn sẽ được gửi lại cho Claude dưới dạng phản hồi, để nó có thể điều chỉnh cách tiếp cận của mình.

Claude Code có những sự kiện hook nào?

Claude Code cung cấp hơn 15 sự kiện: PreToolUse và PostToolUse cho thực thi công cụ, Notification cho cảnh báo, Stop cho kết thúc phiên, SessionStart cho khởi tạo, UserPromptSubmit cho lọc đầu vào, PreCompact và PostCompact cho quản lý ngữ cảnh, cùng các sự kiện mới hơn như ConfigChange, FileChanged, TaskCreated và PermissionDenied. Xem bảng tham khảo đầy đủ tại phần sự kiện hook ở trên.

Hooks khác với MCP tools và Skills như thế nào?

Hooks có tính xác định — chúng luôn kích hoạt khi có sự kiện khớp, bất kể Claude quyết định ra sao. MCP tools mở rộng khả năng của Claude (truy cập cơ sở dữ liệu, gọi API) nhưng Claude sẽ tự chọn thời điểm sử dụng chúng. Skills là các gói hướng dẫn có thể tái sử dụng, được gọi bằng lệnh slash. CLAUDE.md cung cấp hướng dẫn về hành vi. Hãy dùng hooks khi có việc bắt buộc phải xảy ra mỗi lần, và dùng MCP khi Claude cần thêm khả năng mới.

Hook của Claude Code có hoạt động ở chế độ headless không?

Có, nhưng có một số lưu ý. Các hook vẫn kích hoạt bình thường ở chế độ headless (claude -p), nhưng những hook dành riêng cho máy tính để bàn, chẳng hạn như thông báo trên macOS, sẽ cần các phương án dự phòng. Điều quan trọng là các hook PreToolUse thoát với mã 2 có thể tạm dừng các phiên headless để chờ con người phê duyệt thông qua --resume. Điều này cho phép xây dựng các quy trình CI/CD có sự tham gia của con người (human-in-the-loop), trong đó một số hành động nhất định yêu cầu sự xác nhận thủ công.

Bao nhiêu hook là quá nhiều? Hook có làm chậm Claude Code không?

Không có giới hạn cứng, nhưng mỗi hook đồng bộ đều làm tăng độ trễ. Các hook SessionStart chạy lúc khởi động, vì vậy hãy giữ chúng nhanh (dưới 1 giây mỗi hook). Các hook PreToolUse và PostToolUse kích hoạt ở mọi lệnh gọi công cụ khớp điều kiện, các script nặng ở đây sẽ tích lũy độ trễ rất nhanh. Tôi khuyên nên giữ tổng số hook dưới 10-15, sử dụng trường if để thu hẹp phạm vi, và thêm giá trị timeout để ngăn script chạy quá lâu.

Tôi có thể dùng hook để tự động định dạng code bằng Prettier hoặc Black không?

Có, đây là trường hợp sử dụng hook phổ biến nhất. Hãy tạo một hook PostToolUse khớp với Write|Edit, trích xuất đường dẫn tệp từ JSON của stdin, rồi chạy trình định dạng phù hợp dựa trên phần mở rộng của tệp. Xem ví dụ số một trong phần ví dụ production để có một cấu hình hoàn chỉnh, sẵn sàng sao chép-dán, xử lý được các tệp TypeScript, JavaScript và Python.

Hook của Claude Code có an toàn không? Những rủi ro bảo mật là gì?

Hook chạy với toàn bộ quyền người dùng của bạn, không hề có sandbox. Một hook độc hại có thể đọc khóa SSH, xóa tệp hoặc đánh cắp dữ liệu. Chỉ sử dụng hook từ các nguồn đáng tin cậy, xem xét kỹ mọi tệp .claude/settings.json được chia sẻ trước khi đưa vào dự án của bạn, và sử dụng .claude/settings.local.json cho các hook cá nhân không nên được chia sẻ. Để tìm hiểu thêm về các mẫu an toàn AI rộng hơn, hãy xem hướng dẫn về guardrail cho LLM của chúng tôi.

Thẻ

claude code hooksclaude codecông cụ cho lập trình viêntự động hóa AItự động hóa quy trìnhsettings.jsonPreToolUsePostToolUse

Chia sẻ bài viết này

Bài viết liên quan

Thêm từ chuyên mục ai-machine-learning

ai-machine-learning
Jul 20, 2026

8 API Web Scraping AI Tốt Nhất Năm 2026 (Đã Kiểm Thử Trên Chính Agent Stack Của Chúng Tôi)

Chúng tôi đã kiểm thử 8 API web scraping AI với mức giá thực tế năm 2026 được kéo qua chính agent stack của mình. Firecrawl, Bright Data, ScrapingBee và 5 công cụ khác, xếp hạng theo đầu ra sẵn sàng cho LLM, khả năng vượt anti-bot và hỗ trợ MCP.

9 min read phút đọc
Đọc
ai-machine-learning
Jul 20, 2026

Kỹ thuật Prompt cho Lập trình: 7 Mẫu Chúng Tôi Dùng Hàng Ngày trong Claude Code và Cursor (2026)

Hầu hết các bài viết về 'prompt lập trình AI' chỉ đưa cho bạn 50 mẫu để sao chép. Bài này dạy 7 mẫu chúng tôi dùng mỗi ngày để vận hành quy trình Claude Code gồm 16 agent, với ví dụ thực tế trước-và-sau cho từng mẫu, cùng vị trí áp dụng từng mẫu trong Claude Code, Cursor và Copilot năm 2026.

11 min read phút đọc
Đọc
ai-machine-learning
Jul 19, 2026

Từ PoC AI đến Production: Checklist 12 Điểm Trước Khi Phát Hành

Một bản demo AI chạy được không phải là một hệ thống production. Checklist 12 điểm này đi qua ba giai đoạn mà mọi tính năng AI đều cần trước khi ra mắt: củng cố, ổn định hóa và triển khai, với các ngưỡng cụ thể cho giới hạn chi phí, giới hạn tốc độ, phương án dự phòng và điều kiện kích hoạt hoàn tác.

10 min read phút đọc
Đọc
Xem tất cả bài viết
Khởi động dự án của bạn

Sẵn sàng tạo nên điều gì đó đột phá?

Hãy biến tầm nhìn của bạn thành hiện thực. Đội ngũ của chúng tôi sẵn sàng đồng hành cùng bạn tạo ra phần mềm tạo nên sự khác biệt.

Đặt lịch gọi ý tưởng 30 phútXem dự án của chúng tôi

Công cụ hot trong kho

Claude Skills

Xem tất cả
  • New Post

    Full SEO blog pipeline: research, brief, write, validate, image, translate, publish to Sanity. Autonomous from start to finish.

  • Content Refresh

    Audit a stale post, find decay drivers, and ship a SERP-aligned refresh without losing existing rankings.

  • SEO Audit

    Site-wide SEO audit with prioritized fix list: technical, on-page, and EEAT signals.

Tự động hoá AI

Xem tất cả
  • Security Auditor

    Weekly SCA + IaC scan with prioritized fix PRs.

  • Cold Email Writer

    Generates first-touch emails grounded in one specific public detail.

  • Lead Research Agent

    Enrich an email into a profile, score fit, alert in Slack.

Công cụ hot trong kho

Claude Skills

Xem tất cả
  • New Post

    Full SEO blog pipeline: research, brief, write, validate, image, translate, publish to Sanity. Autonomous from start to finish.

  • Content Refresh

    Audit a stale post, find decay drivers, and ship a SERP-aligned refresh without losing existing rankings.

  • SEO Audit

    Site-wide SEO audit with prioritized fix list: technical, on-page, and EEAT signals.

Tự động hoá AI

Xem tất cả
  • Security Auditor

    Weekly SCA + IaC scan with prioritized fix PRs.

  • Cold Email Writer

    Generates first-touch emails grounded in one specific public detail.

  • Lead Research Agent

    Enrich an email into a profile, score fit, alert in Slack.

Dịch vụ

  • Giải pháp doanh nghiệp
  • Ứng dụng di động
  • Ứng dụng web

Giải pháp

  • Hệ thống CRM
  • Tích hợp AI
  • Giải pháp ERP
  • Voice Agent
  • Tự động hóa quy trình
  • Bảo mật thông tin

Thư viện

  • Blog
  • Dự án

Cộng đồng

  • Tự động hoá AI
  • Claude Skills

Công cụ

  • Tính phí làm ứng dụng mobile
  • Tính phí dùng OpenAI / LLM API
  • Tính phí làm MVP
  • Tính phí làm Voice AI Agent

Công ty

  • Giới thiệu
  • Cộng sự
  • Liên hệ

Pháp lý

  • Chính sách quyền riêng tư
  • Điều khoản dịch vụ
  • Chính sách cookie

Dịch vụ

  • Giải pháp doanh nghiệp
  • Ứng dụng di động
  • Ứng dụng web

Giải pháp

  • Hệ thống CRM
  • Tích hợp AI
  • Giải pháp ERP
  • Voice Agent
  • Tự động hóa quy trình
  • Bảo mật thông tin

Thư viện

  • Blog
  • Dự án

Cộng đồng

  • Tự động hoá AI
  • Claude Skills

Công cụ

  • Tính phí làm ứng dụng mobile
  • Tính phí dùng OpenAI / LLM API
  • Tính phí làm MVP
  • Tính phí làm Voice AI Agent

Công ty

  • Giới thiệu
  • Cộng sự
  • Liên hệ
Pháp lýChính sách quyền riêng tưĐiều khoản dịch vụChính sách cookie
TECHSY
© 2026 Techsy. Bảo lưu mọi quyền.