TL;DR dan putusan
Empat tugas yang terus kamu ketik ke Claude Code masing-masing punya file yang berbeda. Checklist rilis adalah skill. Aturan yang tidak boleh dilanggar adalah hook PreToolUse. Audit yang membaca banyak file adalah subagent. Data yang tidak bisa dilihat Claude adalah server MCP.
Kami menjalankan keempatnya di satu repo nyata, sebuah API invoice dengan 34 tes, dan setiap kali membuat pilihan yang salah dulu. Pilihan yang salah itu gagal di layar:
- Checklist di CLAUDE.md menambah baris
Memory files: 210 tokenske /context, di setiap giliran. - Hook pertama jalan, mencetak peringatannya, dan penulisan lolos (unitPrice 8000 jadi 12000).
- Audit yang dijalankan inline memenuhi thread: Messages di 19.3k token, dibanding 7.2k dengan subagent yang disebut namanya.
- Tanpa server docs, Claude menjawab "I couldn't find that setting... I won't guess one."
Putusan: pilih jenisnya dari tabel docs, lalu buat file itu menjawab, bukan sekadar ada. Hook yang hanya mencatat log bersifat saran saja, seperti baris CLAUDE.md yang digantikannya. Dari keempatnya, hanya hook yang tidak pernah bertanya.
Salin file di bawah, commit, dan mulai dari yang paling sering kamu ketik ulang.
Sintesis bersumber
Apa yang dimuat sesimu sebelum kata pertamamu. /context baseline kami menunjukkan 26.2k/1m token, tanpa baris memory dan tanpa baris MCP. Setiap tugas yang kamu tambahkan akan menaruh satu baris di tabel itu atau tidak. Baca dulu, lalu ukur terhadapnya.
Aturan CLAUDE.md adalah permintaan, hook adalah penegakan. Docs menyebut instruksi seperti "never edit .env" di CLAUDE.md atau skill sebagai permintaan, dan hook PreToolUse yang memblokir edit sebagai penegakan s1. Halaman Memory menyebut CLAUDE.md sebagai context, bukan penegakan s8. Sebuah thread di Hacker News melaporkan hal yang sama dari sisi hook: hook yang keluar dengan 0 tidak memblokir apa pun s10.
Tabel pemicu memberi tahu file mana. Prosedur yang ditempel untuk ketiga kalinya berarti skill. Output yang membanjiri chat berarti subagent. Tab yang tidak terlihat Claude berarti server MCP. Sesuatu yang harus terjadi setiap kali berarti hook s1.
Tugas 1, checklist rilis, adalah skill.
- Prosedur yang tumbuh di dalam CLAUDE.md tempatnya di skill, dan isinya dimuat hanya saat dipakai s3.
- Pada run kami, checklist yang ditempel ke CLAUDE.md menambah baris
Memory files: 210 tokens. Sebagai skill dengandisable-model-invocation: true, /context kembali ke baseline. /releasemenjalankan enam langkah (34 tes, 0.4.0 ke 0.4.1, tag v0.4.1). Ia juga menangkap bahwagit commit -ammelewatkan file yang belum dilacak, jadi ia men-stage changelog baru lebih dulu.
Tugas 2, aturan yang harus tegak, adalah hook, dan jaminannya adalah jawaban yang dikembalikannya.
- Exit 0 tanpa output bukan keputusan. Exit 2 memblokir. JSON deny juga memblokir s2.
- Hook pertama kami mencatat log, exit 0, dan penulisan lolos (unitPrice 8000 jadi 12000). Balasan Claude tidak pernah menyebut hook itu.
- Hook yang sama dengan mengembalikan JSON deny menolak edit dengan
PreToolUse:Edit hook error: Stored data is never edited by hand: write a migration in src/store/migrations.ts (README § Conventions).Lalu Claude bertanya: override, atau tulis migrasinya. - Docs menerbitkan resep PreToolUse untuk file yang dilindungi s23.
- Batasnya: hook ini memantau Edit dan Write. Cakup shell juga, atau jauhkan shell dari daftar allow-mu.
onFailure: "block"membuat hook yang gagal memblokir, bukan gagal terbuka. Ini muncul di v2.1.295 s2 s15.
Tugas 3, audit yang membanjiri, adalah subagent.
- Subagent mulai tanpa konteks dan mengembalikan ringkasan s4.
- Inline, Messages terbaca 19.3k. Dengan subagent yang disebut namanya, 7.2k.
- File agent saja mendelegasikan 0 dari 2 run. Menyebut namanya di prompt membuatnya mendelegasikan. File membuatnya ada, prompt-mu membuat Claude memakainya.
- Pin
model:di file. Tagihannya tidak bergerak: pembacaan tetap terjadi, hanya tidak di window-mu.
Tugas 4, data yang tak terjangkau Claude, adalah server MCP.
claude mcp add --scope projectmenulis.mcp.json, dan tool search hanya memuat nama tool s5.- Ada server HTTP gratis tanpa login untuk docs Claude Code sendiri, dengan
search_claude_code_docsdanquery_docs_filesystem_claude_code_docss24. - Tanpanya, Claude menjawab "I couldn't find that setting... I won't guess one." Dengannya, Claude menjawab
"onFailure": "block", ditambahkan di v2.1.295, sementara instalasi kami 2.1.294. - Server docs untuk library yang sudah diketahui model tidak mengubah apa pun bagi kami. Hubungkan yang tidak bisa dimiliki model.
Laporan lapangan. Sebuah thread Reddit melaporkan Claude mengabaikan baris "MUST use agent" di CLAUDE.md s9. Kami mengutipnya sebagai laporan, bukan pengukuran. Tulisan engineering Anthropic membahas pembagian yang sama s6 s7.
Code
Empat file dari run ini, ditambah dua pembantu. Path adalah tempat masing-masing berada di repo-mu.
1. Skill rilis, di .claude/skills/release/SKILL.md. Ketik /release. disable-model-invocation: true membuatnya hanya kamu yang memulai, dan itu yang kamu mau untuk sesuatu yang commit dan tag.
SKILL.md
---
name: release
description: Cut a patch release of ledgerly (typecheck, tests, version bump, changelog line, commit, tag).
disable-model-invocation: true
---
Run these steps in order and stop at the first failure:
1. `pnpm typecheck` must exit 0.
2. `pnpm test` must pass.
3. Bump the patch version in `package.json` (e.g. 0.4.0 -> 0.4.1).
4. Add one line at the top of `CHANGELOG.md` (create it if missing): `## vX.Y.Z - YYYY-MM-DD` followed by a one-line summary of the commits since the last tag.
5. `git commit -am "release vX.Y.Z"`
6. `git tag vX.Y.Z`. Never push.
2. Hook protect-data, di .claude/settings.json. Ia mengembalikan keputusan deny dengan alasan yang dibaca Claude. Ia butuh jq di PATH-mu dan muat inline, jadi hook tidak butuh file script sendiri. Ganti pola data/.*\.json$ dan alasannya sesuai aturanmu.
settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -c 'if (.tool_input.file_path // \"\") | test(\"data/.*\\\\.json$\") then {hookSpecificOutput: {hookEventName: \"PreToolUse\", permissionDecision: \"deny\", permissionDecisionReason: \"Stored data is never edited by hand: write a migration in src/store/migrations.ts (README § Conventions).\"}} else empty end'"
}
]
}
]
}
}
3. Conventions auditor, di .claude/agents/conventions-auditor.md. Tool dibatasi ke yang hanya-baca dan modelnya di-pin. Edit daftar konvensi agar cocok dengan README-mu.
conventions-auditor.md
---
name: conventions-auditor
description: Use when asked to audit the code against the README conventions
model: sonnet
tools: Read, Grep, Glob
---
You audit ledgerly's source against README § Conventions:
- Money is always an integer number of cents. Never floats.
- Domain functions return new objects; they never mutate their input.
- Validation failures throw `ValidationError` (400), missing records `NotFoundError` (404), illegal state transitions `ConflictError` (409).
- A change of stored shape bumps `schemaVersion` and adds a migration in `src/store/migrations.ts`.
Read every file under `src/`. Return only the findings: one line per violation as `file:line - convention - what is wrong`, then borderline cases the same way, then one line with the count of files read. No file contents, no summary of clean files.
conventions-auditor.md on GitHub
4. Config MCP, disimpan sebagai .mcp.json di root repo. Inilah yang ditulis claude mcp add --transport http claude-docs --scope project https://code.claude.com/docs/mcp. Claude Code mencantumkan server project sebagai pending sampai kamu menyetujuinya di sesi berikutnya.
mcp.json
{
"mcpServers": {
"claude-docs": {
"type": "http",
"url": "https://code.claude.com/docs/mcp"
}
}
}
Pembantu. ctx.sh menjalankan /context di sesi headless dan mencetak baris token, supaya kamu bisa membandingkan sebelum dan sesudah. mcp-probe.sh mengirim initialize dan tools/list ke url MCP HTTP, untuk memeriksa server menjawab sebelum kamu menambahkannya.
ctx.sh
#!/usr/bin/env bash
# Usage: ctx.sh <step> -> runs "/context" through run-session.sh, writes context-<step>.txt (honours STRICT_MCP / EXTRA_ALLOW)
C="$(cd "$(dirname "$0")" && pwd)"
"$C/run-session.sh" "$C/out/context-$1.json" "/context" >/dev/null
python3 -c "import json,sys;d=json.load(open(sys.argv[1]));print(d['result'])" "$C/out/context-$1.json" > "$C/context-$1.txt"
grep -E '^\*\*Tokens|^\| (System prompt|System tools|MCP tools|Memory files|Skills|Custom agents|Messages) ' "$C/context-$1.txt"
mcp-probe.sh
#!/usr/bin/env bash
# Usage: mcp-probe.sh <url> [tools/call json params] -> initialize + notifications/initialized + tools/list (+ optional tools/call) over streamable HTTP
U="$1"; H=$(mktemp)
curl -s -D "$H" -m 30 -X POST "$U" -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}'
echo; SID=$(grep -i '^mcp-session-id:' "$H" | tr -d '\r' | cut -d' ' -f2); echo "session-id: ${SID:-none}"
HS=(-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream'); [ -n "$SID" ] && HS+=(-H "Mcp-Session-Id: $SID")
curl -s -m 30 -X POST "$U" "${HS[@]}" -d '{"jsonrpc":"2.0","method":"notifications/initialized"}' >/dev/null
curl -s -m 30 -X POST "$U" "${HS[@]}" -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'; echo
[ -n "${2:-}" ] && { curl -s -m 90 -X POST "$U" "${HS[@]}" -d "{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\"params\":$2}"; echo; }
rm -f "$H"
Lakukan ini hari Senin
- Buka sesi baru dan jalankan /context. Catat totalnya. Itu baseline-mu.
- Pilih checklist yang paling sering kamu tempel. Pindahkan ke
.claude/skills/<name>/SKILL.md, tambahkandisable-model-invocation: truejika ia commit atau tag, dan jalankan dengan/<name>. - Ambil satu aturan yang tidak boleh dilanggar dan taruh di hook PreToolUse yang mengembalikan
permissionDecision: "deny"atau exit 2. Minta Claude melanggar aturan itu, dan periksa bahwa edit ditolak. - Jika hook-mu hanya mencatat log, ubah. Hook yang exit 0 tidak memblokir apa pun.
- Pindahkan satu tugas yang membaca banyak file ke
.claude/agents/<name>.mddenganmodel:yang di-pin. Sebut namanya di prompt-mu sampai Claude memilihnya sendiri. - Periksa satu fakta yang belakangan ditebak Claude untukmu. Jika lebih baru dari model, tambahkan server docs dengan
claude mcp add --transport http <name> --scope project <url>dan commit.mcp.json. - Periksa versi Claude Code-mu sebelum mengandalkan sebuah setting.
onFailure: "block"butuh 2.1.295. - Jalankan
git add -A && git statusdan commit file barunya. Run kami menunjukkan tepat empat.
Lanjutkan
Kartu pemilih. Satu halaman. Ini baris-baris docs s1 dengan keempat tugas kami tertulis di atasnya. Bintang paket ini adalah keempat file di atas ditambah kartu ini.
| Jenis | Fungsinya | Pakai saat | Tugas kami | File kami |
|---|---|---|---|---|
| CLAUDE.md | Context persisten yang dimuat di setiap percakapan | Konvensi yang dua kali salah dilakukan Claude | Satu baris, bukan prosedur | tidak ada |
| Skill | Instruksi dan alur kerja yang bisa dipakai Claude | Kamu menempel playbook yang sama untuk ketiga kalinya | Checklist rilis | .claude/skills/release/SKILL.md |
| Hook | Script yang dipicu event | Kamu ingin itu terjadi setiap kali, tanpa bertanya | Jangan pernah edit data tersimpan secara manual | .claude/settings.json |
| Subagent | Context terisolasi yang mengembalikan hasil berupa ringkasan | Tugas sampingan membanjiri percakapanmu | Audit konvensi | .claude/agents/conventions-auditor.md |
| MCP | Terhubung ke layanan eksternal | Kamu terus menyalin data dari tab yang tidak terlihat Claude | Docs Claude Code | .mcp.json |
| Plugin | Membundel keempatnya jadi satu unit yang bisa diinstal | Repository kedua butuh setup yang sama | Tidak dipakai | tidak ada |
Kartu menentukan jenis, bukan kualitas. Hook yang hanya mencatat log, subagent yang tidak kamu sebut namanya, dan server untuk docs yang sudah diketahui model, semuanya berada di jenis yang tepat dan gagal. Pilih jenisnya, lalu buat file itu menjawab.
Kapan tidak perlu memakai ini.
- Konvensi yang terus salah dilakukan Claude tetap di CLAUDE.md sebagai satu baris, bukan sebagai prosedur.
- Tugas yang kamu arahkan bolak-balik, dengan riwayatmu terlihat, tetap di thread utama, bukan di subagent.
- Server docs untuk library yang sudah diketahui model memakan context dan tidak mengubah apa pun.
pnpm testadalah CLI yang sudah kamu punya. Itu bukan tugas MCP.
Plugin. Plugin adalah kotak yang mengirim keempatnya bersama. Pakai saat repo lain butuh setup yang sama.
Skill plus MCP. Docs memasangkan keduanya: server memberi koneksi, dan skill mengajari Claude cara memakainya dengan baik.
Skill dengan context: fork. Sebuah skill bisa jalan di subagent yang di-fork, sehingga pembacaannya tetap di luar window-mu. Uji pada satu tugas sebelum kamu mengandalkannya.
Jenis hook selain command. Command yang kami pakai. Referensi hook mendaftar jenis handler lain, termasuk hook http dan prompt. Aturannya sama: apa yang dikembalikan hook yang menentukan, dan hook yang diam tidak memutuskan apa pun.
MCP versus CLI. Ada perdebatan terbuka soal server MCP yang memakan context, dengan satu tulisan yang membela CLI lebih dulu s11 dan satu lagi soal biaya context server MCP s12. Aturan kami: jika CLI sudah bisa mengerjakannya, pakai itu. Pakai MCP untuk yang tidak punya CLI. Tool search kini hanya memuat nama, jadi ukur dengan /context di setup-mu sendiri sebelum memutuskan s5.
Jaga skill tetap singkat dan terverifikasi. Satu skill singkat per tugas, dicek terhadap run nyata. Lihat makalah SkillsBench s13 dan pandangan praktisi tentang mengapa skill murah sampai dipakai s14.
FAQ
Kenapa hook-ku jalan tetapi edit tetap lolos? Hook hanya memutuskan lewat apa yang dikembalikan perintahnya. Exit 0 tanpa output bukan keputusan s2. Kembalikan JSON deny, atau exit 2.
Kenapa Claude membaca file sendiri padahal aku punya subagent? Pada run kami, file agent saja mendelegasikan 0 dari 2 run. Sebut namanya di prompt, misalnya "use the conventions auditor subagent".
Apakah hook mencakup semua yang bisa dilakukan Claude? Tidak. Milik kami cocok dengan Edit dan Write. Claude menawarkan membuat perubahan lewat shell pada run berikutnya, jadi cakup shell atau jauhkan dari daftar allow-mu.
Haruskah aku menambah server MCP untuk setiap library yang kupakai? Tidak. Jika model sudah mengenal library itu, server tidak mengubah apa pun dan memakan context. Tambahkan untuk data yang lebih baru dari model atau di luar disk-mu, dan cocokkan versi yang terinstal dengan versi yang menambahkan fiturnya.
Bisakah aku commit semua ini?
Bisa. Skill, file settings, file agent, dan .mcp.json semuanya ada di repo, jadi siapa pun yang meng-clone-nya mendapatkannya. Setujui server MCP project sekali di sesi berikutnya.
AIDive