Dùng tham chiếu @file, allowed-tools, subagent và tool MCP để nâng slash command từ phím tắt lên thành thư viện workflow của team.
Hai bài trước nói về slash command là gì (một file Markdown) và cách dùng tiền tố ! để bơm output shell vào context. Bài này đi xa hơn: làm sao để một command điều phối những năng lực mạnh nhất của Claude Code — tham chiếu file, subagent, công cụ MCP — và giữ quyền trong tầm kiểm soát.
Khi viết đến tầng này, command không còn chỉ là "phím tắt cho prompt" mà đã trở thành các workflow nhỏ có thể tái sử dụng.
@file: cách tiêm nội dung tĩnh hợp lý hơn !cat!cat file.md có thể nhét nội dung file vào context, nhưng nó đi qua shell và có vài nhược điểm: mỗi lần kích hoạt phải dựng một tiến trình con; đường dẫn file có khoảng trắng hoặc ký tự đặc biệt phải escape thêm; và Claude Code không nhận diện nó là "một file" mà chỉ xem là một đoạn text.
Tham chiếu @ thì native:
---
description: Review thay đổi theo quy chuẩn dự án
---
Tham khảo các quy chuẩn sau:
@.claude/context/coding-standards.md
@.claude/context/security-checklist.md
Giờ hãy review các thay đổi trong git diff, chỉ ra mọi chỗ vi phạm quy chuẩn.
!`git diff HEAD`
@path bảo Claude Code "đính file này vào hội thoại như một attachment". Khác biệt nằm ở:
| Tình huống | Dùng !cat |
Dùng @ |
|---|---|---|
Path đến từ tham số ($ARGUMENTS) |
✅ Chỉ có thể !cat |
❌ @ không hỗ trợ mở rộng biến |
| Quy chuẩn, template cố định của dự án | ⚠️ Dùng được nhưng nặng | ✅ Native, đỡ một lần shell |
| Nội dung động (diff, log, kết quả test) | ✅ Bắt buộc ! |
❌ Không được |
Quy luật: file tĩnh dùng @, output động dùng !, path có tham số dùng !cat $ARGUMENTS.
allowed-tools: đặt biên quyền cho commandMặc định, khi command chạy, model được dùng tất cả tool có trong session. Đôi khi đó không phải điều bạn muốn — ví dụ /review là tác vụ review chỉ đọc, bạn không muốn nó "tiện tay" sửa dù chỉ một dòng code.
Thêm allowed-tools vào frontmatter, trong thời gian command có hiệu lực chỉ những tool được liệt kê mới được phép:
---
description: Review code chỉ đọc
allowed-tools: Read, Grep, Glob, Bash(git diff:*), Bash(git log:*)
---
Review sự khác biệt giữa branch hiện tại và master, chỉ đọc không sửa.
!`git diff master...HEAD`
Vài điểm cần lưu ý:
Bash(git diff:*) là cấp quyền chi tiết — chỉ cho phép các lệnh bash bắt đầu bằng git diff, git push sẽ bị chặnRead / Grep / Glob chỉ rõ chỉ cấp các tool chỉ đọcEdit / Write, nên model dù có muốn sửa code cũng không gọi đượcTương tự, một command quyền cao như /deploy có thể được cấp quyền theo chiều ngược lại:
---
description: Deploy branch hiện tại
allowed-tools: Bash(kamal deploy:*), Bash(git push:*), Read
---
Ghi cứng "command này được làm gì" đáng tin hơn nhiều so với việc mỗi lần chạy lại dựa vào xét duyệt thủ công từng prompt bash.
Có những tác vụ sẽ làm vỡ context của hội thoại chính — duyệt hàng chục file để tìm mọi call site của một hàm, chạy thống kê codebase, kéo một đoạn log lớn để phân tích. Làm thẳng trong hội thoại chính thì hàng ngàn dòng output sẽ nằm lại trong context, và các lượt đối thoại sau sẽ chậm đi và kém thông minh.
Cách đúng là giao việc đó cho subagent: subagent chạy trong một context độc lập, xong chỉ mang kết luận về hội thoại chính. Trong command chỉ cần chỉ thị rõ:
---
description: Điều tra sâu mọi cách dùng của một symbol
allowed-tools: Task
---
Dùng subagent Explore điều tra sâu mọi cách dùng của symbol sau: $ARGUMENTS
Yêu cầu subagent bao quát:
- Tất cả call site (kể cả file test)
- Các tình huống nghiệp vụ đã được chạm tới
- Có cách triển khai thay thế tương đương hay không
Sau khi subagent trả kết quả, chỉ đưa lại cho tôi bản tóm tắt ≤300 từ, đừng dán đoạn code gốc.
Kích hoạt /trace SomeClass#some_method, Claude Code sẽ dựng một subagent Explore quét codebase song song, còn hội thoại chính chỉ nhận được kết luận đã được chắt lọc. Không có output grep, không có đoạn file, context sạch sẽ.
Cách chơi cao hơn:
---
description: Điều tra song song ba phương án ứng cử
allowed-tools: Task
---
Dựng đồng thời 3 subagent, lần lượt điều tra ba hướng triển khai sau:
1. Dùng ActiveJob + Sidekiq sẵn có
2. Dùng Solid Queue
3. Tự xây queue nhẹ
Mỗi agent trả lời: khối lượng công việc, rủi ro, mức độ xâm lấn vào code hiện có. Khi cả ba kết luận về, tôi sẽ tự so sánh.
Ba subagent chạy song song, hội thoại chính chỉ chờ một lượt kết quả. Đây là một trong những đòn bẩy lớn nhất mà command mang lại — biến những tác vụ nghiên cứu "tốn rất nhiều token mới rút ra được kết luận" thành một workflow chỉ cần một cú chạm.
Nếu session đã kết nối đến MCP server (Linear, GitHub, Sentry, proxy database tự xây, v.v.), command có thể chỉ thị cho model gọi thẳng các tool đó:
---
description: Sinh todo triển khai từ Linear issue
allowed-tools: mcp__linear__*, Read, Grep
---
Đọc toàn bộ mô tả và comment của Linear issue $ARGUMENTS.
Kết hợp với hiện trạng codebase (tự dùng Grep/Read tìm các file liên quan), lập một danh sách todo triển khai:
- Cần sửa những file nào
- Mỗi bước commit riêng hay gộp chung
- Có điểm mơ hồ nào cần confirm với PM trước không
Đừng bắt đầu viết code, chỉ ra kế hoạch.
mcp__linear__* cấp quyền cho mọi tool Linear MCP, model có thể kéo chi tiết issue, comment, trạng thái. Cả command trở thành điểm khởi động cho workflow "từ ticket tới kế hoạch triển khai".
Điểm mấu chốt: khi ghi tên tool MCP trong allowed-tools phải dùng tiền tố đầy đủ (mcp__<server>__<tool>), nếu không quyền sẽ không có hiệu lực.
Một ngộ nhận rất phổ biến: viết /test trong file của /review và nghĩ rằng sẽ kích hoạt command test. Không đâu. Slash command chỉ được mở rộng một lần ở tầng input cấp cao nhất của người dùng; /xxx bên trong một command chỉ là text thường — model đọc được nó, nhưng Claude Code sẽ không đi thực thi.
Muốn compose nhiều command, có vài cách đúng:
Cách A: Tách logic dùng chung ra file context, các command dùng @ hoặc !cat để tham chiếu
@.claude/context/review-checklist.md
@.claude/context/security-checklist.md
Cách B: Trong command ghi rõ "làm giống như /review" + lặp lại các chỉ thị then chốt
Không thanh lịch nhưng hiệu quả. Chỉ cần prompt đủ rõ, model sẽ đi theo cùng một lối.
Cách C: Một command dùng tool Task để dựng subagent, prompt của subagent lại dùng lại chính bộ file context đó
Điều phối workflow thực sự đều đi theo con đường này. Command cha chịu trách nhiệm điều phối và tổng hợp, subagent chịu trách nhiệm thực thi các bước cụ thể.
Anti-pattern cần tránh: viết command dài hàng trăm dòng, cố gắng dùng một chỉ thị làm xong mọi thứ. Một khi độ mịn vỡ ra, chi phí bảo trì sẽ tăng vọt, và một command cũng sẽ ngốn hết budget token của một lượt chạy.
Đến đây, các cơ chế để tiêm "năng lực bên ngoài" vào command của Claude Code về cơ bản đã đủ. Chọn thế nào:
| Nhu cầu | Cơ chế ưu tiên |
|---|---|
| Quy chuẩn, template, tài liệu context cố định | Tham chiếu @file |
| Trạng thái thời gian thực (diff, log, kết quả test, query DB) | Tiêm !shell |
| Nội dung file có tham số | !cat $ARGUMENTS |
| Nghiên cứu ngốn context, tìm kiếm liên file | subagent qua Task |
| Hệ thống ngoài (issue tracker, monitoring, dữ liệu production) | Công cụ MCP + allowed-tools |
| Workflow nhiều bước tuần tự/song song | Command cha điều phối subagent |
Biên quyền được khai báo rõ qua allowed-tools, nhất là với các command dùng chung trong team — ghi cứng nó được làm gì đáng tin hơn là dựa vào duyệt thủ công mỗi lần.
Ráp tất cả lại, hãy xem một command "điều tra hướng triển khai dựa trên Linear ticket":
---
description: Tạo phương án triển khai dựa trên Linear ticket
allowed-tools: mcp__linear__*, Task, Read, Grep, Glob, Bash(git log:*)
---
## Context
@.claude/context/architecture.md
@.claude/context/coding-standards.md
## Hiện trạng codebase
!`git log --oneline -10`
## Nhiệm vụ
Kéo mô tả, comment và các ticket liên quan của Linear ticket $ARGUMENTS.
Sau đó dựng hai subagent chạy song song:
1. Cái thứ nhất: tìm trong codebase mọi implementation liên quan hiện có, các module có thể tái sử dụng
2. Cái thứ hai: đánh giá rủi ro — thay đổi lần này sẽ chạm vào những đường code lưu lượng cao nào, có khoảng hở về test coverage không
Sau khi cả hai agent trả kết quả, xuất ra:
- Các bước triển khai (sắp theo thứ tự phụ thuộc)
- Danh sách rủi ro
- Khuyến nghị độ mịn commit
Đừng bắt đầu viết code.
Kích hoạt /plan ENG-4213, một chỉ thị chạy xong tất cả: kéo ticket → điều tra codebase song song → đánh giá rủi ro → tổng hợp phương án. Người dùng chỉ cần đọc kết luận rồi quyết định bắt tay vào làm.
Đây chính là vòng cung trọn vẹn của ba bài đầu trong loạt slash command: định nghĩa prompt tái sử dụng (intro) → tiêm context động (context) → điều phối công cụ và subagent (bài này). Đến tầng này, .claude/commands/ không còn là phím tắt nữa, mà là thư viện workflow nhỏ của cả team.