Custom commands đã được gộp vào Skills. Khi nào nên chuyển sang `.claude/skills/` và chuyển xong được thêm gì.
Ba bài trước đã nói hết cách dùng slash command: từ file Markdown, đến chèn !command, rồi điều phối subagent và MCP. Những thứ đó vẫn còn nguyên giá trị—nhưng phía sau, đội ngũ chính thức đã gộp lại: custom commands đã được nhập vào Skills.
File .claude/commands/review.md của bạn vẫn chạy, /review vẫn dùng được, không cần sửa gì cả. Nhưng nếu bạn muốn command đó lớn lên với nhiều năng lực hơn (nhiều file, chạy fork, tự kích hoạt theo path), đường đi mới là .claude/skills/review/SKILL.md. Bài này nói rõ hai chuyện: chuyển như thế nào, và có đáng chuyển không.
Cam kết tương thích của phía chính thức rất rõ: .claude/commands/deploy.md và .claude/skills/deploy/SKILL.md đều được đăng ký là /deploy, chức năng y như nhau. Khi trùng tên, skills được ưu tiên.
Các bước chuyển tối thiểu:
cd .claude/commands
mkdir -p ../skills/review
mv review.md ../skills/review/SKILL.md
Nội dung file không cần sửa một dòng nào. YAML frontmatter, !`command`, @file, $ARGUMENTS—tất cả đều tương thích.
Nhưng nếu chỉ làm tới đó, người đọc sẽ hỏi: thế chuyển để làm gì? Câu trả lời nằm ở chỗ thư mục skill có thể chứa nhiều file, trong khi command chỉ một.
SKILL.md là cửa vào, cùng thư mục có thể đặt bất kỳ file phụ trợ nào. Hình dung một cấu trúc thế này:
.claude/skills/review/
├── SKILL.md # cửa vào, chỉ thị ngắn gọn + tham chiếu
├── checklist.md # checklist code review dài
├── examples/
│ └── good-diff.md # ví dụ tốt
└── scripts/
└── lint.sh # script mà SKILL.md có thể gọi
Trong SKILL.md dùng path tương đối để tham chiếu:
Rà soát diff hiện tại, tuân theo các tiêu chuẩn trong [checklist.md](checklist.md).
Tham khảo [examples/good-diff.md](examples/good-diff.md) để hiểu định dạng đầu ra mong muốn.
Những file phụ trợ này không tự động vào context—Claude chỉ đọc khi cần. Khuyến nghị chính thức là giữ SKILL.md dưới 500 dòng, phần còn lại đẩy sang file phụ trợ.
disable-model-invocation: skill nào chỉ bạn được tay kích hoạtMặc định, khi gặp thời điểm phù hợp Claude sẽ tự gọi bất kỳ skill nào. Điều này nguy hiểm với những command có tác dụng phụ như /deploy, /commit, /send-email—bạn không muốn nó "thấy code ổn là đem deploy luôn".
---
name: deploy
description: Deploy lên production
disable-model-invocation: true
allowed-tools: Bash(kamal deploy:*), Bash(git push:*)
---
Thêm dòng này vào rồi, /deploy chỉ được kích hoạt khi bạn tự gõ; Claude sẽ không tự tiện gọi giữa cuộc hội thoại.
Ngược lại, user-invocable: false có nghĩa "chỉ Claude được gọi, nhưng không hiện trong menu /"—phù hợp với skill kiểu kiến thức nền (ví dụ legacy-system-context: Claude tự nạp trong tình huống liên quan, còn bạn kích hoạt tay thì vô nghĩa).
context: fork: cho skill chạy trong subagentĐây là nâng cấp lớn nhất. Bài trước có nói command có thể dùng allowed-tools: Task để bảo model mở subagent—nhưng bạn phải tự tay mô tả "mở một subagent Explore để làm..." trong prompt.
SKILL chỉ cần một dòng frontmatter là xong:
---
name: deep-research
description: Nghiên cứu sâu một symbol
context: fork
agent: Explore
---
Nghiên cứu mọi cách dùng của $ARGUMENTS:
- Tất cả điểm gọi
- Bối cảnh nghiệp vụ
- Các cách triển khai thay thế
Trả về tóm tắt ≤300 từ.
Khi kích hoạt /deep-research SomeClass: toàn bộ SKILL.md trở thành prompt của một subagent độc lập, chạy với agent type Explore, xong việc chỉ trả về kết luận. Context cuộc hội thoại chính hoàn toàn sạch.
Nói cách khác, việc "mở subagent" trước đây là chữ trong prompt, giờ trở thành thuộc tính khai báo của skill.
paths: tự kích hoạt theo loại file---
name: rails-conventions
description: Quy ước code cho dự án Rails
paths: ["app/**/*.rb", "config/**/*.rb"]
---
Tuân theo quy ước Rails của dự án này:
- Dùng service object thay vì fat controller
- ActiveRecord scope phải đặt tên
...
Khi bạn đang sửa app/models/user.rb, skill này tự động được nạp vào context; sửa package.json thì không. Chính xác hơn nhiều so với CLAUDE.md vốn mang tính toàn cục—giống như "CLAUDE.md phân lớp theo path".
/plan thành skillVí dụ /plan cuối bài trước vốn là command một file:
.claude/commands/plan.md
Nâng cấp thành skill:
.claude/skills/plan/
├── SKILL.md
├── research-prompt.md # chỉ thị cho subagent 1
└── risk-prompt.md # chỉ thị cho subagent 2
SKILL.md:
---
name: plan
description: Tạo phương án triển khai dựa trên Linear ticket
disable-model-invocation: true
allowed-tools: mcp__linear__*, Task, Read, Grep, Bash(git log:*)
---
## Context
@.claude/context/architecture.md
## Trạng thái
!`git log --oneline -10`
## Nhiệm vụ
Lấy mô tả và comment của Linear ticket $ARGUMENTS.
Dùng Task mở hai subagent chạy song song:
1. Nghiên cứu code: prompt xem [research-prompt.md](research-prompt.md)
2. Đánh giá rủi ro: prompt xem [risk-prompt.md](risk-prompt.md)
Tổng hợp kết quả rồi đưa ra các bước triển khai + danh sách rủi ro + gợi ý granularity commit.
Prompt của hai subagent để riêng ra file; khi chỉnh sửa chỉ động một chỗ mà không phải đụng SKILL.md. Bản thân SKILL.md gọn gàng dưới 30 dòng, còn file phụ trợ có thể dài hàng trăm dòng chi tiết.
Nếu không muốn tự mình điều phối subagent, có thể quyết liệt hơn—ném cả skill vào fork, để Explore agent thực thi một mạch:
---
name: plan
context: fork
agent: Explore
allowed-tools: mcp__linear__*
---
Kích hoạt /plan ENG-4213 → Explore agent trong context độc lập nhận toàn bộ nội dung SKILL.md như nhiệm vụ → chỉ trả về phương án cuối cùng. Cuộc hội thoại chính hoàn toàn không bị bẩn.
Không phải command nào cũng đáng nâng cấp. Những trường hợp vẫn nên ở .claude/commands/:
/commit, /pr-desc và tương tự chỉ cần một frontmatter cộng vài dòng prompt—đặt ở .claude/commands/ còn trực quan hơn. Phía chính thức đã nói rõ hai hình thức tồn tại song song, không cái nào bị loại bỏ.
Cách tổ chức .claude/ sạch sẽ nhất hiện nay:
.claude/
├── commands/ # nhẹ: một file + prompt đơn giản
│ ├── commit.md
│ └── pr-desc.md
├── skills/ # nặng: nhiều file / fork / kiểm soát quyền
│ ├── plan/
│ │ ├── SKILL.md
│ │ ├── research-prompt.md
│ │ └── risk-prompt.md
│ ├── deploy/
│ │ └── SKILL.md # disable-model-invocation
│ └── rails-conventions/
│ └── SKILL.md # tự kích hoạt theo paths glob
└── context/
└── coding-standards.md
Đừng chuyển hết một lượt. Điều kiện kích hoạt việc chuyển là "command này bắt đầu phình ra"—nội dung vượt 200 dòng, cần tách tài liệu, muốn chạy bằng subagent. Đến lúc đó mới đổi path, chỉ vài phút.
| Năng lực mong muốn | commands/ |
skills/ |
|---|---|---|
| Shortcut prompt một file | ✅ | ✅ |
!`command` / @file / $ARGUMENTS |
✅ | ✅ |
Kiểm soát quyền qua allowed-tools |
✅ | ✅ |
| File phụ trợ (reference, scripts) | ❌ | ✅ |
disable-model-invocation chống kích hoạt nhầm |
❌ | ✅ |
context: fork + agent: thực thi cách ly |
❌ | ✅ |
Tự kích hoạt theo paths: glob |
❌ | ✅ |
Ba mục đầu commands và skills tương đương hoàn toàn; bốn mục sau là đặc quyền của skills. Cần cái nào thì dùng cái đó, không cần thì đừng hành xác.
Đường đi chính thức đang nghiêng về phía skills, nhưng cam kết tương thích với commands/ rất rõ—đây không phải thay đổi kiểu "chuyển ngay hoặc bị đào thải", mà là mở rộng "cho thêm năng lực nhưng không bắt buộc". Hiểu rõ khác biệt, chuyển khi cần, đừng chạy theo sự gọn gàng bề mặt.