# Claude Code Plugin Eval: Menguji Skill yang Tak Pernah Aktif

> Plugin adalah dependency yang dipasang orang lain, jadi yang dibutuhkan bukan demo tapi test suite. Bentuk sebuah eval case, kenapa ablation arm tanpa plugin adalah bagian yang benar-benar menguji activation, dan cacat yang lolos kalau langkah ini dilewati.

URL: https://www.matthewswong.com/id/blog/claude-code-plugin-eval-test-suite/

- Author: Matthews Wong (https://www.matthewswong.com/id/about/)
- Published: 2026-09-06
- Updated: 2026-09-06
- Category: Software Development

> **Key takeaway:** Command claude plugin eval di Claude Code menjalankan eval case yang dinilai terhadap sebuah plugin dan, secara default, menjalankan ulang setiap case tanpa plugin apa pun. Arm kedua itulah yang membuktikan plugin benar-benar berpengaruh. Plugin yang dirilis tanpa langkah ini gagal tanpa suara: skill terpasang, tidak pernah aktif, dan tidak ada yang melapor.

Saya merilis sebuah plugin ke tiga rekan kerja dan dua minggu berikutnya sunyi. Tidak ada laporan bug, tidak ada pertanyaan, tidak ada keluhan. Ketika akhirnya saya tanya, ketiganya sudah memasang dan mengaktifkannya, dan tidak satu pun pernah melihat plugin itu melakukan apa-apa. Skill di dalamnya sama sekali belum pernah aktif.

Plugin adalah dependency yang dipasang orang lain, dan itu sebabnya yang dibutuhkan adalah test suite, bukan demo. Tulisan ini membahas bentuk sebuah eval case, cara membaca ablation arm tanpa plugin, apa yang diberikan report dan exit code untuk CI, serta cacat di balik dua minggu sunyi saya. Belum ada halaman dokumentasi publik untuk claude plugin eval, jadi semua flag dan path di bawah ini saya ambil dari claude plugin eval --help pada Claude Code 2.1.259, dan saya sebutkan setiap kali sebuah klaim tidak ada di dokumentasi resmi.

## Apa yang sebenarnya dibuktikan oleh install yang lancar

Semua pemeriksaan yang saya jalankan sebelum merilis adalah pemeriksaan struktur. Flag --plugin-dir memuat direktorinya, skill muncul di menu help dengan namespace-nya, mengetik slash command secara manual menghasilkan output yang saya inginkan, dan claude plugin validate lolos. Keempat hal itu sama benarnya untuk plugin yang tidak akan pernah dipicu siapa pun, dan justru bagian itu yang tidak saya pikirkan.

Dokumentasi skills merangkum celahnya dalam satu kalimat: melihat sebuah skill aktif hanya membuktikan Claude menemukannya, bukan bahwa hasilnya sesuai maksud Anda. Kebalikannya justru yang lebih mahal, dan tidak ada validator yang menjangkaunya. Description adalah persoalan pencocokan — mirip atau tidak mirip dengan kalimat yang diketik pengguna Anda — dan mem-parse frontmatter tidak bisa membedakan description yang cocok dengan prompt nyata dari description yang berbunyi seperti nama file.

## Sebuah eval case adalah satu prompt plus sekumpulan grader

Eval suite adalah direktori berisi case, dan satu case adalah satu prompt plus kriteria untuk menilai jawabannya. Harness membacanya dari eval dir, default-nya evals/, yang bisa dipindah dengan --eval-dir atau lewat manifest plugin. Setiap direktori case berisi case.yaml, atau pasangan yang lebih sederhana seperti yang disebut help text untuk template kosong: satu prompt.md yang isi filenya adalah prompt itu sendiri, dan satu direktori graders/ berisi file markdown yang frontmatter-nya menyatakan type.

Tulis prompt seperti kalimat yang benar-benar akan dikirim pengguna, dan tahan keinginan menyebut nama skill Anda sendiri di dalamnya. Menyebut namanya adalah draf pertama saya untuk setiap case, dan itu lebih buruk daripada tidak punya test sama sekali: prompt yang berbunyi pakai skill format-receipt hanya menilai isi skill yang sudah Anda suruh Claude muat. Simpan juga satu case yang skill Anda harus diam, karena suite yang isinya hanya prompt should-trigger memberi nilai bagus pada description yang aktif di segala hal.

## Ablation arm adalah bagian yang menguji activation

Default-nya dua arm per case, bukan satu. Setiap kali target berhasil di-resolve sebagai plugin — lewat path, lewat nama, atau lewat pasangan plugin dan marketplace — harness menambahkan baseline arm tanpa plugin dan melaporkan selisih skor antara keduanya. Memberi --ablation none mengembalikannya ke penilaian satu arm, tapi selisih itulah angka yang berharga, karena hanya selisih yang memisahkan plugin yang berguna dari model yang sebenarnya sudah bisa mengerjakannya sendiri.

Ini metode yang sama dengan yang disarankan dokumentasi skills secara manual: kumpulkan prompt yang realistis, jalankan masing-masing di session baru dengan skill tersedia lalu ulangi dengan skill dimatikan, kemudian bandingkan. Session baru itu penting, karena context sisa dari proses menulis skill menutupi lubang pada instruksi yang sebenarnya Anda tulis. Harness melakukannya per case dan tiga kali masing-masing secara default, jumlah pengulangan yang kira-kira sama dengan batas kesabaran saya kalau dikerjakan manual.

## Membaca kegagalan: threshold, report, exit code

Satu run menulis aggregate result di bawah eval dir dan sebuah HTML report yang berdiri sendiri sehingga bisa dikirim ke mana saja. Untuk sebuah gate, dua flag yang penting adalah --threshold, yang keluar dengan exit 1 begitu ada case bernilai di bawah angka yang Anda beri, dan --max-cost-usd, yang membatalkan run dengan exit 2 serta melaporkan hasil sebagian ketimbang membiarkan biaya membengkak. Default threshold adalah 1.0, lebih ketat daripada yang bisa dilewati suite nyata mana pun, jadi pilih angka yang memang Anda rela pakai untuk memblokir rilis.

Baca case yang gagal dari type grader-nya dulu sebelum membaca skornya, karena enam type itu gagal dengan alasan yang berbeda dan hanya dua di antaranya berbiaya. Help text menyebut dengan jelas bahwa llm dan baseline adalah grader berbayar: ketika batas biaya tembus di tengah run, keduanya dilewati dan grader gratis tetap menilai run tersebut. Rancang suite Anda mengikuti asimetri itu. Taruh assertion mekanis yang murah pada perilaku yang paling Anda pedulikan, dan simpan kriteria berbentuk prosa untuk bagian yang hanya bisa dinilai model.

| Type grader | Apa yang dipastikannya | Apa yang tidak bisa dijawabnya |
| --- | --- | --- |
| regex | Jawaban memuat, tidak memuat, atau memuat tepat N kali sebuah pattern yang Anda tulis | Apakah kata-kata yang cocok itu muncul karena alasan yang benar |
| tool_order | Satu tool dipanggil sebelum tool lain di dalam trace run | Apakah salah satu dari dua panggilan itu memang perlu |
| tool_used | Sebuah tool dipanggil, dan berapa kali ia dipanggil | Apa yang diminta ke tool itu, atau apa yang dikembalikannya |
| file_exists | Run meninggalkan file di lokasi yang disebut case | Apa pun tentang isi file tersebut |
| llm | Sebuah model menilai jawaban terhadap kriteria lulus yang Anda tulis dalam prosa | Apa pun yang bisa diulang dari satu run saja, dan itu alasan default runs-nya tiga |
| baseline | Jawaban dinilai terhadap sebuah referensi, bukan terhadap kriteria tertulis | Apakah referensi itu masih jawaban yang Anda inginkan hari ini |

*Sebagian besar plugin dirilis hanya berdasarkan tiga band pertama, dan ketiganya sudah terpenuhi oleh plugin yang tidak pernah dijangkau prompt apa pun. Hanya band keempat yang mengajukan pertanyaan yang dijawab band terakhir.*

> Jalankan suite baru sekali dengan --ablation none sebelum mempercayai selisih apa pun. Case yang skornya buruk di kedua arm biasanya berarti case-nya rusak, bukan plugin-nya, dan angka satu arm memberi tahu Anda yang mana tanpa harus membaca dua kolom penilaian grader.

## Hal-hal yang harness menolak lakukan untuk Anda

Kejutan yang menyenangkan adalah betapa sedikitnya eval harness ini mempercayai file case. Bash, Write, Edit, WebFetch dan semua tool MCP dijaga di balik operator grant yang eksplisit di command line, dan grant itu menerima pattern, bukan seluruh tool. Sebuah case juga boleh membawa scaffold script untuk menyiapkan fixture-nya, dan script itu berjalan sebagai Anda, jadi ia tidak dieksekusi sama sekali kecuali Anda memberi --scaffold. Help text menyebutkannya terang-terangan: pakai hanya pada file case yang Anda tulis sendiri.

Server MCP diberi stand-in secara default, dibaca dari direktori mocks di dalam eval dir, dan itulah bedanya antara suite yang bisa dijalankan setiap rilis dengan suite yang membuat ticket sungguhan setiap kali. Mematikan mocks akan menjalankan server yang sebenarnya, tetap dijaga oleh --allow-tools, jadi ada dua kunci antara file case dan Jira production Anda. Kalau sebuah run berperilaku aneh, --keep-temp menyimpan direktori scaffold sehingga Anda bisa membaca apa yang benar-benar dilakukan case itu.

> Eval run tidak gratis dan default-nya berlipat. Setiap case berjalan tiga kali kecuali Anda ubah, kedua ablation arm berjalan untuk masing-masingnya, dan setiap grader llm atau baseline adalah panggilan model tambahan. Pasang --max-cost-usd pada run pertama suite baru, bukan setelah tagihan datang: batas itu membatalkan run dengan exit 2 dan tetap melaporkan hasil sebagiannya.

## Memasangnya di CI sebagai release gate

Pecah gate-nya jadi dua, karena kedua bagian punya biaya yang sangat berbeda. Command validate gratis, non-interaktif dan cepat, jadi tempatnya di setiap push. Saya mengukurnya keluar dengan exit 0 saat ada warning dan exit 1 dengan --strict, sehingga versi --strict itulah yang layak dipasang di job. Suite yang dinilai memanggil model, jadi ia menjaga release tag, dan claude plugin tag memberi Anda bentuk tag untuk dicocokkan: ia menulis tag berisi nama dan versi hanya setelah plugin.json dan entry marketplace di sekitarnya sepakat.

Satu catatan jujur soal workflow itu. Command eval masih early access. Di akun saya, command-nya ada, flag-nya terbaca, lalu ia keluar dengan exit 1 dan pesan bahwa plugin eval sedang early access, jadi job di atas adalah gate yang strukturnya saya tulis dan periksa, bukan yang sudah saya lihat berwarna hijau. Bagian validate berjalan hari ini di semua install sejak v2.1.233, versi yang mengajarinya memeriksa frontmatter di direktori skills tanpa manifest.

*Panel ketiga adalah yang paling layak diperdebatkan. Setiap barisnya adalah satu cara agar plugin yang sudah melewati kedua gate tetap tidak melakukan apa-apa di mesin orang lain.*

## Cacat yang lolos kalau langkah ini dilewati

Dua minggu sunyi saya punya satu penyebab: description yang ditulis untuk saya sendiri, bukan untuk orang yang akan memasangnya. Description itu menjelaskan skill-nya dengan kosakata skill tersebut, sementara rekan kerja saya mengetik kosakata masalah mereka. Kedua sisi tidak salah dan tidak ada yang error, dan justru karena itu masalahnya bertahan dua minggu. Tooling Anthropic sendiri memperlakukan ini sebagai cacat utama sebuah skill. Plugin skill-creator menghasilkan prompt should-trigger dan should-not-trigger, mengukur hit rate-nya, lalu mengusulkan perbaikan description, dan Anthropic melaporkan bahwa penerapannya pada enam skill pembuat dokumen yang publik memperbaiki triggering pada lima di antaranya.

Ada versi lanjutan dari kegagalan yang sama, yang tidak bisa ditangkap eval case mana pun di mesin Anda, karena kejadiannya sebelum model membaca description Anda. Claude Code memuat nama dan description skill ke dalam sebuah listing dengan budget satu persen dari context window model, dan ketika listing itu melebihi budget, description mulai dibuang dari skill yang paling jarang Anda panggil. Plugin Anda, menurut definisinya, adalah yang paling jarang dipanggil pengguna baru — jadi di mesin yang sibuk ia bisa tercantum hanya dengan namanya, tanpa satu pun keyword yang seharusnya cocok dengan prompt. Empat pemeriksaan berikut sekarang berdiri antara plugin saya dan sebuah rilis.

1. Tulis dua case per skill sebelum menulis fitur ketiga: satu prompt yang harus diklaim skill itu, dengan kata-kata orang lain dan bukan kata-kata Anda, dan satu prompt serupa yang skill itu harus diam.
2. Jalankan suite dengan ablation arm aktif dan baca selisihnya, bukan skornya. Case yang lolos di kedua arm berarti skill itu tidak menopang apa-apa; case yang gagal di kedua arm berarti case-nya yang salah.
3. Periksa indikator activation, bukan hanya angkanya. Grader with-only pada tool Skill yang tidak pernah menyala berarti plugin-nya tidak pernah aktif, dan itu bug yang berbeda dari aktif lalu menjawab dengan buruk.
4. Buka laporan context di mesin yang sudah punya banyak skill lain, baca baris Skills, dan taruh use case utama di awal description supaya pemotongan mengambil kata-kata yang paling tidak berguna, bukan keyword Anda.

Aturan yang saya bawa dari kejadian ini pendek: plugin adalah dependency, dan dependency yang gagal tanpa suara lebih buruk daripada yang crash. Uji activation sebelum perilaku, simpan satu case should-not-trigger per skill, jaga setiap push dengan pemeriksaan struktur yang gratis dan release tag dengan suite yang dinilai, lalu baca selisihnya alih-alih skornya. Plugin yang tidak diuji tidak gagal dengan berisik. Ia hanya duduk di sana, terpasang dan mati, sementara semua orang menganggapnya bekerja.

## Sumber dan bacaan lanjutan

- Dokumentasi Claude Code — Agent Skills, termasuk cara mengevaluasi dan menyempurnakan sebuah skill
- Dokumentasi Claude Code — Create plugins, termasuk pengujian lokal dan validasi
- Dokumentasi Claude Code — Plugins reference, termasuk debugging and development tools
- Plugin skill-creator — anthropics/claude-plugins-official di GitHub
- Anthropic — Improving skill-creator: test, measure and refine agent skills

## Source links

- https://code.claude.com/docs/en/skills
- https://code.claude.com/docs/en/plugins
- https://code.claude.com/docs/en/plugins-reference
- https://github.com/anthropics/claude-plugins-official/tree/main/plugins/skill-creator
- https://claude.com/blog/improving-skill-creator-test-measure-and-refine-agent-skills

## FAQ

### Apa sebenarnya yang dilakukan claude plugin eval?

Ia menjalankan eval case yang dinilai terhadap sebuah plugin Claude Code dan melaporkan skor untuk masing-masingnya. Satu case adalah satu prompt plus direktori graders yang menyatakan seperti apa jawaban yang baik, dan harness membacanya dari eval dir, default-nya evals/. Secara default ia juga menjalankan setiap case sekali lagi tanpa plugin apa pun, jadi angka yang Anda baca adalah perbandingan, bukan skor mutlak.

### Kenapa skill di plugin saya tidak pernah aktif padahal install-nya lancar?

Hampir selalu karena description-nya tidak mirip kalimat yang diketik pengguna Anda. Install, loading dan validasi manifest semuanya lolos untuk plugin yang tidak akan pernah dipicu siapa pun, jadi tidak ada error dan tidak ada yang melapor. Penyebab umum lainnya adalah budget skill listing: Claude Code memasukkan description skill ke sekitar satu persen context window dan membuang description skill yang paling jarang Anda panggil ketika budget itu terlampaui.

### Apakah claude plugin validate sudah cukup untuk menguji plugin sebelum rilis?

Belum, tapi tetap layak dijalankan di setiap push karena gratis dan cepat. Ia memeriksa manifest, file hooks, serta frontmatter skill, agent dan command Anda untuk kesalahan sintaks dan schema. Ia sama sekali tidak memeriksa apakah sebuah description akan cocok dengan prompt nyata, dan justru itu cacat yang paling sering lolos. Tambahkan --strict kalau Anda ingin warning ikut menggagalkan job.

### Bagaimana supaya biaya eval run tidak lebih besar dari perkiraan?

Pasang --max-cost-usd, yang membatalkan run dengan exit code 2 dan tetap melaporkan hasil sebagiannya. Default-nya berlipat dengan cepat: setiap case berjalan tiga kali kecuali Anda ubah dengan --runs, kedua ablation arm berjalan untuk masing-masingnya, dan grader llm serta baseline adalah panggilan model. Grader regex, tool_order, tool_used dan file_exists gratis, jadi manfaatkan itu sebisa mungkin.

### Bisakah claude plugin eval dipakai sebagai CI gate sekarang?

Command eval masih early access, jadi di akun yang belum diaktifkan, command-nya membaca flag lalu keluar dengan exit 1 dan menyebutkan hal itu. Gate yang bisa Anda pasang hari ini adalah claude plugin validate --strict di setiap push, ditambah claude plugin tag saat rilis, dan satu job eval yang menyala begitu akun Anda punya akses. Pakai --threshold untuk menentukan skor yang memblokir rilis dan --no-publish agar HTML report tidak terbit ke claude.ai.

---

- HTML version: https://www.matthewswong.com/id/blog/claude-code-plugin-eval-test-suite/
- English: https://www.matthewswong.com/en/blog/claude-code-plugin-eval-test-suite/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
