Viết file CLAUDE.md
#Vấn đề: Agent quên hết mỗi khi mở session mới
Bạn đã từng gặp tình huống này chưa?
Mở Claude Code, giải thích cho agent: "Project này dùng Next.js 15, pnpm, 2-space indentation, commit theo conventional commit." Xong việc, đóng session.
Hôm sau mở lại. Agent lại hỏi: "Bạn muốn dùng package manager nào?" Lại giải thích. Lại đóng session.
Mỗi lần mở session mới, agent bắt đầu từ zero. Nó không nhớ bạn là ai, project của bạn dùng tech stack gì, convention ra sao. Mọi context bạn đã build trong session trước — mất hết.
Đây chính là lý do CLAUDE.md tồn tại.
#CLAUDE.md là gì?
CLAUDE.md là file markdown mà Claude Code tự động đọc mỗi khi bắt đầu session. Think of nó như .editorconfig hay .eslintrc — nhưng thay vì config cho editor hay linter, nó config cho agent.
Nội dung trong CLAUDE.md trở thành background knowledge của agent. Nó không cần bạn nhắc lại mỗi lần.
Ví dụ đơn giản. Tạo file CLAUDE.md ở root project:
# Project: MyApp
- Framework: Next.js 15, App Router
- Package manager: pnpm (không dùng npm)
- Ngôn ngữ: TypeScript strict mode
- Styling: Tailwind CSS
- Test: Vitest + Testing LibraryTừ giờ, mỗi khi mở session trong project này, agent đã biết:
- Dùng pnpm, không phải npm
- Viết TypeScript, không phải JavaScript
- Dùng Tailwind, không phải CSS modules
Bạn không cần nhắc lại. Tiết kiệm thời gian, giảm sai sót.
#Đặt CLAUDE.md ở đâu?
Claude Code tìm CLAUDE.md ở nhiều vị trí, theo thứ tự ưu tiên:
#1. Project root (phổ biến nhất)
./CLAUDE.md # root của project
./.claude/CLAUDE.md # thư mục .claude (tương đương)Hai vị trí này tương đương nhau. Chọn cái nào bạn thấy gọn hơn. Nội dung apply cho tất cả người dùng trong team — nên commit vào git.
#2. User-level (cá nhân)
~/.claude/CLAUDE.mdÁp dụng cho tất cả project trên máy bạn. Phù hợp cho preferences cá nhân mà không muốn commit vào repo, ví dụ: "Luôn trả lời bằng tiếng Việt", "Giải thích code bằng comment tiếng Anh".
#3. Local overrides (không commit)
CLAUDE.local.md # gitignore file nàyDùng cho config cá nhân liên quan đến project cụ thể. Ví dụ: đường dẫn local database, port dev server riêng. Phải thêm vào .gitignore — không ai trong team cần biết config local của bạn.
#Thứ tự load
Claude Code load tất cả các vị trí trên, merge lại. Nếu có conflict, CLAUDE.md ở project root ghi đè user-level. CLAUDE.local.md ghi đè tất cả.
⚠️ Cẩn thận: CLAUDE.local.md phải nằm trong
.gitignore. Nếu bạn commit nhầm, mọi người trong team sẽ thấy config cá nhân của bạn — có thể chứa đường dẫn local, token, hoặc preferences không phù hợp.
#Tạo nhanh với /init
Không muốn viết từ đầu? Claude Code có lệnh /init:
/initLệnh này sẽ:
- Scan project của bạn (package.json, tsconfig, file structure)
- Tự tạo CLAUDE.md với thông tin cơ bản về tech stack
- Hiển thị để bạn review trước khi lưu
Kết quả thường bao gồm: framework, ngôn ngữ, package manager, test framework, cấu trúc thư mục. Bạn nên review và chỉnh sửa — /init chỉ tạo bản nháp, không biết business logic hay convention riêng của team bạn.
#Viết gì trong CLAUDE.md?
Nguyên tắc vàng: càng cụ thể, càng ngắn, càng tốt. Dưới 100 dòng là lý tưởng.
#Nên include
Tech stack cơ bản:
- Runtime: Node.js 20 LTS
- Framework: Next.js 15, App Router
- Database: PostgreSQL + Prisma ORM
- Package manager: pnpmBuild & test commands:
- Dev: `pnpm dev`
- Build: `pnpm build`
- Test: `pnpm test` (Vitest)
- Lint: `pnpm lint` (ESLint + Prettier)Đây là phần quan trọng nhất. Khi agent cần chạy test hoặc build, nó đã biết lệnh chính xác — không phải dò từng file package.json.
Coding conventions:
## Conventions
- 2-space indentation
- Dùng `const` trước `let`, không dùng `var`
- Interface đặt trong `src/types/`, không đặt inline
- Error handling: dùng custom AppError class, không throw stringArchitecture overview (ngắn gọn):
## Architecture
- `src/app/` — Next.js App Router pages
- `src/components/` — Reusable UI components
- `src/lib/` — Business logic, utilities
- `src/types/` — TypeScript interfaces & types
- `prisma/` — Database schema & migrationsDomain-specific rules:
## Business Rules
- User role gồm 3 loại: admin, editor, viewer
- Permission check phải dùng hàm `checkPermission()` trong src/lib/auth.ts
- Không hardcode role string, dùng enum từ src/types/auth.ts#Không nên include
- Đoạn dài giải thích — CLAUDE.md là reference, không phải documentation
- Thông tin thay đổi thường xuyên — version number, URL staging
- Toàn bộ coding style guide — link đến file riêng thay vì paste vào đây
#Anti-pattern: Viết mơ hồ
Sai lầm lớn nhất khi viết CLAUDE.md là mơ hồ.
❌ "Format code nicely"
❌ "Viết code sạch"
❌ "Follow best practices"
❌ "Use proper naming conventions"Agent không biết "nicely" là gì. "Sạch" theo tiêu chuẩn nào? "Best practices" của framework nào?
Thay vào đó:
✅ "2-space indentation, single quotes, trailing commas"
✅ "Function name: camelCase. File name: kebab-case."
✅ "Mỗi file chỉ export 1 component. Dùng named export, không dùng default export."
✅ "Error message phải mô tả được hành động user nên làm tiếp theo"Một rule cụ thể bằng mười rule mơ hồ. Agent có thể follow chính xác nếu bạn nói chính xác. Nó không thể đọc ý bạn nếu bạn viết chung chung.
⚠️ Cẩn thận: Đừng viết CLAUDE.md như viết README. README dành cho người đọc (developer mới vào team). CLAUDE.md dành cho agent — nó cần actionable instructions, không cần context dài dòng.
#Cấu trúc CLAUDE.md hiệu quả
Sau đây là template thực tế mà tôi dùng trong nhiều project:
# Project Name
Short description (1-2 dòng).
## Tech Stack
- Framework, language, runtime
- Package manager
- Database, ORM
## Commands
- Dev: `command`
- Build: `command`
- Test: `command`
- Lint: `command`
## Conventions
- Bullet list các quy ước cụ thể
- Mỗi bullet = 1 rule rõ ràng
## Architecture
- Mô tả cấu trúc thư mục chính
- File nào chứa logic gì
## Don'ts
- Không dùng X, dùng Y thay thế
- Không commit file Z
- Không hardcode giá trị WPhần ## Don'ts rất quan trọng. Nhiều khi nói rõ không nên làm còn hiệu quả hơn nói nên làm. Agent sẽ tránh những anti-pattern mà bạn đã liệt kê.
#Kích thước: ngắn là tốt
CLAUDE.md lý tưởng dưới 100 dòng, tối đa khoảng 200 dòng. Tại sao?
Mỗi session, CLAUDE.md được load vào system prompt — phần đầu context window. CLAUDE.md càng dài, càng chiếm nhiều chỗ cho system prompt, ít chỗ hơn cho code và conversation.
Nếu bạn thấy CLAUDE.md dài quá 200 dòng, đã đến lúc:
- Cắt bỏ phần redundant
- Chuyển sang
.claude/rules/(bài tiếp theo sẽ nói kỹ) - Link đến file riêng thay vì paste nội dung
#Demo: Tạo CLAUDE.md cho project thực
Giả sử bạn có project Next.js. Đây là quy trình:
Bước 1: Chạy /init để tạo bản nháp.
Bước 2: Review output. Thường sẽ thiếu một số thứ quan trọng với project của bạn.
Bước 3: Bổ sung commands cụ thể. Mở package.json, xem scripts, thêm vào:
## Commands
- Dev: `pnpm dev`
- Build: `pnpm build`
- Test: `pnpm test:unit` (unit tests), `pnpm test:e2e` (E2E với Playwright)
- DB: `pnpm prisma migrate dev` (chạy migration), `pnpm prisma studio` (xem data)Bước 4: Thêm conventions. Nhìn vào codebase hiện tại, rút ra pattern:
## Conventions
- Dùng Server Component mặc định, chỉ thêm 'use client' khi cần event handler
- API route đặt trong app/api/, dùng Zod để validate request
- Component props dùng interface, không dùng type alias
- Commit message: conventional commits (feat:, fix:, chore:)Bước 5: Commit CLAUDE.md vào git. Cả team cùng dùng.
#Bài tập thực hành
#Bài tập 1: Tạo CLAUDE.md với /init
Mở Claude Code trong project của bạn. Chạy /init. Review output, ghi nhận: những gì /init đã detect đúng? Những gì thiếu? Chỉnh sửa lại cho đúng với project thực tế.
#Bài tập 2: Chuyển đổi từ mơ hồ sang cụ thể
Lấy một project bất kỳ, viết CLAUDE.md với tất cả rules mơ hồ bạn nghĩ ra ("use good naming", "write clean code", "follow patterns"). Sau đó nhờ Claude Code review: "Đọc CLAUDE.md và chỉ ra những rule nào không thể follow vì quá mơ hồ." Rồi sửa lại cho cụ thể.
#Bài tập 3: So sánh hiệu quả có/không có CLAUDE.md
Tạo 2 session mới trong cùng một project. Session 1: xóa (hoặc rename) CLAUDE.md, hỏi agent "Chạy test cho project này." Session 2: giữ CLAUDE.md có ghi test command. So sánh: session nào agent biết lệnh đúng ngay lần đầu?
#Tổng kết
CLAUDE.md là "bộ nhớ cố định" của agent — mỗi session tự động load, không cần nhắc lại. Đặt ở project root hoặc .claude/, giữ dưới 100 dòng, viết cụ thể và actionable. Dùng /init để tạo nhanh, rồi customize theo project.
Nguyên tắc cốt lõi: specificity beats verbosity — một rule cụ thể đáng giá hơn mười đoạn mô tả chung chung.
Bài tiếp theo sẽ đi sâu vào CLAUDE.md nâng cao: cách dùng @import, .claude/rules/ cho path-scoped rules, và pattern "mỗi lần agent sai — thêm rule" của Boris Cherny.