Slash Command Lanjutan: Membuat Perintah yang Memahami Konteks

Gunakan prefiks ! untuk menjalankan perintah shell di dalam slash command, otomatis menyuntikkan diff, isi file, dan hasil test ke prompt


Slash command kebanyakan orang biasanya seperti ini:

Tinjau kualitas perubahan kode saat ini dan beri saran konkret.

Ini bisa jalan, tapi ada batas mendasarnya: Claude harus menebak sendiri "perubahan saat ini itu apa". Kalau command Anda bisa langsung menyuntikkan konteks ke dalamnya, hasilnya akan sangat berbeda.

Artikel ini membahas cara membuat command yang "punya mata" — saat dipicu, ia otomatis membaca isi file, status git, info proyek, lalu menjejalkan semuanya ke dalam prompt sehingga Claude tidak perlu menebak.


Mekanisme inti: !`perintah` menyuntikkan output shell

Custom slash command mendukung penyematan perintah shell di dalam prompt. Sintaksnya: bungkus perintah dengan backtick lalu beri tanda seru di depannya — !`perintah`. Saat dipicu, perintah dijalankan terlebih dahulu, outputnya menggantikan placeholder, dan Claude menerima prompt yang sudah jadi.

Berikut git diff saat ini:

!`git diff HEAD`

Tinjau perubahan ini, fokus pada bug logika dan masalah keamanan.

Untuk perintah multi-baris, gunakan fenced code block yang diawali ```!:

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

Saat /review dipicu, isi yang sebenarnya diterima Claude adalah:

Berikut git diff saat ini:

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

Tinjau perubahan ini, fokus pada bug logika dan masalah keamanan.

Anda tidak perlu menyalin-tempel apa pun. Begitu command dipicu, diff sudah ada di dalamnya.


Pola yang berguna

Suntikkan isi file saat ini

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

Berikut isi lengkap file saat ini:

!`cat $ARGUMENTS`

Temukan semua potensi masalah performa di file ini, sebutkan nomor baris dan saran perbaikan konkret.

Cara pakai: /perf app/models/order.rb

$ARGUMENTS menerima path file, cat membaca isinya dan menyuntikkannya. Claude mendapatkan kode asli, bukan deskripsi samar seperti "lihat file saat ini".

allowed-tools di frontmatter sudah memberi otorisasi untuk perintah cat, jadi tidak ada konfirmasi izin yang muncul saat dipicu. Tanpa baris ini, Anda harus menekan "Allow" setiap kali dijalankan. Contoh-contoh berikut perlu dideklarasikan dengan cara yang sama.

Suntikkan status git

Branch saat ini dan status perubahan:

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

Berdasarkan info di atas, buat deskripsi PR yang ringkas, mencakup isi perubahan dan motivasinya.

Command /pr ini tidak menuntut Anda menjelaskan "saya mengubah apa" — ia membacanya sendiri.

Suntikkan info khusus proyek

Stack teknologi proyek:

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

Skema database saat ini (tabel inti):

!`head -100 db/schema.rb`

Berdasarkan latar belakang di atas, tulis script migrasi untuk $ARGUMENTS sesuai konvensi proyek.

Tulis info latar proyek lebih dulu di direktori .claude/context/, lalu biarkan command membacanya saat dibutuhkan, tanpa harus mengulang deskripsi proyek setiap kali.

Baca hasil tes secara dinamis

Hasil run tes terakhir:

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

Di atas adalah tes yang gagal. Analisis akar masalahnya dan beri solusi perbaikan, jangan ubah tesnya.

Saat /fix-tests dipicu, ia langsung menjalankan tes dan mengambil hasilnya. Yang dilihat Claude adalah pesan error sungguhan.


Contoh lengkap: review kode yang sadar konteks

Gabungkan semua yang di atas, dan /review bisa jadi cukup tajam:

---
description: Tinjau perubahan saat ini, otomatis suntikkan diff dan latar terkait
allowed-tools: Bash(git diff:*), Bash(cat:*)
---

## Perubahan kali ini

!`git diff HEAD`

## Daftar file yang terdampak

!`git diff HEAD --name-only`

## Ringkasan konvensi coding proyek

!`cat .claude/context/coding-standards.md 2>/dev/null || echo "(tidak ada file konvensi)"`

---

Tinjau perubahan di atas:

1. Kebenaran logika: edge case yang tidak ditangani, bug logika
2. Masalah keamanan: SQL injection, otorisasi, kebocoran data sensitif
3. Kepatuhan konvensi: apakah sesuai gaya proyek
4. Keterbacaan: penamaan, komentar, struktur

Untuk setiap masalah, sebutkan nama file, nomor baris, dan saran konkret. Kalau tidak ada masalah, katakan tidak ada — jangan dibuat-buat.

Command ini tidak butuh persiapan apa pun. Saat dipicu, diff, daftar file, dan konvensi coding semuanya disuntikkan otomatis.


Menangani perintah yang gagal

Perintah shell bisa gagal (file tidak ada, perintah tidak ada di PATH, dll.). Pakai || untuk memberi nilai default agar command tidak terhenti karenanya:

!`git diff HEAD 2>/dev/null || echo "(tidak ada perubahan git atau bukan repo git)"`
!`cat .env.example 2>/dev/null || echo "(file .env.example tidak ada)"`
!`which rspec > /dev/null 2>&1 && bundle exec rspec --dry-run 2>&1 | head -20 || echo "(RSpec tidak terdeteksi)"`

Saat perintah gagal, Claude menerima teks penjelasan, bukan kekosongan, sehingga ia bisa menyesuaikan strateginya.


Pertimbangan performa: jangan terlalu banyak menyuntikkan

Output dari perintah ! semuanya masuk ke context window. Beberapa jebakan yang umum:

Jangan cat file besar utuh-utuh

# Bahaya: bisa menyuntikkan puluhan ribu baris
!`cat db/schema.rb`

# Lebih baik: hanya ambil bagian yang dibutuhkan
!`grep -A 5 "create_table \"orders\"" db/schema.rb`

Batasi jumlah baris untuk file log

!`tail -50 log/development.log`

Potong output tes

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

Semakin presisi konteksnya, semakin baik jawaban Claude. Menjejalkan seluruh codebase tidak membuatnya lebih pintar — hanya membuatnya tersesat di tengah noise.


Pembagian kerja dengan CLAUDE.md

Pertanyaan umum: info latar proyek sebaiknya ditaruh di CLAUDE.md atau disuntikkan dinamis lewat !?

Patokannya:

Tipe info Letakkan di mana
Latar proyek yang selalu dibutuhkan (stack, struktur direktori, konvensi) CLAUDE.md
State yang berubah seiring waktu (diff saat ini, hasil tes, isi file) Suntikkan dinamis lewat !
Latar yang hanya dibutuhkan untuk tugas tertentu (dokumen desain modul tertentu) Baca on-demand dengan !cat

CLAUDE.md adalah pengetahuan latar yang persisten, ! adalah snapshot real-time saat tugas dijalankan. Keduanya saling melengkapi — jangan duplikasi.


Direktori .claude/commands/ yang lengkap

.claude/
├── commands/
│   ├── review.md        # Review: suntikkan diff + konvensi
│   ├── test.md          # Tulis tes: suntikkan file target
│   ├── fix-tests.md     # Perbaiki tes: suntikkan hasil yang gagal
│   ├── pr.md            # Deskripsi PR: suntikkan git log + status
│   ├── explain.md       # Jelaskan kode: suntikkan isi file
│   └── migrate.md       # Tulis migrasi: suntikkan potongan schema
├── context/
│   ├── stack.md         # Penjelasan stack teknologi
│   └── coding-standards.md  # Konvensi coding
└── settings.json

Direktori context/ menyimpan file latar statis untuk dibaca oleh berbagai command sesuai kebutuhan. Struktur ini bisa langsung di-commit ke git dan dibagikan ke seluruh tim.


Perbandingan hasil

Command statis:

Tinjau perubahan kode saat ini.

Claude harus bertanya dulu "perubahannya di mana", atau mencari sendiri — hasilnya tidak konsisten.

Command yang sadar konteks:

Ini diff (lengkap dengan isinya), ini konvensi terkait (lengkap dengan isinya), tolong tinjau.

Claude langsung mulai menganalisis — jawabannya presisi, tidak bertele-tele, tidak perlu konfirmasi bolak-balik.

Bedanya bukan pada kemampuan Claude, tapi pada seberapa banyak informasi nyata yang Anda berikan kepadanya.