Sembilan puluh persen, dan kalimat yang menjualnya
Setup Spotify Claude Code adalah sebuah tulisan blog dari Dimitri Mazmanov, product manager di Spotify, dengan kodenya di GitHub: ia mengatakan konfigurasi yang dipakai timnya memangkas pemakaian token Claude Code miliknya sebesar 90%. Kalimat pertamanya memuat seluruh argumennya: sebagian besar yang dilakukan agent coding AI bukan berpikir, melainkan I/O. Membaca lima file untuk menjawab pertanyaan tentang satu method, atau menulis file test ke-21 yang menyalin dua puluh file di sebelahnya, menghabiskan ribuan token dengan nyaris tanpa penalaran.
Satu tweet membawa tulisan itu ke satu setengah juta views lewat satu kalimat: aturan tertulis cuma saran, blokir bukan saran. Hacker News menaruhnya di halaman depan, 271 poin dan 173 komentar, dan separuh komentar mengajukan pertanyaan yang sama: 90% dari apa? Kualifikasi Spotify sendiri adalah "bulk read". Artikel ini membangun ulang setup tersebut di dalam Claude Code polos, lalu mengukurnya, supaya kamu tahu persis apa yang dibeli oleh kualifikasi itu.
Apa sebenarnya Portal (dan kenapa kamu tidak bisa menjalankannya)
Portal bukan router. Portal adalah portal developer internal Spotify, dibangun di atas Backstage, platform developer yang di-open-source-kan Spotify. Fitur yang relevan di dalamnya bernama Modes: menurut definisi Spotify, sebuah mode adalah agent deklaratif yang berjalan di runtime ephemeral, kira-kira AWS Lambda untuk agent. Kamu menulis instruksinya, memilih model, mengatur temperature, memasang tools. Mazmanov membuat dua di antaranya, bulk reader dan code writer, keduanya di Gemini Flash dengan temperature 0.2, jadi keduanya sengaja dibuat murah dan membosankan.
Routing-nya tinggal di sebuah plugin Claude Code bernama Shunt. Plugin ini publik di GitHub dan terpasang dalam dua perintah. Namun langkah kedua mengautentikasi command line Portal ke instance Portal milikmu, dan kamu tidak punya instance itu. Plugin-nya publik; hal yang menjadi tujuan delegasinya tidak.
Jadi langkah yang berguna adalah melupakan plugin-nya dan menyimpan polanya. Pola ini punya tiga lapis, dengan kata-katanya sendiri: hooks, scripts, skills. Setiap lapis punya padanan di Claude Code polos, dan itulah yang dibangun dan diukur di sisa artikel ini.
Lapis satu: hook yang memblokir, bukan bertanya
Versi 1 dari setup ini adalah sekumpulan aturan routing di file instruksi proyek. Menurut Mazmanov, versi itu "kurang lebih bekerja": aturannya bersifat anjuran, tidak dipaksakan, Claude bisa mengabaikannya, dan setiap proyek butuh salinannya sendiri. Versi 2 memindahkan keputusan itu keluar dari prompt ke lapisan tool dengan dua hook, keduanya menyala sebelum pemanggilan tool. Satu mengawasi setiap pembacaan file, yang lain mengawasi shell.
Hook baca ini adalah 33 baris bash. Ia membaca ambang batas dari environment, 350 baris secara default, lalu meloloskan tiga hal:
- Pembacaan dengan offset atau limit, karena Claude sudah tahu apa yang ia butuhkan.
- File yang tidak ada.
- File yang berada di atau di bawah ambang batas, karena mendelegasikan sesuatu yang kecil lebih mahal daripada membacanya.
Selebihnya diblokir, dengan pesan yang dibaca Claude sebagai ganti file-nya: file ini sekian baris, gunakan skill bulk reader, dan kalau kamu butuh isi persisnya untuk sebuah edit, baca ulang bagian itu saja. Hook shell menangkap cat, head, tail, less, dan more pada file besar. Perintah yang di-pipe lolos, karena pipe ke grep adalah pembacaan yang terarah.
Poin Mazmanov soal pelapisan adalah yang penting: bahkan jika Claude tidak pernah membaca deskripsi skill-nya, hook tetap memblokir pembacaan yang mahal. Skill membuat pengalihannya lebih mulus; blokir membuatnya nyata. Satu detail penting untuk nanti: script ini menjawab dengan sebuah decision tingkat atas bernama "block". Ingat kata itu.
Lapis dua dan tiga: worker dan angka-angkanya
Worker-nya adalah dua prompt. Reader: "kamu adalah analis kode yang presisi, keluarkan hanya bullet terstruktur, tanpa sapaan, tanpa prosa, awali setiap bullet dengan nama, tipe, atau nomor baris yang persis." Writer: "ikuti pola, penamaan, dan gaya yang ada dengan persis; keluarkan hanya kodenya, tanpa fence, tanpa penjelasan." Tanpa baris terakhir itu, model membungkus semuanya dalam Markdown yang kemudian harus di-parse Claude.
Dua script membungkus keduanya. Bulk-read menerima pertanyaan dan path file lalu mengirimkannya. Code-write menerima spesifikasi dan file referensi lalu menulis hasilnya langsung ke disk, sehingga Claude tidak pernah melihat kode yang dihasilkan. Setiap delegasi bersifat one-shot: tindak lanjut mengirim file-nya lagi. Itu gratis di tempat yang penting, karena korpusnya pergi ke worker dan tidak pernah masuk ke context Claude.
Lapis tiga adalah file skill yang memberi tahu Claude kapan harus mendelegasikan: file di atas 350 baris, pertanyaan yang melintasi tiga file atau lebih, diff besar. Baris terakhirnya adalah "verifikasi nomor baris sebelum kamu mengedit".
Tabel Spotify mencakup satu monorepo Java dan tiga skenario baca. Kasus satu file turun dari sekitar 34,000 token menjadi di bawah 6,000, dan rata-rata penghematan di tiga baris itu adalah 90%.
| Benchmark Spotify | Nilai |
|---|---|
| Repositori | 1 Java monorepo |
| Skenario | 3, semuanya bulk read |
| Kasus satu file, sebelum | ~34,000 tokens |
| Kasus satu file, sesudah | < 6,000 tokens |
| Rata-rata penghematan | 90% |
| Estimasi token | 4 karakter per token |
| Penegakan pada writer | tidak ada (hanya reader yang punya hook) |
Dua catatan dicetak oleh Spotify sendiri: token diestimasi empat karakter per token, dan writer sama sekali tidak punya penegakan. Jadi 90% itu adalah rata-rata dari tiga baris bulk read dalam estimasi token input, tanpa skor kualitas dan tanpa angka dolar di mana pun. Itulah angka yang harus diuji.
Rebuild, bagian satu: subagent dengan field model
Claude Code menyertakan subagent Explore bawaan, dan sejak rilis terbaru subagent itu mewarisi model utamamu, dengan batas atas Opus, sehingga "reader murah" itu tidak murah lagi. Dokumentasinya memberikan perbaikannya dalam satu kalimat: subagent proyek bernama Explore menimpa yang bawaan dan mempertahankan field model-nya sendiri. Satu file markdown, sebuah front matter, dan baris model-nya berbunyi Haiku. Itulah bulk reader-nya. Writer-nya adalah file kedua: model Sonnet, tools hanya Read dan Write, dan isinya adalah instruksi Spotify sendiri yang ditempel apa adanya.
Ini bekerja karena setiap subagent memulai dengan context window yang segar dan terisolasi. Apa yang ia baca mendarat di sana, bukan di percakapan utama. Itulah delegasi one-shot Spotify tanpa perjalanan bolak-balik lewat jaringan.
Lalu datang bagian yang tidak direncanakan siapa pun. Di Reddit minggu ini, Fable diperintahkan memunculkan agent Opus dan malah memunculkan lima agent Fable: 73% dari batas mingguan habis dalam tiga puluh menit. Jawaban teratasnya adalah sebuah hook yang berjalan saat model mengirim subagent, memaksanya memilih model secara eksplisit, dan menyuruhnya memilih model termurah yang sanggup mengerjakan tugasnya. Itulah hook nomor tiga: ia mengawasi tool Agent, dan panggilan tanpa model ditolak dengan satu kalimat, "pilih model secara eksplisit".
Skill Spotify menjadi tiga baris di file instruksi proyek: file di atas 350 baris pergi ke explorer, boilerplate pergi ke writer, setiap panggilan agent menetapkan model. Opsi kasarnya juga ada: dua environment variable yang memaksa satu model pada setiap subagent. Batas jujurnya adalah reader memakai model yang lebih murah, sehingga apa yang ia kembalikan adalah semua yang diketahui model utama. Bagian pengukuran membahas hal itu.
Rebuild, bagian dua: deny, dalam format hook saat ini
Ingat kata "block". Script Spotify mengembalikan decision tingkat atas, tetapi dokumentasi Claude Code saat ini mengatakan hal yang berbeda: hook PreToolUse mengembalikan keputusannya di dalam objek output khusus hook, dan field-nya bernama permissionDecision. Ada empat hasil, allow, deny, ask, dan defer, dan yang diinginkan di sini adalah deny. Apa pun yang ditulis hook sebagai alasan ditampilkan ke Claude, dan jika beberapa hook menjawab, deny menang.
Hook baca yang dibangun ulang mempertahankan ambang batas yang sama, 350, dan tiga pengecualian yang sama, dan alih-alih "block" ia mengembalikan deny dengan alasan yang menyebut subagent Explore dan model yang harus dipakai. Satu jebakan yang dinyatakan dokumentasi dengan gamblang: hook dari settings-mu juga berjalan di dalam subagent. Tanpa jalan keluar, reader Haiku ditolak pada pembacaannya sendiri dan tidak akan pernah bisa bekerja, jadi script memeriksa siapa yang memanggil dan meloloskan kedua worker.
Pengkabelannya adalah satu file settings dengan tiga matcher, Read, Bash, dan Agent, masing-masing menunjuk ke script-nya, dan ambang batas diatur sebagai environment variable. Dalam praktiknya, pembacaan file 1,090 baris kembali sebagai error dengan kalimat yang ditulis: delegasikan pembacaan ini ke explorer, model Haiku. Delegasinya lalu menyusul: model utama menghitung barisnya dulu, memanggil explorer dengan model diatur ke Haiku, dan bullet-nya kembali, masing-masing dengan nomor baris. Tiga giliran, 44 detik.
Kalimat Spotify tetap berlaku: pelapisan ini berarti sistemnya menurun dengan anggun. Instruksi melakukan routing, hook adalah jaringnya. Jaring itu punya lubang, bagaimanapun. Model yang menginginkan seluruh file bisa memotongnya dengan offset dan limit, yang lolos, atau membuangnya lewat shell dengan rentang sed, yang tidak ditangkap hook ini. Pengukurannya menghitung keduanya.
Pengukurannya
Repositori uji adalah Fastify, web framework Node: 294 file, 63 di antaranya di atas ambang batas. Dua clone identik, satu-satunya perbedaan adalah folder .claude dan file aturan. Model utama Opus, default CLI; reader Haiku; writer Sonnet. Sesi satu prompt, tanpa tindak lanjut, setiap skenario dijalankan dua kali per konfigurasi, enam belas run total. Empat skenarionya sama dengan Spotify: export dari satu file besar, tiga file dan bagaimana mereka saling memanggil, sebuah file sumber terhadap test-nya, dan file test baru yang ditulis ke disk dari file yang sudah ada.
| Skenario | Context utama, tanpa | Context utama, dengan | Perubahan | Biaya total, tanpa | Biaya total, dengan | Perubahan | Durasi, tanpa | Durasi, dengan | Perubahan |
|---|---|---|---|---|---|---|---|---|---|
| Satu file besar | 88,693 | 51,552 | -41.9% | $0.139 | $0.087 | -37.8% | 22 s | 44 s | +100.8% |
| Tiga file | 357,166 | 73,440 | -79.4% | $0.581 | $0.218 | -62.4% | 52 s | 129 s | +149.9% |
| Sumber vs test | 303,808 | 114,136 | -62.4% | $0.451 | $0.374 | -17.1% | 93 s | 125 s | +33.6% |
| File test baru | 143,432 | 121,818 | -15.1% | $0.295 | $0.302 | +2.6% | 66 s | 87 s | +32.2% |
| Keempatnya | 223,274 | 90,236 | -59.6% | $0.366 | $0.245 | -33.1% | 58 s | 96 s | +65.3% |
Context utama, token yang benar-benar dilihat model mahal, adalah kolom pertama yang penting. Pada pertanyaan tiga file, angkanya turun 79%, dan di keempat skenario turun 59.6%. Tagihannya turun lebih sedikit, sepertiga secara keseluruhan, karena token reader sendiri tidak gratis, dan pada tugas kecil menulis test tagihannya naik 2.6%. Waktu bergerak ke arah sebaliknya: rata-rata 58 detik tanpa setup, 96 dengan setup. Delegasi selalu lebih lambat.
Kualitas adalah tempat kedua konfigurasi paling berbeda. Tanpa setup, model utama membuang file lewat shell tanpa nomor baris dan menghitung manual, menghasilkan nomor baris yang salah di mana-mana: sebuah function yang dilaporkan di baris 149 sebenarnya ada di baris 156. Dengan setup, satu run dari empat menerima ringkasan reader begitu saja dan membawa tiga klaim palsu, salah satunya sebuah function yang menurut reader tidak pernah dipanggil file route, padahal dipanggil, di baris 553. Keempat file test yang dihasilkan lolos, dan hook deny menyala nol kali dalam enam belas run: dengan file aturan yang ada, model utama memeriksa jumlah baris dan mendelegasikan sendiri setiap kali.
Satu hal lagi dari trace: tanpa aturan, model utama tidak pernah memakai tool Read. Ia membaca semuanya lewat shell, dan pembacaan rentang lewat shell memakan token yang sama dan lolos dari hook. Jadi tabel Spotify bilang 90; tabel ini bilang 60 untuk context dan sepertiga untuk tagihan.
Simpan blokirnya. Jangan harap tagihan turun sembilan puluh.
Tiga hal layak disimpan: subagent Explore proyek di Haiku, aturan tiga baris di file instruksi, dan hook baca sebagai jaring pengaman. Hasil terukurnya adalah 60% lebih sedikit context utama, sepertiga dari tagihan, dan dua pertiga lebih banyak waktu tunggu.
Sebelum memercayai hook-nya, perbaiki dua hal. Hook berjalan di dalam subagent, jadi kecualikan worker-mu. Dan lubang shell-nya: hook bash menangkap cat, head, dan tail, tetapi pembacaan rentang lolos, dan model utama memakai persis itu ketika tidak punya aturan.
Batas-batas yang disebut Spotify sendiri tetap berlaku. Kamu tidak bisa mendelegasikan editing dan tidak bisa mendelegasikan penalaran; worker melewatkan bug thread-safety yang ditangkap Claude dalam hitungan detik, dan setiap delegasi adalah perjalanan bolak-balik. Para skeptis Hacker News juga benar soal satu hal: token input bukan tagihannya. Token output lebih mahal, dan setup ini tidak berbuat apa-apa untuk itu.
Siapa yang berhemat tergantung caramu membayar. Di API, sepertiga lebih murah. Di paket Pro atau Max, setup yang sama menggeser jendela lima jam dan mingguanmu, bukan dolar. Perhatikan juga ambang batasnya: di bawahnya, delegasi lebih mahal daripada yang dihemat, dan kasus test 45 baris adalah buktinya dengan plus 2.6%. Terakhir, dalam dua run dari delapan, ringkasan reader membawa kesalahan, dan giliran verifikasi model utama menangkapnya. Lewati giliran itu dan kesalahan-kesalahan tersebut sampai ke edit-mu.
AIDive