Giải thích hook trong Claude Code

Prompt là context, hook là code: Josh nhờ Claude Code viết ba hook (PreToolUse chặn npm install lạ, PostToolUse chạy lint, Stop) và nói hook dừng ở đâu.

Đã duyệt độc lập · cập nhật 27/10/2026 · 15 min

1. AI là xác suất, nên một chỉ dẫn cơ bản vẫn có thể bị bỏ qua

Josh mở đầu (video đăng ngày 25/10/2026) bằng một nhận xét về bản chất của AI hay LLM: đó là các model xác suất (probabilistic), nghĩa là chính model quyết định bước tiếp theo sẽ làm gì. Theo anh, nhìn chung model làm theo các chỉ dẫn cơ bản khá tốt, nhưng điều đó không được bảo đảm. Cùng một prompt có thể cho ra nhiều kết quả khác nhau.

Tệ hơn, theo Josh (video đăng ngày 25/10/2026), prompt càng dài thì context window càng lớn, và AI càng hay bắt đầu trôi (drift) và quên những chỉ dẫn cơ bản. Với những ai muốn chạy các agentic loop dài, điều đó có thể có nghĩa là một vài thứ bị quên, hoặc một vài việc lẽ ra phải xảy ra thì không xảy ra. Anh nói đó là lý do Claude đưa ra khái niệm hook.

Slide The Problem: AI is probabilistic, so even a basic instruction can be missed. Hooks make certain actions always happen.
Slide "The Problem" mở đầu video đăng ngày 25/10/2026: "AI is probabilistic, so even a basic instruction can be missed", và dòng màu cam "Hooks make certain actions always happen".

Anh hứa rằng tới cuối video (đăng ngày 25/10/2026), người xem sẽ biết ba loại hook, khi nào dùng chúng, và về cơ bản là cách thiết lập để agent cho ra cùng một kết quả mỗi lần, không cần prompt lại và không phải làm đủ thứ chỉ để giữ một loop chạy lâu.

2. Prompt là context, hook là code

Bất cứ thứ gì ta nói với agent đều là context, Josh nói (video đăng ngày 25/10/2026). Về cơ bản đó chỉ là một prompt, hoặc một file skill hay các rule mà model đọc rồi hành động theo.

Hook thì khác một chút. Theo Josh (video đăng ngày 25/10/2026), hook là thứ Claude Code chạy tại một điểm cố định trong vòng lặp của agent. Có những giai đoạn mà bạn có thể "móc" code của mình vào: trước khi một tool chạy, sau khi nó chạy, hoặc thậm chí những điểm để chặn agent kết thúc khi một điều kiện chưa được đáp ứng. Điểm quan trọng, anh nhấn mạnh, là Claude không quyết định khi nào hook chạy. Hook chạy mọi lần, theo cách deterministic, nên dù session dài tới đâu, bạn vẫn luôn nhận được cùng một kết quả.

Slide A prompt is context, a hook is code: bảng so sánh what it is, who decides, can the agent skip it
Bảng so sánh trên slide (video đăng ngày 25/10/2026): prompt là context, model quyết định, agent có thể bỏ qua (yes); hook là code, Claude Code quyết định, agent không thể bỏ qua (no).

3. Mental model: hook gắn vào việc dùng tool

Trước khi đi tiếp, Josh tự giới thiệu (video đăng ngày 25/10/2026): anh tên Josh, là một software developer, và đang đặt cho mình sứ mệnh cá nhân là dùng AI để tự động hoá mọi việc nhàm chán, để mọi người tập trung vào những gì quan trọng.

Trước khi vào các ví dụ (video đăng ngày 25/10/2026), anh muốn vẽ ra một mental model về hook là gì, vì đây không phải thứ mà ta cứ vào Claude là có sẵn một UI đẹp được tạo ra. Như đã nói, hook về cơ bản chỉ là code được gắn vào việc dùng tool (tool usage) trong Claude. Tool usage có thể là Bash, các tool tuỳ chỉnh bạn tự làm, hay việc ghi và sửa file.

Theo Josh (video đăng ngày 25/10/2026), với mỗi hook, bạn định nghĩa các rule để chạy một đoạn code nhất định trên tool của mình. Có những lần chạy phổ biến: trước khi mỗi tool được chạy, ta có thể kích hoạt một đoạn code để làm gì đó; sau khi tool chạy xong, ta có thể kích hoạt một hook khác; và ta cũng có thể kích hoạt hook khi agent làm xong.

agent quyết địnhtool chạyBash, ghi, sửa fileagent xong hook trước toolhook sau toolhook khi xong code của bạn được móc vào những điểm cố định
Hình 3.1Mental model Josh mô tả trong video đăng ngày 25/10/2026: hook là code gắn vào việc dùng tool, có thể chạy trước khi tool chạy, sau khi tool chạy, và khi agent làm xong.

4. Hook có thể chạy ở đâu: 33 event, ba cái trong video

Josh cho biết tài liệu hiện có tới 33 hook (tính theo video đăng ngày 25/10/2026), nhưng video chỉ đi qua ba cái. Anh sẽ build từng cái ngay trong video, chạy nó trên project mới, và xem chuyện gì xảy ra khi thực thi.

Slide Where a hook can run: UserPromptSubmit, PreToolUse, PostToolUse, Stop; dòng chú thích 33 hook events in the docs
Slide "Where a hook can run" (video đăng ngày 25/10/2026): khi gửi prompt là UserPromptSubmit, trước một tool là PreToolUse, sau một tool là PostToolUse, khi dừng là Stop. Dòng dưới ghi "33 hook events in the docs", ba cái màu cam là ba cái trong video.

5. Ví dụ 1: một lệnh cài mà Josh chưa từng duyệt

Ví dụ hook đầu tiên là một lệnh chặn (block command). Josh kể chuyện đã xảy ra với anh nhiều lần (video đăng ngày 25/10/2026): anh bảo Claude đi làm việc gì đó, rồi với "trí tuệ vô hạn" của mình, nó quyết định npm install nhiều package khác nhau, hoặc thậm chí chiếm quyền điều khiển trình duyệt của anh để đi tải nhiều file khác nhau.

Vì vậy, trong ví dụ này, anh cho thấy cách tạo một hook để chặn một số lệnh không cho chạy. Theo anh (video đăng ngày 25/10/2026), cách này tốt về mặt bảo mật và những thứ tương tự.

01 Blocks a commandguard hook,trước khi tool chạy 02 Lints every savelint hook,sau Edit hoặc Write 03 Checks before it finishesstop hook,trước khi "done" được tính ví dụ 1 trong video đăng ngày 25/10/2026: một lệnh cài mà Josh chưa từng duyệt
Hình 5.1Ba ví dụ theo slide "Example 1" của Josh (video đăng ngày 25/10/2026); ô đầu được làm nổi vì đây là ví dụ đang nói.

6. PreToolUse và file settings của một guard

Ở ví dụ này, Josh dùng hook PreToolUse. Theo anh (video đăng ngày 25/10/2026), trước khi dùng thứ gì đó như npm install, hook sẽ kiểm tra lại context rồi chặn không cho nó xảy ra. Ta có thể tạo một hook kích hoạt trước khi npm được gọi, và định nghĩa các rule, tiêu chí về cái gì được cài và cái gì không. Mục đích không phải là chặn hẳn việc cài, mà là chặn những thứ ta không muốn hay không lường trước.

Slide Example 1 The Hook: PreToolUse; Runs before a tool call executes; Sees tool_name + tool_input; Exit 2 blocks the tool call; Here no installs, no writes outside the folder
Slide PreToolUse (video đăng ngày 25/10/2026): chạy trước khi một tool call thực thi, nhìn thấy tool_name và tool_input, exit code 2 thì chặn tool call; trong ví dụ này là "no installs, no writes outside the folder". Dưới cùng là link code.claude.com/docs/en/hooks.

Josh nói (video đăng ngày 25/10/2026) tất cả hook về cơ bản là một file JSON, nơi bạn định nghĩa cái gì được kích hoạt. Anh đi qua một ví dụ trên slide "A guard's settings, line by line", file .claude/settings.json: khai báo PreToolUse, rồi khai báo các tool mà ta muốn kích hoạt hook, những thứ cơ bản như Bash, PowerShell, ghi file; sau đó định nghĩa bản thân hook. Trong ví dụ này, mỗi khi điều kiện được kích hoạt, ta chỉ muốn chạy một script.

{ "hooks": { "PreToolUse": [{
    "matcher":
      "Bash|PowerShell|Write|Edit|MultiEdit|NotebookEdit",
    "hooks": [{
      "type": "command",
      "command":
        "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/guard.js\"",
      "shell": "bash",
      "timeout": 15,
      "onFailure": "block",
      "statusMessage": "Checking project guard"
}]}]}}

Các chú thích bên phải slide (video đăng ngày 25/10/2026) giải thích từng dòng: PreToolUse là event; matcher là những tool kích hoạt nó; command là script nó chạy; shell là chạy bằng bash; timeout là số giây trước khi bị huỷ; onFailure: "block" nghĩa là không chạy được thì vẫn chặn; statusMessage là dòng hiện ra trong lúc chạy. Dòng cuối slide ghi: đặt trong .claude/ là cho project này, trong ~/.claude/ là cho mọi project.

Script đó, theo Josh (video đăng ngày 25/10/2026), có thể làm những việc như đọc hoặc định nghĩa cái gì nên hay không nên được cài, hay về cơ bản là bất cứ thứ gì bạn muốn, vì đó là logic của chính bạn. Đó là hook tóm gọn. Anh nói bạn không cần biết nhiều về phần này, và điều đó thật ra rất tuyệt với AI thời nay: chỉ cần hỏi Claude và Claude sẽ tự tìm ra cách cho bạn.

7. Demo: nhờ Claude Code viết block hook cho npm

Josh chuyển sang Claude Code để tạo block hook. Thanh đầu màn hình ghi Claude Code v2.1.310, Opus 5.5 with high effort, Claude Max (demo trong video đăng ngày 25/10/2026). Anh gõ /clear rồi gõ prompt sau (giữ nguyên lỗi chính tả trên màn hình):

create a block hook for me that prevents me from installing unknown packges on npm, but don't stop me from running other npm commands, please prove and test it works on a fake proejct

Claude trả lời bằng một plan (demo trong video đăng ngày 25/10/2026): một hook PreToolUse viết bằng Node trên Bash và PowerShell, phân tích các lệnh npm/npx và chỉ chặn những lệnh cài package không nằm trong một allowlist hoặc chưa có sẵn trong package.json của project; sau đó nó sẽ chứng minh trên một project dùng thử.

Terminal Claude Code: lệnh /clear, prompt tạo block hook, plan PreToolUse và lỗi tạo worktree
Đầu phiên demo (video đăng ngày 25/10/2026): prompt của Josh, plan của Claude, rồi lỗi đỏ "Cannot create a worktree: not in a git repository"; Claude chuyển sang làm trực tiếp trong ~/.claude/hooks/, cạnh hook drive-rule.mjs có sẵn.

Josh đọc phần logic đang hiện ra: có thể định nghĩa những package cụ thể không được phép cài, nên agent quyết định dùng một allow list. Anh nói có vẻ nó gặp vài vấn đề về worktree và git repo, nhưng không sao. Thêm vào đó, có vẻ code chạy vào một bug và nó tự quyết định sửa (demo trong video đăng ngày 25/10/2026). "Khá hay đấy", anh nói.

8. Kết quả: allowlist 241 package, sketchy-thing bị chặn

Khi Claude xong, Josh xem nó đã làm gì (demo trong video đăng ngày 25/10/2026). Nó tạo một allow list cho hook, cho phép sẵn 241 package lấy từ tất cả các project anh đang có. Trên màn hình, Claude giải thích: một package chỉ được phép nếu nằm trong allowlist hoặc đã có trong package.json của project; allowlist được lấp bằng 241 package mà các project của anh đang dùng, lấy từ 255 file package.json dưới ~/Projects, cộng các MCP server của anh. Thanh trạng thái ghi phiên chạy mất 4 phút 11 giây.

Bản tóm tắt của Claude: How unknown is decided, What gets blocked, What still runs, How I tested it, Limits, Files
Bản tóm tắt Claude in ra sau 4 phút 11 giây (demo trong video đăng ngày 25/10/2026): cách quyết định package "unknown", cái gì bị chặn, cái gì vẫn chạy, cách nó đã test, giới hạn, và ba file nó tạo hoặc sửa.

Theo bản tóm tắt trên màn hình (demo trong video đăng ngày 25/10/2026), những thứ bị chặn gồm:

  • npm install / i / add với một package lạ, kể cả với -g, --prefix và alias (foo@npm:bar) (demo trong video đăng ngày 25/10/2026);
  • npx <unknown> và npm exec <unknown> (demo trong video đăng ngày 25/10/2026);
  • cài từ git, dạng viết tắt GitHub (user/repo) hoặc URL (demo trong video đăng ngày 25/10/2026);
  • những lệnh trên khi giấu trong chuỗi cd … &&, bash -c "…", powershell -Command "…" và cmd /c "…" (demo trong video đăng ngày 25/10/2026).

Vẫn chạy bình thường (demo trong video đăng ngày 25/10/2026): npm install trần, npm ci, npm test, npm run, npm view, npm uninstall, npm audit, cài từ đường dẫn local, và npx cho các tool đã cài trong project.

Phần "How I tested it" trên màn hình (demo trong video đăng ngày 25/10/2026): riêng hook được chạy với 40 lệnh mẫu (22 lệnh phải bị chặn, 18 lệnh phải chạy) và tất cả cho kết quả đúng. Chạy thật trên một project giả: npm install is-odd bị chặn, npx cowsay hi bị chặn, npm i -D sketchy-thing trong PowerShell bị chặn; npm install, npm i [email protected] (đã có trong package.json) và npm test đều chạy, test in ra "tests ok"; npm ls chỉ thấy left-pad, nghĩa là package bị chặn chưa hề được cài. Trong lúc test, một commit message có nhắc tới npm i bị chặn nhầm, và Claude đã sửa trước lần chạy cuối 40/40.

Phần "Limits" (demo trong video đăng ngày 25/10/2026): hook chỉ kiểm các lệnh Claude chạy, không kiểm lệnh bạn tự gõ trong terminal của mình; Claude có thể tự sửa allowlist, nên đây là "một lớp kiểm tra mạnh chứ không phải một ổ khoá cứng"; thông báo chặn bảo Claude phải hỏi bạn trước khi thêm package, và để duyệt một package, bạn chỉ cần bảo nó "add X".

Josh cuộn lên để xem các lệnh đã chạy (demo trong video đăng ngày 25/10/2026). Ở đó Claude thử npm install, và lệnh bị chặn bởi npm guard. Màn hình hiện lỗi "BLOCKED by npm-guard: unknown package install", kèm dòng "Do not work around this. Ask Josh to approve the package; once he does, add its name to the allowlist." Trong các lệnh thử có cả lệnh cài những thứ như sketchy-thing. "Mừng là mình bắt được nó", Josh nói: sketchy-thing không được cài, và hook đang làm đúng việc của nó, trong khi các lệnh npm thông thường vẫn chạy. Anh nói thêm: bạn không cần chỉ tin lời Claude, nó đã test mọi thứ vừa nói tới.

9. Mở code trong VS Code

Josh mở VS Code để xem tất cả những gì đã được tạo (demo trong video đăng ngày 25/10/2026). "Tôi thậm chí sẽ không giả vờ là mình biết đoạn code này làm gì", anh nói, nhưng đây là code được kích hoạt mỗi lần lệnh npm được gọi. Anh đoán nó chỉ đang đọc danh sách, đọc package rồi so với allow list.

VS Code mở file npm-guard.mjs với phần comment đầu file và các import
File npm-guard.mjs do Claude viết (demo trong video đăng ngày 25/10/2026). Comment đầu file ghi: hook PreToolUse (Bash + PowerShell) chặn npm/npx cài những package không "known", mọi lệnh npm khác đi qua nguyên vẹn; và "Exit 2 + stderr = block (Claude Code shows the reason to the model)".

Tab bên cạnh là npm-allowlist.txt, danh sách những package được hỗ trợ, tức được phép cài. Tab thứ ba là settings.json, nơi có bản thân hook: Josh chỉ vào khối PreToolUse trỏ tới npm guard (demo trong video đăng ngày 25/10/2026). Đó là sức mạnh của block hook, anh nói: nó giúp ngăn bạn cài những npm package đáng ngờ, cùng nhiều thứ khác.

10. Ví dụ 2: PostToolUse chạy lint sau mỗi lần sửa

Ví dụ tiếp theo là thứ Josh nói anh rất hào hứng: bảo đảm lint được chạy sau mỗi lần viết code. Để làm vậy, anh dùng một thứ gọi là PostToolUse. Như tên gọi, theo Josh (video đăng ngày 25/10/2026), nó chạy sau mỗi lần một tool call thành công. Rule giống như đã nói, chỉ khác là ở đây matcher là edit và write, và cách duy nhất để hook kết thúc là thấy linter đã được chạy.

Slide Example 2 The Hook: PostToolUse; Runs after a tool call succeeds; Matcher Edit|Write; Exit 2 shows stderr, the tool already ran; Here lint the file it just saved
Slide PostToolUse (video đăng ngày 25/10/2026): chạy sau khi một tool call thành công, matcher Edit|Write, exit code 2 thì hiện stderr nhưng tool đã chạy rồi; trong ví dụ này là lint file vừa lưu. Góc trên phải là ảnh thu nhỏ của terminal ở phần demo sau.

Josh nói có thể hình dung điều này rất tốt cho các agentic session chạy lâu (video đăng ngày 25/10/2026). Bạn viết code, và AI không có cách nào biết code đúng hay không, hay có theo chuẩn nào không, trừ khi bản thân model thông minh. Nhưng khi đặt post hook này, ta ép model chạy linter của mình, và anh gọi đó là cách có được code chắc chắn, được enforce một cách deterministic.

Đây là ví dụ ngắn về hình dạng của nó (video đăng ngày 25/10/2026), trên slide "Same shape, a different event": không khác mấy so với cái đã xem, khác biệt chính chỉ là PostToolUse thay vì PreToolUse. "Tôi biết, khoa học tên lửa", Josh nói.

{ "hooks": { "PostToolUse": [{
    "matcher": "Write|Edit|MultiEdit",
    "hooks": [{
      "type": "command",
      "command":
        "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/lint-words.mjs\""
}]}]}}

Chú thích trên slide (video đăng ngày 25/10/2026): event chạy sau khi một tool thành công, matcher là các tool lưu một file, command là script lint; dòng cuối ghi "it runs after the save, so it can report, not undo". Slide trước ghi matcher là Edit|Write, còn file mẫu này ghi Write|Edit|MultiEdit.

11. Prompt thứ hai, và Claude tự thêm một Stop hook

Josh quay lại cùng phiên Claude cũ để làm một ví dụ nhanh (demo trong video đăng ngày 25/10/2026), và gõ:

next help create a linter hook that makes sure that we run lint on any of our projects and fix it before we are done writing code. Please also test it and make sure it works

"Xem nó có hiểu thứ tiếng Anh lủng củng của tôi không", anh nói, rồi chờ.

Terminal Claude Code: recap của block hook, prompt tạo linter hook và plan hai phần PostToolUse cùng Stop
Prompt thứ hai và plan của Claude (demo trong video đăng ngày 25/10/2026): một hook hai phần, PostToolUse trên Edit/Write ghi lại các file code đã đổi trong session, và một Stop hook lint đúng những file đó bằng linter của project, không cho Claude kết thúc tới khi sạch lỗi.

"Ồ, có vẻ ta đã nhảy sang ví dụ thứ hai", Josh nói. Dựa trên cách anh diễn đạt, Claude quyết định làm PostToolUse để chạy lint, và cũng quyết định làm thêm một Stop hook để bảo đảm lint thật sự chạy (demo trong video đăng ngày 25/10/2026). Plan trên màn hình giải thích thêm: chỉ lint những file đã chạm vào nghĩa là bạn sẽ không bị buộc phải sửa nợ lint có sẵn của các agent khác; trước hết, nó khảo sát nhanh xem các project của anh thực sự dùng linter nào.

12. Stop hook: ngăn Claude dừng lại

Trong lúc chờ, Josh tóm lại Stop hook là gì. Như tên gọi, theo Josh (video đăng ngày 25/10/2026), khi Claude xong lượt của nó, Stop hook được dùng để ngăn Claude dừng lại. "Thử nói câu đó hai lần thật nhanh xem", anh nói. Cách duy nhất để thoát về cơ bản là một flag, hoặc một bộ đếm kiểu bạn thử XYZ lần, và hook về cơ bản sẽ buộc Claude quay lại thử tiếp.

Slide Example 3 The Hook: Stop; Runs when Claude finishes responding; Exit 2 prevents Claude from stopping; Way out a flag, or a count; Here run my check from the project root
Slide Stop (video đăng ngày 25/10/2026): chạy khi Claude trả lời xong, exit code 2 ngăn Claude dừng, lối thoát là một flag hoặc một bộ đếm; trong ví dụ này là chạy phần kiểm tra của Josh từ project root.

Theo Josh (video đăng ngày 25/10/2026), cách làm về cơ bản giống những gì đã làm: tạo Stop, và một khi đã cài, bạn chỉ chạy một đoạn code được kích hoạt mọi lần. Slide "Stop has no matcher: it always fires" cho thấy file mẫu:

{ "hooks": { "Stop": [{
    "hooks": [{
      "type": "command",
      "command":
        "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/stop-check.js\"",
      "timeout": 30
}]}]}}

Chú thích trên slide (video đăng ngày 25/10/2026): không có dòng matcher; script được tìm từ project root; timeout là số giây phần kiểm tra được cho; và $CLAUDE_PROJECT_DIR là project root nơi session bắt đầu.

13. Hai điều cần để ý với Stop hook

Điều thứ nhất, Josh nói (video đăng ngày 25/10/2026): khi chơi nhiều với Stop hook, bạn sẽ gặp những tình huống, nhất là ở các session chạy lâu, mà Claude cố biện minh vì sao việc đã xong, bắt đầu bịa ra lý do hoặc làm đủ thứ để kết thúc sớm trước khi thật sự quay lại làm. Đó là thứ cần để ý khi chạy session dài.

Điều thứ hai, theo Josh (video đăng ngày 25/10/2026): Stop hook không có matcher hay gì cả, nó luôn được kích hoạt. Điều đó dẫn tới những vấn đề thú vị khi chạy trên các project của bạn: bạn có thể thấy Stop hook dành cho một project không liên quan can thiệp vào những codebase khác mà bạn đang làm. Anh gợi ý luôn có thể cài nó ở project root thay vì thư mục gốc, để đúng Stop hook được kích hoạt đúng lúc. "Cứ chơi thử đi, tôi chắc bạn sẽ gặp và bị nó làm phiền", anh nói.

cài ở thư mục gốccài ở project root project Aproject Bproject C project Aproject Bproject C có thể chạy cả ở project không liên quanđúng Stop hook chạy đúng lúc
Hình 13.1Gợi ý của Josh trong video đăng ngày 25/10/2026: Stop hook không có matcher nên luôn chạy; có thể cài ở project root thay vì thư mục gốc để đúng Stop hook được kích hoạt đúng lúc.

14. Stop hook chạy thật trên ba lỗi ESLint

Josh quay lại xem Claude đang làm gì (demo trong video đăng ngày 25/10/2026). Nó tạo một project thử cho lint test, rồi post tool hook ghi nhận nó; ta chạy nó sau khi tạo, rồi Stop hook kích hoạt. Anh đoán Claude đang báo là nó phát hiện ra vấn đề, nên nó sửa, và rồi mọi thứ chạy được.

Terminal: ESLint báo 3 lỗi trong live.js, Stop hook chặn Claude, Claude sửa file và in bản tóm tắt lint hook
Stop hook chặn Claude bằng ba lỗi ESLint thật trong live.js: biến leftover gán mà không dùng, tham số name khai báo mà không dùng, và nme chưa được định nghĩa. Claude sửa đúng như hook bảo rồi kết thúc lại (demo trong video đăng ngày 25/10/2026).

Lint hook đã được dựng xong, Josh nói (demo trong video đăng ngày 25/10/2026). Có vẻ Claude có một logic khá phức tạp về cách chạy linter: có giới hạn năm lần sửa thất bại để không rơi vào vòng lặp vô hạn, và có vẻ nó đã tính tới những trục trặc có thể có với npm install. "Những tình huống nó cân nhắc khá thú vị với tôi", anh nói. Nó test trực tiếp: viết một đoạn JavaScript có lỗi lint đã biết, kích hoạt lỗi, bị chặn, và Claude phải sửa trước khi lượt kết thúc.

Bản tóm tắt trên màn hình (demo trong video đăng ngày 25/10/2026) ghi cách hook làm việc:

  • mỗi file Claude sửa hoặc ghi, kể cả qua lệnh shell, đều được ghi lại (demo trong video đăng ngày 25/10/2026);
  • khi Claude định kết thúc, hook chỉ lint những file đó, bằng ESLint cho JS/TS và Ruff cho Python; có lỗi thì Claude bị gửi trở lại cùng danh sách lỗi để sửa (demo trong video đăng ngày 25/10/2026);
  • chỉ kiểm file Claude đã chạm, nên nó không bị đẩy vào việc sửa lỗi lint cũ của agent khác (demo trong video đăng ngày 25/10/2026);
  • nếu project có cấu hình linter mà linter chưa được cài, hook cũng chặn và bảo Claude chạy npm install (demo trong video đăng ngày 25/10/2026);
  • sau 5 lần sửa thất bại liên tiếp, hook cho Claude kết thúc nhưng hiện một cảnh báo thay vì lặp mãi (demo trong video đăng ngày 25/10/2026).

Phần test trên màn hình (demo trong video đăng ngày 25/10/2026): bản live viết live.js với 3 lỗi lint, Stop hook chặn với cả 3 lỗi ESLint thật, Claude sửa và lần kết thúc thứ hai được cho qua; các kịch bản trên project giả đạt 16/16; trên project thật (chỉ đọc), ESLint chạy xong và file sạch trong khoảng 2 giây, lần chạy lạnh đầu tiên mất 100 giây nên Stop hook được đặt timeout 300 giây. Claude cũng báo việc test này lộ ra hai bug trong npm guard làm hôm trước (màn hình ghi "yesterday's npm guard") (2>&1 bị đọc nhầm thành tên package, và nội dung heredoc bị quét như lệnh), cả hai đã được sửa, và npm guard giờ qua 52/52 lệnh test, tăng từ 40.

Claude còn đưa ra các "gaps". Josh hiểu là nó đang báo các project có sẵn của anh có lỗi, và nói không sao, lúc này anh không quan tâm chuyện đó; trên màn hình, mục Gap ghi rằng hook chỉ chạy được ở những project đã có linter, khoảng 10 trong khoảng 50 project của anh, và hỏi có muốn thêm cấu hình ESLint cơ bản cho số còn lại không (demo trong video đăng ngày 25/10/2026).

Điều Josh thấy hay là cách agent tự lên kế hoạch và cân nhắc cả hook vừa tạo ở ví dụ 1, pre hook với npm install (demo trong video đăng ngày 25/10/2026). Đây là các file, anh nói, nhưng anh sẽ không mở chúng vì về cơ bản giống như trước, "và thành thật mà nói, trong thời đại AI, ai còn thực sự đọc code nữa".

15. Hỏi trong prompt, enforce bằng hook

Sau khi build xong cả ba ví dụ, Josh nói giờ có thể thấy cách nâng khả năng code cùng AI lên thêm (video đăng ngày 25/10/2026): bạn có thể prompt để giao phần lớn công việc, rồi dùng hook để enforce một số hành vi nhất định, vì code luôn chạy deterministic dù thế nào đi nữa, nên bạn có thể dựa vào code.

Slide The Solution: Ask in the prompt, enforce with a hook; ba ô the guard hook, the lint hook, the stop hook
Slide "Ask in the prompt, enforce with a hook" (video đăng ngày 25/10/2026): guard hook chặn một lệnh, lint hook kiểm mỗi lần lưu, stop hook chạy phần kiểm tra của Josh; dòng dưới ghi "one hook for each place the loop can break".

Dù vậy, Josh cũng khuyến khích các kỹ sư đừng quá "nghiện hook" mà enforce mọi thứ (video đăng ngày 25/10/2026). Những hook như lint thì ổn, và một số thứ bạn muốn luôn chạy thì hợp lý. Anh nhắc lại điều đã nói: ở nhiều project anh làm, agent, nhất là trong các session dài, rốt cuộc sẽ cố biện minh rằng việc đã xong rồi tự kết thúc sớm.

16. Hook là miếng băng dán, không thay được spec và việc kiểm tra

Vì thế, Josh lập luận (video đăng ngày 25/10/2026), ở một số khía cạnh hook giống như một miếng băng dán (band-aid) cho một vấn đề nằm bên dưới. Bạn tất nhiên nên dùng, vì nó là một tool, nhưng về căn bản anh sẽ đặt câu hỏi: prompt hay spec bạn gửi cho agent là gì mà gây ra vấn đề ngay từ đầu? Bạn đang bảo agent làm quá nhiều, hay không rõ bạn muốn nó làm gì?

Theo Josh (video đăng ngày 25/10/2026), không lượng code deterministic nào cứu được bạn nếu bạn bảo agent cứ implement một thứ mà không có spec đầy đủ chi tiết, rồi đặt một hook bảo "đừng dừng tới khi xong". Đưa cho agent một prompt như vậy thì không hook nào cứu được, trừ khi bản thân hook đã có sẵn các rule nói cần làm gì.

hook tự động hoávẫn là việc của kỹ sư việc dev phải làm tay,như chạy lệnh để chạy linter planning, prompting, thinkingspec đủ chi tiếtnhìn output, bảo đảm đúng
Hình 16.1Kết luận của Josh trong video đăng ngày 25/10/2026: hook giúp tự động hoá phần việc dev, nhưng không lấy đi việc lên kế hoạch, viết prompt, suy nghĩ và kiểm tra output.

Tóm lại, Josh nói (video đăng ngày 25/10/2026), hook giúp bạn tự động hoá nhiều phần việc dev mà lẽ ra bạn phải làm tay, như chạy lệnh để chạy linter, nhưng nó không lấy đi việc lên kế hoạch, viết prompt và suy nghĩ của bạn. Rốt cuộc, trách nhiệm của các kỹ sư vẫn là thực sự nhìn vào output mình tạo ra và bảo đảm mọi thứ đều đúng.

Anh khép lại video (đăng ngày 25/10/2026): anh đã đưa ra ba ví dụ về việc dùng hook để làm gì, và chào tạm biệt.

Nguồn và liên kết 8 nguồn

  1. Tên gốc: Claude Code Hooks Explained | Agentic Engineering
  2. Sự kiện: YouTube
  3. Video gốc: https://www.youtube.com/watch?v=WwD3ANglHeE youtube.com
  4. Kênh YouTube Josh's DevBox (Josh's DevBox): youtube.com/channel/UCpozECHF9QxfEu6LfWYVfKw youtube.com
  5. Tài liệu hooks của Claude Code, trang tham chiếu các hook event (PreToolUse, PostToolUse, Stop và các event khác), input và cách exit code 2 chặn hành động (đọc ngày 27/10/2026): code.claude.com/docs/en/hooks code.claude.com
  6. Tổng quan Claude Code (đọc ngày 27/10/2026): code.claude.com/docs/en/overview code.claude.com
  7. ESLint, linter cho JavaScript/TypeScript mà lint hook trong demo dùng (demo trong video đăng ngày 25/10/2026; trang đọc ngày 27/10/2026): eslint.org eslint.org
  8. Ruff, linter cho Python mà lint hook trong demo dùng (demo trong video đăng ngày 25/10/2026; trang đọc ngày 27/10/2026): docs.astral.sh/ruff docs.astral.sh