Chuyển đến nội dung chính

Claude Code Hooks: Hướng dẫn thực hành về tự động hóa quy trình làm việc

Tìm hiểu cách tự động hóa dựa trên hook hoạt động và bắt đầu dùng Claude Code hooks để tự động hóa các tác vụ như kiểm thử, định dạng và nhận thông báo.
Đã cập nhật 22 thg 7, 2026  · 15 phút đọc

Khám phá với AI

Mở trong ChatGPTMở trong ClaudeMở trong Perplexity

Khi làm việc với Claude Code, bạn sẽ nhận ra một vấn đề quen thuộc: Nó viết mã tốt nhưng quên các bước quan trọng như định dạng, chạy kiểm thử hoặc tuân thủ quy chuẩn bảo mật. Bạn sẽ phải lặp đi lặp lại cùng những lời nhắc. Claude Code Hooks cho phép bạn tự động hóa các lời nhắc này bằng cách chạy các lệnh shell tự động tại những điểm cụ thể trong quy trình làm việc.

Trong hướng dẫn này, tôi trình bày cách thiết lập hooks cho định dạng mã, thực thi kiểm thử, thông báo và bảo vệ tệp. Bạn sẽ xây dựng một hệ thống tự động hóa thực thi các tiêu chuẩn phát triển của bạn mà không cần can thiệp thủ công.

Để tìm hiểu thêm về Claude Code, hãy xem hướng dẫn thực tiễn tốt nhất cho Claude Code và bài Claude Skills. Nếu bạn muốn học cách cấu hình hướng dẫn ở cấp dự án, xem hướng dẫn viết CLAUDE.md.

Tóm tắt nhanh

  • Claude Code Hooks là các lệnh shell chạy tự động tại những điểm xác định trong vòng đời của Claude Code (trước/sau khi gọi tool, khi bắt đầu phiên, khi Claude dừng)

  • Cấu hình trong .claude/settings.json (dự án) hoặc ~/.claude/settings.json (toàn cục) dùng JSON với sự kiện, matcher và lệnh

  • Dùng hooks PreToolUse để chặn thao tác nguy hiểm trước khi xảy ra (mã thoát 2 = chặn)

  • Dùng hooks PostToolUse cho tác vụ dọn dẹp như định dạng, linting, hoặc chạy kiểm thử sau khi Claude viết mã

  • Hooks nhận ngữ cảnh JSON qua stdin và truyền kết quả qua mã thoát, stdoutstderr

Claude Code Hooks là gì?

Claude Code Hooks là các lệnh shell chạy tự động khi những sự kiện cụ thể diễn ra trong phiên coding với AI của bạn. Hãy coi chúng như các kích hoạt tự động thực thi script tùy chỉnh của bạn vào những thời điểm chính xáctrước khi Claude ghi tệp, sau khi nó chạy lệnh, hoặc khi nó gửi thông báo cho bạn.

Hệ thống hoạt động bằng cách theo dõi các hành động của Claude Code và so khớp chúng với các quy tắc bạn định nghĩa trong tệp cấu hình. Khi có khớp, lệnh bạn chỉ định sẽ chạy với quyền truy cập vào ngữ cảnh về những gì vừa xảy ra. Điều này giúp bạn kiểm soát hành vi của Claude và tự động hóa các tác vụ lặp lại vốn cần can thiệp thủ công.

Dưới đây là một hook cơ bản chạy trình định dạng mã mỗi khi Claude ghi một tệp Python:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "python -m black ."
          }
        ]
      }
    ]
  }
}

Hook này có ba phần: 

  • Sự kiện: PostToolUse (sau khi Claude hoàn tất một hành động)

  • Matcher: Write (chỉ khi ghi tệp)

  • Lệnh: python -m black . (định dạng các tệp Python trong thư mục hiện tại)

Hook nhận thông tin chi tiết về hành động Claude vừa thực hiện thông qua dữ liệu JSON gửi vào đầu vào của script, vì vậy bạn có thể xây dựng tự động hóa tinh vi hơn phản hồi theo các thay đổi tệp cụ thể.

Nếu muốn tiến xa hơn với tự động hóa Claude Code, hướng dẫn Claude Code Routines trình bày cách lập lịch hooks và agent chạy định kỳ trên đám mây.

Hãy xem cách tạo hooks từ đầu và đăng ký chúng trong Claude Code.

Yêu cầu tiên quyết

Bạn cần chuẩn bị một vài thứ trước khi bắt đầu:

  • Đã cài đặt và chạy Claude Code: Bạn nên sử dụng Claude Code thành thạo cho các tác vụ lập trình cơ bản

  • Quen thuộc dòng lệnh: Hooks chạy lệnh shell, nên bạn cần biết cách viết các lệnh terminal cơ bản trên hệ điều hành của mình

  • Có trình soạn thảo văn bản: Bạn sẽ chỉnh sửa các tệp cấu hình JSON để thiết lập hooks

  • Thư mục dự án: Một dự án mã nơi bạn có thể thử nghiệm hooks an toàn mà không ảnh hưởng công việc quan trọng

Bạn không cần là chuyên gia shell scripting, nhưng hiểu cách chạy các lệnh như ls, cd, và các thao tác tệp cơ bản sẽ giúp bạn theo kịp ví dụ. Nếu bạn mới với bash hoặc terminal, tôi khuyến nghị khóa Introduction to Shell của chúng tôi.

Bắt đầu với Claude Code Hooks

Giờ bạn đã hiểu hooks là gì, hãy thiết lập tự động hóa đầu tiên. Quy trình gồm chọn sự kiện phù hợp, cấu hình một quy tắc đơn giản và kiểm thử với một lệnh cơ bản.

Tìm hiểu các sự kiện hook

Claude Code cung cấp hơn 25 sự kiện hook. Bảng dưới đây bao quát 10 sự kiện bạn sẽ dùng thường xuyên nhất. Danh sách đầy đủ xem trong tài liệu tham chiếu hooks chính thức.

PreToolUsePostToolUse là các sự kiện phổ biến nhất. PreToolUse chạy trước khi Claude thực hiện hành động như ghi tệp hoặc chạy lệnh, rất phù hợp để kiểm tra hoặc chặn thao tác nguy hiểm. PostToolUse chạy sau khi Claude hoàn tất hành động, phù hợp cho tác vụ dọn dẹp như định dạng mã hoặc chạy kiểm thử.

UserPromptSubmit kích hoạt khi bạn gửi prompt cho Claude, trước khi nó xử lý yêu cầu. Bạn có thể dùng để bổ sung ngữ cảnh cho cuộc trò chuyện hoặc xác thực prompt đáp ứng các yêu cầu nhất định.

Notification chạy khi Claude gửi cảnh báo cho bạn, như xin quyền chạy lệnh hoặc khi cần bạn nhập liệu. PermissionRequest kích hoạt khi Claude Code hiển thị hộp thoại cấp quyền, cho phép bạn tự động chấp thuận hoặc từ chối thay mặt người dùng.

StopSubagentStop kích hoạt khi Claude kết thúc phản hồi, hữu ích cho kiểm tra cuối cùng hoặc tạo báo cáo. Khác biệt ở chỗ Stop xảy ra khi Claude kết thúc phản hồi tổng thể, còn SubagentStop xảy ra khi trình trợ giúp do tool sinh ra (“subagent”) hoàn thành công việc.

Các sự kiện còn lại, PreCompact, SessionStart, và SessionEnd, xử lý các tình huống theo vòng đời. PreCompact chạy ngay trước khi Claude rút gọn lịch sử hội thoại. ‘SessionStart’ kích hoạt ở đầu phiên mới để thiết lập mặc định, và SessionEnd kích hoạt khi phiên đóng, cho phép dọn dẹp hoặc báo cáo cuối cùng.eporting.

Tên sự kiện

Thời điểm kích hoạt

Trường hợp sử dụng chính

PreToolUse

Trước khi Claude thực hiện một hành động (ví dụ: ghi tệp, chạy lệnh).

Xác thực hành động hoặc chặn thao tác nguy hiểm.

PostToolUse

Sau khi Claude hoàn tất một hành động.

Dọn dẹp, định dạng mã, hoặc chạy kiểm thử.

UserPromptSubmit

Khi bạn gửi prompt, trước khi bắt đầu xử lý.

Bổ sung ngữ cảnh cho hội thoại hoặc xác thực yêu cầu của prompt.

Notification

Khi Claude gửi cảnh báo (ví dụ: yêu cầu nhập liệu hoặc cấp quyền).

Xử lý cảnh báo hệ thống và các yêu cầu thu hút sự chú ý của người dùng.

PermissionRequest

Khi một hộp thoại cấp quyền được hiển thị.

Tự động chấp thuận hoặc từ chối thay mặt người dùng.

Stop

Khi Claude kết thúc phản hồi tổng thể.

Kiểm tra cuối cùng hoặc tạo báo cáo cho phản hồi chính.

SubagentStop

Khi một trình trợ giúp ("subagent") do tool tạo ra hoàn tất công việc.

Kiểm tra cuối cùng dành riêng cho hoạt động của subagent.

PreCompact

Ngay trước khi lịch sử cuộc trò chuyện được rút gọn.

Quản lý dọn dẹp hội thoại và bảo toàn ngữ cảnh.

SessionStart

Bắt đầu một phiên mới.

Khởi tạo và thiết lập mặc định.

SessionEnd

Khi phiên kết thúc.

Dọn dẹp cuối cùng hoặc báo cáo cuối phiên.

Tìm hiểu về matcher

Matcher là các bộ lọc quyết định hành động nào của Claude Code sẽ kích hoạt một hook. Về kỹ thuật, chúng là các chuỗi được diễn giải như biểu thức chính quy, vì vậy bạn có thể dùng khớp chính xác hoặc mẫu linh hoạt hơn. 

Các matcher liên quan nhất là các mẫu đơn giản như Write (kích hoạt khi Claude ghi tệp) hoặc Edit (khi chỉnh sửa nội dung), và các tổ hợp như Edit|Write để bao phủ nhiều hành động. 

Bạn cũng có thể dùng mẫu tiền tố như Notebook.* để khớp tất cả các tool bắt đầu với “Notebook.” Nếu bạn muốn hook kích hoạt trên mọi hành động, dùng regex phổ quát .*, chuỗi rỗng ("") hoặc để trống matcher.

Vì matcher phân biệt hoa thường và chỉ áp dụng cho tên hành động, tốt nhất hãy giữ chúng cụ thể nhất có thể. Khi bạn cần kiểm soát chi tiết hơn (ví dụ, giới hạn hook cho một số loại tệp), bạn có thể đọc payload JSON mà Claude truyền vào hook và áp dụng regex hoặc điều kiện riêng ở đó.

Tạo hook đầu tiên trong Claude Code

Claude Code cung cấp hai cách thiết lập hooks: qua lệnh tương tác /hooks hoặc chỉnh sửa trực tiếp tệp cấu hình. Hãy bắt đầu với cách tương tác vì thân thiện cho người mới.

Dùng lệnh /hooks:

  1. Mở Claude Code và gõ /hooks trong giao diện chat

  2. Chọn sự kiện kích hoạt (chọn PostToolUse cho ví dụ này)

  3. Chọn "Add new hook" từ menu

  4. Đặt mẫu matcher (nhập Write để nhắm vào hành động ghi tệp)

  5. Nhập lệnh của bạn:

    • Mac: say "Task complete"

    • Windows: powershell -c [console]::beep()

    • Linux: spd-say "Task complete"

  6. Lưu cấu hình và quay lại Claude Code bằng cách nhấn Esc ba lần

Lệnh /hooks sẽ tự động cập nhật tệp cài đặt và nạp lại cấu hình. Bạn cũng có thể dùng /hooks bất cứ lúc nào để xem hooks hiện có hoặc chỉnh sửa.

Nếu bạn thích chỉnh sửa tệp cấu hình trực tiếp, hooks nằm ở ~/.claude/settings.json cho cài đặt toàn cục, .claude/settings.json trong thư mục dự án của bạn (commit vào repo để chia sẻ hooks với đội), hoặc .claude/settings.local.json cho hooks cá nhân được gitignore mặc định. Với ví dụ ở trên, nó sẽ như sau:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "say 'Task complete'"
          }
        ]
      }
    ]
  }
}

Sau khi chỉnh sửa thủ công, hãy khởi động lại Claude Code hoặc dùng lệnh /hooks để nạp lại cấu hình. Giờ mỗi khi Claude ghi tệp, bạn sẽ nghe thông báo âm thanh.

Kiểm thử hook của bạn

Trước khi tiếp tục, hãy xác minh hook thực sự hoạt động:

  1. Yêu cầu Claude viết bất kỳ tệp Python nào (ví dụ, "Tạo tệp hello.py in ra hello world")

  2. Bạn sẽ nghe thông báo âm thanh khi Claude hoàn tất thao tác ghi

  3. Nếu không nghe thấy gì, kiểm tra transcript của Claude Code bằng cách nhấn Ctrl-O để xem thông báo lỗi

  4. Các lỗi thường gặp gồm lệnh hook không tìm thấy, quyền tệp sai, hoặc lỗi cú pháp trong tệp cấu hình

Thiết lập kiểm thử cơ bản này sẽ giúp bạn tiết kiệm thời gian gỡ lỗi khi xây dựng các hooks phức tạp hơn. Nếu bạn vừa chỉnh sửa tệp cài đặt thủ công, thay đổi matcher hoặc sự kiện, hoặc cài công cụ mới để dùng trong lệnh hook, việc mở lại /hooks hoặc khởi động lại Claude để nạp cấu hình cũng hữu ích.

Mẫu cơ bản này (sự kiện, matcher, lệnh) là nền tảng cho mọi tự động hóa hook. Bạn có thể mở rộng bằng cách thêm nhiều lệnh chạy đồng thời khi cùng sự kiện kích hoạt. Ví dụ, bạn có thể vừa phát âm thanh vừa tạo bản sao lưu khi Claude ghi tệp. 

Bạn cũng có thể tạo các matcher riêng cho các tool khác nhau trong cùng một sự kiện, để việc ghi tệp kích hoạt hành động khác với chỉnh sửa mã. Tất cả hooks khớp cùng mẫu tool sẽ chạy song song. Nếu bạn cấu hình nhiều matcher cho cùng sự kiện, mỗi hook sẽ chạy khi matcher của nó được kích hoạt.

Làm việc với đầu vào của Hook

Khi Claude Code kích hoạt một hook, nó gửi thông tin về những gì vừa xảy ra qua đầu vào chuẩn (stdin), một luồng dữ liệu chảy trực tiếp tới lệnh của bạn khi chạy. Đây là yếu tố khiến hooks trở nên mạnh mẽ thay vì chỉ là các script ngẫu nhiên chạy vào lúc tùy ý. 

Claude Code đóng gói thông tin này thành JSON và cung cấp cho bất kỳ lệnh nào bạn cấu hình, dù là lệnh terminal đơn giản hay script tùy chỉnh.

Cấu trúc đầu vào hook

Mỗi hook nhận một đối tượng JSON với các trường cơ bản về phiên hiện tại:

{
  "session_id": "abc123",
  "transcript_path": "/Users/you/.claude/projects/my-project/conversation.jsonl", 
  "cwd": "/Users/you/my-project",
  "hook_event_name": "PostToolUse"
}

Giải thích từng thành phần:

  • session_id: định danh cuộc trò chuyện hiện tại

  • transcript_path: đường dẫn tới lịch sử hội thoại

  • cwd: thư mục làm việc

  • hook_event_name: cho biết sự kiện nào đã kích hoạt

Với ngữ cảnh này, hooks của bạn có thể ra quyết định thông minh: theo dõi cuộc trò chuyện nào đã kích hoạt hành động, truy cập đầy đủ lịch sử chat nếu cần, hoặc chạy lệnh trong đúng thư mục.

Biến thể đầu vào theo sự kiện

Các sự kiện công cụ như PreToolUsePostToolUse bao gồm chi tiết bổ sung về hành động, đây là nơi hooks thực sự hữu ích cho tự động hóa. Trong PreToolUse, có tool_input, và thêm tool_response trong PostToolUse:

{
  "session_id": "abc123",
  "hook_event_name": "PostToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.py",
    "content": "print('Hello world')"
  },
  "tool_response": {
    "filePath": "/path/to/file.py", 
    "success": true
  }
}

Trong đầu vào hook, file_path cho biết đường dẫn tệp đang được ghi hoặc chỉnh sửa, còn content chứa chính xác nội dung công cụ sắp ghi. Sau khi thực thi, phản hồi của công cụ phản ánh lại filePath cuối cùng (lưu ý camelCase) để xác nhận tệp nào thực sự bị tác động, cùng cờ success cho biết thao tác có thành công hay không. 

Thông tin chi tiết này cho phép hooks phản hồi khác nhau tùy theo những gì thực sự xảy ra. Bạn có thể chỉ định dạng các tệp Python, chỉ sao lưu thư mục quan trọng, hoặc chỉ gửi thông báo khi những loại tệp nhất định bị sửa đổi.

Các sự kiện như UserPromptSubmit đơn giản hơn vì không liên quan tới tool:

{
  "session_id": "abc123",
  "hook_event_name": "UserPromptSubmit", 
  "prompt": "Write a function to calculate factorial"
}

Lưu ý rằng hooks UserPromptSubmit không dùng matcher trong cấu hình. Chúng kích hoạt trên mọi prompt, không phải thao tác của tool. Điều này khiến chúng hoàn hảo để ghi log hội thoại, tự động thêm ngữ cảnh dự án, hoặc xác thực prompt trước khi Claude xử lý.

Đọc đầu vào hook trong thực tế

Hãy tạo một hook ghi log mọi prompt của người dùng. Điều này giải quyết vấn đề khó theo dõi những gì bạn đã yêu cầu Claude làm, đặc biệt trong các phiên lập trình dài. Trước tiên, cấu hình hook:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.claude/log_prompts.py"
          }
        ]
      }
    ]
  }
}

Tiếp theo, tạo script Python tại ~/.claude/log_prompts.py với nội dung sau:

#!/usr/bin/env python3
import json
import sys
from datetime import datetime

# Read JSON data from stdin
input_data = json.load(sys.stdin)

# Extract information
session_id = input_data.get("session_id", "unknown")
prompt = input_data.get("prompt", "")
timestamp = datetime.now().isoformat()

# Log the prompt
log_entry = f"{timestamp} | Session: {session_id[:8]} | {prompt}\n"
with open("prompt_history.txt", "a") as f:
    f.write(log_entry)

Script đọc dữ liệu JSON mà Claude Code gửi và ghi log prompt kèm ngữ cảnh phiên. Điều này tạo ra lịch sử có thể tìm kiếm cho các tương tác của bạn, rất hữu ích khi bạn cần nhớ cách mình đã giải một vấn đề sau hàng tuần.

Làm việc với đầu ra của Hook

Sau khi lệnh hook chạy, nó cần báo cho Claude Code biết điều gì đã xảy ra và có nên tiếp tục bình thường không. Cơ chế kiểm soát này biến hooks từ công cụ ghi log đơn giản thành tự động hóa quy trình làm việc mạnh mẽ có thể định hướng hành vi của Claude. Việc này diễn ra qua ba kênh: đầu ra chuẩn (stdout), lỗi chuẩn (stderr), và mã thoát.

Kênh đầu ra và mã thoát

Đầu ra chuẩn (stdout) là đầu ra bình thường. Ví dụ, nếu bạn in ra, nó sẽ đi tới stdout. Với hầu hết hooks, đây là nội dung hiển thị trong transcript của Claude Code khi bạn nhấn Ctrl-O, cung cấp bản ghi những gì tự động hóa của bạn đã làm mà không làm lộn xộn cuộc trò chuyện chính.

Lỗi chuẩn (stderr) là thông báo lỗi. Bạn có thể ghi ra stderr bằng 

  • Python: print("message", file=sys.stderr) hoặc

  • Dòng lệnh: echo "message" >&2

Điểm khác biệt quan trọng là stderr có thể được gửi trực tiếp cho Claude để xử lý tự động, cho phép nó phản hồi các vấn đề hooks phát hiện.

Mã thoát cho Claude Code biết cần làm gì tiếp theo:

  • Mã thoát 0: Thành công (hiển thị stdout cho người dùng)

  • Mã thoát 2: Lỗi chặn (gửi stderr tới Claude)

  • Mã khác: Lỗi không chặn (hiển thị stderr cho người dùng, nhưng vẫn tiếp tục)

Hệ thống này cho bạn quyền kiểm soát tinh vi về thời điểm Claude nên dừng, tiếp tục, hoặc nhận phản hồi về những gì tự động hóa của bạn phát hiện. Hãy cùng xem ví dụ cho hai mã thoát quan trọng nhất.

Mã thoát 0: Hoạt động bình thường

Hầu hết hooks dùng mã thoát 0 để chỉ mọi thứ diễn ra tốt. Đây là một hook hoàn chỉnh ghi log thao tác tệp và thông báo cho người dùng:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "python3 -c \"import datetime; open('activity.log','a').write('File written: ' + datetime.datetime.now().isoformat() + '\\n'); print('Logged file operation')\""
          }
        ]
      }
    ]
  }
}

Hook này chạy hai lệnh: ghi log vào tệp, rồi in thông báo vào transcript. Có nhiều cách để làm việc này, nhưng cách tiếp cận này đa nền tảng và tránh phụ thuộc đặc thù dòng lệnh.

Vì không có mã thoát tường minh, mặc định là 0. Thông điệp được in sẽ xuất hiện trong transcript của Claude Code, cho bạn phản hồi rằng việc ghi log đã thành công. Mẫu này rất phù hợp để xây dựng nhật ký kiểm toán hoặc theo dõi các thay đổi Claude thực hiện với dự án theo thời gian.

Mã thoát 2: Chặn kèm phản hồi

Mã thoát 2 gửi thông điệp lỗi trực tiếp tới Claude, cho phép nó phản hồi tự động. Đây là lúc hooks trở thành cơ chế an toàn chứ không chỉ là tự động hóa. Dưới đây là hook chặn thao tác tệp nguy hiểm:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.claude/security_check.py"
          }
        ]
      }
    ]
  }
}

Bạn cần tạo script kiểm tra bảo mật tại ~/.claude/security_check.py:

#!/usr/bin/env python3
import json
import sys

# Read hook input
input_data = json.load(sys.stdin)
tool_input = input_data.get("tool_input", {})
file_path = tool_input.get("file_path", "")

# Check for dangerous patterns
dangerous_paths = ["/etc/", "/usr/", "production.conf"]
is_dangerous = any(pattern in file_path for pattern in dangerous_paths)

if is_dangerous:
    # Block the operation and tell Claude why
    print(f"Blocked modification of {file_path} - this appears to be a system or production file", file=sys.stderr)
    sys.exit(2)  # Sends stderr message to Claude
else:
    # Allow the operation
    print(f"Approved modification of {file_path}")
    sys.exit(0)  # Shows stdout in transcript

Khi hook này phát hiện đường dẫn nguy hiểm, nó thoát với mã 2. Claude Code gửi thông điệp stderr tới Claude, sau đó Claude có thể giải thích cho bạn vì sao thao tác bị chặn và gợi ý phương án thay thế. Điều này ngăn ngừa hư hại ngoài ý muốn tới tệp hệ thống đồng thời giúp Claude nắm rõ chính sách bảo mật của bạn.

Xây dựng Hook thông báo thông minh cho Claude Code

Hãy xây dựng hook thông báo nâng cao kết hợp xử lý đầu vào và điều khiển đầu ra thông minh. Điều này giải quyết vấn đề “ồn ào” từ hook ban đầu của chúng ta vốn cảnh báo trên mọi thay đổi tệp:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.claude/smart_notify.py"
          }
        ]
      }
    ]
  }
}

Tạo script thông báo tại ~/.claude/smart_notify.py:

#!/usr/bin/env python3
import json
import sys
import os
import subprocess

# Read the hook input
input_data = json.load(sys.stdin)
tool_input = input_data.get("tool_input", {})
file_path = tool_input.get("file_path", "")

# Categorize file importance
important_extensions = [".py", ".js", ".ts", ".java", ".cpp"]
config_files = ["Dockerfile", "requirements.txt", "package.json"]

is_code = any(file_path.endswith(ext) for ext in important_extensions)
is_config = any(filename in file_path for filename in config_files)

if is_code:
    # Important: notify and log
    print(f"Code file modified: {os.path.basename(file_path)}")
    subprocess.run(["say", "Code updated"], check=False)  # Mac
    sys.exit(0)  # Show message in transcript
elif is_config:
    # Very important: louder notification
    print(f"Configuration file changed: {os.path.basename(file_path)}")
    subprocess.run(["say", "Configuration updated - review changes"], check=False)
    sys.exit(0)
else:
    # Not important: silent success
    sys.exit(0)

Hook này đọc đầu vào để hiểu tệp nào bị sửa, đưa ra quyết định về mức độ quan trọng của thông báo dựa trên loại tệp, dùng stdout để ghi log các thay đổi quan trọng vào transcript, kích hoạt thông báo âm thanh khác nhau theo loại tệp, và luôn thoát với mã 0 vì đây là hành động thông tin, không phải chặn.

Sự kết hợp giữa phân tích đầu vào và điều khiển đầu ra tạo nên một hook hành xử thông minh theo ngữ cảnh, đồng thời cung cấp mức phản hồi phù hợp cho cả bạn và Claude Code. Thay vì nhận thông báo phiền nhiễu cho mọi tệp tạm, bạn chỉ nghe về các thay đổi thực sự quan trọng với dự án.

Lưu ý ví dụ này dùng lệnh say có sẵn trên macOS. Trên Linux, bạn có thể dùng notify-send, và trên Windows, một lệnh PowerShell, để có thông báo tương tự.

Những lỗi thường gặp với Claude Code Hooks

Một vài điều khiến hầu hết mọi người vấp phải trong tuần đầu dùng hooks:

Các câu lệnh echo trong profile shell phá vỡ hooks. Hooks chạy trong shell không tương tác, có nguồn từ ~/.zshrc hoặc ~/.bashrc của bạn. Nếu profile có câu lệnh echo vô điều kiện, chúng sẽ chèn tiền tố vào stdout của hook và làm hỏng việc phân tích JSON. Hãy bọc chúng trong kiểm tra shell tương tác:

if [[ $- == *i* ]]; then
  echo "Welcome back"
fi

Stop hooks có thể lặp vô hạn. Một hook Stop thoát với mã 2 buộc Claude tiếp tục làm việc. Nếu script của bạn không kiểm tra stop_hook_active từ JSON đầu vào và thoát gọn khi nó là true, bạn sẽ quay vòng cho đến khi hết thời gian. Luôn thêm điều kiện thoát sớm.

Matcher phân biệt chữ hoa/thường. bash không khớp với Bash. Hãy dùng đúng tên tool như hiển thị trong Claude Code.

Đầu ra bị giới hạn 10.000 ký tự. Nếu hook của bạn sinh nhiều hơn, nó sẽ bị cắt trước khi đưa vào ngữ cảnh của Claude. Giữ stdout gọn và chỉ bộc lộ những gì mô hình cần để hành động.

Nhầm lẫn giữa hooks cấp đội và cá nhân. Hooks trong .claude/settings.json được chia sẻ với đội (commit vào repo). Với hooks cá nhân bạn không muốn chia sẻ, dùng .claude/settings.local.json, mặc định được gitignore.

Hooks và skills: khi nào dùng loại nào

Hooks và Claude Skills phục vụ các mục đích khác nhau và phối hợp tốt với nhau. Một skill là tệp markdown dạy Claude cách làm điều gì đó (quy trình, quy ước, mẫu). Một hook là lệnh shell áp đặt quy tắc một cách quyết định, bất kể Claude chọn gì.

Sự khác biệt rất quan trọng: skill là gợi ý mà mô hình có thể bỏ qua khi bị áp lực; hook thì kích hoạt mỗi lần. Viết một skill để ghi lại quy trình di trú của đội. Viết một hook PostToolUse để chạy linter di trú trên mọi tệp .sql mà Claude viết. Skill giúp Claude thành thạo; hook giúp Claude có trách nhiệm.

Nhu cầu

Dùng skill

Dùng hook

Kiến thức thủ tục Claude nạp khi phù hợp

Không

Cưỡng chế nghiêm ngặt không thể bỏ qua

Không

Chạy một cách quyết định mỗi lần

Không

Vẫn hoạt động khi mô hình cư xử sai

Không

Mẫu nâng cao cho Claude Code Hooks

Vượt ra ngoài thông báo và ghi log cơ bản, hooks có thể giải quyết các vấn đề quy trình phát triển thực tế mà đội ngũ gặp phải hằng ngày. Dưới đây là vài ý tưởng bạn có thể điều chỉnh cho dự án của mình.

Điều tuyệt vời là bạn không cần tự tay xây dựng các hooks này. Bạn chỉ cần đưa cho Claude Code một trong những ý tưởng prompt dưới đây, cùng với tài liệu tham chiếu Hooks, và nó sẽ sinh mã và JSON cấu hình tương ứng.

Mỗi mẫu dưới đây có thể tùy biến theo công cụ và quy trình của bạn. Hãy bắt đầu với những mẫu giải quyết bức xúc lớn nhất hằng ngày, rồi mở rộng tự động hóa khi bạn quen dần với việc phát triển hook.

Hooks nâng cao cho bảo mật và tuân thủ

Hooks rất hữu ích để thực thi quy tắc bảo mật và tiêu chuẩn tuân thủ. Dưới đây là bốn trường hợp sử dụng.

Trình quét khóa API

  • Vấn đề: Vô tình commit bí mật vào hệ thống quản lý phiên bản

  • Kích hoạt: Trước khi ghi bất kỳ tệp nào

  • Giải pháp: Quét nội dung tệp tìm khóa API, token và mật khẩu bằng regex

“Tạo một script Python đọc JSON đầu vào của hook, trích xuất nội dung tệp và dùng regex để phát hiện các định dạng bí mật phổ biến như api_key=, token:, hoặc password=.  Với mọi khớp nghi ngờ, hãy xác minh cục bộ và không bao giờ gửi bí mật thô ra bên ngoài. 

Chỉ gửi các trích đoạn đã che (ví dụ, giữ 4 ký tự đầu/cuối) hoặc băm tới Anthropic API để phân tích chuỗi nghi ngờ và xác định đó có phải bí mật thực sự hay chỉ là tên biến. Thoát với mã 2 và cung cấp phản hồi cho Claude về bí mật phát hiện và phương án an toàn hơn.”

Trình cưỡng bức header giấy phép

  • Vấn đề: Dự án mã nguồn mở thiếu header giấy phép bắt buộc trong các tệp mới

  • Kích hoạt: Trước khi ghi các tệp mã nguồn

  • Giải pháp: Xác thực các tệp .py, .js, .java mới có chứa đoạn giấy phép phù hợp

“Phân tích đầu vào hook để lấy nội dung tệp và kiểm tra xem 10 dòng đầu có chứa văn bản giấy phép bằng so khớp chuỗi hay không. Với xác thực tinh vi hơn, gửi phần header của tệp tới Claude qua Anthropic API để xác minh có ghi chú bản quyền và thông tin giấy phép phù hợp. Chặn tạo tệp với mã 2 nếu thiếu header, và cung cấp cho Claude mẫu giấy phép chính xác để bổ sung.”

Bảo vệ tệp sản xuất

  • Vấn đề: Vô tình chỉnh sửa các tệp cấu hình hệ thống quan trọng

  • Kích hoạt: Trước khi chỉnh sửa tệp trong thư mục nhạy cảm

  • Giải pháp: Chặn thay đổi với /etc/, nginx.conf, database.yml, và cấu hình quan trọng khác

“Trích xuất đường dẫn tệp từ JSON đầu vào của hook và kiểm tra xem nó có khớp các mẫu như /etc/, production.yml, hoặc các tên tệp quan trọng khác không. Dùng API của Claude để phân tích đường dẫn và xác định đó có phải tệp cấu hình có thể ảnh hưởng hệ thống sản xuất hay không. Thoát với mã 2 và cung cấp hướng dẫn cụ thể về thực hành phát triển an toàn khi phát hiện đường dẫn nguy hiểm.”

Trình tối ưu hóa ảnh

  • Vấn đề: Tệp ảnh lớn làm chậm ứng dụng và kho mã

  • Kích hoạt: Sau khi thêm tệp ảnh mới

  • Giải pháp: Nén tệp PNG/JPEG trong khi giữ chất lượng hiển thị

“Phân tích đầu vào hook để lấy đường dẫn tệp và kiểm tra xem đó có phải tệp ảnh bằng cách so đuôi mở rộng. Chạy công cụ nén như imageoptim hoặc gọi TinyPNG API để nén ảnh trong khi bảo toàn chất lượng. Ghi kết quả nén ra stdout để bạn có thể thấy phần tiết kiệm dung lượng trong transcript của Claude.”

Hooks nâng cao cho tự động hóa quản lý phiên bản

Quy trình Git và tài liệu là khu vực hooks cũng rất hữu ích. Hãy xem một số ý tưởng.

Trình xác thực nhánh Git

  • Vấn đề: Thành viên đội vô tình đẩy thay đổi lên nhánh được bảo vệ

  • Kích hoạt: Trước bất kỳ thao tác ghi hoặc chỉnh sửa tệp nào

  • Giải pháp: Kiểm tra nhánh Git hiện tại và chặn thao tác trên main/master/production

“Dùng lệnh bash đơn giản git branch --show-current để lấy tên nhánh hiện tại và so với danh sách nhánh được bảo vệ. Nếu đang ở nhánh bảo vệ, thoát với mã 2 và gửi cho Claude thông điệp lỗi giải thích chính sách bảo vệ nhánh. Với quy tắc đặt tên nhánh phức tạp, dùng API của Claude để phân tích tên nhánh và xác định có khớp mẫu bảo vệ hay không.”

Tự động commit thông minh

  • Vấn đề: Quên commit thay đổi hoặc viết thông điệp commit kém

  • Kích hoạt: Sau bất kỳ sửa đổi tệp nào

  • Giải pháp: Tự động stage và commit thay đổi với thông điệp do AI tạo, giàu mô tả

“Đọc các đường dẫn tệp sửa đổi từ đầu vào hook, chạy git diff để lấy thay đổi, và gửi diff tới API của Claude với prompt yêu cầu một thông điệp commit súc tích. Dùng thông điệp sinh ra cùng lệnh git addgit commit để tự động commit thay đổi. Bao gồm tên tệp và loại thay đổi trong prompt API để đảm bảo thông điệp commit theo chuẩn conventional commits.”

Trình tạo tài liệu

  • Vấn đề: Tài liệu API không đồng bộ với thay đổi mã

  • Kích hoạt: Sau khi sửa đổi các tệp giao diện (controller, model, API)

  • Giải pháp: Tự động chạy công cụ tạo tài liệu như JSDoc, Sphinx, hoặc OpenAPI

“Kiểm tra đường dẫn tệp sửa đổi để xác định đó có phải endpoint API, model, hoặc tệp giao diện bằng so mẫu. Gửi nội dung tệp tới API của Claude, yêu cầu trích xuất thay đổi API và tạo cập nhật tài liệu. Chạy công cụ tạo tài liệu phù hợp (jsdoc, sphinx-build, v.v.) và tự động commit tài liệu đã cập nhật.

Hooks nâng cao cho cộng tác và tích hợp quy trình

Cuối cùng, hooks có thể giúp tất cả thành viên trong đội luôn được cập nhật.

Tích hợp Slack

  • Vấn đề: Đội không biết về các thay đổi quan trọng với codebase chung

  • Kích hoạt: Khi gửi thông báo cho các thao tác quan trọng

  • Giải pháp: Đăng thông điệp định dạng lên kênh đội với tên tệp và tóm tắt thay đổi

“Trích xuất thông tin tệp từ đầu vào hook và lọc theo các loại tệp quan trọng như mã nguồn hoặc cấu hình. Dùng API của Claude để tạo tóm tắt dễ đọc về những gì đã thay đổi dựa trên tên và loại tệp. Gửi thông điệp định dạng tới Slack bằng webhook URL kèm đề cập thành viên cho thay đổi quan trọng.”

Trình phân phối webhook

  • Vấn đề: Kích hoạt pipeline CI/CD thủ công gây trì hoãn triển khai

  • Kích hoạt: Khi các sự kiện cụ thể xảy ra (thay đổi cấu hình, sửa tệp triển khai)

  • Giải pháp: Gọi API bên ngoài để kích hoạt build, triển khai, hoặc quy trình tự động khác

“Kiểm tra đường dẫn tệp sửa đổi với các mẫu như Dockerfile, package.json, hoặc cấu hình triển khai để xác định có nên kích hoạt CI/CD hay không. Dùng thư viện requests trong Python để gọi webhook URL với header xác thực và payload dữ liệu về thay đổi. Bao gồm đường dẫn tệp và siêu dữ liệu thay đổi trong payload để hệ thống bên ngoài có thể đưa ra quyết định thông minh về việc build hay triển khai.”

Trình cập nhật trang trạng thái

  • Vấn đề: Khách hàng không biết về hoạt động bảo trì hoặc triển khai

  • Kích hoạt: Khi các tệp triển khai hoặc hạ tầng được sửa đổi

  • Giải pháp: Cập nhật trang trạng thái dịch vụ với thông báo bảo trì

“Phân tích đầu vào hook để tìm thay đổi tệp hạ tầng như manifest Kubernetes hoặc cấu hình Terraform bằng mẫu đường dẫn. Tạo thông điệp bảo trì bằng API của Claude dựa trên loại thay đổi hạ tầng được phát hiện. Đăng cập nhật trạng thái tới các dịch vụ như StatusPage.io hoặc PagerDuty qua REST API của họ với loại sự cố và thời lượng ước tính phù hợp.”

Trình thông báo trạng thái đội

  • Vấn đề: Xung đột khi nhiều lập trình viên làm cùng một tính năng mà không biết

  • Kích hoạt: Khi bắt đầu một phiên Claude Code mới

  • Giải pháp: Cảnh báo kênh đội rằng bạn bắt đầu làm việc trên một dự án hoặc thành phần cụ thể

“Đọc thư mục dự án từ đầu vào hook và dùng API của Claude để phân tích các tệp gần đây hoặc lịch sử git nhằm hiểu loại công việc đang được thực hiện. Gửi thông điệp định dạng tới kênh giao tiếp của đội với tên bạn, tên dự án và khu vực trọng tâm. Bao gồm thời lượng ước tính và mời các thành viên phối hợp nếu họ đang làm việc trên các tính năng liên quan.”

Lời kết

Claude Code Hooks biến trợ lý coding AI khó đoán thành các quy trình tự động chạy đúng lúc bạn cần. Trong hướng dẫn này, bạn đã học cách thiết lập hooks bằng cả lệnh tương tác /hooks và cấu hình thủ công, hiểu dữ liệu đầu vào JSON vận hành tự động hóa thông minh, và kiểm soát hành vi Claude thông qua mã thoát và đầu ra có cấu trúc. 

Các mẫu thực tế chúng ta đã đề cập gồm các bộ kiểm tra bảo mật chặn thao tác nguy hiểm và thông báo thông minh giảm tiếng ồn. Những ví dụ này cho thấy hooks giải quyết vấn đề phát triển thực sự trong khi cho bạn toàn quyền kiểm soát trợ lý AI. Giờ bạn đã nắm vững nền tảng, bạn có thể xây dựng tự động hóa phù hợp với nhu cầu quy trình của đội mình. 

Để học thêm về làm việc với công cụ AI, hãy xem khóa Understanding Prompt Engineering của DataCamp, khóa học bao quát các chiến lược nhắc lệnh hoạt động trực tiếp với phát triển hook. Với kỹ năng coding AI rộng hơn, hãy thử khóa Intermediate ChatGPT để phát triển kỹ năng giúp trợ lý AI trở thành đối tác tin cậy hơn trong quy trình phát triển của bạn.

Claude Code Hooks FAQs

What are Claude Code Hooks?

Claude Code Hooks là các kích hoạt tự động thực thi lệnh shell khi các sự kiện cụ thể xảy ra trong phiên Claude Code của bạn. Chúng giải quyết vấn đề Claude viết mã tốt nhưng quên các bước quan trọng như định dạng, chạy kiểm thử hoặc kiểm tra bảo mật. Thay vì phải nhắc Claude thủ công mỗi lần, hooks tự động hóa các lời nhắc này bằng cách chạy lệnh tự động: ví dụ, định dạng mã Python sau khi Claude viết, chạy kiểm thử sau khi sửa đổi, hoặc chặn thay đổi nguy hiểm lên tệp nhạy cảm. Hooks theo dõi phiên của bạn, phát hiện sự kiện phù hợp và thực thi các lệnh đã cấu hình với quyền truy cập ngữ cảnh chi tiết về những gì Claude vừa làm.

How do I use hooks in Claude Code?

Bạn có thể thiết lập hooks theo hai cách. Cách dễ nhất là dùng lệnh tương tác /hooks trong Claude Code, công cụ sẽ hướng dẫn bạn chọn sự kiện (như PostToolUse), mẫu matcher (như Write cho ghi tệp), và lệnh của bạn (như python -m black .). Ngoài ra, bạn có thể chỉnh sửa cấu hình thủ công tại ~/.claude/settings.json (toàn cục) hoặc .claude/settings.json (mức dự án) để định nghĩa hooks bằng JSON. Khi đã cấu hình, hooks sẽ tự động được nạp và hoạt động. Bạn có thể xem, sửa, hoặc nạp lại hooks bất cứ lúc nào bằng cách chạy /hooks hoặc khởi động lại Claude Code.

What's the difference between PreToolUse and PostToolUse hooks?

PreToolUse chạy trước khi Claude thực thi hành động (như ghi hoặc chỉnh sửa tệp), rất lý tưởng cho xác thực và chặn thao tác nguy hiểm. Bạn có thể kiểm tra những gì Claude sắp làm và dừng lại nếu cần bằng cách thoát với mã 2. Hooks PostToolUse chạy sau khi Claude hoàn tất hành động, rất phù hợp cho tác vụ dọn dẹp như định dạng mã, chạy kiểm thử hoặc ghi lại những gì đã xảy ra. Dùng PreToolUse khi bạn cần kiểm soát phòng ngừa và PostToolUse khi bạn cần tự động hóa phản ứng.

How do I pass information about what Claude did to my hook script?

Claude Code gửi thông tin chi tiết qua đầu vào chuẩn (stdin) dưới dạng JSON, chứa ngữ cảnh như đường dẫn tệp, nội dung được ghi, ID phiên, và nhiều hơn nữa. Script hook của bạn đọc JSON này bằng json.load(sys.stdin) trong Python hoặc phương thức tương tự ở ngôn ngữ khác. Payload JSON này cho phép hook đưa ra quyết định thông minh, ví dụ, chỉ định dạng tệp Python bằng cách kiểm tra phần mở rộng tệp, hoặc chặn sửa đổi một số thư mục bằng cách kiểm tra đường dẫn tệp.

What does exit code 2 do, and when should I use it?

Mã thoát 2 báo cho Claude Code biết một thao tác nên bị chặn, và nó gửi thông điệp lỗi của bạn (ghi vào stderr) trực tiếp tới Claude. Sau đó Claude có thể giải thích vấn đề cho bạn và đề xuất phương án thay thế. Dùng mã thoát 2 cho kiểm tra bảo mật (chặn sửa đổi tệp nguy hiểm), xác thực tuân thủ (thiếu header bắt buộc), hoặc cổng an toàn (ngăn commit lên nhánh bảo vệ). Với hooks thông tin không bao giờ nên chặn, dùng mã 0 hoặc mã khác.

Can Claude Code hooks cause infinite loops?

Đúng, hooks Stop có thể lặp vô hạn nếu không xử lý cẩn thận. Một hook Stop thoát với mã 2 buộc Claude tiếp tục làm việc. Nếu script của bạn không kiểm tra stop_hook_active từ JSON đầu vào của hook và thoát gọn khi nó là true, Claude sẽ phản hồi, kích hoạt lại hook Stop, lại bị chặn, và lặp lại cho tới khi phiên hết thời gian. Luôn thêm một điều kiện bảo vệ ở đầu script Stop hook để kiểm tra trường này và trả về mã thoát 0 ngay lập tức khi nó đã hoạt động.

What types of hooks does Claude Code support besides shell commands?

Claude Code hỗ trợ năm loại hook: command (lệnh shell, phổ biến nhất), http (POST tới URL cho tích hợp webhook), mcp_tool (gọi tool trên máy chủ MCP đã kết nối), prompt (gửi prompt tới mô hình Claude cho đánh giá một lượt), và agent (tạo subagent có thể dùng tool để xác minh điều kiện). Với hầu hết trường hợp, hooks command đã đáp ứng nhu cầu. Xem tham chiếu hooks chính thức để biết chi tiết từng loại.


Bex Tuychiev's photo
Author
Bex Tuychiev
LinkedIn

Tôi là người sáng tạo nội dung về khoa học dữ liệu với hơn 2 năm kinh nghiệm và là một trong những tài khoản có lượng theo dõi lớn nhất trên Medium. Tôi thích viết các bài chuyên sâu về AI và ML với chút giọng điệu mỉa mai, vì bạn cũng phải làm gì đó để chúng bớt nhàm chán. Tôi đã xuất bản hơn 130 bài viết và một khóa học trên DataCamp, và đang ấp ủ thêm một khóa nữa. Nội dung của tôi đã tiếp cận hơn 5 triệu lượt xem, trong đó có 20 nghìn người trở thành người theo dõi trên cả Medium và LinkedIn. 

Chủ đề

Học lập trình với AI cùng DataCamp!

Courses

Lập trình với AI dành cho Developer

1 giờ 30 phút
7.7K
Nâng cao kỹ năng lập trình của bạn với trí tuệ nhân tạo — hướng dẫn trợ lý lập trình của bạn để viết, kiểm thử và tài liệu hóa mã nguồn một cách hiệu quả.
Xem chi tiếtRight Arrow
Bắt Đầu Khóa Học
Xem thêmRight Arrow
Có liên quan

blogs

Claude Opus 4.6: Tính năng, điểm chuẩn, các bài kiểm tra thực hành và hơn thế nữa

Mô hình mới nhất của Anthropic dẫn đầu bảng xếp hạng về mã hóa theo hướng tác nhân và suy luận phức tạp. Thêm nữa, nó có cửa sổ ngữ cảnh 1M.
Matt Crabtree's photo

Matt Crabtree

10 phút

Xem ThêmXem Thêm