Phân cấp CLAUDE.md, Phạm vi áp dụng và Tổ chức theo Module
Những điều bạn cần biết
Claude Code đọc cấu hình từ các file CLAUDE.md ở ba cấp độ khác nhau. Hiểu cấp độ nào áp dụng ở đâu — và chẩn đoán khi nào sai cấp độ đã được dùng — là một trong những khái niệm được hỏi thường xuyên nhất trong kỳ thi.
Phân cấp ba tầng
Cấp người dùng: ~/.claude/CLAUDE.md
File này chỉ áp dụng cho riêng bạn. Nó nằm trong thư mục home, bên ngoài mọi repository. Nó không được quản lý bằng git, không được chia sẻ qua git. Khi một thành viên mới clone repository của bạn, họ không nhận được các hướng dẫn này. Dùng cấp độ này cho các sở thích cá nhân thuần túy — cài đặt độ chi tiết, kiểu output ưa thích, các phím tắt cá nhân.
Cấp dự án: .claude/CLAUDE.md hoặc CLAUDE.md ở gốc
File này áp dụng cho tất cả mọi người làm việc trên dự án. Nó nằm trong repository và được quản lý bằng git. Mọi developer clone hoặc pull repo đều tự động nhận các hướng dẫn này. Các chuẩn chung của cả nhóm nên đặt ở đây: quy ước đặt tên, mẫu xử lý lỗi, yêu cầu kiểm thử, quyết định kiến trúc, checklist review code.
Cả .claude/CLAUDE.md (bên trong thư mục .claude) lẫn CLAUDE.md ở gốc repository đều là vị trí cấp dự án hợp lệ. Đề thi có thể đưa ra cả hai đường dẫn.
Cấp thư mục: các file CLAUDE.md trong thư mục con
Các file này áp dụng khi bạn làm việc trong thư mục cụ thể đó. Dùng chúng cho các quy ước riêng của từng package, khác với quy ước ở gốc dự án. Ví dụ, /packages/api/CLAUDE.md có thể chứa các quy ước riêng cho REST không áp dụng cho package frontend.
Thứ tự nạp và cách xử lý xung đột
Các file CLAUDE.md không phải là một cấu hình theo kiểu ưu tiên nghiêm ngặt. Tài liệu memory của Anthropic nói rõ: "Tất cả các file được tìm thấy đều được ghép nối vào context thay vì ghi đè lên nhau." Mọi file phù hợp đều được nạp vào cùng một context window — không file nào thay thế file nào.
Tài liệu mô tả một thứ tự nạp đã được ghi chép, không phải một chuỗi ưu tiên:
- Các file được sắp xếp từ phạm vi rộng nhất đến cụ thể nhất. Một hướng dẫn ở cấp dự án xuất hiện trong context sau hướng dẫn cấp người dùng. Xét trên toàn cây thư mục, "nội dung được sắp xếp từ gốc hệ thống file xuống đến thư mục làm việc của bạn", nên "các hướng dẫn gần nơi bạn khởi chạy Claude nhất được đọc sau cùng".
- Trong cùng một thư mục,
CLAUDE.local.mdđược nối thêm vào sauCLAUDE.md, nên các ghi chú cá nhân của bạn là thứ Claude đọc cuối cùng ở cấp đó.
Đây không phải là kiểu phân cấp "kẻ thắng lấy tất cả". Tài liệu nói rõ điều này: "nếu hai quy tắc mâu thuẫn nhau, Claude có thể chọn một cách tùy ý." CLAUDE.md được gửi đi dưới dạng một tin nhắn của người dùng — không phải là một phần của system prompt — và Anthropic nói rằng "không có gì đảm bảo tuân thủ nghiêm ngặt". Hãy coi CLAUDE.md như hướng dẫn mà model thường tuân theo, chứ không phải một tầng cấu hình có khả năng ghi đè tất định.
Hệ quả thực tế: nếu một quy tắc bắt buộc phải được tuân thủ ở mọi lần chạy (một tool bị chặn, một formatter bắt buộc, một chính sách quyền), đừng dựa vào phạm vi CLAUDE.md để thực thi nó. Hãy mã hóa nó trong settings.json (được client thực thi bất kể Claude quyết định gì) hoặc trong một hook (kích hoạt tại một sự kiện vòng đời cố định). Tài liệu của Anthropic nói thẳng điều này: "Các quy tắc trong settings được client thực thi bất kể Claude quyết định làm gì. Các hướng dẫn trong CLAUDE.md định hình hành vi của Claude nhưng không phải là một tầng thực thi cứng."
Bẫy thi: Đừng nhầm CLAUDE.md với settings.json
settings.json có một chuỗi ưu tiên nghiêm ngặt (managed policy > local > project > user, trong đó managed luôn thắng). CLAUDE.md thì không — các file được ghép nối và xung đột có thể được giải quyết tùy ý. Nếu câu hỏi hỏi "CLAUDE.md nào thắng khi xung đột?", câu trả lời đúng theo tài liệu là "không file nào được đảm bảo thắng — chuyển quy tắc đó sang settings.json hoặc một hook". Cẩn thận với các phương án gây nhiễu tuyên bố "phạm vi cụ thể hơn thắng" hay "cấp người dùng ghi đè cấp dự án": cả hai đều là diễn giải mà tài liệu chính thức chưa bao giờ nói.
Tổ chức theo module bằng import đường dẫn @
Khi vượt quá vài trăm dòng, một file CLAUDE.md duy nhất trở nên khó bảo trì. Cú pháp @ cho phép bạn chia nó ra nhiều file và tham chiếu chúng từ file chính. Chỉ thị đơn giản là @ theo sau bởi một đường dẫn. Không có từ khóa @import, dù một nửa tài liệu bạn tìm thấy trên mạng viết theo kiểu đó.
Cú pháp trong CLAUDE.md của bạn:
markdownCopy
# .claude/CLAUDE.md
Coding standards:
@./standards/naming-conventions.md
@./standards/error-handling.md
@./standards/testing-requirements.mdMỗi dòng @<đường dẫn> khiến file đó được chèn trực tiếp vào CLAUDE.md tại thời điểm nạp. Các file CLAUDE.md riêng của từng package chỉ có thể import những chuẩn áp dụng cho chúng. Package API kéo vào các quy ước API, package frontend kéo vào các quy tắc component. Không trùng lặp.
Một điều mà tài liệu không nói rõ: import được nạp ngay lập tức (eager). File được tham chiếu bị chèn vào ngay khi Claude đọc CLAUDE.md của bạn, y hệt như bạn đã dán nó vào. Vậy nên chia một file CLAUDE.md 600 dòng thành sáu import 100 dòng giúp mã nguồn dễ làm việc hơn, nhưng context mà Claude thực sự thấy vẫn có kích thước như cũ. Nếu bạn muốn thu nhỏ context cho mỗi phiên, công cụ phù hợp là .claude/rules/ với frontmatter theo phạm vi đường dẫn (được trình bày ở Task Statement 3.3). Các file đó chỉ nạp khi Claude đang làm việc trong các đường dẫn khớp.
CLAUDE.local.md, các override chỉ dùng cục bộ
CLAUDE.local.md nằm cạnh CLAUDE.md ở bất kỳ cấp nào trong phân cấp và được nạp theo cùng cách, với ba khác biệt nhỏ đáng lưu ý:
- Thứ tự nạp.
CLAUDE.local.mdđược nối thêm sauCLAUDE.mdở cùng cấp, nên nó có tiếng nói cuối cùng khi xảy ra xung đột trong thư mục đó. - Được gitignore theo quy ước. Hậu tố
.localđánh dấu các file bạn không muốn commit. Hầu hết các nhóm thêmCLAUDE.local.mdvào.gitignoređể các tinh chỉnh cá nhân vẫn ở mức cá nhân. - Dùng để làm gì.
CLAUDE.mdchung là quy tắc của cả nhóm.CLAUDE.local.mdbên cạnh nó là những đặc thù của riêng bạn cho repo này: một đường dẫn scratchpad ưa thích, một lời giải thích dài dòng bạn cứ phải dán lại nhiều lần, một ghi chú debug tạm thời bạn sẽ xóa vào tuần sau.
Hãy nghĩ CLAUDE.local.md như phiên bản có phạm vi dự án của ~/.claude/CLAUDE.md: cùng ý tưởng, phạm vi hẹp hơn. Nếu bạn thấy mình đang dùng nó để diễn đạt một quy tắc chung của cả nhóm, quy tắc đó nên nằm trong CLAUDE.md thay vào đó.
Thư mục .claude/rules/
Như một cách thay thế cho một file CLAUDE.md duy nhất, thư mục .claude/rules/ chứa các file quy tắc theo từng chủ đề:
testing.md— quy ước đặt tên test, mẫu assertion, cách dùng fixtureapi-conventions.md— quy ước đặt tên endpoint, schema request/responsedeployment.md— checklist deploy, cấu hình môi trường
Mỗi file có thể tùy chọn kèm frontmatter YAML với phạm vi theo đường dẫn (được trình bày chi tiết ở Task Statement 3.3). Nếu không có frontmatter, các file rules được nạp cho mọi phiên.
Lệnh /memory
Lệnh /memory xác minh những file memory nào đang được nạp trong phiên làm việc hiện tại của bạn. Đây là công cụ debug cho các hành vi không nhất quán giữa các phiên hoặc giữa các developer. Khi Claude Code hành xử khác nhau với các thành viên khác nhau trong nhóm, /memory tiết lộ liệu các file cấu hình mong đợi có thực sự được nạp hay không.
Khái niệm chính
Lệnh /memory không nạp các file cấu hình — nó chỉ tiết lộ những file nào đã được nạp sẵn. Các file cấu hình tự động nạp dựa trên cấp độ và vị trí của chúng. Dùng /memory để chẩn đoán, không phải để kích hoạt.
Kịch bản thi kinh điển: thành viên mới không nhận được hướng dẫn
Đây là bẫy yêu thích của đề thi cho Task Statement 3.1. Kịch bản thường được trình bày như sau:
Developer A đã ở trong nhóm nhiều tháng. Claude Code tuân theo hoàn hảo mọi quy ước của nhóm — đặt tên API, cấu trúc test, xử lý lỗi. Developer B gia nhập nhóm, clone repository, và Claude Code cho ra kết quả không nhất quán, bỏ qua các quy ước.
Nguyên nhân gốc rễ luôn giống nhau: các quy ước được lưu trong cấu hình cấp người dùng của Developer A (~/.claude/CLAUDE.md) thay vì cấu hình cấp dự án (.claude/CLAUDE.md hoặc CLAUDE.md ở gốc). Cấu hình cấp người dùng không được chia sẻ qua git. Developer B chưa bao giờ nhận được các hướng dẫn đó.
Cách sửa: chuyển các hướng dẫn từ cấu hình cấp người dùng sang cấu hình cấp dự án.
Bạn phải chẩn đoán được điều này ngay lập tức trong đề thi. Khi thấy "thành viên mới" và "hành vi không nhất quán", hãy kiểm tra cấu hình đang nằm ở đâu.
Bẫy thi
Bẫy thi: Thành viên mới không nhận được hướng dẫn của Claude Code dù đang làm việc trên cùng repo và cùng branch
Các hướng dẫn nằm trong cấu hình cấp người dùng (~/.claude/CLAUDE.md) thay vì cấp dự án. Cấp người dùng không được quản lý hay chia sẻ qua git. Chuyển sang .claude/CLAUDE.md để áp dụng cho toàn nhóm.
Bẫy thi: Nghĩ rằng /memory kích hoạt việc nạp cấu hình
/memory là một lệnh chẩn đoán cho biết những file nào đang được nạp. Các file cấu hình tự động nạp dựa trên vị trí của chúng trong phân cấp. /memory giúp bạn debug — nó không kích hoạt bất cứ điều gì.
Bẫy thi: Cho rằng CLAUDE.md cấp thư mục là giải pháp tốt nhất cho các quy ước xuyên nhiều thư mục
CLAUDE.md cấp thư mục chỉ áp dụng cho một thư mục duy nhất. Với các quy ước trải rộng trên nhiều thư mục (như các file test nằm rải rác khắp codebase), hãy dùng rules theo phạm vi đường dẫn trong .claude/rules/ với glob pattern thay vì vậy.
Tình huống luyện tập
Không tìm thấy câu hỏi luyện tập "q-3-1-001".
Bài tập thực hành
Xây dựng cấu hình CLAUDE.md nhiều cấp
Bạn sẽ học được gì
- Hiểu phân cấp CLAUDE.md ba tầng (người dùng, dự án, thư mục) và khi nào dùng từng tầng
- Cấu hình các chuẩn dự án theo module bằng import đường dẫn @
- Dùng .claude/rules/ cho các file quy tắc theo chủ đề
- Chẩn đoán các vấn đề về phạm vi cấu hình bằng lệnh /memory
- Xác định nguyên nhân gốc rễ khi một thành viên mới không nhận được hướng dẫn
Các bước
Vì sao: Cấu hình cấp dự án là nền tảng của các chuẩn chung toàn nhóm. Đề thi kiểm tra xem bạn có đặt các quy ước dùng chung ở đây thay vì trong cấu hình cấp người dùng hay không, đó là tình huống cấu hình sai phổ biến nhất.
Bạn sẽ thấy: Một file .claude/CLAUDE.md tại gốc repository chứa ít nhất ba phần: quy ước đặt tên, mẫu xử lý lỗi, và checklist review code. Chạy /memory ở gốc dự án cho thấy file này đã được nạp.
Vì sao: Cấu hình cấp thư mục giới hạn phạm vi quy ước cho một package cụ thể. Đề thi kiểm tra xem bạn có biết CLAUDE.md cấp thư mục chỉ áp dụng trong thư mục đó, không áp dụng cho toàn dự án hay không.
Bạn sẽ thấy: Một file CLAUDE.md bên trong /packages/api/ chứa các quy ước riêng cho REST. Khi bạn chạy /memory trong lúc làm việc ở /packages/api/, cả file cấp dự án lẫn cấp thư mục đều xuất hiện là đã nạp.
Vì sao: Thư mục .claude/rules/ chứa các file quy tắc theo chủ đề, có thể tùy chọn kèm frontmatter YAML để giới hạn phạm vi theo đường dẫn. Hiểu cơ chế này được kiểm tra song song với các rules theo phạm vi đường dẫn ở Task Statement 3.3.
Bạn sẽ thấy: Một file testing.md bên trong .claude/rules/ chứa ít nhất ba quy ước về test. Chạy /memory cho thấy file rules này đã được nạp trong phiên của bạn.
Vì sao: Cú pháp import @ cho phép tổ chức các quy ước theo module. Không có từ khóa @import — một đường dẫn có tiền tố @ đứng riêng trên một dòng chính là câu lệnh import. Mỗi package chỉ có thể import những chuẩn liên quan, giảm trùng lặp và lệch pha trong các file nguồn. Đề thi kiểm tra xem bạn có biết cơ chế này tồn tại và cú pháp thực tế trông như thế nào.
Bạn sẽ thấy: File .claude/CLAUDE.md cấp dự án chứa một dòng bắt đầu bằng @ trỏ đến ./standards/naming.md. Một file riêng tại .claude/standards/naming.md (hoặc standards/naming.md tương đối so với CLAUDE.md) tồn tại với các quy ước đặt tên. Chạy /memory xác nhận nội dung được import đã được nạp inline.
Vì sao: Lệnh /memory là công cụ chẩn đoán để xác minh những file cấu hình nào đang hoạt động. Đề thi kiểm tra cụ thể việc /memory tiết lộ các file đã nạp nhưng không kích hoạt việc nạp — cấu hình tự động nạp dựa trên vị trí.
Bạn sẽ thấy: Ở gốc dự án, /memory hiển thị CLAUDE.md cấp dự án và các file rules. Trong /packages/api/, /memory hiển thị thêm CLAUDE.md cấp thư mục. Nội dung file chuẩn được import xuất hiện như một phần của cấu hình cấp dự án.
Vì sao: Đây là kịch bản bẫy yêu thích của đề thi. Khi các quy ước nằm trong cấu hình cấp người dùng, các thành viên mới clone repo sẽ không nhận được chúng. Chứng minh ranh giới này bằng thực nghiệm giúp khắc sâu khái niệm.
Bạn sẽ thấy: Sau khi chuyển một quy ước sang ~/.claude/CLAUDE.md, /memory của chính bạn cho thấy nó đã được nạp. Một phiên người dùng thứ hai được mô phỏng (hoặc một bản clone mới không có cấu hình thư mục home của bạn) KHÔNG hiển thị quy ước đó. Điều này xác nhận ranh giới phạm vi.