Dùng tiền tố ! để chạy lệnh shell trong slash command, tự động chèn diff, nội dung file và kết quả test vào prompt
Slash command của đa số mọi người trông như thế này:
Hãy đánh giá chất lượng các thay đổi code hiện tại và đưa ra gợi ý cụ thể.
Cách này dùng được, nhưng có một giới hạn cốt lõi: Claude phải tự suy đoán "thay đổi hiện tại là gì". Nếu command của bạn có thể chủ động bơm ngữ cảnh vào, kết quả sẽ khác hẳn.
Bài này nói về cách biến command thành một lệnh "có mắt" — khi được kích hoạt, nó tự động đọc nội dung file, trạng thái git, thông tin dự án rồi nhét tất cả vào prompt, để Claude khỏi phải đoán.
!`lệnh` bơm output của shellCustom slash command hỗ trợ nhúng lệnh shell ngay trong prompt. Cú pháp là bọc lệnh trong backtick rồi thêm dấu chấm than ở trước: !`lệnh`. Khi kích hoạt, lệnh chạy trước, output thay thế placeholder, và Claude nhận được prompt đã được ráp hoàn chỉnh.
Đây là git diff hiện tại:
!`git diff HEAD`
Hãy review các thay đổi này, tập trung vào lỗi logic và vấn đề bảo mật.
Với lệnh nhiều dòng, dùng fenced code block bắt đầu bằng
```!:```! node --version git status --short ```
Khi /review được kích hoạt, nội dung Claude thực sự nhận được là:
Đây là git diff hiện tại:
diff --git a/app/models/user.rb b/app/models/user.rb
index 3a2f1c8..9b4e2d1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -12,6 +12,9 @@ class User < ApplicationRecord
...
Hãy review các thay đổi này, tập trung vào lỗi logic và vấn đề bảo mật.
Bạn không cần copy-paste thủ công gì cả. Ngay khoảnh khắc command được kích hoạt, diff đã nằm sẵn trong đó.
---
allowed-tools: Bash(cat:*)
---
Đây là toàn bộ nội dung file hiện tại:
!`cat $ARGUMENTS`
Hãy tìm tất cả vấn đề tiềm ẩn về hiệu năng trong file này, kèm số dòng cụ thể và cách sửa.
Cách dùng: /perf app/models/order.rb
$ARGUMENTS nhận đường dẫn file, cat đọc nội dung và bơm vào. Claude lấy được code thật, không phải mô tả mơ hồ kiểu "hãy nhìn file hiện tại".
allowed-toolstrong frontmatter đã pre-authorize lệnhcat, nên khi kích hoạt sẽ không hỏi quyền. Nếu thiếu dòng này, mỗi lần chạy bạn phải bấm "Allow" thủ công. Các ví dụ phía dưới đều cần khai báo theo cùng kiểu.
Branch hiện tại và trạng thái thay đổi:
!`git status --short`
!`git log --oneline -10`
Dựa vào thông tin trên, hãy viết một mô tả PR ngắn gọn, bao gồm nội dung thay đổi và động cơ.
Command /pr này không cần bạn mô tả "tôi đã sửa cái gì" — nó tự đọc.
Tech stack của dự án:
!`cat .claude/context/stack.md`
Cấu trúc database hiện tại (các bảng quan trọng):
!`head -100 db/schema.rb`
Dựa trên ngữ cảnh trên, hãy viết script migration cho $ARGUMENTS theo đúng quy chuẩn dự án.
Hãy ghi sẵn thông tin nền của dự án vào thư mục .claude/context/, và để command đọc khi cần — không phải lặp lại mô tả dự án mỗi lần.
Kết quả lần chạy test gần nhất:
!`bundle exec rspec --format progress 2>&1 | tail -30`
Phía trên là các test đã fail. Hãy phân tích nguyên nhân gốc và đưa ra phương án sửa, đừng đụng vào bản thân test.
Khi /fix-tests được kích hoạt, nó chạy test và lấy kết quả ngay tại chỗ. Cái Claude nhìn thấy là thông báo lỗi thật.
Ghép tất cả những thứ trên lại, /review có thể làm rất chuẩn:
---
description: Review thay đổi hiện tại, tự động bơm diff và ngữ cảnh liên quan
allowed-tools: Bash(git diff:*), Bash(cat:*)
---
## Thay đổi lần này
!`git diff HEAD`
## Danh sách file bị ảnh hưởng
!`git diff HEAD --name-only`
## Tóm tắt quy chuẩn coding của dự án
!`cat .claude/context/coding-standards.md 2>/dev/null || echo "(không có file quy chuẩn)"`
---
Hãy review các thay đổi trên:
1. Tính đúng đắn về logic: edge case chưa xử lý, lỗi logic
2. Vấn đề bảo mật: SQL injection, kiểm soát quyền, lộ thông tin nhạy cảm
3. Mức độ tuân thủ quy chuẩn: có đúng coding standard của dự án không
4. Khả năng đọc: đặt tên, comment, cấu trúc
Mỗi vấn đề ghi rõ tên file, số dòng, gợi ý cụ thể. Không có vấn đề thì nói không có, đừng cố nặn ra.
Command này không cần bạn chuẩn bị bất cứ gì — khi kích hoạt, diff, danh sách file, quy chuẩn coding đều được bơm tự động.
Lệnh shell có thể fail (file không tồn tại, lệnh không có trong PATH, v.v.). Dùng || để cấp giá trị mặc định, tránh để command bị đứt giữa chừng:
!`git diff HEAD 2>/dev/null || echo "(không có thay đổi git hoặc không phải git repo)"`
!`cat .env.example 2>/dev/null || echo "(không có file .env.example)"`
!`which rspec > /dev/null 2>&1 && bundle exec rspec --dry-run 2>&1 | head -20 || echo "(không phát hiện thấy RSpec)"`
Khi lệnh fail, Claude nhận được dòng giải thích thay vì khoảng trống, và có thể điều chỉnh hướng trả lời theo đó.
Output của lệnh ! sẽ vào hết context window. Một vài cái bẫy thường gặp:
Đừng cat cả file lớn
# Nguy hiểm: có thể bơm vào hàng vạn dòng
!`cat db/schema.rb`
# Tốt hơn: chỉ lấy phần cần thiết
!`grep -A 5 "create_table \"orders\"" db/schema.rb`
File log thì giới hạn số dòng
!`tail -50 log/development.log`
Cắt bớt output test
!`bundle exec rspec 2>&1 | tail -40`
Ngữ cảnh càng chính xác, câu trả lời của Claude càng tốt. Nhét cả codebase vào không làm nó thông minh hơn, chỉ khiến nó lạc lối giữa nhiễu.
Câu hỏi thường gặp: thông tin nền của dự án nên đặt vào CLAUDE.md hay bơm động bằng !?
Tiêu chí phân biệt:
| Loại thông tin | Đặt ở đâu |
|---|---|
| Nền dự án luôn cần (tech stack, cấu trúc thư mục, quy chuẩn) | CLAUDE.md |
| Trạng thái thay đổi theo thời gian (diff hiện tại, kết quả test, nội dung file) | Bơm động bằng ! |
| Nền chỉ cần cho task cụ thể (tài liệu thiết kế của một module nào đó) | !cat đọc khi cần |
CLAUDE.md là kiến thức nền lâu dài, ! là ảnh chụp tức thời tại lúc làm task. Hai cái bổ trợ nhau, đừng trùng lặp.
.claude/commands/ hoàn chỉnh.claude/
├── commands/
│ ├── review.md # Review: bơm diff + quy chuẩn
│ ├── test.md # Viết test: bơm file mục tiêu
│ ├── fix-tests.md # Sửa test: bơm kết quả fail
│ ├── pr.md # Mô tả PR: bơm git log + status
│ ├── explain.md # Giải thích code: bơm nội dung file
│ └── migrate.md # Viết migration: bơm đoạn schema
├── context/
│ ├── stack.md # Mô tả tech stack
│ └── coding-standards.md # Quy chuẩn coding
└── settings.json
Thư mục context/ chứa các file nền tĩnh để các command đọc khi cần. Cấu trúc này có thể commit thẳng vào git và chia sẻ cho cả team.
Command tĩnh:
Hãy review các thay đổi code hiện tại.
Claude phải hỏi trước "thay đổi nằm ở đâu", hoặc tự đi tìm — kết quả không ổn định.
Command có ngữ cảnh:
Đây là diff (kèm nội dung thật), đây là quy chuẩn liên quan (kèm nội dung thật), hãy review.
Claude bắt đầu phân tích ngay — câu trả lời chính xác, không lan man, không cần qua lại xác nhận.
Khác biệt không nằm ở năng lực của Claude, mà ở chỗ bạn đã đưa cho nó bao nhiêu thông tin thật.