Đây là câu hỏi nhận được mỗi khi giới thiệu skill với team đã quen Claude Code. Họ có CLAUDE.md, có slash command, một số team tiến xa hơn có subagent, hook, MCP server.
- So sánh skill với 4 cơ chế còn lại trong Claude Code: CLAUDE.md, subagent, hook, MCP server
- Chọn đúng công cụ cho mỗi use case qua decision tree rõ ràng
- Thiết kế setup kết hợp nhiều cơ chế — không force mọi thứ vào skill
- Nhận diện 3 anti-pattern phổ biến khi dev lẫn lộn các cơ chế
5 cơ chế customize Claude Code — overview
Mental model: Claude Code như một "layered system"
Bạn không chọn 1 trong 5. Setup thực tế dùng nhiều cơ chế cùng lúc, mỗi cái một vai trò.
| Cơ chế | Load khi nào | Ai trigger | Mục đích chính |
|---|---|---|---|
| CLAUDE.md | Mỗi conversation | Auto (luôn có mặt) | Project standards luôn áp dụng |
| Skill | Khi match request | Claude semantic match | Task-specific expertise on-demand |
| Subagent | Khi bạn delegate task | User hoặc Claude gọi | Task độc lập, isolated context |
| Hook | Khi có event (save file, tool call) | Event-driven | Side effect tự động |
| MCP server | Khi Claude cần external data | Claude qua tool call | Kết nối data/service bên ngoài |
┌─────────────────────────────────────────────────────┐ │ MCP Servers 🌐 External data │ │ (GitHub, Slack, Connect to outside world │ │ Postgres, ...) │ ├─────────────────────────────────────────────────────┤ │ Subagents 👥 Specialized roles │ │ (frontend-reviewer, Delegated work, isolated │ │ backend-reviewer, ...) contexts │ ├─────────────────────────────────────────────────────┤ │ Skills 🎓 Task expertise │ │ (pr-review, On-demand, triggered │ │ commit-format, ...) by request │ ├─────────────────────────────────────────────────────┤ │ Hooks ⚙️ Event automation │ │ (on-save-lint, Fire on file save, tool │ │ pre-commit, ...) call, etc. │ ├─────────────────────────────────────────────────────┤ │ CLAUDE.md 🏗️ Project foundation │ │ Always-on project context │ └─────────────────────────────────────────────────────┘
Skill vs CLAUDE.md — Load khi nào?
CLAUDE.md: Always-on
File này load vào system prompt mọi conversation. Luôn có mặt. Claude luôn biết "dự án này là Next.js".
Skill: On-demand
Skill pr-description chỉ load khi bạn nói "write PR description". Còn lại, nó ngủ.
Khi nào dùng cái nào?
Ví dụ thực tế — quyết định 5 trường hợp
Anti-pattern: CLAUDE.md phình to
Sai lầm: Nhồi mọi instruction vào CLAUDE.md — review checklist, email template, report format, debug procedure...
Hậu quả: Mỗi conversation ăn 40% context cho content có thể chỉ cần 5%.
Cách đúng: CLAUDE.md chỉ giữ thứ luôn áp dụng. Còn lại → skill.
Otto hỏi ngược: "Look at your current CLAUDE.md file. Is there anything in it that would work better as a skill (loaded only when relevant)?" Answer cho hầu hết team: có.
| Hướng dẫn | Để đâu? Tại sao |
|---|---|
| "Project này dùng Next.js 14" | CLAUDE.md — luôn cần biết |
| "Never modify /migrations/ directly" | CLAUDE.md — constraint luôn luôn |
| "Review PR theo checklist 15 điểm" | Skill — chỉ khi review PR |
| "Format commit theo Conventional Commits" | Skill — trigger khi commit |
| "All API routes live in src/app/api/" | CLAUDE.md — structural, always relevant |
# CLAUDE.md
This project uses Next.js 14 with App Router, TypeScript strict mode,
and Tailwind CSS. We follow conventional commits. Never modify files in
/migrations/ directly — use `pnpm db:migrate` instead.Skill vs Subagent — Cùng context vs isolated
Skill: Join current context
Khi skill pr-review trigger, nó thêm instructions vào cuộc hội thoại đang chạy. Context hiện tại (code bạn đang xem, conversation history) vẫn ở đó. Skill làm Claude thông minh hơn trong context hiện tại.
Subagent: Separate context
Subagent là Claude khác chạy trong context riêng, isolated. Bạn delegate task cho nó, nó làm xong, trả result về bạn. Nó không thấy conversation history của bạn, không share context.
Khi nào dùng cái nào?
Dùng Skill khi:
Dùng Subagent khi:
Skill ↔ Subagent: Hoạt động cùng nhau
Đây là điểm quan trọng dễ miss: Subagent có thể dùng skill.
Otto giải thích:
Skill là portable expertise — share được giữa subagent. Bạn không build lại expertise cho mỗi subagent.
Setup mẫu:
Chi tiết config subagent với skill ở Bài 15.5.
⚠️ Gotcha quan trọng
Built-in agent (Explorer, Plan, Verify) KHÔNG access skill. Otto: "Built-in agents can't access skills at all. Only custom subagents you define can use them and only when you explicitly list them."
Skill load khi subagent start, không on-demand như main conversation. Nên chỉ list skill luôn relevant cho purpose của subagent.
- Bạn muốn cùng conversation smarter về task
- Expertise apply throughout remaining conversation
- Ví dụ: activate PR review skill → mọi review tiếp theo trong session vẫn có expertise đó
- Bạn muốn task độc lập — không polute main context
- Cần tool access khác main conversation (ví dụ subagent có quyền Bash mà main không có)
- Parallelize: chạy 5 subagent concurrent cho 5 file khác nhau
- Ví dụ: delegate "phân tích 10 file log" cho subagent — kết quả về main, không bloat main context
.claude/
├── agents/
│ ├── frontend-reviewer.md ← subagent: skills = [component-patterns, a11y-standard]
│ └── backend-reviewer.md ← subagent: skills = [api-conventions, a11y-standard]
└── skills/
├── component-patterns/ ← riêng frontend
├── api-conventions/ ← riêng backend
└── a11y-standard/ ← SHARED giữa 2 subagentMain conversation:
You working on feature A
↓ (delegate)
Subagent frontend-reviewer:
(fresh context, no memory of your feature A)
Runs task
Returns result
↓
Main conversation continuesSkill vs Hook — Request-driven vs Event-driven
Hook: Fire on event
Hook là automation chạy khi có event xảy ra:
Hook không cần Claude "decide". Nó fire automatically khi event match.
Skill: Fire on request
Skill trigger khi user hỏi điều match với description. Claude làm trung gian.
Khi nào dùng cái nào?
Rule of thumb
Case: Lint workflow
Cách tệ (dùng skill):
- File save → run linter
- Before bash call → validate input
- After Edit tool → auto-format
- Hook = "operation chạy không cần Claude suy nghĩ" — tự động, deterministic
- Skill = "knowledge để Claude dùng khi reasoning" — Claude vẫn là người quyết định
| Situation | Hook | Skill |
|---|---|---|
| Auto-format file sau save | ✅ | ❌ |
| Validate input trước khi run bash | ✅ | ❌ |
| Review PR theo standard | ❌ | ✅ |
| Write commit message | ❌ | ✅ |
| Log mỗi tool call ra file | ✅ | ❌ |
| Explain code when asked | ❌ | ✅ |
// .claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "prettier --write ${file}"
}
]
}
]
}
}Case: Lint workflow
Problem: Skill chỉ trigger khi user nói "commit". Nếu user quên → không lint.
Cách đúng (dùng hook):
Skill lint-before-commit:
description: "Runs linter before commits. Use when committing."Skill vs Hook — Request-driven vs Event-driven (tiếp)
Hook fire luôn luôn khi có bash command match git commit. Không dựa vào user.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "[[ \"$TOOL_INPUT\" == *\"git commit\"* ]] && pnpm lint"
}
]
}
]
}
}Skill vs MCP Server — Expertise vs Data connection
Đây là phần gây confuse nhất. Vì cả skill và MCP đều "extend Claude".
MCP (Model Context Protocol): Connection tới external world
MCP là open protocol cho phép Claude truy cập data/service bên ngoài:
MCP server expose tools để Claude gọi. Ví dụ:
Claude dùng các tool này khi cần data đó.
Skill: Expertise về cách làm gì với data
Skill không fetch data. Skill chứa instructions.
Otto's killer one-liner
Clean nhất trong tất cả explanation. Memorize đi.
Ví dụ cụ thể — MCP + Skill hoạt động cùng nhau
Setup:
- MCP server cho GitHub → Claude đọc/write issue, PR, code
- MCP server cho Postgres → Claude query database
- MCP server cho Slack → Claude đọc tin nhắn
MCP server github/ expose tools:
- list_issues
- create_pr
- get_file_content
- ...
MCP server postgres/ expose tools:
- execute_query
- list_tables
- describe_schemaVí dụ cụ thể — MCP + Skill hoạt động cùng nhau
User: "Review PR #142"
Claude:
MCP cho access tới GitHub. Skill dạy Claude quy trình review. Không cái nào đủ một mình:
Setup cho team thực tế
Litton (AI University) cho workflow mẫu:
Skill orchestrate. MCP cung cấp tool. 2 thứ complement, không compete.
Decision:
- Match skill pr-review → load instructions (Bài 15.2)
- Instructions nói: gh pr view 142 hoặc dùng MCP github.get_pr(142) lấy diff
- Instructions nói: check X, Y, Z theo checklist
- Instructions nói: comment review qua MCP github.comment_pr(142, ...)
- Chỉ MCP không skill → Claude có thể đọc PR nhưng review không theo style team
- Chỉ skill không MCP → Claude biết cách review nhưng không access được PR
| Câu hỏi | Trả lời | Dùng cái gì |
|---|---|---|
| Bạn cần Claude access data ở external system? | YES | MCP server |
| Bạn cần dạy Claude quy trình theo style của team? | YES | Skill |
| Cả 2 | YES | Skill + MCP cùng lúc |
MCP server: github-mcp (list PRs, read code, comment)
Skill: pr-review (checklist + style + tone)Decision Tree — Chọn cơ chế nào?
Flowchart dạng checklist
- Cần fetch data từ GitHub/Slack/DB/API? → MCP server
- Cần side-effect tự động khi save/call tool? → Hook
- Instruction luôn luôn áp dụng trong mọi conversation của project? → CLAUDE.md
- Muốn task chạy isolated, không polute main context? → Subagent
- Instruction chỉ áp dụng khi user hỏi về task đó, Claude tự nhận? → Skill
┌─────────────────────────────────────────────────────────┐
│ Bắt đầu: Bạn muốn customize Claude Code làm gì? │
└─────────────────────────────────────────────────────────┘
↓
┌───────────────┴───────────────┐
↓ ↓
┌─────────────────┐ ┌─────────────────┐
│ Cần external │ │ Cần automation │
│ data/service? │ │ trên event │
│ │ │ (save, tool │
│ (GitHub, │ │ call)? │
│ Postgres...) │ │ │
└─────────────────┘ └─────────────────┘
│ │
YES YES
↓ ↓
┌─────────┐ ┌──────────┐
│ MCP │ │ Hook │
│ server │ │ │
└─────────┘ └──────────┘
↓ (không cần 2 cái trên)
┌────────────────┴────────────────┐
↓ ↓
┌──────────────────┐ ┌────────────────┐
│ Instruction này │ │ Muốn task chạy │
│ có LUÔN áp dụng │ │ trong context │
│ mọi conversation?│ │ ISOLATED khỏi │
│ │ │ main? │
└──────────────────┘ └────────────────┘
│ │
YES YES
↓ ↓
┌─────────┐ ┌──────────┐
│CLAUDE.md│ │ Subagent │
└─────────┘ └──────────┘
↓ (không cần những cái trên)
┌──────────────────┐
│ Instruction cần │
│ Claude tự kích │
│ hoạt khi relevant│
│ │
│ → SKILL │
└──────────────────┘Setup hoàn chỉnh: Case study team engineering
Để thấy 5 cơ chế sống chung thế nào, hãy xem setup của 1 team engineering giả lập nhưng realistic:
Team 12 người, làm SaaS trên Next.js 14 + TypeScript + Postgres. Ship code hàng tuần. Yêu cầu: code quality, security, consistency.
Tầng 1: CLAUDE.md — Foundation
Vai trò: Foundation context. Claude luôn biết stack + constraint.
Tầng 2: MCP servers — Data connections
# CLAUDE.md
This project uses Next.js 14 (App Router), TypeScript strict mode,
and Tailwind CSS. Database: Postgres 16 with Drizzle ORM.
Conventions:
- Conventional commits (feat, fix, chore, refactor, docs, test)
- PR target main, squash merge
- Never modify /migrations/ directly (use `pnpm db:migrate`)
- All API routes in src/app/api/
- Test coverage must stay ≥ 80%
Tools available: pnpm, gh (GitHub CLI), docker, drizzle-kit.Tầng 2: MCP servers — Data connections
Vai trò: Access external data. Skill gọi MCP tool khi cần.
Tầng 3: Skills — Expertise
Vai trò: Task-specific expertise. Trigger on-demand khi team member làm task đó.
Tầng 4: Subagents — Specialized roles
Vai trò: Isolated task delegation. Khi tech lead gõ "ask frontend-reviewer to check PR #142" → subagent chạy riêng.
Tầng 5: Hooks — Automation
.claude/agents/
├── frontend-reviewer.md
│ └── skills: [pr-review, a11y-audit, design-system-check]
├── backend-reviewer.md
│ └── skills: [pr-review, api-conventions, sql-perf-check]
└── security-auditor.md
└── skills: [security-scan, owasp-checklist]Configured MCP servers:
- github (list issues, read PRs, create reviews)
- linear (track tickets)
- postgres (query read-only to staging DB)
- sentry (error analytics)Tầng 5: Hooks — Automation
Vai trò: Auto-format sau mỗi edit, chạy lint+test trước push.
Kết quả
Workflow điển hình của 1 dev:
5 tầng, mỗi tầng 1 vai trò. Không cơ chế nào làm việc của cơ chế khác.
- Dev mở task "thêm API endpoint". CLAUDE.md đã cho Claude biết stack + convention.
- Dev gõ "tạo API route cho POST /api/users". Skill api-route-generator trigger (đúng convention team).
- Claude generate code qua MCP file system + pnpm tool.
- Dev edit code → Hook prettier --write auto format.
- Dev commit. Skill commit-format trigger khi nói "viết commit message".
- Dev push → Hook pnpm lint && pnpm test chạy.
- Dev mở PR qua MCP github. Skill pr-review bảo subagent backend-reviewer review → subagent dùng skills pr-review, api-conventions, sql-perf-check cho review toàn diện.
{
"hooks": {
"PostToolUse": [
{ "matcher": "Edit.*\\.ts$", "hooks": [{ "command": "pnpm prettier --write ${file}" }] }
],
"PreToolUse": [
{ "matcher": "Bash.*git push.*", "hooks": [{ "command": "pnpm lint && pnpm test" }] }
]
}
}Anti-patterns — Khi dev lẫn lộn các cơ chế
❌ Anti-pattern 1: Nhồi review checklist vào CLAUDE.md
Triệu chứng: CLAUDE.md 800 dòng, nửa là review checklist không ai cần khi đang viết feature mới.
Tại sao tệ: Overhead mỗi conversation. Claude confused (quá nhiều context).
Cách đúng: Review checklist → skill pr-review. CLAUDE.md giữ foundation (stack, convention luôn áp dụng).
❌ Anti-pattern 2: Dùng skill thay cho hook
Triệu chứng: Skill auto-format-on-save description "Formats code after save. Use whenever editing."
Tại sao tệ: Skill chỉ fire khi user nói gì đó match. Save file không phải là "user request" → skill không trigger. Format không happen.
Cách đúng: Hook PostToolUse fire on Edit tool. Skill dành cho "expertise Claude cần suy nghĩ để apply", không phải automation mechanical.
❌ Anti-pattern 3: MCP cho mọi thứ
Triệu chứng: Build MCP server cho "team coding standards" — trả về rules.
Tại sao tệ: MCP thiết kế cho data/service external. Coding standard là expertise, không phải data cần fetch. Overhead, slow, complex.
Cách đúng: Coding standard → skill với instructions. Dùng MCP cho data thực sự ở external system.
❌ Anti-pattern 4: Subagent thay vì skill
Triệu chứng: Tạo subagent pr-reviewer thay vì skill pr-review.
Tại sao tệ: Subagent chạy isolated context → mất context PR bạn đang xem. Phải pass lại toàn bộ context. Overhead.
Cách đúng: Skill pr-review join main context, review với full context sẵn có. Chỉ dùng subagent khi cần isolation thực sự (parallelization, different tool access, large delegated task).
Áp dụng ngay
Bài tập 1: Audit CLAUDE.md của bạn (~10 phút)
Mở CLAUDE.md của project hiện tại. Đọc từng section, trả lời cho mỗi section:
Ghi ra:
Bài tập 2: Thiết kế setup cho use case của bạn (~10 phút)
Pick 1 workflow bạn làm thường xuyên (ví dụ: "review PR", "ship feature", "on-call response"). Điền bảng:
Nếu trả lời có 5 cơ chế khác nhau — bạn đã hiểu rồi.
- Section cần giữ ở CLAUDE.md: _____
- Section cần move thành skill: _____
- Ước tính % giảm size CLAUDE.md: _____
| Aspect của workflow | Dùng cơ chế nào | Giải thích |
|---|---|---|
| Luôn-luôn biết stack + convention | _____ | |
| Fetch data (CRM, DB, Slack...) | _____ | |
| Automation khi save / commit | _____ | |
| Expertise theo task | _____ | |
| Delegate task lớn isolated | _____ |
Tóm tắt bài học
🎯 5 cơ chế, 5 vai trò. CLAUDE.md = foundation. MCP = external data. Subagent = isolated roles. Skill = on-demand expertise. Hook = event automation.
🎯 Otto's one-liner: "MCP connects to data, Skills teach Claude what to do with it." — Memorize.
🎯 Decision tree quick check: Cần external data? → MCP. Event-driven? → Hook. Luôn áp dụng? → CLAUDE.md. Isolated? → Subagent. On-demand task expertise? → Skill.
🎯 Combine, không compete. Setup hoàn chỉnh dùng cả 5 cơ chế. Skill gọi MCP, subagent dùng skill, hook complement skill.
🎯 Skill là đúng khi: (1) task-specific, (2) Claude tự nhận qua semantic, (3) join current context, (4) portable qua project (personal) hoặc share team (project).
- Anthropic Academy — "Skills vs. other Claude Code features"
- Video — "Choosing the right feature"
- Model Context Protocol — MCP spec
- Otto, "Claude Agent Skills Explained" — quote sources