Checklist rilis biasanya hidup di tiga tempat: halaman wiki yang nggak pernah dibuka, pesan Slack yang kamu pin dua kuartal lalu, dan satu bagian CLAUDE.md yang ikut kebaca di setiap turn. Dua yang pertama basi pelan-pelan. Yang ketiga tetap makan token walaupun hari itu kamu cuma ganti nama variabel.
Agent Skills ada buat masalah ketiga itu. Skill itu folder berisi file SKILL.md. Waktu mulai, agent cuma baca nama dan description tiap skill yang terpasang, sekitar 100 token per skill menurut estimasi spec-nya sendiri. Body-nya baru dimuat kalau ada task yang cocok. Anthropic merilis format ini sebagai open standard pada 18 Desember 2025, dan folder yang sama sekarang jalan di Claude Code, claude.ai, dan Agent SDK.
Yang biasanya rusak bukan body-nya. Yang rusak description, karena string itu satu-satunya yang dilihat model sebelum memutuskan buka file.
Yang perlu disiapkan
- Claude Code 2.x (
claude --version), atau client lain yang bisa baca format Agent Skills - Repo git buat uji coba
- python3 plus PyYAML, cuma buat validator di langkah 6
Langkah 1: Bikin foldernya
mkdir -p ~/.claude/skills/changelog-from-commits/{scripts,references}
~/.claude/skills/
└── changelog-from-commits/
├── SKILL.md # wajib
├── scripts/collect.py # kerjaan deterministik
└── references/grouping.md
Skill personal di ~/.claude/skills/ kepakai di semua project di mesin kamu. Skill project di .claude/skills/ kepakai buat siapa pun yang clone repo itu, dan ini yang lebih cocok buat prosedur tim. Dua-duanya nerima folder symlink kalau kamu simpan skill di repo dotfiles.
Struktur tiga lapis itu inti desainnya. Metadata selalu nangkring di prompt. Body masuk context pas skill aktif. File di scripts/ dan references/ cuma dibaca kalau body-nya nyuruh agent baca, makanya spec bilang jumlah context yang bisa kamu bawa praktis nggak terbatas.
Langkah 2: Frontmatter yang lolos validasi
Open standard mewajibkan dua field dan ngasih empat field opsional:
name: maksimal 64 karakter, cuma huruf kecil, angka, dan hyphen, nggak boleh diawali atau diakhiri hyphen. Samain sama nama folder. Tool packaging dan apa pun yang baca filesystem pakai nama folder sebagai kunci.description: 1 sampai 1024 karakter, nggak boleh kosong, jelasin skill ini ngapain dan kapan dipakai.license,compatibility(maks 500 karakter),metadata(map string ke string),allowed-tools(statusnya eksperimental).
Claude Code lebih longgar dari standard. Field name opsional dan fallback ke nama folder, dan cuma description yang disarankan. Aman selama skill-nya cuma di laptop kamu. Begitu di-upload ke claude.ai atau dikirim lewat Skills API, cuma enam field standard yang diterima, dan key tambahan bikin upload gagal total, bukan diabaikan. Field extension Claude Code kayak argument-hint, context, model, dan paths justru yang paling sering kena.
Jadi tulis dua field wajibnya walau Claude Code membolehkan kamu skip salah satu.
Dua aturan parsing lain yang sering bikin orang buang satu sore: --- pembuka harus jadi baris pertama file, dan YAML-nya harus benar-benar valid. Langgar salah satu, skill tetap ke-load tapi tanpa metadata. Panggilan lewat slash jalan, trigger otomatis nggak pernah jalan.
Langkah 3: Bikin description-nya kepicu
Sisa isi file nggak kelihatan waktu model memutuskan. Claude Code memotong gabungan description dan when_to_use di 1.536 karakter per entri, dan kalau total listing lewat budget, defaultnya 1 persen dari context window model, dia mulai buang description dari skill yang paling jarang kamu pakai. Skill yang description-nya kebuang nggak bisa terpicu sendiri, sebagus apa pun body-nya.
Bandingin:
description: Helps with deploys.
description: Builds a grouped changelog from git commits since the last tag and
writes it to CHANGELOG.md. Use when the user asks for release notes, a changelog,
"what shipped", or to prepare a release.
Yang kedua nyebut artefaknya, input-nya, dan frasa yang beneran bakal diketik orang. Taruh use case utama di kalimat pertama, karena itu bagian yang selamat dari pemotongan.
Langkah 4: Body-nya pendek, karena dia nempel
Setelah skill ke-load, isinya nempel di percakapan sampai sesi selesai dan Claude Code nggak baca ulang file-nya di turn berikutnya. Tiap baris jadi biaya berulang. Spec menyarankan body instruksi di bawah 5.000 token, dan 500 baris batas atas yang masuk akal.
Langkah bernomor, kalimat perintah, tanpa alasan panjang. Kalau satu baris cuma menjelaskan kenapa aturannya penting, pindahin ke komentar di script atau ke references/, bukan ke body.
Langkah 5: Kerjaan deterministik masuk ke scripts
Ini file skill yang saya pakai buat ngetes, body 21 baris dengan description 189 karakter:
---
name: changelog-from-commits
description: Builds a grouped changelog from git commits since the last tag and
writes it to CHANGELOG.md. Use when the user asks for release notes, a changelog,
"what shipped", or to prepare a release.
license: MIT
metadata:
author: arya
version: "1.0"
---
# Changelog from commits
Turn the commits since the last tag into release notes grouped by type.
## Steps
1. Run `python3 ${CLAUDE_SKILL_DIR}/scripts/collect.py` to get the commit list
as JSON. Do not call `git log` yourself.
2. Group the commits: `feat` under Features, `fix` under Fixes, `perf` under
Performance, everything else under Other. Drop merge commits and `chore`.
3. Write the result above the previous entry in `CHANGELOG.md`. Keep the
existing heading style and never rewrite older entries.
4. Show the user the new section and the commit count.
## Edge cases
- No previous tag: use the first commit as the baseline and say so.
- Empty list: report that nothing shipped and stop.
- A subject line with no `type:` prefix: put it under Other, do not invent a type.
See `references/grouping.md` for the exact heading format the repo uses.
Script-nya ngerjain satu hal, dan source-nya nggak pernah masuk context window. Cuma output-nya. Itu bedanya antara bayar 40 baris Python dan bayar 48 objek JSON yang padat.
import json
import subprocess
def git(*args):
out = subprocess.run(["git", *args], capture_output=True, text=True, check=True)
return out.stdout.strip()
try:
rev = git("describe", "--tags", "--abbrev=0") + "..HEAD"
except subprocess.CalledProcessError:
rev = "HEAD"
commits = []
for line in filter(None, git("log", rev, "--no-merges", "--pretty=format:%h|%s").splitlines()):
sha, subject = line.split("|", 1)
kind, sep, rest = subject.partition(":")
commits.append({
"sha": sha,
"type": kind.strip().lower() if sep else "other",
"subject": rest.strip() if sep else subject,
})
print(json.dumps(commits, indent=2))
Saya jalanin ke repo yang jadi host blog ini, yang belum punya tag, jadi dia fallback ke HEAD dan balikin 48 objek. Fallback-nya penting: skill yang crash di rilis pertama gara-gara nggak ada tag sebelumnya lebih parah daripada nggak punya skill.
${CLAUDE_SKILL_DIR} mengembang jadi folder tempat SKILL.md berada, jadi path-nya tetap benar di mana pun skill dipasang. Variabel yang sama juga disubstitusi di dalam allowed-tools, jadi kamu bisa pre-approve tepat satu command:
allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/collect.py *)
Langkah 6: Pahami field permission-nya
allowed-tools itu pre-approval, bukan sandbox. Di Claude Code field ini daftar tool yang boleh dipakai tanpa nanya selama turn yang memicu skill, dan izinnya hilang begitu kamu kirim pesan berikutnya. disallowed-tools kebalikannya: dia buang tool dari pool selama skill aktif. Dua-duanya nggak membatasi apa yang bisa dilakukan script yang kamu bundle begitu dia jalan.
Versi standard dari allowed-tools disebut sebagai pre-approved tools dan ditandai eksperimental, jadi siap-siap semantiknya beda antar client. Anggap field ini kemudahan buat skill read-only, dan taruh kebijakan permission yang sebenarnya di level client.
Isi skill itu instruksi plus kode yang bisa dieksekusi, artinya tempat yang jelas buat menyembunyikan sesuatu. Saran Anthropic sendiri: pasang skill cuma dari sumber yang kamu percaya, dan baca script yang dibundle sebelum diaktifkan. Terutama yang datang dari marketplace.
Langkah 7: Validasi sebelum dipercaya
Pemeriksaan bawaan: claude plugin validate ~/.claude/skills (Claude Code v2.1.233 ke atas) buat frontmatter yang nggak bisa di-parse, dan /doctor buat estimasi ongkos listing skill di context.
Saya juga mau batasan dari standard-nya, jadi saya tulis checker kecil dan taruh di sebelah skill-nya:
#!/usr/bin/env python3
"""Validate a SKILL.md against the Agent Skills open standard."""
import re
import sys
from pathlib import Path
import yaml
NAME_RE = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")
SPEC_FIELDS = {"name", "description", "license", "compatibility", "metadata", "allowed-tools"}
path = Path(sys.argv[1]).expanduser() / "SKILL.md"
text = path.read_text(encoding="utf-8")
if not text.startswith("---"):
sys.exit("FAIL frontmatter must start on line 1")
fm = yaml.safe_load(text.split("---")[1]) or {}
problems = []
name, desc = str(fm.get("name", "")), str(fm.get("description", ""))
if not name:
problems.append("missing required field: name")
elif not NAME_RE.match(name) or len(name) > 64:
problems.append(f"name '{name}' must be lowercase-hyphenated, max 64 chars")
elif name != path.parent.name:
problems.append(f"name '{name}' does not match directory '{path.parent.name}'")
if not desc:
problems.append("missing required field: description")
elif len(desc) > 1024:
problems.append(f"description is {len(desc)} chars, max is 1024")
listing = len(desc) + len(str(fm.get("when_to_use", "")))
if listing > 1536:
problems.append(f"listing text is {listing} chars, Claude Code cuts at 1536")
extra = sorted(set(fm) - SPEC_FIELDS - {"when_to_use"})
if extra:
problems.append(f"non-spec fields break claude.ai upload: {', '.join(extra)}")
print(f"{name}: description {len(desc)} chars, {len(extra)} non-spec fields")
for p in problems:
print(f" FAIL {p}")
sys.exit(1 if problems else 0)
Di skill yang benar dia cetak changelog-from-commits: description 189 chars, 0 non-spec fields lalu exit 0. Di skill yang sengaja dirusak, folder deploy dengan name: deploy-helper dan key argument-hint, dia cetak dua kegagalan dan exit 1:
deploy-helper: description 919 chars, 1 non-spec fields
FAIL name 'deploy-helper' does not match directory 'deploy'
FAIL non-spec fields break claude.ai upload: argument-hint
Baris kedua itu yang paling sering saya temuin di skill orang lain. Jalan mulus di Claude Code, gagal pas upload. Tempat yang jelek buat tahu masalahnya.
Langkah 8: Uji trigger-nya, bukan cuma output-nya
Coba tiga kalimat berbeda yang seharusnya cocok sama description, lalu satu yang seharusnya nggak. Kalau tiga yang pertama nyala dan yang keempat diam, berarti description-nya bekerja. Kalau nggak ada yang nyala, jalankan claude --debug dan cari di log; frontmatter yang rusak cuma muncul di situ.
Claude Code mantau folder skill, jadi edit ke skill yang sudah ada langsung kepakai di sesi berjalan. Folder skills top-level yang baru dibikin butuh /reload-skills dulu.
Kapan skill bukan jawabannya
- Fakta yang harus berlaku di setiap turn, kayak package manager atau perintah test kamu, tempatnya di CLAUDE.md. Skill buat prosedur.
- Data live atau API eksternal tempatnya di belakang MCP server. Skill bisa jelasin cara pakai tool, tapi skill bukan tool-nya.
- Aturan yang nggak boleh pernah dilewat tempatnya di hook. Body skill dibaca sekali waktu dipanggil, dan model yang sudah pindah fokus bakal lewat baris yang dia baca 20 turn lalu.
Penutup
Satu tes yang nentuin penempatannya: ini prosedur dengan langkah dan materi referensi? Berarti skill. Tulis dua field wajibnya, taruh frasa trigger di kalimat pertama description, jaga body-nya nggak lebih dari satu dua layar, dan pindahkan apa pun yang mekanis ke scripts/.
Langkah berikutnya: ambil checklist yang terakhir kamu tempel ke chat minggu ini, ubah jadi folder skill, dan jalankan validatornya sebelum nulis body. Kalau frontmatter-nya salah, semua yang di bawahnya nggak ada artinya.
Referensi
- Spesifikasi Agent Skills, aturan frontmatter dan progressive disclosure: https://agentskills.io/specification
- Dokumentasi skills Claude Code, lokasi folder, referensi frontmatter, troubleshooting: https://code.claude.com/docs/en/skills
- Anthropic Engineering, alasan skills ada dan cara memuatnya: https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills