CLAUDE.md nâng cao

#Vấn đề: CLAUDE.md phình to và mất kiểm soát

Bạn đã viết CLAUDE.md cho project. Tốt. Nhưng rồi:

  • Tuần 1: agent dùng npm thay vì pnpm → bạn thêm rule "dùng pnpm"
  • Tuần 2: agent commit message sai format → thêm rule
  • Tuần 3: agent tạo component với default export → thêm rule
  • Tuần 4: agent quên validate request body → thêm rule
  • Tháng 2: CLAUDE.md đã 300 dòng, chồng chéo, trùng lặp

Mỗi lần agent sai, bạn lại nhồi thêm rule. CLAUDE.md trở thành bãi rác instructions — dài, lộn xộn, và paradoxically agent lại hiểu kém hơn vì context bị nhiễu.

Bài này sẽ dạy bạn cách quản lý CLAUDE.md ở quy mô thực: phân tách rules, scope theo đường dẫn, và tận dụng auto memory.

#Boris Cherny pattern: mỗi lần agent sai, thêm rule

Boris Cherny — engineer tại Figma — chia sẻ một pattern đơn giản nhưng hiệu quả:

Mỗi lần Claude Code mắc lỗi, ngay lập tức thêm một rule vào CLAUDE.md để ngăn lỗi đó tái diễn.

Ví dụ thực tế. Bạn nhờ agent tạo API endpoint:

Tạo endpoint POST /api/users để tạo user mới

Agent tạo code nhưng không validate request body. Bạn sửa lại, rồi thêm rule:

- API endpoint phải validate request body bằng Zod schema trước khi xử lý
- Zod schema đặt trong cùng file với route handler

Lần sau agent tạo endpoint mới, nó sẽ tự động validate. Lỗi đó không bao giờ xảy ra nữa.

Sau vài tuần, CLAUDE.md của bạn sẽ chứa toàn bộ bài học từ thực tế — mỗi rule là một lần agent đã sai và bạn đã fix. Đây chính là "institutional knowledge" về cách agent nên làm việc trong project của bạn.

Quy trình lặp lại:

  1. Agent mắc lỗi
  2. Bạn xác định rule cần thiết
  3. Viết rule cụ thể (không mơ hồ)
  4. Thêm vào CLAUDE.md hoặc .claude/rules/
  5. Lần sau agent sẽ không mắc lỗi đó nữa

⚠️ Cẩn thận: Boris Cherny pattern chỉ hiệu quả nếu rule cụ thể. "Don't make mistakes" không phải rule. "Always validate request body with Zod before processing" mới là rule. Nếu bạn viết rule mơ hồ, bạn sẽ lại thấy lỗi tương tương tự xuất hiện — chỉ khác hình thức.

#Section "Don'ts": anti-patterns quan trọng hơn bạn nghĩ

Trong CLAUDE.md, section ## Don'ts (hoặc ## Anti-patterns) thường hiệu quả hơn section "Nên làm" — vì nó ngăn lỗi trực tiếp.

Ví dụ:

## Don'ts
- Không dùng `any` type — dùng `unknown` và type guard
- Không dùng default export — luôn dùng named export
- Không hardcode API URL — dùng environment variable từ .env
- Không throw string — luôn throw Error object hoặc custom AppError
- Không dùng `console.log` trong production code — dùng logger từ src/lib/logger.ts

Mỗi dòng ngăn một loại lỗi cụ thể. Khi agent đọc section này, nó biết những gì cần tránh — và tự nhiên sẽ đi theo hướng đúng.

Một pattern hay: ghi cả lý do. "Không dùng any — phá vỡ type safety" hiệu quả hơn chỉ viết "Không dùng any". Agent hiểu tại sao sẽ follow tốt hơn.

#@import: tham chiếu file bên ngoài

CLAUDE.md hỗ trợ directive @path/to/file để import nội dung file khác vào CLAUDE.md. Rất hữu ích khi bạn muốn tham chiếu tài liệu mà không paste trực tiếp.

Ví dụ:

# Project: MyApp
 
## Architecture
Xem chi tiết tại:
@docs/architecture.md
 
## API Conventions
@docs/api-style-guide.md

Khi Claude Code load CLAUDE.md, nó sẽ tự động đọc nội dung docs/architecture.mddocs/api-style-guide.md — CLAUDE.md gọn gàng, nội dung gốc update riêng biệt.

⚠️ Cẩn thận: Mỗi @import sẽ thêm nội dung vào context window. Nếu bạn import file lớn (schema 500 dòng, type definitions 300 dòng), CLAUDE.md sẽ phình to rất nhanh. Chỉ import file thực sự cần thiết cho mỗi session. Nếu file quá lớn, tạo bản tóm tắt riêng và import bản tóm tắt.

#.claude/rules/: path-scoped rules

Khi project lớn, bạn không muốn tất cả rules apply cho mọi file. Ví dụ:

  • Rules về React components chỉ nên apply trong src/components/
  • Rules về API routes chỉ nên apply trong src/app/api/
  • Rules về database chỉ nên apply trong prisma/

Đây là lúc .claude/rules/ phát huy tác dụng.

#Cấu trúc

.claude/
  rules/
    react-components.md
    api-routes.md
    database.md

#Path-scoped frontmatter

Mỗi file rule có thể dùng frontmatter để scope theo đường dẫn:

---
paths:
  - "src/components/**"
---
 
## React Component Rules
- Dùng functional component, không dùng class component
- Props phải có interface riêng, đặt cùng file
- Không dùng `useEffect` cho derived state — dùng `useMemo`

Rule này chỉ apply khi agent thao tác với file trong src/components/. Khi agent sửa file ở src/app/api/, rule này không được load — tiết kiệm context window.

Ví dụ khác:

---
paths:
  - "src/app/api/**"
---
 
## API Route Rules
- Mỗi route handler phải validate request body bằng Zod
- Response phải dùng helper `successResponse()` hoặc `errorResponse()` từ src/lib/api-utils.ts
- Không return raw error object — wrap bằng AppError

#So sánh: CLAUDE.md vs .claude/rules/

CLAUDE.md.claude/rules/
Phạm viToàn projectScoped theo path
Vị tríProject root.claude/rules/
FrontmatterKhôngCó (paths)
Kích thướcDưới 200 dòngMỗi file nên dưới 50 dòng
Git commit
Phù hợpGlobal rules, tech stack, commandsModule-specific rules

#Auto memory system

Ngoài CLAUDE.md và rules, Claude Code còn một hệ thống memory tự động:

~/.claude/projects/<project-hash>/memory/MEMORY.md

Đây là nơi agent tự ghi lại những gì đã học — không phải bạn viết, agent tự viết. Ví dụ: "Project này dùng Result<T, E> pattern thay vì throw exception", "Test file đặt cùng thư mục với source file."

Memory được load vào mỗi session (tối đa 200 dòng đầu). Đây là cách agent "học" project qua thời gian — bên ngoài CLAUDE.md.

⚠️ Cẩn thận: Auto memory không phải lúc nào cũng đúng. Agent có thể ghi nhận sai pattern. Định kỳ review ~/.claude/projects/<project>/memory/MEMORY.md và xóa observation không chính xác — memory sai sẽ khiến agent liên tục mắc lỗi.

#MEMORY.md vs CLAUDE.md

  • CLAUDE.md: bạn viết, bạn kiểm soát, commit vào git, mang tính "chính thức"
  • MEMORY.md: agent viết, semi-automated, không commit, mang tính "observation"

CLAUDE.md là luật. MEMORY.md là kinh nghiệm. Cả hai đều quan trọng.

#Khi nào dùng gì? Decision matrix

Tình huốngDùng gì
Tech stack, build commands, conventions chungCLAUDE.md
Rule áp dụng cho 1 module/path cụ thể.claude/rules/ với paths
Rule cá nhân, không muốn commitCLAUDE.local.md
Agent mắc lỗi lặp lại → ngăn recurrenceBoris Cherny pattern (thêm rule)
Pattern agent tự học đượcAuto memory (MEMORY.md)
Tham chiếu file lớn, không muốn paste@import trong CLAUDE.md

#Anti-pattern: CLAUDE.md 500+ dòng

Anti-pattern phổ biến nhất ở team lớn. Mỗi developer thêm một ít, sau vài tháng CLAUDE.md dài 500 dòng:

  1. Context window bị chiếm nhiều — ít chỗ cho code thực tế hơn
  2. Rules chồng chéo — rule ở dòng 50 mâu thuẫn với rule ở dòng 300
  3. Agent mất focus — quá nhiều instructions, nó không biết ưu tiên cái nào
  4. Khó maintain — không ai dám sửa vì sợ phá cái gì

Giải pháp 5 bước:

  1. Audit — đánh dấu rule nào "global" vs rule nào nên chuyển sang .claude/rules/
  2. Tách module-specific rules ra .claude/rules/ với path scope
  3. Xóa rules redundant hoặc đã được enforce bởi tool (ví dụ: nếu có tsconfig.json strict mode, rule "dùng TypeScript" là thừa)
  4. Merge rules tương tự — 5 rules về naming convention gộp thành 1 rule với 5 bullet
  5. Giữ CLAUDE.md dưới 100 dòng, dùng @import nếu cần

#Demo: Setup rules cho project thực

Giả sử project Next.js với 3 module: components, API routes, database.

CLAUDE.md (global, ~10 dòng):

# MyApp
- Next.js 15, App Router, TypeScript strict, pnpm
- Test: Vitest. Run: `pnpm test`
- Commit: conventional commits (feat:, fix:, refactor:)
- Không dùng `any`, không dùng default export

.claude/rules/react-components.md (path: src/components/**): Functional component only, props dùng interface, không dùng useEffect cho derived state.

.claude/rules/api-routes.md (path: src/app/api/**): Validate request body bằng Zod, dùng successResponse()/errorResponse() từ src/lib/api-utils.ts, wrap error bằng AppError.

.claude/rules/database.md (path: prisma/**, src/lib/db/**): Migration dùng pnpm prisma migrate dev, không sửa migration đã deploy, query phải có error handling.

CLAUDE.md gọn, mỗi rule file 5-7 dòng, scoped chính xác. Agent chỉ load rules liên quan đến file nó đang thao tác.

#Bài tập thực hành

#Bài tập 1: Áp dụng Boris Cherny pattern

Trong 1 tuần, mỗi lần agent mắc lỗi, ghi lại vào một file tạm. Cuối tuần, review: có bao nhiêu lỗi lặp lại? Viết rule cho mỗi lỗi đó. Thêm vào CLAUDE.md hoặc .claude/rules/. Tuần sau: những lỗi đó có còn xuất hiện?

#Bài tập 2: Tách rules ra .claude/rules/

Lấy CLAUDE.md hiện tại của bạn (hoặc tạo mới nếu chưa có). Đọc lại, đánh dấu rule nào "global" (áp dụng mọi nơi) và rule nào "scoped" (chỉ áp dụng cho module/path cụ thể). Tách các rule scoped ra .laude/rules/ với path frontmatter thích hợp.

#Bài tập 3: Audit auto memory

Tìm file ~/.claude/projects/<project-hash>/memory/MEMORY.md (thay <project-hash> bằng tên thư mục project của bạn). Đọc nội dung: agent đã ghi nhận những gì? Có gì sai không? Xóa những observation không chính xác, giữ lại những insight hữu ích.

#Tổng kết

CLAUDE.md ở mức nâng cao không chỉ là viết instructions — mà là quản lý hệ thống knowledge cho agent. Boris Cherny pattern biến mỗi lỗi thành rule. .claude/rules/ với path scope giữ mọi thứ gọn gàng. Auto memory giúp agent "học" project qua thời gian.

Nguyên tắc cốt lõi: CLAUDE.md là luật, rules là quy tắc module, memory là kinh nghiệm. Dùng đúng công cụ cho đúng mục đích, và agent của bạn sẽ ngày càng hiểu project sâu hơn — mà không cần bạn nhắc lại.

Bài tiếp theo sẽ chuyển sang chủ đề mới: cách dùng Claude Code để refactor codebase lớn — từ single file đến cross-module refactor, với workflow thực tế và strategy để giữ an toàn.