SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor

CLAUDE.md quá dài? Cách cắt gọn để agent nghe lời hơn

Lệnh /init quét cả repo rồi ghi hết vào CLAUDE.md, và mỗi lượt chat đều gửi lại cả file. Cách giữ đúng thứ agent cần, phần còn lại chuyển sang skill và rules.

Vì sao CLAUDE.md quá dài ngay từ đầu

CLAUDE.md quá dài gần như luôn có cùng một nguyên nhân: nó được sinh ra bởi /init, hoặc bởi một câu lệnh kiểu "viết cho tôi file CLAUDE.md". Cả hai cách đều quét repo rồi ghi lại mọi thứ vừa nhìn thấy: cây thư mục, danh sách dependency, mô tả kiến trúc, quy ước đặt tên. Kết quả là một bài giới thiệu codebase hơn là một bộ hướng dẫn. Agent đọc code là tự biết phần lớn những thứ đó, nên file dài mà không dạy được gì mới.

Cái giá của độ dài không nằm ở việc đọc một lần. CLAUDE.md được nạp vào cửa sổ ngữ cảnh (context window) ngay khi phiên làm việc bắt đầu, và mỗi lượt trao đổi sau đó đều gửi lại toàn bộ ngữ cảnh lên API. Vì thế mỗi dòng thừa được trả tiền lặp lại ở từng lượt. Con số cụ thể cho từng gói và từng model nằm trong bài cách Claude Code tiêu token, bài này chỉ tập trung vào việc cắt.

Tài liệu chính thức của Claude Code, trang "How Claude remembers your project" (đọc tháng 9/2026), khuyên giữ mỗi file CLAUDE.md dưới 200 dòng, và nói thẳng rằng file dài hơn vừa tốn ngữ cảnh vừa làm agent tuân thủ kém hơn. Lý do là CLAUDE.md chỉ là ngữ cảnh, không phải cấu hình bắt buộc: model đọc rồi cố gắng làm theo, và một chỉ dẫn quan trọng lẫn giữa năm mươi dòng mô tả thư mục thì rất dễ bị bỏ qua. Nếu bạn từng thắc mắc vì sao agent phớt lờ hướng dẫn của bạn, độ dài file là nghi phạm đầu tiên.

Quy tắc chọn: giữ thứ agent không tự suy ra được

Mỗi dòng trong CLAUDE.md phải qua một câu hỏi: nếu xóa dòng này, agent đọc code có tự biết không? Nếu có, xóa. Nếu agent đọc code xong vẫn làm sai, giữ.

Những thứ đáng giữ:

  • Lệnh build, test, lint và chạy dự án, đúng cú pháp dự án dùng. Ví dụ pnpm test --filter api, không phải npm test.
  • Quy ước khác với mặc định của công cụ. Nếu dự án dùng tab thay vì space trong khi Prettier mặc định là space, ghi lại.
  • Điều cấm làm. "Không sửa file trong migrations/ đã commit." "Không chạy git push --force."
  • Bẫy đã biết. Test tích hợp cần Redis chạy cục bộ. Biến DATABASE_URL trong .env.example trỏ về staging.

Những thứ nên xóa:

  • Mô tả kiến trúc. Agent đọc src/ và biết ngay.
  • Danh sách file và thư mục. Lệnh ls làm việc này miễn phí.
  • Danh sách dependency. Đã có package.json hoặc pyproject.toml.
  • Lời khuyên chung chung. "Viết code sạch", "xử lý lỗi cẩn thận", "tuân thủ SOLID", "viết test cho tính năng mới". Model đã được huấn luyện để làm vậy, nhắc lại không thay đổi gì.
  • Lịch sử dự án và lý do ra đời. Không giúp agent viết dòng code tiếp theo.

Ví dụ: file do /init sinh ra, trước và sau

Dưới đây là một file CLAUDE.md minh họa, giống kiểu /init sinh ra cho một dự án TypeScript nhỏ. Nội dung được rút gọn để dễ đọc, nhưng hình dáng thì ai từng chạy /init cũng nhận ra.

# Project: shop-api

## Overview
shop-api is a REST API for an e-commerce platform built with Node.js, TypeScript, Express and PostgreSQL. It handles products, carts, orders and payments.

## Project structure
- src/index.ts: application entry point
- src/routes/: Express route handlers (products.ts, carts.ts, orders.ts, payments.ts)
- src/services/: business logic, one file per domain
- src/db/: Prisma client and migrations
- src/middleware/: auth, logging, error handling
- tests/: Jest tests, mirrors the src/ layout
- scripts/: seed and maintenance scripts

## Dependencies
- express 4.x for HTTP
- prisma 5.x as ORM
- zod for request validation
- jest and supertest for testing
- pino for logging

## Architecture
Requests flow from routes to services to the database layer. Services never import from routes. Validation happens in middleware using zod schemas defined in src/schemas/. Errors are normalised by the error middleware and returned as JSON.

## Development commands
- npm install
- npm run dev
- npm test
- npm run lint
- npm run build

## Coding standards
- Write clean, readable code
- Add comments where necessary
- Follow existing patterns
- Handle errors properly
- Write tests for new features

## Git workflow
- Create a feature branch from main
- Write descriptive commit messages
- Open a pull request for review

Gần như toàn bộ phần này agent tự đọc được. Cây thư mục là kết quả của một lệnh ls. Danh sách dependency là package.json. Phần kiến trúc là thứ agent nhìn ra sau khi mở hai file. Phần "coding standards" không chứa thông tin nào cả. Chỉ có mục lệnh là đáng giữ, và nó còn thiếu đúng thứ quan trọng: npm test cần Postgres chạy trước.

Cùng file đó sau khi cắt:

# shop-api

## Commands
- Test: `docker compose up -d db && npm test` (Jest fails with ECONNREFUSED if db is not up)
- One test file: `npx jest tests/orders.test.ts`
- Lint before commit: `npm run lint`. CI rejects warnings.

## Rules
- Never edit files in `prisma/migrations/`. Create a new migration with `npx prisma migrate dev --name <name>`.
- Prices are integers in cents. Never use float for money.
- `src/routes/` must not import from `src/db/`. Go through a service.

## Gotchas
- `.env.example` points at staging. Copy to `.env` and set `DATABASE_URL` to localhost first.
- `npm run build` runs `prisma generate`. Run it after any schema change or the types are stale.

Từ 42 dòng còn 15 dòng, và file sau chứa nhiều thông tin hữu ích hơn file trước. Mọi dòng còn lại đều là thứ agent sẽ làm sai nếu không được bảo. Số dòng cụ thể không quan trọng, nguyên tắc mới quan trọng: file càng ngắn thì mỗi dòng càng có trọng lượng.

Chuyển quy trình nhiều bước sang skill

Một CLAUDE.md dài thường chứa vài "công thức": cách phát hành phiên bản mới, hay cách chạy bộ test end-to-end với đúng biến môi trường. Những quy trình này chỉ cần khi làm đúng việc đó, nhưng nằm trong CLAUDE.md thì được nạp ở mọi phiên, kể cả phiên chỉ sửa một lỗi chính tả.

Đó là việc của skill. Một skill là một thư mục chứa SKILL.md, chỉ được nạp khi bạn gọi nó hoặc khi agent thấy nó liên quan đến yêu cầu. Chuyển mục "Release process" sang .claude/skills/release/SKILL.md, và CLAUDE.md chỉ còn một dòng: "Phát hành phiên bản: dùng skill release." Bài agent skills là gì và khi nào nên dùng giải thích cấu trúc thư mục và cách agent quyết định nạp một skill.

Tách theo thư mục: CLAUDE.md lồng nhau và .claude/rules/

Trong monorepo, phần lớn nội dung CLAUDE.md ở gốc chỉ đúng với một gói. Quy ước React không giúp gì khi agent đang sửa worker viết bằng Go. Claude Code xử lý việc này theo hai cách, cả hai đều được ghi trong trang tài liệu đã nêu.

Cách thứ nhất là CLAUDE.md lồng nhau. File ở thư mục con không được nạp lúc khởi động, mà chỉ được đưa vào ngữ cảnh khi agent đọc file trong thư mục đó. Đặt apps/web/CLAUDE.md chứa quy ước frontend, services/worker/CLAUDE.md chứa quy ước Go, và file gốc chỉ giữ những gì đúng cho cả repo. Bài cách tổ chức file hướng dẫn lồng nhau cho monorepo đi sâu vào bố cục này.

Cách thứ hai là thư mục .claude/rules/. Mỗi file .md trong đó là một chủ đề, và có thể giới hạn theo đường dẫn bằng frontmatter:

---
paths:
  - "src/api/**/*.ts"
---

# API rules
- Every handler validates input with a zod schema from src/schemas/
- Return errors through AppError, never a raw throw

Rule có paths chỉ được nạp khi agent đọc file khớp mẫu. Rule không có paths được nạp ở mọi phiên, giống CLAUDE.md, nên tách file mà không thêm paths thì chỉ gọn về mặt tổ chức chứ không tiết kiệm ngữ cảnh.

Import bằng @path: gọn file, không gọn ngữ cảnh

CLAUDE.md có thể nhúng file khác bằng cú pháp @path/to/file. Đường dẫn tương đối tính từ file chứa dòng import, không phải từ thư mục làm việc. File được import có thể import tiếp, tối đa bốn cấp. Cú pháp này bị bỏ qua khi nằm trong dấu backtick hoặc trong khối code, nên muốn nhắc tới một đường dẫn mà không import, hãy bọc nó trong backtick.

See @README for the project overview.
- Git workflow: @docs/git-instructions.md

Điểm cần nói rõ, vì nhiều người hiểu nhầm: file import được mở rộng và nạp cùng lúc với CLAUDE.md khi khởi động. Tài liệu ghi thẳng rằng tách nội dung sang import giúp tổ chức chứ không giảm ngữ cảnh. Nếu mục tiêu là bớt token mỗi lượt, import không phải công cụ đúng. Dùng nó khi bạn muốn CLAUDE.md dễ đọc hơn với con người, hoặc khi cần dùng chung một file với công cụ khác: một CLAUDE.md chỉ chứa dòng @AGENTS.md là cách chính thức để Claude Code và các agent khác đọc cùng một bộ hướng dẫn.

Sở thích cá nhân để ở file cấp người dùng

"Trả lời bằng tiếng Việt" và "luôn dùng pnpm thay vì npm" là sở thích của bạn, không phải quy ước của dự án. Đưa vào CLAUDE.md của repo thì cả team phải chịu, và file repo lại dài thêm. Claude Code có ba chỗ cho loại nội dung này:

  • ~/.claude/CLAUDE.md: áp dụng cho mọi dự án trên máy bạn.
  • ~/.claude/rules/: như trên, nhưng tách theo chủ đề.
  • ./CLAUDE.local.md ở gốc dự án: chỉ cho dự án này, chỉ cho bạn. Thêm vào .gitignore.

Mở /memory trong một phiên để thấy danh sách các file này và tạo file còn thiếu ngay từ đó.

Kiểm tra sau khi cắt

Cắt xong, mở một phiên mới và chạy /context. Mục "Memory files" liệt kê đúng những file đang được nạp, và nếu CLAUDE.md không xuất hiện ở đó thì agent không hề thấy nó, dù bạn viết hay đến đâu. Cùng màn hình đó cho biết ngữ cảnh khởi động đang chiếm bao nhiêu, và bài quản lý cửa sổ ngữ cảnh trong Claude Code giải thích cách đọc các con số này.

Từ Claude Code v2.1.206, /doctor có thêm bước đề xuất cắt CLAUDE.md: nó chỉ ra nội dung agent tự suy ra được (cây thư mục, danh sách dependency, mô tả kiến trúc, lịch sử dự án) và giữ lại phần agent không thể tự biết, ví dụ bẫy đã gặp hoặc quy ước khác với mặc định. Đó chính là quy tắc trong bài này, chạy tự động, nên hãy dùng nó làm vòng kiểm tra cuối.

Một mẹo nhỏ cho ghi chú dành cho người: comment HTML dạng <!-- ghi chú --> trong CLAUDE.md bị loại bỏ trước khi đưa vào ngữ cảnh, nên ghi chú cho đồng đội ở đó không tốn token.

Toàn bộ logic trên áp dụng nguyên vẹn cho AGENTS.md của các agent khác và .github/copilot-instructions.md của Copilot: cùng một file được gửi lại mỗi lượt, cùng một cách chọn giữ và bỏ.

FAQ

/init sinh ra CLAUDE.md quá dài, có nên xóa hết viết lại không?

Không cần xóa hết. Giữ mục lệnh (build, test, lint, chạy), sửa lại cho đúng cú pháp dự án, rồi xóa phần mô tả cấu trúc, dependency, kiến trúc và lịch sử dự án. Thêm những điều cấm và bẫy mà /init không thể biết. Nếu chạy /init lần nữa khi file đã tồn tại, nó đề xuất cải tiến thay vì ghi đè.

CLAUDE.md nên dài bao nhiêu dòng?

Tài liệu Claude Code (tháng 9/2026) khuyên dưới 200 dòng mỗi file, vì file dài hơn tốn ngữ cảnh và giảm mức tuân thủ. Số này là mức trần. Một file 20 dòng toàn quy tắc thật thường tốt hơn một file 150 dòng.

Dùng @import để tách CLAUDE.md có giảm token không?

Không. File import được nạp cùng CLAUDE.md lúc khởi động, nên tổng ngữ cảnh không đổi. Muốn nội dung chỉ nạp khi cần, dùng CLAUDE.md trong thư mục con hoặc rule có paths trong .claude/rules/. Với quy trình nhiều bước, dùng skill.

Làm sao biết CLAUDE.md đã được nạp?

Chạy /context trong phiên và tìm file dưới mục "Memory files". Không thấy tên file ở đó nghĩa là agent không đọc nó. Kiểm tra vị trí file: ./CLAUDE.md, ./.claude/CLAUDE.md, ./CLAUDE.local.md hoặc ~/.claude/CLAUDE.md.

Cắt rồi mà agent vẫn không làm theo một quy tắc, tại sao?

Kiểm tra xem hai file có mâu thuẫn nhau không, ví dụ file gốc nói dùng npm còn file thư mục con nói dùng pnpm; khi đó model chọn tùy ý. Viết quy tắc cụ thể hơn: "chạy npm run lint trước khi commit" thay vì "kiểm tra code". Với việc bắt buộc phải xảy ra tại một thời điểm cố định, dùng hook thay vì CLAUDE.md, vì hook chạy bất kể model quyết định gì.

#claude-code#claude-md#agent-instructions#context#tokens