Press ESC to close

Kenapa Claude Code Bisa Boros Token? Ada 4 Mekanisme Tersembunyi

Ini adalah artikel yang cukup panjang, setelah saya mengarahkan Claude Code ke router LLM sendiri (menggunakan 9Router), bukan langsung ke API resmi Anthropic, supaya bisa memakai beberapa provider yang lebih murah untuk pemakaian harian yang berat.

Semua trafik claude-code dilewatkan ke satu titik endpoint dari 9router, dan 9router mencatat setiap request input-output di log-nya secara mentah. Dari situ muncul sesuatu yang tidak pernah kelihatan selama berbulan-bulan memakai Claude Code langsung ke Anthropic, yakni adanya request yang terus dikirim secara internal, memakai model yang sedang tidak kita gunakan.

Jadi, ada mekanisme internal di dalam Claude Code sendiri yang diam-diam memanggil model lain, di luar sepengetahuan kita sebagai pemakai. 🤔

claude-code-token
Sebagian request Claude Code ternyata tidak pernah kalian minta.

Awal Kecurigaan

Setup yang dipakai adalah Claude Code mengarah ke 9Router, router open source yang meneruskan setiap request ke provider pilihan sendiri, tergantung kombinasi model yang sedang aktif. Paket CommandCode jadi andalan utama sehari-hari, sementara paket token MiMo dipasang sebagai cadangan untuk dipakai kalau jatah CommandCode mulai mepet. 😆

Suatu malam saya iseng memeriksa log 9Router, dan menemukan pola yang janggal. Sesi malam itu berjalan di combo MiMo, sama sekali tidak menyentuh CommandCode. Tapi di log, tiap kali request MiMo selesai, combo CommandCode ikut menyusul beberapa detik kemudian:

[02:47:45] POST claude-mimo-flash → xiaomi-tokenplan/mimo-v2.5 · STREAM · 7 MSG · 30 TOOL
[02:47:50] Model xmtp/mimo-v2.5 succeeded
[02:48:04] POST claude-deepseek-flash → cmd-cli/deepseek/deepseek-v4-flash · JSON · 3 MSG
[02:48:04] DONE 19634ms · IN 266 (CACHE 30592) · OUT 133
[02:48:09] DONE 4908ms · IN 31629 (CACHE 27904) · OUT 214
[02:48:09] Model cmd-cli/deepseek/deepseek-v4-flash succeeded
[02:48:15] POST claude-mimo-flash → xiaomi-tokenplan/mimo-v2.5 · STREAM · 10 MSG · 30 TOOL

Baris claude-deepseek-flash adalah combo yang merupakan kumpulan dari model-model dari CommanCode, dan itulah request janggal yang berada di tengah MiMo. Formatnya juga beda dari request chat biasa: JSON, bukan STREAM, dan isinya 3 pesan saja, bukan mengikuti seluruh histori sesi.

Awalnya terlihat seperti aman saja, dan mengira bahwa mungkin ada session lain yang menggunakan deepseek. Malam berikutnya saya membuka sesi lama lewat /resume, memilih kombinasi MiMo, lalu mengirim 1 pesan. Polanya jauh lebih parah 😤:

03:24:17 mimo (1187 pesan) → 03:24:48 deepseek
03:25:00 mimo (1190 pesan) → 03:25:06 deepseek
03:27:11 mimo (1193 pesan) → 03:28:28 deepseek
03:28:33 mimo (1196 pesan) → 03:28:49 deepseek
03:28:56 mimo (1199 pesan) → 03:29:06 deepseek
03:29:14 mimo (1202 pesan) → 03:29:20 deepseek

7 request MiMo, 6 di antaranya langsung disusul DeepSeek. Request pertama DeepSeek sendiri membawa 390k lebih token input tanpa cache sama sekali, hampir seluruh isi sesi memang ada ribuan pesan yang baru saja di-/resume. Dari 1 pesan itu saja, kuota CommandCode ikut terpakai 6 kali dalam 5 menit. Benar-benar membagongkan dan membuat penasaran.

Kenapa Ini Baru Kelihatan Sekarang

Kalau kalian memakai Claude Code langsung ke API resmi Anthropic dengan paket langganan (Misal Pro atau Max), pola ini kemungkinan besar tidak pernah kalian sadari, karena tagihannya digabung jadi satu angka bulanan. Sebuah analisis mendalam soal arsitektur Claude Code menyebut ini sebagai keputusan desain yang disengaja, bukan cacat. Istilah conversation history di kutipan berikut merujuk ke seluruh isi sesi sejauh itu, yaitu tiap pesan, tiap berkas yang dibaca, dan tiap keluaran tool:

Berbeda dari skema harga per token yang bisa mendorong pengembang memangkas dan memampatkan konteks demi menghemat biaya, model langganan dengan plafon pemakaian tinggi membuka pendekatan “tak perlu berhemat”.

Claude Code bisa “boros” token, menjejalkan seluruh conversation history, prompt yang panjang, dan isi berkas ke dalam context window, karena itu langsung diterjemahkan jadi hasil kerja yang lebih berkualitas dan lebih bisa diandalkan.

Asumsi ini masuk akal kalau kalian berlangganan langsung ke Anthropic. Begitu gateway diganti ke provider third party yang menagih per token atau per kuota, seperti setup saya di atas, asumsinya menjadi berbalik dan membuat kita “rugi”. Dan keboncosan ini baru akan terlihat kalau ada yang mengaudit tiap request satu per satu, bukan dari melihat total tagihan.

4 Mekanisme Tersembunyi

Dokumentasi resmi Claude Code dan laporan bug publik di GitHub-nya menjelaskan sebagian besar pola itu. 4 mekanisme berikut yang paling cocok, diurutkan dari yang paling jarang muncul ke yang paling sering.

Sebelum saya bercerita lebih jauh, 2 istilah “agak asing” ini akan sering muncul, yaitu

  • Recap adalah ringkasan singkat yang disisipkan begitu kalian kembali mengetik setelah idle.

  • Check-in adalah Claude Code mengecek sendiri progres pekerjaan yang masih berjalan di latar belakang. Pemicunya berbeda, tapi keduanya sama-sama jalan otomatis tanpa diminta, dan sama-sama mengirim full context, yaitu seluruh isi context window sesi itu, tiap kali terpicu.

1. Session Recap Diam-diam Setelah Kita Idle

Claude Code punya fitur session recap: begitu kalian kembali mengetik setelah idle beberapa menit, ia menyisipkan ringkasan singkat tentang apa yang sedang kalian kerjakan (bisa juga dipanggil manual lewat /recap). Fiturnya berguna, masalahnya ada di model yang dipakai untuk membuatnya. Laporan bug publik di GitHub Anthropic, issue #85922, membongkarnya lewat data telemetri dari real session user tersebut:

FiturModel yang jalanToken promptBiaya
generate_session_titlemodel Haiku yang di-set623$0,0007
repl_main_thread (42 panggilan)Opus—$3,81
away_summary (idle recap)Opus (salah)148.589$0,09

Recap ini membawa seluruh isi context tiap kali dipanggil, padahal hasilnya dua kalimat ringkasan saja. Seharusnya recap dikerjakan model kecil dan murah yang sudah disediakan Anthropic khusus untuk background functionality, diatur lewat env var ANTHROPIC_DEFAULT_HAIKU_MODEL. Kenyataannya recap melewati slot itu dan jatuh ke model kelas atas, model yang sama dengan yang kalian pakai untuk pekerjaan berat. 😤

Cara menutup problem recap ini bagaimana? Dikonfirmasi lewat dokumentasi env var resmi dan diskusi komunitas di Reddit: set env var CLAUDE_CODE_ENABLE_AWAY_SUMMARY=0 sebelum menjalankan Claude Code. Ini memaksa recap mati total, mengalahkan pengaturan apa pun di /config.

2. Goal Check-in untuk Background Task yang Masih Berjalan

Kalau kalian memakai fitur /goal (menyuruh Claude terus bekerja sampai kondisi tertentu terpenuhi) dan ada background task yang masih berjalan saat sesi idle, Claude Code akan mengecek progresnya sendiri tiap 30 menit, tiap check-in mengirim full context. Sebelum versi 2.1.246, jumlah check-in ini tidak dibatasi sama sekali.

Sesi yang diperiksa tidak memakai /goal sama sekali, jadi mekanisme ini kemungkinan bukan penyebab polanya. Tapi tetap patut disebut karena satu keluarga masalah yang sama: pengecekan latar belakang yang mengirim full context, dan bisa dimatikan lewat CLAUDE_CODE_GOAL_CHECKIN_MINUTES=0 kalau kalian memakai fitur ini.

3. Ringkasan Otomatis Saat Membuka Sesi Lama

Ini yang menjelaskan lonjakan 390k token di kasus kedua tadi. Dokumentasi resmi Claude Code menyebutnya resume from a summary:

Claude Code mengirim satu permintaan ringkasan atas seluruh conversation history, lalu menggantinya dengan ringkasan itu ditambah pertukaran terbaru dan hingga lima berkas yang baru dibaca. Permintaan-permintaan berikutnya membawa ringkasan itu, bukan riwayat penuh.

Secara keseluruhan fitur ini justru menghemat, bukan memboroskan. Namun ada satu biaya besar di depan, meski setelah itu permintaan-permintaan berikutnya jauh lebih murah ketimbang membawa riwayat penuh 1.187 pesan tiap kali kalian mengetik.

Masalahnya adalah model yang dipakai untuk membuat ringkasan itu sendiri jatuh ke slot model yang mahal, sama seperti kasus away_summary di atas. Dan juga tidak ada laporan komunitas yang membahas ini secara spesifik, dan tidak ada env var resmi untuk memaksanya memakai model kecil.

4. Catatan Sesi yang Terus Diperbarui di Background

Ini pola paling mengganggu di log, karena berulang hampir tiap beberapa request, bukan sekali di awal saja. Dokumentasi resmi Anthropic tidak membahasnya secara eksplisit, tapi dua analisis independen yang membedah kode sumber Claude Code, Decode Claude dan Finisky Garden, menjelaskan mekanisme yang polanya persis. Keduanya menyebutnya session memory:

Sepanjang sesi berjalan, ada proses latar belakang yang secara berkala mengekstrak “catatan sesi”, sebuah berkas markdown terstruktur berisi status kini, berkas dan fungsi yang disentuh, kesalahan dan perbaikannya.

Proses ini berjalan sebagai agen bercabang yang terisolasi dari main thread, yaitu alur percakapan utama yang kalian ajak bicara, dan dipicu hanya saat respons terakhir tidak mengandung pemanggilan tool, supaya ekstraksi terjadi di sela antar-turn, bukan di tengah alur kerja.

Penjelasan itu cocok persis dengan polanya di log. Request-nya muncul setelah MiMo selesai menjawab, bukan di tengah pemanggilan tool, formatnya 3 pesan JSON yang khas proses latar belakang, dan ukuran cache-nya naik pelan (108.160 lalu 108.544 lalu 108.672 lalu 109.056), jauh lebih kecil dibanding lompatan jumlah pesan MiMo. Artinya proses itu berbagi sebagian besar cache dengan sesi utama, menambah sedikit saja tiap kali, bukan membaca ulang semuanya dari nol.

Satu catatan soal nama, istilah session memory datang dari analisis pihak ketiga yang membaca kode Claude Code, bukan dari dokumentasi resmi Anthropic. Polanya cocok persis dengan yang muncul di log, tapi nama resminya sendiri tidak pernah diumumkan Anthropic. Tidak ada env var resmi untuk mematikan proses ini.

Menghindari Boros, Tapi Salah Sasaran

Ini yang membedakan temuan di sini dari keluhan token-boros yang sudah lama dibahas komunitas Claude Code, misalnya skema tool MCP yang dimuat penuh di tiap request meski MCP tersebut tidak pernah dipakai.

Satu laporan di GitHub mencatat 88.000 token skema tool menumpang di tiap panggilan API sepanjang sesi, padahal nol di antaranya benar-benar dipanggil. Keluhan di issue tersebut adalah perihal jumlah token. Sedangkan temuan di artikel saya ini adalah soal model yang salah dipilih.

Anthropic sendiri menyediakan mekanisme resmi untuk memisahkan model per kelas:

ANTHROPIC_MODEL                 → model utama sesi, dipilih eksplisit lewat --model / env var / settings
ANTHROPIC_DEFAULT_HAIKU_MODEL   → slot kelas "haiku", untuk background functionality ringan
ANTHROPIC_DEFAULT_SONNET_MODEL  → slot kelas "sonnet", dipakai saat kode internal kelas menengah

Semua mekanisme di atas idealnya jatuh ke baris kedua (Haiku, menurut saya). Semuanya tugas ringan yang tidak butuh model kelas atas: meringkas history, mencatat status kerja. Kenyataannya di log, keempatnya jatuh ke baris ketiga, yakni Si sonnet, yang di setup ini kebetulan diarahkan ke combo CommandCode dengan kuota lebih mahal dan lebih terbatas.

Dua percobaan berurutan membuktikannya. Percobaan pertama mengganti ANTHROPIC_MODEL dari DeepSeek ke Mistral, combo gratis, sementara slot sonnet dibiarkan tetap DeepSeek. Buka sesi baru, /resume sesi besar, /model mimo, kirim beberapa pesan. Hasilnya phantom request tetap jatuh ke DeepSeek, tidak berubah sama sekali.

Percobaan kedua mengarahkan slot sonnet ke Mistral juga, dengan skenario yang sama persis:

[04:08:34] POST claude-mimo-flash → xiaomi-tokenplan/mimo-v2.5 · STREAM · 1238 MSG · 17 TOOL
[04:08:40] Model xmtp/mimo-v2.5 succeeded
[04:08:48] POST claude-mistral → mistral/codestral-latest · JSON · 3 MSG · ACC:mistral
[04:08:54] DONE 5293ms · IN 111527 (CACHE 6528) · OUT 8
[04:08:54] POST claude-mistral → mistral/codestral-latest · JSON · 3 MSG · ACC:mistral
[04:08:55] DONE 1552ms · IN 111500 (CACHE 111360) · OUT 30
[04:08:55] POST claude-mimo-flash → xiaomi-tokenplan/mimo-v2.5 · STREAM · 1241 MSG · 17 TOOL

Phantom-nya berpindah ke Mistral. Pola perilakunya identik: formatnya tetap JSON, isinya tetap 3 pesan, cache-nya tetap sekitar 111K, dan tetap muncul persis setelah request MiMo selesai. Bedanya modelnya sekarang mengikuti ANTHROPIC_DEFAULT_SONNET_MODEL, dan kuota CommandCode tidak tersentuh sama sekali.

KonfigurasiSasaran phantom request
ANTHROPIC_MODEL dan slot sonnet sama-sama DeepSeekDeepSeek (kuota mahal)
Hanya ANTHROPIC_MODEL diganti Mistral, slot sonnet tetap DeepSeekDeepSeek, tidak berubah
ANTHROPIC_MODEL dan slot sonnet sama-sama MistralMistral (gratis)

Kalau dipikir ulang, pilihan kelas menengah ini masuk akal secara desain. Tugas meringkas conversation history terlalu berat untuk kelas Haiku, hasilnya akan kasar, tapi tidak butuh kelas Opus yang mahal. Jadi Claude Code meminta kelas menengah secara internal, apa pun model yang sedang kalian pakai lewat /model saat itu. Masalahnya, dokumentasi menjanjikan slot Haiku sebagai tempat background functionality berjalan, dan slot itulah yang justru dilewati.

Bagaimana Solusinya?

Perbaikan intinya ada di satu variabel, dan ini yang paling penting kalau kalian memakai router dengan beberapa tingkatan model atau istilah kerennya Combo. Caranya, arahkan slot sonnet ke combo termurah atau gratis yang kalian punya, bukan sebatas ANTHROPIC_MODEL. Combo mahal tetap bisa dipanggil eksplisit lewat /model untuk kerja aktif.

# fix inti: slot sonnet jadi sasaran proses background, arahkan ke combo gratis
export ANTHROPIC_DEFAULT_SONNET_MODEL="claude-mistral"
export ANTHROPIC_MODEL="claude-mistral"

# matikan dua mekanisme yang memang punya tombol resmi
export CLAUDE_CODE_ENABLE_AWAY_SUMMARY=0
export CLAUDE_CODE_GOAL_CHECKIN_MINUTES=0

Satu env var lain juga ikut dihapus, yaitu CLAUDE_AUTOCOMPACT_PCT_OVERRIDE. Sebelumnya nilainya saya set rendah, 75 persen, dengan niat biar cepat diringkas supaya hemat. Ternyata logikanya terbalik: makin rendah ambangnya, makin sering proses peringkasan yang mahal itu terpicu. Nilainya kembali ke bawaan Anthropic.

Satu penyetelan terakhir tidak langsung soal token, melainkan soal kebiasaan kerja: crossSessionInbound diubah ke hold di berkas pengaturan Claude Code. Saya sering membiarkan satu sesi menganggur berhari-hari sambil kerja di sesi lain. Tanpa pengaturan ini, pesan dari sesi lain bisa “membangunkan” sesi yang menganggur dan ikut mengirim konteks penuhnya. Dengan hold, pesan itu ditahan sebagai notifikasi saja, tidak pernah sampai ke model sampai disetujui manual.

Mekanisme resume from a summary dan session memory sendiri sengaja dibiarkan hidup. Keduanya memang berguna untuk menghemat token secara keseluruhan dan membuat kompaksi (compact) jadi lebih murah. Yang berubah sebatas model mana yang keduanya pakai, bukan apakah keduanya berjalan.

Jika Kalian Tidak Pakai Router Custom

Dua hal ini tetap relevan buat kalian, walau memakai Claude Code langsung ke Anthropic dengan paket langganan:

  • CLAUDE_CODE_ENABLE_AWAY_SUMMARY=0 tetap mengurangi jumlah token yang terpakai per sesi, walau tidak berpengaruh ke tagihan langganan bulanan secara langsung. Berguna kalau sesi panjang kalian sering mendekati batas jendela konteks dan kalian ingin menunda peringkasan otomatis selama mungkin.
  • Jalankan /context sesekali untuk melihat berapa persen jendela konteks kalian terpakai oleh skema tool MCP yang bahkan tidak pernah kalian panggil. Kalau kalian memasang banyak MCP server tapi memakai sebagian kecil saja, pindahkan konfigurasinya jadi per-proyek (.mcp.json) daripada global, supaya server yang tidak relevan tidak ikut termuat di tiap sesi.

Kesimpulan

4 mekanisme ini baru ketahuan setelah berbulan-bulan memakai Claude Code, dan itu pun karena kebetulan sedang mengaudit log router, bukan karena membaca dokumentasinya baik-baik. Dasbor tagihan yang digabung jadi satu angka bulanan itu nyaman, tapi justru menyembunyikan detail yang paling berguna.

Intinya bukan seberapa banyak cost yang kalian habiskan, melainkan untuk apa saja token yang kita beli itu benar-benar dipakai.

Kalau kalian mengelola biaya AI coding assistant dengan anggaran ketat, entah lewat router custom seperti ini atau langsung ke API berbayar per token, sekali-kali bukalah log request mentahnya, bukan sebatas dasbor ringkasannya. Angka yang sudah digabung selalu terlihat masuk akal. Baru kelihatan janggal kalau ditelusuri satu per satu.


Catatan

Semua pengamatan di artikel ini diambil dari Claude Code 2.1.258 pada 3 September 2026, lewat log 9Router yang berjalan lokal. Anthropic merilis versi baru hampir tiap hari, dan sebagian temuan di sini memang berstatus bug yang sudah dilaporkan publik (issue #85922 di Github Claude Code untuk away_summary).

Kalau kalian membaca ini di versi yang jauh lebih baru, cek dulu perilakunya di setup kalian sendiri sebelum menerapkan fix-nya: bisa jadi slot model yang ditembak sudah diperbaiki, atau env var yang disebut di sini sudah berganti nama. Cara mengeceknya adalah dengen melihat log request mentah dari router atau gateway kalian, lalu perhatikan model apa yang muncul saat kalian tidak meminta apa-apa.

M. Khoirul Huda

A non exhausted blogger person within fullstack engineer (spicy food), open source religion, self-taught driver and maybe you know or don't like it. Simply says, Hello from Me!

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *

Cek untuk notifikasi e-mail jika komentar dibalas.

This site uses Akismet to reduce spam. Learn how your comment data is processed.