arrow_backHướng dẫn
Vibe Coding

Cách tổ chức Skills cho project lớn

Mô hình 4 tầng (global/domain/module/task), CLAUDE.md đa cấp, quy tắc đặt tên, xử lý xung đột skill — đúc kết từ codebase monorepo 80k LOC.

calendar_today11/05/2026·schedule5 phút đọc

> Khi project vượt mốc 50.000 dòng code, cách bạn tổ chức skills sẽ quyết định AI giúp được bạn hay phá hỏng mọi thứ. Bài này chia sẻ kinh nghiệm thực chiến: chia tầng skill, đặt tên file, viết CLAUDE.md ở nhiều cấp, và xử lý xung đột quy ước giữa các module — đúc kết từ codebase QNifyTech (~80k LOC, monorepo Express + Next.js).

Mục lục nhanh

  1. Vấn đề khi skill "dồn cục"
  2. Mô hình 4 tầng: global → domain → module → task
  3. Cấu trúc thư mục skill/ chuẩn cho monorepo
  4. CLAUDE.md đa cấp: gốc, package, feature
  5. Quy tắc đặt tên & nguyên tắc "1 skill = 1 trách nhiệm"
  6. Cross-cutting concerns: auth, logging, error, i18n
  7. Khi 2 skill mâu thuẫn — ai thắng?
  8. Versioning skill khi codebase đổi quy ước
  9. Checklist audit định kỳ
  10. FAQ

1. Vấn đề khi skill "dồn cục"

Bạn bắt đầu nhỏ với 5-7 file skill: auth.md, database.md, frontend-impl.md... Mọi thứ ổn cho đến khi:

  • Codebase có 3 service riêng (web, mobile, admin) dùng chung 1 database nhưng quy ước UI khác nhau
  • Module payments/ cần override quy ước REST mặc định vì phải tuân thủ idempotency của VNPay
  • Team mới vào không biết file nào áp dụng ở đâu — AI lúc thì viết theo frontend-impl.md, lúc lại theo mobile.md
  • Skill database.md 800 dòng — AI đọc xong quên phần đầu khi áp dụng phần cuối

Triệu chứng cụ thể bạn sẽ thấy:

Triệu chứngNguyên nhân gốc
AI viết code không khớp convention của moduleSkill quá chung, không có override cấp module
AI "quên" skill giữa session dài1 file skill quá dài, vượt khả năng giữ trong context active
Cùng 1 task nhưng mỗi lần AI làm 1 kiểuKhông có anchor (CLAUDE.md cấp dưới) để cố định lựa chọn
Sửa skill chung làm vỡ module khácSkill chia theo "kỹ năng" thay vì theo "ranh giới ảnh hưởng"

2. Mô hình 4 tầng: global → domain → module → task

Tôi đề xuất chia skill thành 4 tầng, mỗi tầng có phạm vi ảnh hưởng và tần suất thay đổi khác nhau:

┌─────────────────────────────────────────────────────────────┐

│ TẦNG 1 — GLOBAL (áp dụng toàn project, hiếm khi đổi) │

│ • coding-style.md • git-workflow.md • naming.md │

│ • security-baseline.md • code-review.md │

├─────────────────────────────────────────────────────────────┤

│ TẦNG 2 — DOMAIN (theo lĩnh vực kỹ thuật) │

│ • backend-api.md • frontend-web.md • mobile.md │

│ • database.md • devops.md • testing.md │

├─────────────────────────────────────────────────────────────┤

│ TẦNG 3 — MODULE (theo ranh giới nghiệp vụ) │

│ • modules/auth.md • modules/payment.md │

│ • modules/license.md • modules/affiliate.md │

├─────────────────────────────────────────────────────────────┤

│ TẦNG 4 — TASK (việc lặp lại nhiều lần) │

│ • tasks/add-api-endpoint.md • tasks/migrate-db.md │

│ • tasks/release.md • tasks/incident-response.md │

└─────────────────────────────────────────────────────────────┘

Nguyên tắc đọc: Tầng dưới override tầng trên. Khi AI làm task trong modules/payment/, nó đọc theo thứ tự: Global → Domain (backend-api) → Module (payment) → Task (nếu có). Module thắng nếu có xung đột.

Nguyên tắc viết:

  • Tầng 1 (Global): chỉ ghi những thứ KHÔNG BAO GIỜ ngoại lệ. Vd "không commit secret", "luôn typecheck trước khi push".
  • Tầng 2 (Domain): mặc định cho 80% trường hợp. Có thể bị override ở tầng 3.
  • Tầng 3 (Module): ghi rõ "khác với mặc định ở chỗ nào và tại sao".
  • Tầng 4 (Task): quy trình bước-bước cho việc lặp lại — copy/paste vẫn đúng.

3. Cấu trúc thư mục skill/ chuẩn cho monorepo

Với monorepo có nhiều package, đây là layout đã chứng minh hoạt động tốt:

my-project/

├── CLAUDE.md ← entry point, trỏ vào skill/

├── skill/

│ ├── README.md ← index của toàn bộ skill

│ ├── GUIDE.md ← hướng dẫn AI cách CHỌN skill

│ │

│ ├── global/

│ │ ├── coding-style.md

│ │ ├── git-workflow.md

│ │ ├── naming.md

│ │ ├── security-baseline.md

│ │ └── code-review.md

│ │

│ ├── domain/

│ │ ├── backend-api.md

│ │ ├── frontend-web.md

│ │ ├── mobile.md

│ │ ├── database.md

│ │ ├── devops.md

│ │ └── testing.md

│ │

│ ├── modules/

│ │ ├── auth.md

│ │ ├── payment.md

│ │ ├── license.md

│ │ └── affiliate.md

│ │

│ ├── tasks/

│ │ ├── add-api-endpoint.md

│ │ ├── migrate-db.md

│ │ ├── release.md

│ │ └── incident-response.md

│ │

│ └── _archive/ ← skill cũ đã thay thế, giữ lại để truy nguyên

│ └── 2025-03-old-payment.md

├── packages/

│ ├── backend/

│ │ └── CLAUDE.md ← override cấp package

│ ├── web/

│ │ └── CLAUDE.md

│ └── mobile/

│ └── CLAUDE.md

└── apps/

└── admin/

└── CLAUDE.md

Tại sao tách _archive/? Khi quy ước đổi (vd chuyển từ Redux sang Zustand), đừng xoá skill cũ — chuyển vào archive với ngày. Lý do: PR cũ vẫn cần review theo skill cũ, và bạn có thể truy nguyên "trước đây ta quyết định thế nào".


4. CLAUDE.md đa cấp: gốc, package, feature

CLAUDE.md cấp gốc không nên chứa toàn bộ quy ước. Nó là bản đồ dẫn AI tới đúng file skill.

CLAUDE.md gốc — template

```markdown

Project: <tên project>

Bắt đầu mọi task

  1. Đọc skill/GUIDE.md để hiểu cách chọn skill phù hợp với task
  2. Đọc các file skill được chỉ định trong GUIDE
  3. Nếu task ở trong packages/<x>/, đọc thêm packages/<x>/CLAUDE.md

Stack tổng quan

  • Backend: Node.js + Express + Prisma + Postgres
  • Frontend web: Next.js 15 (App Router)
  • Mobile: Expo / React Native
  • Deploy: Render (BE) + Vercel (FE)

Ranh giới module (KHÔNG ĐƯỢC CHÉO)

  • packages/backend/src/modules/payment/ ↔ chỉ team payment sửa
  • packages/backend/src/modules/auth/ ↔ cần security review trước khi merge
  • packages/web/src/app/(admin)/ ↔ chỉ admin role mới truy cập

Khi không chắc — HỎI, đừng đoán

Phase 1 của mọi skill: hỏi user trước khi code. Vi phạm là lỗi nghiêm trọng.

CLAUDE.md cấp package — chỉ override

packages/web — Next.js App

Đè quy ước global tại đây

  • Sử dụng TanStack Query thay vì SWR (skill/domain/frontend-web.md có giải thích)
  • Mọi route trong app/(site)/ phải có metadata động + JSON-LD
  • Component dùng shadcn/ui, KHÔNG cài thêm Material UI

File quan trọng

  • src/lib/api.ts — chỉ dùng client này để gọi BE, đừng dùng fetch trực tiếp
  • src/app/(site)/layout.tsx — đã có SEO defaults, đừng override trừ khi cần

CLAUDE.md cấp feature — khi cần

Một số feature có quy ước cực đặc biệt — nên có CLAUDE.md riêng:

packages/backend/src/modules/payment/

├── CLAUDE.md ← quy ước riêng cho payment

├── webhooks/

├── reconciliation/

└── ...

  1. Quy tắc đặt tên & nguyên tắc "1 skill = 1 trách nhiệm" {#dat-ten}

Đặt tên file

Tốt Tệ

auth.md authentication-and-authorization.md

payment-vnpay.md vnpay-integration-guide-final-v2.md

tasks/add-api-endpoint.md tasks/how-to-add-new-route.md

Quy tắc:

Dùng kebab-case, ngắn gọn

Tầng module: prefix theo domain nếu có ambiguity — payment-vnpay.md thay vì vnpay.md

Tầng task: bắt đầu bằng động từ — add-, migrate-, deploy-, debug-

Không dùng version trong tên (v1, v2, final) — dùng git history hoặc _archive/

Mỗi skill phải có header chuẩn

Để AI biết nhanh skill này dùng làm gì:


scope: module # global | domain | module | task

applies-to: packages/backend//payment/

overrides: domain/backend-api.md

last-reviewed: 2026-04-10


Payment module

Khi nào đọc file này

  • Khi viết code trong packages/backend/src/modules/payment/
  • Khi tích hợp gateway mới (VNPay, MoMo, PayOS, Stripe)
  • Khi sửa webhook handler

Tóm tắt 3 dòng

  1. Mọi webhook PHẢI verify chữ ký + idempotent theo gateway event ID
  2. State machine: pending → awaiting_payment → paid | failed | expired
  3. Reconciliation job chạy mỗi 15 phút để bắt giao dịch lạc

Chi tiết

...

Lợi ích: AI quét header ⇒ biết có cần đọc tiếp không, không tốn context cho skill không liên quan.

"1 skill = 1 trách nhiệm"

Nếu skill của bạn dài hơn 400 dòng, gần như chắc chắn nó đang ôm 2-3 trách nhiệm. Tách ra:

Trước (1 file 900 dòng) Sau (4 file 200-300 dòng)

payment.md payment-overview.md

payment-vnpay.md

payment-momo.md

payment-reconciliation.md

Sau đó payment-overview.md chỉ làm 1 việc: trỏ vào file con phù hợp.

  1. Cross-cutting concerns: auth, logging, error, i18n {#cross-cutting}

Có những thứ xuyên suốt mọi module — đừng nhồi vào skill của module:

Auth & permissions: đặt ở global/security-baseline.md + modules/auth.md

Logging: đặt ở global/coding-style.md (format) + domain/devops.md (vận hành)

Error handling: đặt ở global/code-review.md (nguyên tắc) + domain/backend-api.md (response envelope)

i18n: nếu có, tách domain/i18n.md riêng

Quy tắc: Nếu một quy ước áp dụng cho >= 3 module, nó thuộc tầng Domain hoặc Global, không phải Module.

Khi viết skill module, trích dẫn skill cross-cutting thay vì copy:

Validation

Tuân thủ global/security-baseline.md mục "Input validation".

Bổ sung riêng cho module này:

  • Số tiền PHẢI là integer (đơn vị VND, không có thập phân)
  • Mã đơn hàng tối đa 50 ký tự ASCII
  1. Khi 2 skill mâu thuẫn — ai thắng? {#mau-thuan}

Đây là tình huống bạn sẽ gặp chắc chắn. Ví dụ:

domain/backend-api.md nói: "Response envelope là { data, meta }"

modules/legacy-license.md nói: "Phải giữ format cũ { license, ok } để không vỡ client v1"

Quy tắc giải quyết, theo thứ tự ưu tiên

Tầng thấp hơn thắng (module > domain > global). Đây là quy tắc mặc định.

Skill ghi rõ overrides: trong header — đó là tuyên bố override chính thức.

Khi cả 2 skill cùng tầng mâu thuẫn, AI PHẢI dừng lại và hỏi user.

Quy ước an toàn (security) không bao giờ bị override — kể cả từ module. Nếu cần, phải có ngoại lệ có document riêng + ngày hết hạn.

Bảo AI áp dụng quy tắc này

Trong CLAUDE.md gốc, thêm:

Khi skill mâu thuẫn

Thứ tự ưu tiên: task > module > domain > global.

Trừ 1 ngoại lệ: quy ước security trong global/security-baseline.md

KHÔNG được override. Nếu phát hiện module cần làm khác, dừng và hỏi user.

  1. Versioning skill khi codebase đổi quy ước {#versioning}

Project lớn sẽ đổi convention theo thời gian. Đừng "edit in place" thầm lặng — sẽ làm vỡ PR đang mở và làm AI confused khi review code cũ.

Quy trình đổi 1 skill

Tạo nhánh — đừng đổi trên main trực tiếp

Đánh dấu deprecated ở đầu file cũ:

> ⚠️ DEPRECATED từ 2026-05-01. Xem domain/frontend-web-v2.md.

> File này giữ để review PR mở trước ngày đổi.

Tạo file mới với hậu tố hoặc tên mới

Cập nhật skill/GUIDE.md để trỏ vào file mới

Sau 30 ngày không có PR cũ nào tham chiếu, chuyển file cũ vào _archive/

Ghi changelog ở cuối mỗi skill quan trọng

Changelog

  • 2026-05-01: Đổi state management Redux → Zustand. Migration guide ở...
  • 2026-02-15: Bỏ class component, full function + hooks
  • 2025-11-03: Khởi tạo

AI đọc đoạn này hiểu đâu là quy ước hiện hành, không nhầm với code cũ trong repo.

  1. Checklist audit định kỳ {#checklist}

Mỗi quý làm 1 lần để skill không "thối":

Mọi skill có last-reviewed: cách đây ≤ 6 tháng không?

File nào dài > 400 dòng — có thể tách không?

File nào không có trong skill/GUIDE.md — còn dùng không hay quên xoá?

Quy ước trong skill có khớp với code thực tế trên main không? (chạy 1 vòng đối chiếu)

CLAUDE.md cấp package có còn đúng sau các refactor không?

_archive/ có file nào không còn PR liên quan — có thể xoá hẳn?

Có quy ước mới được lặp lại trong PR review nhiều lần — đã viết thành skill chưa?

AI có hay làm sai 1 chỗ cụ thể không — chỗ đó cần skill mới hoặc làm rõ skill cũ?

Audit này bạn có thể nhờ AI làm hộ:

Đọc toàn bộ thư mục skill/ và checklist trong skill-organization.md

mục 9. Báo cáo cho mình: file nào vi phạm, file nào nên gộp, file nào

nên tách. Đề xuất kế hoạch refactor skill trong 1 tuần.

  1. FAQ {#faq}

Project nhỏ (< 5k LOC) có cần 4 tầng không?

Không. Project nhỏ giữ flat — 5-10 file skill trong 1 thư mục là đủ. Bắt đầu tách tầng khi: có >= 3 module nghiệp vụ riêng, hoặc có > 2 developer, hoặc có >= 2 quy ước UI khác nhau.

Có nên auto-generate skill từ code không?

Không nên. Skill là ý định + lý do, code là kết quả. Auto-generate ra file mô tả code hiện tại — AI đọc xong vẫn không hiểu "tại sao chọn cách này thay vì cách kia". Viết tay, ngắn gọn, kèm WHY.

Skill có nên versioning theo git tag không?

Không cần tag riêng. Skill thay đổi cùng code trong cùng PR — git history là đủ. Khi cần truy nguyên "ngày X quy ước là gì", git blame skill/<file>.md vẫn hoạt động.

Khi nào dùng CLAUDE.md, khi nào dùng skill/*.md?

CLAUDE.md: bản đồ + những thứ AI cần đọc ngay khi mở project. Giữ ngắn (< 100 dòng).

skill/*.md: chi tiết quy trình, đọc khi làm task cụ thể.

Quy tắc: nếu AI cần biết để tránh disaster ngay từ giây đầu (vd "module X cấm sửa trực tiếp"), đặt ở CLAUDE.md. Còn lại đặt ở skill/.

AI có đọc hết file skill không hay nó "skim"?

Tuỳ cách bạn ra lệnh. Nếu nói "đọc skill X rồi làm task Y", AI thường đọc đầy đủ. Nếu file quá dài, AI có thể chỉ đọc các phần khớp với query → đó là lý do tách file < 400 dòng và đặt header tóm tắt 3 dòng.

Bao nhiêu skill là quá nhiều?

Kinh nghiệm: > 30 file skill mà chưa có GUIDE.md rõ ràng → AI sẽ confused. Mỗi 10 file skill mới, đầu tư 30 phút cập nhật skill/GUIDE.md (bảng "task X → đọc skill nào").

Team mới vào dự án — cần làm gì?

Cho họ đọc theo thứ tự: CLAUDE.md (gốc) → skill/README.md → skill/GUIDE.md → 2-3 file skill liên quan task đầu tiên của họ. Bộ skill tốt thay được 80% onboarding doc.

Kết

Tổ chức skill cho project lớn là một bài toán information architecture, không phải kỹ thuật. Nguyên tắc tóm lại:

Chia theo ranh giới ảnh hưởng, không theo "loại kỹ năng"

Tầng thấp hơn override tầng cao hơn, trừ security

Mỗi file 1 trách nhiệm, < 400 dòng, có header scope rõ ràng

CLAUDE.md là bản đồ, không phải sách giáo khoa

Audit mỗi quý — skill cũng cần bảo trì như code

Khi đã có bộ skill tốt, AI ngừng đoán mò và bắt đầu hỏi đúng câu. Đó là khoảnh khắc vibe coding scale được lên dự án thật.

Liên kết hữu ích: