Project mẫu và cách Claude đọc project
Agent chăm sóc khách hàng cho shop sách “Sách Hay”, gom mọi thứ của 5 domain vào một project thật. Trang này giải thích bằng sơ đồ: cấu trúc thư mục, Claude Code nạp file nào trước, một lượt xử lý đi qua những bước nào, và agent API chạy ra sao.
Xem mã nguồn trên GitHub Mẹo nhớ1. Cấu trúc thư mục
Màu cam là thư mục. Mỗi file có ghi chú ai đọc nó và khi nào.
2. Ai đọc file nào, khi nào
| File | Ai đọc | Khi nào | Domain |
|---|---|---|---|
CLAUDE.md (+ @docs/architecture.md) | Claude Code | Lúc mở phiên, luôn nằm trong context | Claude Code |
.claude/settings.json | Harness của Claude Code (không phải model) | Lúc mở phiên, áp dụng cho mọi lần gọi tool | Claude Code |
.mcp.json | Claude Code | Lúc mở phiên, hỏi bạn duyệt server lần đầu | Tool Design & MCP |
.claude/skills/*/SKILL.md | Model | Lúc đầu chỉ đọc name + description; nội dung đầy đủ khi skill được dùng | Claude Code |
.claude/agents/*.md | Claude Code | Lúc mở phiên nạp định nghĩa; subagent chạy trong context riêng khi được giao việc | Claude Code |
.claude/rules/python-style.md | Model | Chỉ khi Claude đọc file khớp paths (src/**/*.py) | Context Management |
.claude/hooks/*.sh | Harness chạy như lệnh shell | Trước và sau khi tool Edit/Write chạy | Claude Code |
prompts/system.md + knowledge/*.md | Agent API (src/agent.py) | Mỗi request, được cache nhờ cache_control | Prompt · Context |
src/tools.py | Code của bạn chạy tool; model chỉ thấy schema | Khi model trả tool_use | Tool Design & MCP |
evals/, tests/ | Bạn và CI | Trước khi merge thay đổi prompt hoặc tool | Agentic Architecture |
3. Claude Code nạp gì khi mở phiên
Thứ tự nạp theo tài liệu Claude Code. Settings được gộp trước, sau đó đến bộ nhớ (CLAUDE.md), công cụ (MCP), các mô tả (skills, subagents), cuối cùng là hook SessionStart.
| Thứ tự ưu tiên settings (cao → thấp) | Thứ tự nạp CLAUDE.md |
|---|---|
Rule permission được gộp từ mọi cấp, quy tắc chặt nhất thắng: deny > ask > allow. |
|
4. Vòng đời một phiên Claude Code
Từ lúc gõ claude đến lúc thoát, Claude Code đi qua 4 giai đoạn:
- Khởi động: nạp luật và kiến thức nền.
- Mỗi lượt: nạp thêm file khi cần, gọi tool.
- Khi context gần đầy: tóm tắt (compact) hội thoại.
- Kết thúc phiên.
Từng file: nạp khi nào, để làm gì, không có thì sao
| # | File | Nạp khi nào | Dùng để làm gì | Nếu không có |
|---|---|---|---|---|
| 1 | Managed settings / policy của tổ chức | Khởi động, trước mọi thứ | Luật công ty mà không ai ghi đè được, ví dụ cấm MCP lạ hoặc cấm đọc secret | Chỉ còn luật của team và cá nhân. Không sao với dự án cá nhân, nhưng rủi ro với công ty lớn |
| 2 | ~/.claude/settings.json | Khởi động | Sở thích và quyền cá nhân áp dụng cho mọi project | Dùng mặc định, nên Claude hỏi quyền nhiều hơn |
| 3 | .claude/settings.json | Khởi động | Luật chung của team: allow lệnh test, deny đọc .env, đăng ký hooks | Mỗi người cấu hình một kiểu, không ai chặn đọc .env, hook không chạy |
| 4 | .claude/settings.local.json | Khởi động (ưu tiên cao hơn file 3) | Ghi đè cho riêng bạn, không commit | Không sao, file này là tuỳ chọn |
| 5 | ~/.claude/CLAUDE.md | Khởi động | Thói quen cá nhân, ví dụ “trả lời tiếng Việt”, “dùng pnpm” | Claude không biết sở thích của bạn, bạn phải nhắc lại mỗi phiên |
| 6 | ./CLAUDE.md (và của các thư mục cha) | Khởi động, luôn nằm trong context | Bộ nhớ dự án: lệnh build/test, cấu trúc, điều không hiển nhiên | Mỗi phiên Claude phải tự khám phá lại, tốn token, dễ chạy sai lệnh (ví dụ npm test thay vì pnpm turbo test) |
| 7 | CLAUDE.local.md | Khởi động, nối sau CLAUDE.md | Ghi chú riêng của bạn trong project | Không sao |
| 8 | .claude/rules/*.md không có paths | Khởi động | Quy tắc chung tách khỏi CLAUDE.md cho gọn | Quy tắc phải dồn vào CLAUDE.md |
| 9 | .mcp.json | Khởi động, hỏi duyệt lần đầu | Kết nối công cụ ngoài: DB, GitHub, Jira… | Claude không truy cập được hệ thống ngoài, bạn phải copy dữ liệu vào tay |
| 10 | .claude/skills/*/SKILL.md | Khởi động: chỉ nạp name + description. Toàn bộ nội dung: khi được dùng | Quy trình dùng lại được, ví dụ “thêm migration”, “thêm FAQ” | Mỗi lần bạn phải giải thích lại quy trình, kết quả mỗi lần một kiểu |
| 11 | .claude/agents/*.md | Khởi động nạp định nghĩa, chạy khi được giao việc | Chuyên gia có context riêng và tool giới hạn, ví dụ reviewer chỉ được đọc | Chỉ có các subagent có sẵn, không có reviewer bị giới hạn quyền |
| 12 | Hook SessionStart | Cuối giai đoạn khởi động | Chèn trạng thái dự án, ví dụ nhánh git hoặc ticket đang làm | Claude bắt đầu mà không biết bối cảnh hiện tại |
| 13 | CLAUDE.md ở thư mục con (apps/api/CLAUDE.md) | Khi cần: lúc Claude đọc file trong thư mục đó | Kiến thức riêng từng app: NestJS khác Next.js | Claude dùng quy ước chung, dễ lẫn cách viết giữa backend và frontend |
| 14 | .claude/rules/*.md có paths | Khi cần: lúc đọc file khớp mẫu | Quy tắc theo loại file, chỉ tốn context khi liên quan | Quy tắc phải luôn nằm trong CLAUDE.md, tốn context mọi lúc |
| 15 | .claude/hooks/* (PreToolUse, PostToolUse, Stop…) | Mỗi lần gọi tool / kết thúc lượt | Tự động hoá chắc chắn: chặn secret, format, chạy test | Chỉ còn dựa vào việc model nhớ chỉ dẫn, có lúc sẽ quên |
- Luật bắt buộc → settings hoặc hook.
- Kiến thức luôn cần → CLAUDE.md.
- Kiến thức theo thư mục hoặc loại file → CLAUDE.md thư mục con hoặc rule có
paths. - Quy trình thỉnh thoảng dùng → skill.
- Việc cần context riêng → subagent.
- Dữ liệu và hệ thống ngoài → MCP.
5. Claude “nhìn thấy” gì trong một request
Context được ghép theo thứ tự cố định. Phần trên ổn định nên được cache, phần dưới thay đổi mỗi lượt.
6. Một lượt xử lý trong Claude Code
Ví dụ: bạn gõ “Sửa lỗi định dạng mã đơn trong tools.py”. Hook PreToolUse chạy trước bước kiểm tra permission.
7. Agent API trong src/agent.py chạy thế nào
Ví dụ: khách hỏi “Đơn SH1024 của tôi đang ở đâu?”.
Hai request cho một câu hỏi
- Request 1: system (chỉ dẫn + chính sách, đã cache) + tools + câu hỏi. Claude trả
stop_reason: "tool_use"vớilookup_order({"order_id": "SH1024"}). - Code của bạn chạy
lookup_order, đọcdata/orders.json, trả về{"status": "Đang giao", "eta": "2026-10-03", ...}. - Request 2: gửi lại toàn bộ lịch sử +
tool_result. Lần nàycache_read_input_tokens> 0 vì system không đổi. - Claude trả
end_turn: “Đơn SH1024 đang được giao, dự kiến tới ngày 03/10…”.
Nếu khách gõ sai mã “1024”, tool ném ToolError kèm hướng dẫn định dạng → trả is_error: true → Claude tự hỏi lại khách mã đúng.
8. Cùng một tool, hai cách dùng
tools.py là lõi. agent.py gửi schema của nó qua Messages API cho khách hàng. orders_mcp.py mở cùng các hàm đó qua MCP để nhân viên dùng trong Claude Code. Viết một lần, dùng hai nơi.
9. Thử ngay với Claude Code
| Bạn gõ | Điều xảy ra | Học được |
|---|---|---|
| “Tra đơn SH1025” | Gọi tool mcp__orders__lookup_order, được allow sẵn nên không hỏi | MCP + permission allow |
| “Thêm chính sách thanh toán COD” | Skill add-faq được nạp: tạo file knowledge + thêm eval case | Skill theo mô tả |
| “Sửa file .env thêm key” | Hook protect-secrets.sh exit 2 và rule deny chặn | Phòng thủ nhiều lớp |
| “Sửa src/tools.py cho gọn” | Rule python-style.md được nạp; sau khi sửa, hook chạy ruff format | Rule theo đường dẫn + PostToolUse |
| “Dùng code-reviewer kiểm tra thay đổi” | Subagent chỉ có tool đọc, trả báo cáo tóm tắt | Cô lập context, quyền tối thiểu |
| “Chạy eval” | Hỏi xác nhận vì rule ask (tốn phí API) | Permission ask |
Tóm tắt & mẹo nhớ
Ghi nhớ cốt lõi
- Settings do harness áp dụng; CLAUDE.md là kiến thức cho model. Luật cứng đặt trong settings/hook, còn kiến thức và quy ước đặt trong CLAUDE.md.
- Lúc mở phiên, skill và subagent chỉ nạp mô tả, nội dung đầy đủ chỉ nạp khi dùng. CLAUDE.md ở thư mục con và rule có
pathsnạp khi cần. PreToolUsechạy trước permission. Exit 2 thì chặn tool và gửi stderr cho Claude.- Thứ tự cache: tools → system → messages. Nội dung thay đổi đặt cuối cùng.
- Code của bạn mới là thứ chạy tool; model chỉ thấy schema và kết quả trả về.
Mẹo nhớ nhanh
- “S-M-M-S-H” khi mở phiên: Settings → Memory (CLAUDE.md) → MCP → Skills/Subagents (mô tả) → Hook SessionStart.
- “Chặn trước, hỏi sau”: PreToolUse chặn trước, permission hỏi sau.
- Settings cao → thấp: “Công ty – Lệnh – Local – Team – Tôi” (managed, --settings, local, project, user).
- “Deny là sếp”: deny luôn thắng ask và allow, dù rule nằm ở file nào.
- “Menu trước, món sau”: skill giống menu. Claude đọc tên món (description) trước, gọi món thì bếp mới nấu (nạp SKILL.md).
- “Tủ lạnh – bàn – đĩa” cho cache: tools là tủ lạnh (ít đổi), system là bàn bếp, messages là đĩa thức ăn (đổi liên tục). Đổi tủ lạnh thì phải dọn lại cả bàn lẫn đĩa.