Cho Claude một “phép thử” để tự kiểm tra: test, goal, Stop hook và review theo spec
Tóm tắt
Claude dừng khi việc trông như xong. Cho nó thứ trả về pass/fail (test, typecheck, Stop hook, review bằng subagent) để tự đóng vòng lặp, và đòi bằng chứng là output thật. Quy tắc phải luôn đúng thì đưa vào hook thay vì CLAUDE.md.
Claude dừng lại khi công việc trông như đã xong. Nếu không có gì để chạy và nhận về kết quả pass/fail, "trông như xong" là tất cả những gì nó dựa vào, và trên thực tế bạn trở thành bộ test: mọi lỗi nằm đó cho đến khi bạn tình cờ phát hiện. Đây là một trong những ý quan trọng nhất trong trang best practices của Claude Code. Bài này giải thích ý đó cùng một khái niệm đi kèm: phân biệt chỉ dẫn mà Claude tự quyết với chỉ dẫn mà Claude Code bắt buộc thực thi.
Hai loại chỉ dẫn
| Khía cạnh | Claude tự quyết (không xác định) | Claude Code ép (xác định) |
|---|---|---|
| Làm gì | Prompt, CLAUDE.md, skill | Hook, skill chỉ bạn mới gọi được |
| Được đụng vào đâu | Bộ phân loại của auto mode | Deny rule, sandbox, managed settings |
| Khi nào là xong | Yêu cầu bằng chứng, /goal, /code-review | Test, typecheck, Stop hook, CI |
| Tiêu bao nhiêu | Mức effort | --max-turns, --max-budget-usd, spend limit |
Phần lớn thời gian, cứ để Claude quyết: với code thật trước mặt, model thường phán đoán tốt hơn một quy tắc viết sẵn. Loại xác định dành cho những thứ luôn phải xảy ra (hoặc không bao giờ được xảy ra). Dấu hiệu nhận biết: nếu bạn cứ phải thêm "IMPORTANT" vào một dòng CLAUDE.md mà Claude vẫn bỏ qua, dòng đó nên chuyển thành hook.
Cho Claude một "phép thử" chạy được
Phép thử có thể là bất cứ thứ gì trả về kết quả Claude đọc được: file test, exit code của build, linter, script so output với fixture, hay ảnh chụp trình duyệt đặt cạnh mockup. Nếu repo đã có, dòng hữu ích nhất trong CLAUDE.md chính là lệnh chạy nó.
Bốn mức độ chặt, từ nhẹ đến cứng:
- Trong prompt:
chạy test auth sau khi sửa, tiếp tục đến khi pass. Không cần setup gì. - Đặt goal:
/goal all tests in tests/auth pass and lint is clean. Một model khác kiểm tra điều kiện sau mỗi lượt, hữu ích cho phiên chạy nền dài. - Stop hook: script chạy mỗi khi Claude định kết thúc lượt; exit code 2 bắt Claude quay lại làm tiếp.
- Người khác review:
/code-reviewchạy trong subagent mới, không bị ảnh hưởng bởi lập luận đã sinh ra code.
Stop hook: ép typecheck trước khi xong
// .claude/settings.json
{
"hooks": {
"Stop": [
{ "hooks": [
{ "type": "command", "command": "pnpm tsc --noEmit 1>&2 || exit 2" }
] }
]
}
}
Output lỗi được đẩy sang stderr để quay về Claude làm lý do "chưa được dừng". Có giới hạn an toàn: nếu hook chặn 8 lần liên tiếp mà không có tool call nào ở giữa, Claude Code sẽ cho kết thúc lượt (chỉnh bằng biến môi trường CLAUDE_CODE_STOP_HOOK_BLOCK_CAP).
Đòi bằng chứng, không đòi lời hứa
Dù dùng cách nào, hãy yêu cầu Claude đưa bằng chứng: lệnh đã chạy và output, hoặc ảnh chụp. Một câu "all tests pass" gần như không cho bạn biết gì; đọc output nhanh hơn tự chạy lại. Với phiên chạy khi bạn không ngồi xem, đó là bằng chứng duy nhất bạn có.
Review theo spec, bỏ qua style
use a subagent to review the rate limiter diff against SPEC.md,
check every requirement is implemented and the listed edge cases
have tests, report gaps that affect correctness and skip style
Tài liệu nhấn mạnh đừng bỏ phần "skip style": reviewer được yêu cầu tìm lỗi thì kiểu gì cũng tìm ra cái gì đó. Sửa hết mọi phát hiện, bạn sẽ có thêm lớp trừu tượng thừa và test cho những case không thể xảy ra.
Rủi ro và lưu ý
- Test sai thì vòng lặp sai: Claude sẽ "làm cho pass" theo test bạn đưa. Review test kỹ trước khi giao vòng lặp tự động.
- Hardcode để qua test: nếu thấy code xử lý riêng cho dữ liệu test, đó là dấu hiệu cần nói rõ "giải pháp phải tổng quát".
- Hook chậm: typecheck toàn repo ở mỗi lần dừng có thể tốn thời gian; cân nhắc chỉ kiểm tra phần thay đổi.
Áp dụng thế nào?
- Dev: Thêm vào mọi prompt sửa lỗi một câu "viết test tái hiện lỗi trước, sửa đến khi pass, cho tôi xem output".
- Tech Lead: Ghi lệnh test/typecheck/lint vào CLAUDE.md. Với quy tắc không được ngoại lệ (không sửa
src/gen/, không đọc.env), chuyển sang hook hoặc deny rule. - PM: Viết acceptance criteria dạng kiểm chứng được. Đó chính là "phép thử" để agent tự đóng vòng lặp.
Nguồn & tham khảo
- Best practices for Claude Code — Claude Code Docs