Hướng Dẫn Toàn Diện: Claude Code Skills & Hooks
Mục lục
- Bước 0: Thiết Lập Folder .claude (Bắt Buộc)
- Phần 1: Viết Skill Chuẩn
- Phần 2: Tạo Agent (Subagent)
- Phần 3: Hook — Cơ Chế Ép Buộc Tự Động
- Phần 4: File CLAUDE.md — Bộ Nhớ Dài Hạn Của Agent
- Phần 5: Kiến Trúc Kết Hợp Skill + Hook + Agent + CLAUDE.md
Bước 0: Thiết Lập Folder .claude (Bắt Buộc)
⚠️ Đọc phần này trước khi làm bất cứ điều gì khác. Nếu folder .claude không nằm ở root của dự án, toàn bộ skill, hook, command sẽ không hoạt động — Claude Code đơn giản là không thấy chúng.
Kiểm tra nhanh
Mở Claude Code trong dự án, gõ / rồi nhập tên bất kỳ (ví dụ /my-skill). Nếu:
- Hiện ra danh sách commands/skills → folder
.claudeđang hoạt động, bạn có thể bỏ qua phần này. - Trống trơn, không hiện gì → folder
.claudechưa được thiết lập đúng. Làm theo hướng dẫn bên dưới.
Thiết lập
Cách 1 — Nhờ Claude Code tạo (đơn giản nhất):
Mở Claude Code ở root dự án, gõ:
Hãy thiết lập folder .claude ở root project với cấu trúc chuẩn:
- .claude/settings.json (permissions + hooks)
- .claude/skills/ (folder chứa skills)
- .claude/commands/ (folder chứa custom commands)
Claude sẽ tạo đúng cấu trúc cho bạn.
Cách 2 — Tạo thủ công:
# Chạy ở root dự án
mkdir -p .claude/skills
mkdir -p .claude/commands
mkdir -p .claude/hooks
# Tạo file settings rỗng
echo '{}' > .claude/settings.json
Cấu trúc đúng sau khi thiết lập
my-project/ ← Root dự án
├── .claude/ ← PHẢI nằm ở đây, cùng cấp với package.json
│ ├── settings.json ← Config: permissions, hooks
│ ├── settings.local.json ← Config cá nhân (gitignore)
│ ├── skills/ ← Chứa các skill folders
│ ├── commands/ ← Chứa custom slash commands
│ └── hooks/ ← Chứa script files cho hooks
├── CLAUDE.md ← Context dự án (xem Phần 3)
├── package.json
└── src/
Lỗi thường gặp
- Đặt
.claudetrong subfolder (ví dụsrc/.claude/) → không hoạt động. Phải ở root. - Đặt
.claudetrong home directory (~/.claude/) → đây là config user-level (áp dụng mọi project), không phải project-level. Cả hai có thể cùng tồn tại. - Quên tạo subfolder → chỉ có
settings.jsonmà không cóskills/,commands/→ skill và command không có chỗ để đặt.
Sau khi thiết lập xong, gõ lại / để xác nhận Claude Code đã nhận. Rồi tiếp tục đọc các phần bên dưới.
Phần 1: Viết Skill Chuẩn
1.1. Skill là gì?
Skill là các gói mô-đun (module) mở rộng khả năng của Claude Code bằng kiến thức chuyên môn, quy trình, và công cụ. Mỗi skill là một đơn vị knowledge độc lập mà Claude đọc khi cần — không phải lúc nào cũng load, giúp tiết kiệm context window.
Phân biệt với Agent: Skill cung cấp knowledge (biết làm gì), còn Agent định nghĩa persona + hành vi (làm như thế nào, giao tiếp ra sao). Skill có thể được nhiều agent dùng chung.
Lưu ý quan trọng về độ dài: File SKILL.md nên ngắn gọn, xúc tích — khoảng 300 dòng, tối đa 500 dòng để đạt hiệu quả tốt nhất. SKILL.md dưới 200 dòng đạt tỷ lệ tuân thủ instructions trên 92%, vượt 400 dòng giảm xuống 71% (lost-in-the-middle effect). Trong SKILL.md chỉ nên chứa:
- Những lưu ý cực kì quan trọng mà agent phải luôn nhớ
- Hướng dẫn sử dụng, các bước thực thi
- Bảng Quick Reference link về tài liệu chi tiết
Nếu tài liệu quá dài, quá nhiều trường hợp — đặt vào references/ chứ đừng nhét hết vào SKILL.md. SKILL.md chỉ là routing + core instructions.
1.2. Cấu Trúc Thư Mục
Mỗi skill luôn nằm trong một folder riêng mang tên skill, dù đơn giản chỉ có 1 file SKILL.md. Đây là chuẩn thống nhất:
skill-name/
├── SKILL.md ← Bắt buộc. File chính, chứa routing + instructions.
├── references/ ← Tùy chọn. Tài liệu chi tiết, agent đọc khi cần.
│ ├── guide-a.md ← SKILL.md link về đây: "Read references/guide-a.md"
│ └── guide-b.md
├── scripts/ ← Tùy chọn. Code thực thi (Python, Bash, Node...).
│ ├── build.py
│ └── validate.js
└── assets/ ← Tùy chọn. Templates, fonts, images cho output.
├── template.html
└── logo.png
Nguyên tắc: Toàn bộ tài liệu hướng dẫn chi tiết đặt trong references/. File SKILL.md chỉ chứa routing — link về các file reference để agent đọc khi cần, thay vì nhồi hết nội dung vào SKILL.md.
Ví dụ thực tế — skill tạo slide (pptx):
pptx/
├── SKILL.md ← Routing: bảng Quick Reference link về references/
├── references/
│ ├── editing.md ← Hướng dẫn edit template có sẵn
│ └── pptxgenjs.md ← Hướng dẫn tạo slide từ đầu
├── scripts/
│ ├── thumbnail.py ← Xem preview slide
│ └── office/unpack.py ← Giải nén XML
└── assets/
├── default-font.ttf
└── logo.png
Trong SKILL.md, routing trỏ về references:
## Quick Reference
| Task | Guide |
|--------------------|------------------------------------------------------------|
| Read/analyze | `python scripts/thumbnail.py presentation.pptx` |
| Edit template | Read [references/editing.md](references/editing.md) |
| Create from scratch| Read [references/pptxgenjs.md](references/pptxgenjs.md) |
Skill đơn giản (chỉ 1 file) vẫn giữ đúng cấu trúc folder:
my-simple-skill/
└── SKILL.md ← Dù chỉ có 1 file, vẫn nằm trong folder
1.3. Anatomy Của SKILL.md
File SKILL.md gồm 2 phần:
a) YAML Frontmatter (Metadata)
---
name: ten-skill
description: >
Mô tả skill làm gì VÀ khi nào nên trigger.
Đây là cơ chế kích hoạt chính — Claude dựa vào đây
để quyết định có đọc skill hay không.
---
Hai trường bắt buộc:
name: Tên skill (identifier)description: Mô tả chức năng + điều kiện kích hoạt
Viết description hiệu quả:
Claude có xu hướng "undertrigger" — không dùng skill khi nên dùng. Do đó description cần hơi "pushy":
# ❌ Quá chung chung
description: Tạo PDF files
# ✅ Cụ thể và pushy
description: >
Use this skill whenever the user wants to do anything
with PDF files. This includes reading, extracting text/tables,
combining, splitting, rotating, watermarking, filling forms,
encrypting, OCR. If the user mentions a .pdf file or asks
to produce one, use this skill.
1.3. Ví Dụ Skill Hoàn Chỉnh
Cấu trúc folder:
mongorest-validation/
├── SKILL.md
├── references/
│ ├── ajv-keywords.md
│ ├── type-coercion.md
│ └── test-patterns.md
└── scripts/
└── validate-test.js
⚠️ Lưu ý bắt buộc: File SKILL.md phải bắt đầu bằng YAML frontmatter (khối --- ở đầu file) chứa name và description. Nếu thiếu phần này, Claude Code sẽ không nhận diện và không trigger skill.
File SKILL.md hoàn chỉnh (frontmatter + body trong cùng 1 file):
---
name: mongorest-validation
description: >
Use this skill when working on MongoREST validation logic,
AJV custom keywords, schema validation, or input sanitization.
Trigger when editing files in src/core/validation/ or when
the user mentions "validation", "schema", "AJV", or "sanitize".
---
# MongoREST Validation Skill
## Quick Reference
| Task | Action |
|--------------------------|-----------------------------------------------------|
| Add validation rule | Read [references/ajv-keywords.md](references/ajv-keywords.md) |
| Create new schema | Follow Schema Pattern below |
| Debug validation error | Run `node scripts/validate-test.js` |
## Core Principle
Validation layer is SEPARATE from policy layer.
Validation = "is this data well-formed?"
Policy = "is this user allowed to do this?"
Never mix authorization checks into validation schemas.
## Schema Pattern
Every schema must follow this structure:
1. Define with `$id` matching the collection name
2. Use `additionalProperties: false` by default
3. Custom keywords go in `references/ajv-keywords.md`
## When to Read References
- Working with custom AJV keywords → read `references/ajv-keywords.md`
- Handling date/ObjectId transforms → read `references/type-coercion.md`
- Writing tests → read `references/test-patterns.md`
1.4. Kiến Trúc Multi-Skill
Khi project phức tạp, tách thành nhiều skill nhỏ thay vì một skill khổng lồ. Mỗi skill vẫn tuân theo chuẩn cấu trúc folder ở mục 1.2 — có folder riêng và file SKILL.md bên trong. Dùng CLAUDE.md làm routing layer:
project/
├── CLAUDE.md ← Router: chỉ agent đọc skill nào
├── .claude/
│ ├── skills/
│ │ ├── validation/ ← Mỗi skill = 1 folder
│ │ │ ├── SKILL.md ← ~50 dòng routing
│ │ │ └── references/
│ │ │ ├── ajv-keywords.md ← Chi tiết AJV custom keywords
│ │ │ └── type-coercion.md ← Date/ObjectId transforms
│ │ ├── authorization/
│ │ │ ├── SKILL.md
│ │ │ └── references/
│ │ │ ├── rbac-patterns.md
│ │ │ └── policy-schema.md
│ │ ├── external-resources/
│ │ │ ├── SKILL.md
│ │ │ └── references/
│ │ │ └── http-config.md
│ │ └── api-endpoints/
│ │ ├── SKILL.md
│ │ └── references/
│ │ └── crud-patterns.md
│ └── settings.json
└── docs/ ← Deep reference khi cần
└── architecture/
# CLAUDE.md (root) — Routing Layer
## Skills Reference
- Validation logic: see .claude/skills/validation/SKILL.md
- Auth policies: see .claude/skills/authorization/SKILL.md
- API design: see .claude/skills/api-endpoints/SKILL.md
## Task → Skill Mapping
- Khi làm feature CRUD mới: đọc api-endpoints + validation
- Khi sửa permission: đọc authorization
- Khi tích hợp API ngoài: đọc external-resources
1.5. Checklist Viết Skill Tốt
- Mỗi skill nằm trong folder riêng (tên-skill/SKILL.md)
- SKILL.md dưới 500 dòng (lý tưởng 200-300), chỉ chứa routing
- Tài liệu chi tiết tách vào references/, SKILL.md link về
- Description đủ cụ thể và "pushy" để trigger đúng lúc
- Dùng imperative form, giải thích WHY
- Quick Reference table ở đầu file, link về references/
- Có examples/patterns cho các task phổ biến
- Scripts cho task lặp đi lặp lại (đỡ reinvent the wheel)
Phần 2: Tạo Agent (Subagent)
2.1. Tại sao cần Agent, không chỉ Skill?
Skill cung cấp knowledge — nhưng khi dự án có nhiều skill, một agent duy nhất phải tự quyết định dùng skill nào cho task nào. Giống như một người biết quá nhiều thứ nhưng lại khó chọn đúng công cụ lúc cần. Agent giải quyết vấn đề này bằng cách tạo ra các nhân vật chuyên biệt, mỗi nhân vật chỉ biết và chỉ dùng những skill nhất định.
Hai lý do chính cần tạo Agent:
Lý do 1 — Phân vai khi có quá nhiều skill:
Ví dụ trong dự án có 10+ skill: frontend components, styling, testing, API design, validation, authorization... Nếu để 1 agent tổng xử lý hết, nó sẽ khó chọn đúng skill cho đúng lúc. Thay vào đó, tách thành các agent chuyên biệt:
frontend-dev— chỉ dùng skill: react-components, styling, accessibilitytester— chỉ dùng skill: testing-frontend, test-patterns, coverageapi-designer— chỉ dùng skill: api-endpoints, validation, authorization
Khi cần, gọi đúng nhân vật: "Dùng frontend-dev agent để build component này" thay vì để agent tổng tự đoán.
Lý do 2 — Xử lý song song với luồng custom:
Khi cần xử lý lặp lại nhiều task giống nhau (ví dụ convert 800 file text, review 50 PR, migrate 100 schema), Claude Code sẽ tự spawn subagent để chạy song song. Nhưng subagent tự tạo của Claude chỉ có prompt chung chung. Nếu đã định nghĩa agent trước với luồng xử lý custom đúng ý mình, Claude sẽ dùng agent đó thay vì tự nghĩ ra cách làm — kết quả chính xác và nhất quán hơn nhiều.
2.2. Vị Trí Đặt File Agent
Agent là file Markdown đặt trong .claude/agents/:
.claude/
├── agents/ ← Agent files
│ ├── frontend-dev.md
│ ├── tester.md
│ └── api-designer.md
├── skills/ ← Skills (knowledge)
├── hooks/ ← Hook scripts
└── settings.json
Hai scope:
.claude/agents/— project-level, share với team qua git~/.claude/agents/— user-level, dùng cho mọi project
2.3. Cấu Trúc File Agent
Giống skill, agent cũng dùng YAML frontmatter + body. Trong body chỉ cần nêu rõ: nhân vật này có chức năng gì, có những năng lực gì, và liệt kê các trường hợp sử dụng.
---
name: frontend-dev
description: >
Use this agent for building UI components, implementing React pages,
handling state management, styling with Tailwind, and optimizing
frontend performance. Delegate frontend tasks to this agent.
model: sonnet
tools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
---
You are a senior frontend developer specializing in React + TypeScript.
## Capabilities
- Build React functional components with hooks
- Implement responsive layouts with Tailwind CSS
- Handle state management (useState, useReducer, Zustand)
- Write accessible, semantic HTML
- Optimize rendering performance (memo, useMemo, useCallback)
## Skills to Use
- React components: read .claude/skills/react-components/SKILL.md
- Styling patterns: read .claude/skills/styling-tailwind/SKILL.md
- Accessibility: read .claude/skills/a11y/SKILL.md
## Workflow
1. Read the requirement carefully
2. Check existing components in src/components/ before creating new ones
3. Follow project conventions in CLAUDE.md
4. Always include TypeScript types
5. Test with `npm run test:component`
## When to Use
- "Build a user profile card component"
- "Implement the dashboard page layout"
- "Fix the responsive breakpoint on mobile"
- "Optimize the product list rendering"
2.4. Ví Dụ: Agent Cho Batch Processing
Khi cần xử lý hàng loạt, agent custom đảm bảo mỗi subagent chạy đúng luồng:
---
name: file-converter
description: >
Use this agent for batch file conversion tasks. Converts text files,
markdown, or data files between formats following a strict pipeline.
Invoke when processing multiple files with the same transformation.
model: haiku
tools:
- Read
- Write
- Bash
---
You are a file conversion specialist.
## Capabilities
- Convert Markdown → HTML with custom templates
- Convert CSV → JSON with schema validation
- Convert text files with encoding transformation
- Batch rename and restructure files
## Pipeline (follow exactly)
1. Read source file
2. Validate format and encoding
3. Apply transformation
4. Validate output against expected schema
5. Write to destination with correct naming convention
## Rules
- Never skip validation steps
- If a file fails validation, log error and continue to next file
- Output naming: {original-name}.{target-extension}
- Always report summary: total, success, failed
Khi gõ "Convert 800 file markdown trong docs/ sang HTML", Claude sẽ spawn nhiều file-converter agent chạy song song — mỗi agent đều tuân theo đúng pipeline 5 bước đã định nghĩa, thay vì tự nghĩ ra cách làm khác nhau.
2.5. Agent vs Skill — Khi Nào Dùng Gì?
| Skill | Agent | |
|---|---|---|
| Bản chất | Tài liệu knowledge | Nhân vật chuyên biệt |
| Ai dùng | Agent đọc khi cần | Claude spawn khi delegate task |
| Context | Share context với agent chính | Context riêng, isolated |
| Chạy song song | Không | Có — mỗi agent có context window riêng |
| Khi nào tạo | Cần kiến thức chuyên môn dùng chung | Cần phân vai hoặc xử lý song song |
| Ví dụ | "Cách viết AJV keyword" | "Senior frontend dev" |
Kết hợp: Agent có thể dùng skill. Ví dụ agent frontend-dev đọc skill react-components và styling-tailwind khi thực thi. Skill là kiến thức, agent là người dùng kiến thức đó.
Phần 3: Hook — Cơ Chế Ép Buộc Tự Động
3.1. Hook là gì?
Hook là logic chạy tự động, không cần AI can thiệp. Khi đã cấu hình hook, Claude Code sẽ mặc định thực thi lệnh tại các điểm cụ thể trong workflow — bất kể agent có nhớ hay không, có muốn hay không.
Điểm khác biệt cốt lõi:
- Skill = knowledge cho agent đọc → agent có thể quên hoặc bỏ qua
- Hook = lệnh ép buộc mặc định → luôn chạy, agent không có quyền bỏ qua
Ví dụ thực tế: Bạn có skill tạo slide, trong skill ghi "sau khi tạo HTML xong, chạy script export sang PPTX". Nhưng agent có thể quên bước này. Nếu đặt thành hook, thì mỗi lần Write file HTML vào thư mục output, script export sẽ tự động chạy — agent quên cũng không sao, hook không quên.
3.2. Nơi Cấu Hình
Hook config nằm trong file JSON settings (KHÔNG phải folder riêng):
| File | Scope | Git commit? |
|---|---|---|
~/.claude/settings.json | Mọi project (user-level) | Không |
.claude/settings.json | Project (share với team) | Có |
.claude/settings.local.json | Project (cá nhân) | Không (gitignored) |
Folder .claude/hooks/ chỉ chứa script files mà hook config gọi tới:
.claude/
├── settings.json ← Hook config ở đây
├── settings.local.json ← Hook config cá nhân ở đây
└── hooks/ ← Script files (optional)
└── export-pptx.sh ← Được gọi bởi config
3.3. Các Hook Events
| Event | Khi nào chạy | Có thể chặn? |
|---|---|---|
| PreToolUse | Trước khi tool được gọi | ✅ Có thể deny/allow |
| PostToolUse | Sau khi tool hoàn thành | Không |
| UserPromptSubmit | Khi user gửi prompt | ✅ Có thể modify |
| PermissionRequest | Khi Claude xin permission | ✅ Approve/deny |
| Stop | Khi Claude dừng respond | Không |
| SubagentStop | Khi subagent kết thúc | ✅ Có thể chặn dừng |
| SessionStart | Bắt đầu session | Không |
| SessionEnd | Kết thúc session | Không |
| PreCompact | Trước khi compact context | Không |
| Setup | Init/maintenance repo | Không |
| Notification | Khi có notification | Không |
PreToolUse là hook duy nhất có thể block action — dùng cho security gates, chặn lệnh nguy hiểm.
3.4. Ví Dụ Xuyên Suốt: HTML → PPTX
Bài toán: Mỗi khi Claude tạo file HTML trong thư mục output/, tự động chạy script chuyển sang PPTX. Agent không cần nhớ gọi script — hook ép buộc chạy.
Bước 1 — Config hook trong settings:
// .claude/settings.local.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/export-to-pptx.sh",
"timeout": 300,
"statusMessage": "Exporting HTML to PPTX..."
}
]
}
]
}
}
Giải thích config:
PostToolUse→ chạy sau khi tool hoàn thànhmatcher: "Write"→ chỉ khi tool Write được dùng (không phải Edit, Bash...)type: "command"→ chạy shell command (logic thuần, không cần AI)timeout: 300→ cho phép tối đa 5 phút (export có thể nặng)
Bước 2 — Script xử lý logic:
#!/bin/bash
# .claude/hooks/export-to-pptx.sh
# Hook nhận data qua stdin (JSON), KHÔNG phải env variable
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
# Chỉ chạy nếu file là .html trong thư mục output/
if echo "$FILE_PATH" | grep -q '/output/.*\.html$'; then
node scripts/export-to-pptx.js "$FILE_PATH" 2>&1
fi
# exit 0 = cho phép tiếp tục, không can thiệp
exit 0
Tại sao filter trong script mà không filter ở matcher?
Matcher chỉ filter theo tên tool (Write, Bash, Edit...), không filter được file path. Nên hook sẽ fire mỗi lần Claude dùng Write, nhưng script kiểm tra path rồi exit 0 ngay nếu không match — overhead gần bằng 0. Dù sau này có thêm nhiều skill khác cũng dùng Write, hook chỉ thực sự chạy export khi đúng file HTML trong output/.
Luồng hoạt động:
Claude tạo file slide.html vào output/
↓
Write tool hoàn thành
↓
Hook PostToolUse fire (matcher: "Write" ✅)
↓
Script nhận JSON qua stdin
↓
Kiểm tra: "/output/slide.html" match pattern? ✅
↓
node scripts/export-to-pptx.js chạy tự động
↓
File .pptx được tạo — agent không cần làm gì thêm
3.5. Lưu Ý Kỹ Thuật Quan Trọng
Data chảy qua stdin, không phải env variable — sai ở đây = hook im lặng fail:
INPUT=$(cat) # ✅ Đọc stdin
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command') # ✅ Parse JSON
# ❌ SAI — không có env variable nào tên như vậy
# echo $CLAUDE_TOOL_INPUT
Exit codes:
0= cho phép tiếp tục (không can thiệp)2= block action (chỉ PreToolUse) + hiện lý do- Khác = lỗi, hiện stderr cho user
Luôn exit 0 khi không match — nếu quên, hook có thể block agent vô tình.
Phần 4: File CLAUDE.md — Bộ Nhớ Dài Hạn Của Agent
4.1. CLAUDE.md là gì?
CLAUDE.md là file markdown mà Claude Code tự động đọc mỗi khi mở session mới. Mục đích chính: chú thích cho agent biết dự án hoặc folder đó làm gì, để không phải nhắc lại mỗi khi mở cửa sổ prompt mới. Nếu viết tốt, agent đỡ phải đọc lại code mỗi lần bắt đầu làm việc.
Điểm khác biệt với Skill và Hook:
- Skill = knowledge chuyên môn, load khi cần
- Hook = logic ép buộc, chạy tự động
- CLAUDE.md = context dự án, luôn được đọc khi agent vào folder đó
Đặc tính quan trọng: CLAUDE.md survive /compact. Khi context bị nén (compact), conversation history có thể mất, nhưng Claude Code sẽ đọc lại CLAUDE.md từ disk — nên thông tin trong đây không bao giờ bị mất giữa session.
4.2. Vị Trí Đặt File
CLAUDE.md có thể đặt ở nhiều vị trí trong dự án, mỗi vị trí phục vụ một mục đích:
my-project/
├── CLAUDE.md ← Root: overview toàn bộ dự án
├── src/
│ ├── CLAUDE.md ← Chú thích folder src/
│ ├── core/
│ │ ├── CLAUDE.md ← Chú thích core logic
│ │ ├── validation/
│ │ │ └── CLAUDE.md ← Chú thích module validation
│ │ └── auth/
│ │ └── CLAUDE.md ← Chú thích module auth
│ └── api/
│ └── CLAUDE.md ← Chú thích API layer
├── scripts/
│ └── CLAUDE.md ← Chú thích các script tiện ích
└── docs/
└── CLAUDE.md ← Chú thích cấu trúc tài liệu
Thứ tự đọc: Claude Code đọc theo hierarchy — root trước, rồi folder con khi navigate vào. Nên:
- Root CLAUDE.md chứa overview tổng (stack, convention, project structure)
- Folder con chứa chi tiết cục bộ (module này làm gì, file nào quan trọng)
- Không lặp lại thông tin giữa các tầng
4.3. Root CLAUDE.md — Overview Dự Án
Giữ dưới 200 dòng (compliance >92%). Dùng imperative + bullet list — agent tuân thủ dạng list tốt hơn 60% so với paragraph.
# MongoREST
## Overview
MongoDB REST API framework with RBAC/ABAC authorization.
## Stack
- Runtime: Node.js 20, TypeScript 5.4
- Framework: Fastify 4
- Database: MongoDB 7 (Atlas)
- Tests: Vitest
- Linter: ESLint + Prettier
## Project Structure
- src/core/validation/ — AJV schema validation
- src/core/auth/ — Authorization engine (RBAC/ABAC)
- src/api/ — REST endpoint definitions
- src/shared/ — Shared utilities, error classes
- scripts/ — Build, deploy, seed scripts
## Key Commands
- `npm run dev` — Start dev server
- `npm test` — Run all tests
- `npm run build` — TypeScript compilation
## Conventions
- Use functional style, avoid classes where possible
- All API responses follow { data, error, meta } format
- Validation layer is SEPARATE from authorization layer
- Respond in Vietnamese, use tôi/bạn
## Task → Skill
- Validation/AJV: read .claude/skills/validation/SKILL.md
- Auth/RBAC: read .claude/skills/authorization/SKILL.md
- API design: read .claude/skills/api-endpoints/SKILL.md
4.4. Folder Con CLAUDE.md — Chi Tiết Cục Bộ
Ngắn hơn root — khoảng 20-50 dòng là đủ. Mục đích: agent vào folder này biết ngay module làm gì, file nào quan trọng, pattern nào đang dùng.
# src/core/validation/
## Purpose
AJV-based input validation for all API endpoints.
Validates data shape — NOT authorization (that's in auth/).
## Key Files
- schemas/ — JSON Schema definitions per collection
- keywords/ — Custom AJV keywords (objectId, dateRange, etc.)
- index.ts — Main validator factory, export validateInput()
## Patterns
- Every schema has $id matching collection name
- Use additionalProperties: false by default
- Custom keywords registered in keywords/register.ts
## Recent Changes
- 2026-03-15: Added dateRange keyword for date filtering
- 2026-03-10: Refactored schema loading to lazy init
4.5. Một Dự Án Nên Có Bao Nhiêu CLAUDE.md?
Không có con số cố định — phụ thuộc vào độ phức tạp:
- Dự án nhỏ (1-2 dev, <20 files): 1 file ở root là đủ
- Dự án trung bình (vài module): Root + mỗi module chính 1 file (3-5 file)
- Dự án lớn (nhiều team, microservices): Mỗi folder quan trọng đều nên có (10+ file)
Nếu agent thường xuyên hỏi lại "folder này làm gì?" hoặc đọc sai file — đó là tín hiệu cần thêm CLAUDE.md cho folder đó.
4.6. Cập Nhật CLAUDE.md
Lưu ý quan trọng: CLAUDE.md chỉ hữu ích khi được cập nhật. Có 2 cách:
Cách 1 — Nhờ agent cập nhật (khuyến nghị):
Thêm dòng này vào root CLAUDE.md:
## Maintenance
After significant changes to any module, update the CLAUDE.md
in that folder to reflect new files, patterns, or conventions.
Agent sẽ tự cập nhật CLAUDE.md khi refactor hoặc thêm module mới.
Cách 2 — Dev tự review định kỳ:
Agent có thể cập nhật không chính xác hoặc thêm thông tin thừa. Nên review CLAUDE.md mỗi 1-2 tuần, đặc biệt khi:
- Thêm module/folder mới
- Đổi convention hoặc stack
- Thấy agent liên tục hiểu sai context
4.7. Phân Biệt CLAUDE.md vs Skill vs .claude/rules/
| CLAUDE.md | Skill (SKILL.md) | .claude/rules/ | |
|---|---|---|---|
| Chứa gì | Project context: dự án làm gì, stack, cấu trúc | Domain knowledge: hướng dẫn chuyên môn | Coding rules: format, naming, test |
| Khi nào đọc | Luôn đọc khi vào folder | Chỉ khi trigger bởi description | Luôn đọc (global rules) |
| Ai viết | Dev + agent cùng maintain | Dev viết, agent đọc | Dev viết, agent tuân thủ |
| Ví dụ | "Dự án dùng Fastify + MongoDB" | "Cách viết AJV custom keyword" | "Dùng single quotes, 2-space indent" |
Phần 5: Kiến Trúc Kết Hợp Skill + Hook + Agent + CLAUDE.md
5.1. Nguyên Tắc Vàng
Skill = Knowledge chuyên môn (tài liệu agent đọc khi cần)
Agent = Nhân vật chuyên biệt (dùng skill, chạy song song, context riêng)
Hook = Enforcement tự động (chạy mặc định, không cần AI)
CLAUDE.md = Context dự án (agent luôn đọc khi vào folder)
Không nhầm lẫn vai trò: Skill không enforce, hook không truyền knowledge, agent không thay thế skill (agent dùng skill), CLAUDE.md không chứa hướng dẫn chuyên môn dài.
5.2. Kiến Trúc Đề Xuất Cho Project Thực Tế
project/
├── CLAUDE.md ← Router (~100-200 dòng)
│
├── .claude/
│ ├── settings.json ← Hooks + permissions (shared)
│ ├── settings.local.json ← Hooks cá nhân (gitignored)
│ ├── agents/ ← Nhân vật chuyên biệt
│ │ ├── frontend-dev.md
│ │ ├── tester.md
│ │ └── api-designer.md
│ ├── hooks/ ← Script files cho hooks
│ │ ├── auto-format.sh
│ │ ├── block-dangerous.sh
│ │ └── export-pptx.sh
│ ├── skills/ ← Mỗi skill = 1 folder + SKILL.md
│ │ ├── validation/
│ │ │ ├── SKILL.md
│ │ │ └── references/
│ │ │ └── ajv-keywords.md
│ │ ├── authorization/
│ │ │ ├── SKILL.md
│ │ │ └── references/
│ │ │ └── rbac-patterns.md
│ │ └── api-endpoints/
│ │ ├── SKILL.md
│ │ └── references/
│ │ └── crud-patterns.md
│ ├── rules/ ← Coding conventions
│ │ ├── typescript.md
│ │ └── testing.md
│ └── commands/ ← Custom slash commands
│ ├── deploy.md
│ └── review.md
│
└── docs/ ← Deep reference
├── architecture/
└── glossary.md
5.3. Ví Dụ: Workflow MongoREST Với Skill + Hook
CLAUDE.md (router):
# MongoREST Project
## Stack
Node.js, TypeScript, Fastify, MongoDB. Tests: Vitest.
## Task → Skill
- CRUD endpoints: .claude/skills/api-endpoints/SKILL.md
- Validation/AJV: .claude/skills/validation/SKILL.md
- Auth/RBAC: .claude/skills/authorization/SKILL.md
## After editing .ts files
Hook tự động chạy prettier + eslint (không cần nhớ).
Hook (enforcement):
// .claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/auto-format.sh",
"timeout": 30,
"statusMessage": "Formatting TypeScript..."
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/block-dangerous.sh"
}
]
}
]
}
}
Skill (knowledge):
# .claude/skills/validation/SKILL.md
## Quick Reference
| Task | Action |
|---------------------|----------------------------------------------------------------|
| New validation rule | Read [references/ajv-keywords.md](references/ajv-keywords.md) |
| Custom keyword | Read docs/architecture/ajv-custom.md |
## Core Principle
Validation ≠ Authorization. Keep them separate.
...
5.4. Best Practices Tổng Hợp
Skill:
- Mỗi skill = 1 folder riêng + SKILL.md bên trong (dù chỉ 1 file)
- SKILL.md dưới 500 dòng, lý tưởng 200-300
- Description đủ cụ thể và "pushy" để trigger đúng lúc
- Dùng imperative form, giải thích WHY
- Quick Reference table ở đầu, link về references/
- Tài liệu chi tiết tách vào references/, SKILL.md chỉ routing
- Giải thích WHY, không chỉ MUST
Agent:
- Tạo khi có nhiều skill cần phân vai, hoặc cần xử lý song song
- Giới hạn 3-4 agent chính — quá nhiều thì tốn thời gian chọn agent
- Nêu rõ: chức năng, năng lực, skill nào được dùng, workflow
- Dùng model phù hợp: sonnet cho task phức tạp, haiku cho batch processing
- Agent dùng skill, không thay thế skill
Hook:
- Dùng cho enforcement (format, lint, security), KHÔNG cho knowledge
- Filter path trong script (matcher chỉ filter tool name)
- Tách script phức tạp ra file riêng trong
.claude/hooks/ - Luôn
exit 0khi không match — tránh block agent vô tình - Timeout hợp lý (30s cho format, 300s cho export nặng)
CLAUDE.md:
- Root dưới 200 dòng, folder con 20-50 dòng
- Dùng imperative + bullet list
- Root chứa overview, folder con chứa chi tiết cục bộ — không lặp lại
- Nhờ agent cập nhật khi refactor, dev review định kỳ
- Survive
/compact— Claude đọc lại từ disk sau compact
Tài liệu tổng hợp từ Anthropic official docs, skill-creator skill, và kinh nghiệm thực tế.