121 lines
9.9 KiB
Markdown
121 lines
9.9 KiB
Markdown
# Hướng dẫn viết & maintain các file AGENTS.md
|
||
|
||
`AGENTS.md` là **bộ quy ước, thông tin, business logic ngắn gọn** mà AI/Tools (như Claude Code, Codex, Cursor, Antigravity, ...) nạp vào context khi làm việc. Nó quyết định AI/tools hiểu dự án đến đâu và là nguồn rule chính cho `/code-review` (hoặc các hàm tương tự). Nguyên tắc số một: đây là **bộ luật, không phải tài liệu** — mỗi dòng thừa làm loãng tín hiệu và khiến AI dễ lạc đề.
|
||
|
||
---
|
||
|
||
## Mục lục
|
||
1. [Ba loại CLAUDE.md — đặt ở đâu, dùng cho gì](#1-ba-loai-claudemd)
|
||
2. [Phân cấp & scope](#2-phan-cap--scope)
|
||
3. [Cấu trúc chuẩn (8 phần)](#3-cau-truc-chuan-8-phan)
|
||
4. [Cạm bẫy: khi .md phản tác dụng (nhất là model yếu)](#4-cam-bay)
|
||
5. [Tự động cập nhật (ít sửa tay)](#5-tu-dong-cap-nhat)
|
||
6. [Cập nhật thủ công](#6-cap-nhat-thu-cong)
|
||
|
||
---
|
||
|
||
## 1. Ba loại CLAUDE.md
|
||
|
||
| Loại | Vị trí | Phạm vi | Theo git? |
|
||
|------|--------|---------|-----------|
|
||
| **Cá nhân (global)** | Nằm trong thư mục của tools như `~/.claude/CLAUDE.md` hoặc `.cursor/rules/*.mdc` | Mọi dự án trên máy bạn | Không |
|
||
| **Dự án (root)** | `./CLAUDE.md` hoặc `AGENTS.md`, ... (nằm ở folder root repo) | Cả dự án đó | Có (cả team thấy và sử dụng chung được) |
|
||
| **Thư mục con** | `<module>/*.md` | Chỉ code trong thư mục đó | Có |
|
||
|
||
### a) Cá nhân — `~/.claude/CLAUDE.md` (tương tự ở folder khác cho các tools khác)
|
||
* **Dùng cho:** phong cách & nguyên tắc làm việc của *riêng bạn*, áp cho mọi dự án (ví dụ: nguyên tắc Karpathy, "ưu tiên dùng skill", "lập kế hoạch & hỏi trước khi code").
|
||
* **KHÔNG để:** lệnh build/test hay business rule riêng của một dự án — vì nó áp cho tất cả.
|
||
* **Lưu ý:** chỉ tồn tại trên máy bạn, không đi theo repo nên đồng đội không thấy.
|
||
|
||
### b) Dự án — `./CLAUDE.md` ở gốc repo (tương tự ở folder khác cho các tools khác)
|
||
* **Dùng cho:** mọi thứ thuộc về dự án — tổng quan, lệnh build/test/lint, quy ước, **business rules**, nên làm gì và không được làm gì.
|
||
* **Đặt ở gốc repo** (không phải trong `.claude/`), được commit nên cả team clone về là có.
|
||
* Đây là vị trí **chắc chắn được nạp** và quan trọng nhất cho chất lượng `/code-review`.
|
||
|
||
### c) Thư mục con — `<module>/CLAUDE.md` (tương tự ở folder khác cho các tools khác)
|
||
* **Dùng cho:** rule chỉ dùng cho một module cụ thể (ví dụ `src/payment/CLAUDE.md`: rule về idempotency, xử lý refund).
|
||
* **Vì sao quan trọng:** `/code-review` chỉ áp rule có **cùng path hoặc thư mục cha** của file đang xét. Đặt rule đúng chỗ → review đúng trọng tâm, không lôi rule chỗ khác vào.
|
||
|
||
> Các file được **cộng dồn**: khi làm trong một thư mục con, ví dụ như: Claude sẽ nạp đồng thời CLAUDE.md cá nhân + gốc dự án + thư mục con.
|
||
|
||
---
|
||
|
||
## 2. Phân cấp & scope
|
||
|
||
* **Rule chung** → gốc repo (`./AGENTS.md`).
|
||
* **Rule riêng module** → `<module>/AGENTS.md`. Đừng nhồi hết vào root.
|
||
* **Rule cá nhân, mọi dự án** → `~/.claude/CLAUDE.md` hoặc `.cursor/rules/*.mdc` hoặc tương tự với các tools khác.
|
||
* `/code-review` xét rule theo **scope phân cấp** — đặt sai chỗ thì hoặc bị bỏ qua, hoặc áp nhầm sang code không liên quan.
|
||
|
||
---
|
||
|
||
## 3. Cấu trúc chuẩn (8 phần)
|
||
|
||
Phần 1, 2, 4, 5, 6 là cốt lõi; 3, 7 tùy dự án; 8 tự lớn theo thời gian. (File **cá nhân** chủ yếu dùng phần 4 + 6; file **dự án** dùng đủ; file **thư mục con** chỉ phần thông tin liên quan về module.)
|
||
|
||
* **[1] Tổng quan dự án** **(bắt buộc):** tên, mô tả ngắn, tech stack, env. 3–5 dòng.
|
||
* **[2] Lệnh hay dùng** **(bắt buộc):** build / test / lint / dev / deploy — để AI chạy đúng thay vì đoán.
|
||
* **[3] Cấu trúc thư mục** *(tùy chọn):* chỉ ghi thư mục dễ nhầm (ví dụ: logic ở `services/`, không ở `api/`).
|
||
* **[4] Quy ước code** **(bắt buộc):** naming, pattern, error handling — những rule linter không bắt được.
|
||
* **[5] Business rules** **(bắt buộc):** logic nghiệp vụ AI không thể tự đoán (ví dụ: không cancel order đã "shipped"). **Quan trọng nhất** — viết dạng **ràng buộc/cấm**, không phải mô tả (xem §4).
|
||
* **[6] Do / Don't** **(bắt buộc):** dạng cấm rõ ràng, ngắn, dứt khoát (ví dụ: KHÔNG commit `.env`).
|
||
* **[7] References** *(tùy chọn):* import file ngoài bằng `@[...].md` để giữ file chính gọn.
|
||
* **[8] Learned patterns** *(tự cập nhật):* phần Claude tự ghi sau mỗi phiên, kèm ngày.
|
||
|
||
> Mẹo giữ gọn: phần dài thì tách ra file riêng rồi `@import` (ví dụ `@KarpathyCodeGuidelines.md`). Dùng import cho cả file cá nhân lẫn dự án.
|
||
|
||
> Thứ tự viết lần đầu: làm 1, 2, 6 trước (~30 phút), rồi bổ sung 4, 5 dần theo lúc thấy AI làm sai. Không cần hoàn hảo ngay.
|
||
|
||
---
|
||
<a id="4-cam-bay"></a>
|
||
## 4. Cạm bẫy: khi .md phản tác dụng (nhất là model yếu)
|
||
|
||
Bài học thực tế: `/init` và model tự sinh file **mô tả CÁI ĐANG CÓ**, không phải **RÀNG BUỘC phải giữ**. Đó là lý do file tự sinh hay phản tác dụng — càng rõ với model yếu (minimax-m3, ...).
|
||
|
||
**Vì sao ngược:** model yếu đọc một *fact* như "logic mã hóa userId lặp ở 3 template + `PagesController`" thành **lời mời refactor** → tự gộp/xóa code nhạy cảm không ai yêu cầu. (Case thật repo này: m3 xóa cả 2 block mã hóa AES trùng trong `PagesController` chỉ vì file .md "tả" chúng trùng nhau.)
|
||
|
||
**Nguyên tắc: mô tả → ràng buộc.** Mỗi dòng phải là cái model KHÔNG đọc code ra được: intent, invariant, gotcha, cấm. Fact thuần (model tự đọc được) = nhiễu → xóa.
|
||
|
||
| ❌ Mô tả (fact — model tự đọc được) | ✅ Ràng buộc + ý đồ (đáng giữ) |
|
||
|---|---|
|
||
| "`canAccessAnniCoupon()` join `anni_coupon_register_info`" | "Whitelist anniversary CHỈ quyết ở `canAccessAnniCoupon()`. KHÔNG hardcode danh sách chỗ khác." |
|
||
| "Mã hóa userId lặp ở 3 template + controller" | "3 block mã hóa userId là CỐ Ý (mỗi surface khác param). KHÔNG gộp/xóa trừ khi task yêu cầu." |
|
||
| "`LotteryService` dùng `getUserIndex() % ratioCycle`" | "Lottery deterministic CÓ CHỦ ĐÍCH, KHÔNG phải random. Đừng 'sửa' thành `rand()`." |
|
||
|
||
**Viết cho model yếu:**
|
||
- Câu **cấm mệnh lệnh** (KHÔNG / CHỈ / PHẢI), không phải câu tả. Model yếu làm theo lệnh, không tự suy ý đồ.
|
||
- Mỗi gotcha kèm **hậu quả** ("...nếu không, request bị Gateway chặn trước khi tới action").
|
||
- "Trông như bug nhưng cố ý" → nói thẳng + lý do. Không nói → model sẽ "sửa" cho gãy.
|
||
|
||
**Checklist trước khi commit mỗi file .md** — mỗi dòng tự hỏi:
|
||
1. Model đọc code ra được dòng này không? → Được thì **xóa** (nhiễu).
|
||
2. Có phải invariant / intent / gotcha / cấm không? → Không thì **xóa**.
|
||
3. Đặt đúng scope chưa (rule module ↔ nằm trong file của module đó)?
|
||
|
||
**`/init` = bản nháp, KHÔNG phải bản cuối.** Bắt buộc 1 lượt người sửa: xóa fact, đổi "tả" thành "cấm", thêm ý đồ. Commit thẳng output `/init` chính là nguồn "hiệu quả ngược".
|
||
|
||
---
|
||
**[Claude Code]**
|
||
<a id="5-tu-dong-cap-nhat"></a>
|
||
## 5. Tự động cập nhật
|
||
|
||
Tools AI **không** tự viết lại các file AGENTS.md hoàn toàn — và đó là điều tốt, vì file tự phình liên tục thì sẽ nhiều rác --> sẽ làm hỏng `/code-review`. Nếu chúng ta muốn muốn cập nhật các file .md mà *gần như không phải sửa tay* thì sẽ có một số cách:
|
||
|
||
* **Dùng `#` (ít ảnh hưởng nhất):** gõ tin nhắn bắt đầu bằng `#`, ví dụ `# luôn dùng dayjs thay vì moment` → Claude tự ghi vào memory và hỏi bỏ vào file nào (cá nhân / dự án / thư mục con).
|
||
* **Lệnh `/update-memory` (tự tạo):** tạo `.claude/commands/update-memory.md` yêu cầu Claude rà `git log` + phiên gần đây, đề xuất rule high-signal cho bạn duyệt. Chạy cuối ngày hoặc sau mỗi feature.
|
||
* **Hook (tùy chọn):** gắn hook sự kiện `Stop` để *nhắc* cập nhật. ⚠️ Đừng để hook tự ghi không qua duyệt — dễ tạo vòng lặp và làm file rác.
|
||
|
||
---
|
||
|
||
<a id="6-cap-nhat-thu-cong"></a>
|
||
## 6. Cập nhật thủ công
|
||
|
||
* **`/init`:** quét codebase sinh CLAUDE.md nháp. Nếu đã có file, nó **bổ sung chứ không ghi đè**, nhưng có thể sắp xếp lại — nên `git commit` trước khi chạy để dễ rollback. Hợp cho lúc khởi tạo / làm mới toàn diện. ⚠️ Output là **nháp** — bắt buộc sửa tay theo §4 trước khi commit.
|
||
* **`/memory`:** liệt kê các file memory và mở ra sửa trực tiếp; dùng khi muốn dọn/sắp xếp lại.
|
||
* **Sửa file như thường:** CLAUDE.md chỉ là markdown — mở editor sửa, lưu, lần sau Claude tự đọc lại (không cần restart).
|
||
* **Giữ gọn:** thêm rule mới thì xóa rule lỗi thời; mỗi rule một dòng; phần dài thì tách file rồi `@import`.
|
||
|
||
> Quy trình khuyên dùng: `/init` (1 lần) → dùng `#` bắt rule trong lúc làm → chạy `/update-memory` định kỳ & duyệt.
|
||
|
||
> Lưu ý về session dài: context đầy dần sẽ làm rule bị "loãng" và Claude dễ quên — chia nhỏ session (`/clear` sau mỗi task là tốt nhất, nếu vẫn muốn giữ context hiện tại cho task tiếp theo thì hãy `/compact` nhé) và giữ file và context ngắn giúp rule được ưu tiên hơn.
|