Slash Command ขั้นสูง: ทำให้คำสั่งเข้าใจบริบท

ใช้ prefix ! รันคำสั่ง shell ภายใน slash command เพื่อแทรก diff, เนื้อหาไฟล์ และผลการทดสอบโดยอัตโนมัติ


slash command ของคนส่วนใหญ่มักจะหน้าตาแบบนี้:

รีวิวคุณภาพของโค้ดที่เปลี่ยนแปลงในตอนนี้ และให้คำแนะนำที่เป็นรูปธรรม

แบบนี้ก็ใช้ได้ แต่มีข้อจำกัดพื้นฐาน: Claude ต้องคาดเดาเองว่า "การเปลี่ยนแปลงในตอนนี้คืออะไร" ถ้า command ของคุณสามารถยัดบริบทเข้าไปให้ตรงๆ ได้เลย ผลลัพธ์จะต่างกันโดยสิ้นเชิง

บทความนี้พูดถึงวิธีทำให้ command กลายเป็นคำสั่งที่ "มีตา" — เมื่อทริกเกอร์แล้ว มันจะอ่านเนื้อหาไฟล์ สถานะ git ข้อมูลโปรเจ็กต์โดยอัตโนมัติ แล้วยัดทุกอย่างเข้าไปใน prompt เพื่อที่ Claude จะได้ไม่ต้องเดา


กลไกหลัก: !`คำสั่ง` ฉีดเอาต์พุตของ shell

custom slash command รองรับการฝังคำสั่ง shell ลงใน prompt โดยตรง ไวยากรณ์คือล้อมคำสั่งด้วย backtick แล้วเติมเครื่องหมายตกใจไว้ข้างหน้า: !`คำสั่ง` เมื่อทริกเกอร์ คำสั่งจะถูกรันก่อน เอาต์พุตจะแทนที่ตัว placeholder และ Claude จะได้รับ prompt ที่ประกอบเสร็จเรียบร้อยแล้ว

นี่คือ git diff ปัจจุบัน:

!`git diff HEAD`

ช่วยรีวิวการเปลี่ยนแปลงเหล่านี้ โดยเน้นที่บั๊กเชิงตรรกะและปัญหาด้านความปลอดภัย

สำหรับคำสั่งหลายบรรทัด ให้ใช้ fenced code block ที่ขึ้นต้นด้วย ```!:

```!
node --version
git status --short
```

เมื่อทริกเกอร์ /review เนื้อหาที่ Claude ได้รับจริงๆ คือ:

นี่คือ git diff ปัจจุบัน:

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
...

ช่วยรีวิวการเปลี่ยนแปลงเหล่านี้ โดยเน้นที่บั๊กเชิงตรรกะและปัญหาด้านความปลอดภัย

ไม่ต้องคัดลอกวางเองเลย ทันทีที่ command ทริกเกอร์ diff ก็อยู่ในนั้นเรียบร้อยแล้ว


รูปแบบใช้งานจริง

ฉีดเนื้อหาของไฟล์ปัจจุบัน

---
allowed-tools: Bash(cat:*)
---

นี่คือเนื้อหาทั้งหมดของไฟล์ปัจจุบัน:

!`cat $ARGUMENTS`

หาปัญหาด้านประสิทธิภาพที่อาจเกิดขึ้นทั้งหมดในไฟล์นี้ พร้อมระบุหมายเลขบรรทัดและวิธีแก้ที่เป็นรูปธรรม

วิธีใช้: /perf app/models/order.rb

$ARGUMENTS รับ path ของไฟล์ cat อ่านเนื้อหาแล้วฉีดเข้าไป Claude ได้รับโค้ดจริง ไม่ใช่คำอธิบายคลุมเครืออย่าง "ดูไฟล์ปัจจุบัน"

allowed-tools ใน frontmatter ได้ pre-authorize คำสั่ง cat ไว้แล้ว เวลาทริกเกอร์จะไม่มีการถาม permission ขึ้นมา ถ้าไม่มีบรรทัดนี้ ทุกครั้งที่รันคุณต้องกด "Allow" เอง ตัวอย่างด้านล่างทั้งหมดต้องประกาศในรูปแบบเดียวกัน

ฉีดสถานะ git

branch ปัจจุบันและสถานะการเปลี่ยนแปลง:

!`git status --short`
!`git log --oneline -10`

จากข้อมูลข้างต้น ช่วยสร้างคำอธิบาย PR ที่กระชับ ครอบคลุมเนื้อหาการเปลี่ยนแปลงและเหตุผลที่ทำ

command /pr นี้ไม่ต้องให้คุณบรรยาย "ฉันแก้อะไรบ้าง" — มันอ่านเอง

ฉีดข้อมูลเฉพาะของโปรเจ็กต์

tech stack ของโปรเจ็กต์:

!`cat .claude/context/stack.md`

โครงสร้างฐานข้อมูลปัจจุบัน (ตารางหลัก):

!`head -100 db/schema.rb`

จากบริบทข้างต้น ช่วยเขียน migration script สำหรับ $ARGUMENTS ตามมาตรฐานของโปรเจ็กต์

เขียนข้อมูลพื้นหลังของโปรเจ็กต์ไว้ในไดเรกทอรี .claude/context/ ก่อน แล้วให้ command อ่านตามที่ต้องการ ไม่ต้องอธิบายโปรเจ็กต์ซ้ำทุกครั้ง

อ่านผลการ test แบบ dynamic

ผลการรัน test ครั้งล่าสุด:

!`bundle exec rspec --format progress 2>&1 | tail -30`

ข้างบนคือ test ที่ fail วิเคราะห์สาเหตุที่แท้จริงและให้แนวทางแก้ไข อย่าไปแก้ที่ตัว test เอง

เมื่อ /fix-tests ทริกเกอร์ มันจะรัน test และดึงผลทันที สิ่งที่ Claude เห็นคือข้อความ error จริงๆ


ตัวอย่างเต็ม: code review ที่รับรู้บริบท

รวมทุกอย่างข้างบนเข้าด้วยกัน /review สามารถทำได้แม่นยำพอสมควร:

---
description: รีวิวการเปลี่ยนแปลงปัจจุบัน ฉีด diff และบริบทที่เกี่ยวข้องโดยอัตโนมัติ
allowed-tools: Bash(git diff:*), Bash(cat:*)
---

## การเปลี่ยนแปลงครั้งนี้

!`git diff HEAD`

## รายชื่อไฟล์ที่ได้รับผลกระทบ

!`git diff HEAD --name-only`

## สรุปมาตรฐานการเขียนโค้ดของโปรเจ็กต์

!`cat .claude/context/coding-standards.md 2>/dev/null || echo "(ไม่มีไฟล์มาตรฐาน)"`

---

ช่วยรีวิวการเปลี่ยนแปลงข้างต้น:

1. ความถูกต้องเชิงตรรกะ: เคสขอบที่ยังไม่ได้จัดการ บั๊กเชิงตรรกะ
2. ปัญหาด้านความปลอดภัย: SQL injection การตรวจสิทธิ์ การเปิดเผยข้อมูลที่ละเอียดอ่อน
3. การปฏิบัติตามมาตรฐาน: ตรงตาม coding standard ของโปรเจ็กต์หรือไม่
4. ความอ่านง่าย: การตั้งชื่อ comment โครงสร้าง

แต่ละปัญหาให้ระบุชื่อไฟล์ หมายเลขบรรทัด คำแนะนำที่เป็นรูปธรรม ถ้าไม่มีปัญหาก็บอกว่าไม่มี อย่าหามาเติม

command นี้ไม่ต้องการให้คุณเตรียมอะไรเลย — เมื่อทริกเกอร์ diff รายชื่อไฟล์ และมาตรฐานการเขียนโค้ดทั้งหมดจะถูกฉีดเข้ามาโดยอัตโนมัติ


จัดการกรณีคำสั่ง fail

คำสั่ง shell อาจ fail ได้ (ไฟล์ไม่มี คำสั่งไม่อยู่ใน PATH ฯลฯ) ใช้ || เพื่อให้ค่า default ป้องกันไม่ให้ command หยุดทำงานกลางคัน:

!`git diff HEAD 2>/dev/null || echo "(ไม่มีการเปลี่ยนแปลง git หรือไม่ได้อยู่ใน git repo)"`
!`cat .env.example 2>/dev/null || echo "(ไม่มีไฟล์ .env.example)"`
!`which rspec > /dev/null 2>&1 && bundle exec rspec --dry-run 2>&1 | head -20 || echo "(ตรวจไม่พบ RSpec)"`

เมื่อคำสั่ง fail Claude จะได้รับข้อความอธิบายแทนที่จะเป็นช่องว่าง และสามารถปรับกลยุทธ์การตอบได้


เรื่องประสิทธิภาพ: อย่าฉีดมากเกินไป

เอาต์พุตของคำสั่ง ! จะเข้าสู่ context window ทั้งหมด หลุมพรางที่พบบ่อย:

อย่า cat ไฟล์ใหญ่ทั้งไฟล์

# อันตราย: อาจฉีดเข้าไปหลายหมื่นบรรทัด
!`cat db/schema.rb`

# ดีกว่า: เอาเฉพาะส่วนที่ต้องการ
!`grep -A 5 "create_table \"orders\"" db/schema.rb`

ไฟล์ log ให้จำกัดจำนวนบรรทัด

!`tail -50 log/development.log`

ตัดเอาต์พุตของ test

!`bundle exec rspec 2>&1 | tail -40`

context ยิ่งแม่นยำ คำตอบของ Claude ก็ยิ่งดี การยัด codebase ทั้งหมดเข้าไปไม่ได้ทำให้มันฉลาดขึ้น มีแต่จะทำให้มันหลงทางอยู่ในเสียงรบกวน


การแบ่งบทบาทกับ CLAUDE.md

คำถามที่พบบ่อย: ข้อมูลพื้นหลังของโปรเจ็กต์ควรอยู่ใน CLAUDE.md หรือใช้ ! ฉีดแบบ dynamic?

เกณฑ์การตัดสิน:

ประเภทข้อมูล ใส่ที่ไหน
พื้นหลังโปรเจ็กต์ที่ต้องใช้ทุกครั้ง (tech stack โครงสร้างไดเรกทอรี มาตรฐาน) CLAUDE.md
สถานะที่เปลี่ยนตามเวลา (diff ปัจจุบัน ผล test เนื้อหาไฟล์) ฉีดแบบ dynamic ด้วย !
พื้นหลังเฉพาะงาน (เอกสารออกแบบของโมดูลใดโมดูลหนึ่ง) !cat อ่านตามต้องการ

CLAUDE.md คือความรู้พื้นหลังที่คงอยู่ ส่วน ! คือ snapshot สดในขณะทำงาน ทั้งสองเสริมกัน อย่าทำซ้ำ


ไดเรกทอรี .claude/commands/ ที่สมบูรณ์

.claude/
├── commands/
│   ├── review.md        # รีวิว: ฉีด diff + มาตรฐาน
│   ├── test.md          # เขียน test: ฉีดไฟล์เป้าหมาย
│   ├── fix-tests.md     # แก้ test: ฉีดผลที่ fail
│   ├── pr.md            # คำอธิบาย PR: ฉีด git log + status
│   ├── explain.md       # อธิบายโค้ด: ฉีดเนื้อหาไฟล์
│   └── migrate.md       # เขียน migration: ฉีดส่วน schema
├── context/
│   ├── stack.md         # คำอธิบาย tech stack
│   └── coding-standards.md  # มาตรฐานการเขียนโค้ด
└── settings.json

ไดเรกทอรี context/ เก็บไฟล์พื้นหลังแบบ static ให้ command ต่างๆ อ่านตามต้องการ โครงสร้างแบบนี้สามารถ commit เข้า git ได้เลย เพื่อให้ทีมใช้ร่วมกัน


เปรียบเทียบผลลัพธ์

command แบบ static:

ช่วยรีวิวการเปลี่ยนแปลงโค้ดในตอนนี้

Claude ต้องถามก่อนว่า "การเปลี่ยนแปลงอยู่ที่ไหน" หรือไปหาเอง ผลลัพธ์ไม่แน่นอน

command ที่รับรู้บริบท:

นี่คือ diff (มีเนื้อหาจริง) นี่คือมาตรฐานที่เกี่ยวข้อง (มีเนื้อหาจริง) ช่วยรีวิว

Claude เริ่มวิเคราะห์ทันที — คำตอบแม่นยำ ไม่พูดเพ้อเจ้อ ไม่ต้องไป-มาเพื่อยืนยัน

ความต่างไม่ได้อยู่ที่ความสามารถของ Claude แต่อยู่ที่ว่าคุณให้ข้อมูลจริงกับมันมากแค่ไหน