Status Line Claude Code: Konteks, Biaya, dan Cache Langsung

Arahkan setting statusLine ke sebuah perintah di file setting Anda. Claude Code menjalankan script itu dengan data sesi berupa JSON lewat stdin dan menampilkan apa pun yang dicetaknya ke stdout. Script-nya berjalan lokal dan tidak memakan token API. Pastikan ia executable dan menulis ke stdout, bukan stderr.
Empat penyebab umum: script-nya tidak executable, ia menulis ke stderr alih-alih stdout, ia terlalu lambat — run yang masih berjalan saat pemicu baru datang dibatalkan, bukan diantrekan — atau di Windows dengan Git Bash, backslash pada path perintahnya termakan sebagai karakter escape. Jalankan claude --debug untuk mencatat exit code dan stderr-nya.
Baca environment variable COLUMNS dan LINES, yang disetel Claude Code sebelum tiap run. Claude Code menangkap keluaran script Anda alih-alih menyambungkannya ke terminal, jadi tput cols dan deteksi lebar level bahasa tidak bisa melihat ukuran terminal dari dalam script.
Dari token input saja: input_tokens ditambah cache_creation_input_tokens ditambah cache_read_input_tokens. Ia sengaja mengecualikan token output. Kalau Anda menghitung persentasenya sendiri dari objek current_usage, pakai rumus input-saja yang sama atau angka Anda tidak akan cocok dengan yang ditampilkan Claude Code di tempat lain.
Bisa, dan secara senyap. Kalau disableAllHooks bernilai true di luar managed settings, hanya statusLine dari managed settings yang berjalan. Kalau organisasi Anda menyetel allowManagedHooksOnly, status line kustom Anda lenyap tanpa peringatan dan Anda hanya bisa mendapatkannya dari managed settings. Tanyakan kepada pemilik managed settings Anda.

Ringkasan Utama
Status line Claude Code adalah script shell apa pun yang Anda konfigurasikan. Claude Code menjalankannya dengan data sesi berupa JSON lewat stdin lalu menampilkan apa pun yang dicetaknya ke stdout. Ia berjalan saat sesi dimulai dan pada perubahan pesan, compaction, permission mode, serta vim mode, dengan debounce 300 milidetik, dan run yang masih berjalan saat pemicu baru datang dibatalkan, bukan diantrekan.
Status line pertama saya bekerja sempurna ketika saya uji manual dan sama sekali tidak menampilkan apa pun di dalam Claude Code. Script-nya tidak bermasalah. Ia memanggil sebuah perintah git yang butuh sekitar setengah detik, dan setiap pesan asisten baru membatalkan run itu sebelum selesai — jadi bar-nya selamanya tertinggal satu pembaruan yang tidak pernah rampung.
Status line adalah salah satu kustomisasi termurah yang tersedia sekaligus salah satu yang paling mudah keliru secara halus, karena ia gagal dalam senyap lewat tiga cara berbeda. Tulisan ini membahas model pembaruannya dan aturan pembatalannya, field JSON yang benar-benar layak ditampilkan, jebakan lebar terminal, serta dua setting organisasi yang bisa membuat status line yang berfungsi lenyap tanpa pesan.
Tidak ada yang perlu dipasang. Anda mengarahkan sebuah settings key ke sebuah perintah, dan Claude Code menjalankannya dengan JSON di standard input. Ia berjalan lokal dan tidak memakan token API, serta menyembunyikan diri sementara saat autocomplete, menu bantuan, dan permission prompt.
// settings.json — the script gets JSON on stdin and whatever
// it prints to stdout becomes the bar.
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh",
"refreshInterval": 5000
}
}
# The script runs at session start, then on:
# - a new assistant message
# - /compact finishing
# - a permission mode change
# - a vim mode toggle
# - a change to the command itself
# - a refreshInterval tick, if you set one
#
# Updates debounce at 300ms. A new trigger while the script is
# still running CANCELS the in-flight run — so a slow script
# does not queue up, it just never finishes.Pemicunya berbasis event, artinya ia bisa mendadak senyap justru ketika Anda paling ingin pembaruan — misalnya saat sebuah koordinator menunggu subagent background, tidak ada satu pun pemicu dalam daftar itu menyala. Untuk itulah refresh interval ada: ia menjalankan ulang perintahnya pada pengatur waktu tetap sehingga segmen berbasis waktu atau bersumber eksternal tetap mutakhir selama periode senggang.
Daftar field lengkapnya panjang dan sebagian besarnya pengisi. Ini yang menjawab pertanyaan yang jika tidak, Anda harus menghentikan diri sendiri untuk menanyakannya.
# The fields worth building on, out of a much longer list.
model.display_name "Opus 5"
workspace.current_dir preferred over the identical cwd
workspace.project_dir where Claude Code was LAUNCHED, which
differs from cwd after a /cd
workspace.git_worktree worktree name, for any linked worktree
workspace.repo.host/owner/name parsed from the origin remote
cost.total_cost_usd client-side estimate, resets on /clear
cost.total_duration_ms wall clock
cost.total_api_duration_ms time spent waiting on the API
context_window.used_percentage input tokens ONLY:
input + cache_creation + cache_read
— it does NOT include output tokens
context_window.current_usage the same counts broken out:
input_tokens
output_tokens
cache_creation_input_tokens <- the cache health signal
cache_read_input_tokens <- ratio of these two is what to watch
# current_usage is null before the first API call, and again
# right after /compact until the next call repopulates it.Persentase konteks dihitung dari token input saja — input ditambah cache creation ditambah cache read — dan sengaja mengecualikan token output. Kalau Anda menghitung persentasenya sendiri dari objek usage lalu menyertakan token output, angka Anda tidak akan cocok dengan yang ditampilkan Claude Code di tempat lain, dan Anda akan menghabiskan satu sore memutuskan mana yang keliru. Pakai rumus input-saja yang sama.
Yang satu ini menagih satu jam dari semua orang, sekali. Claude Code menangkap keluaran script Anda alih-alih menyambungkannya ke terminal, jadi cara-cara biasa untuk menanyakan seberapa lebar terminalnya semua gagal dari dalam script — perintah query kolom dan setiap deteksi lebar level bahasa tidak melihat terminal apa pun. Claude Code menyetel dua environment variable sebelum tiap run, dan membacanya adalah satu-satunya cara andal mengukur keluaran Anda.
#!/usr/bin/env bash
# Claude Code CAPTURES stdout rather than attaching it to the
# terminal, so tput cols and language-level width detection
# cannot see the terminal from inside the script.
#
# Read these instead — Claude Code sets both before each run:
: "${COLUMNS:=80}"
: "${LINES:=24}"
input=$(cat)
model=$(echo "$input" | jq -r '.model.display_name')
pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0')
# Cache health: read tokens over created tokens. A high ratio
# means caching is working; creation staying high means
# something in the prefix is moving every turn.
read_tok=$(echo "$input" | jq -r '.context_window.current_usage.cache_read_input_tokens // 0')
made_tok=$(echo "$input" | jq -r '.context_window.current_usage.cache_creation_input_tokens // 0')
printf '%s ctx %s%% cache %s/%s' "$model" "$pct" "$read_tok" "$made_tok"
# Test it without launching Claude Code:
# echo '{"model":{"display_name":"Opus"}}' | ./statusline.shUji script-nya dengan memipa JSON tiruan ke dalamnya alih-alih dengan memulai ulang Claude Code. Satu echo objek minimal sudah menguji segalanya kecuali logika pemicunya, dan itu mengubah siklus edit-lalu-luncurkan lima menit menjadi satu detik. Ia juga cara tercepat menemukan bahwa parsing JSON Anda tersedak pada field bernilai null, dan itu pasti terjadi, karena objek usage bernilai null sebelum panggilan API pertama dan lagi tepat setelah compaction.
Empat penyebab, diurutkan sesuai kelayakan diperiksa:
Dua setting bisa menghapus status line Anda tanpa pesan apa pun, dan keduanya layak diketahui sebelum Anda menyimpulkan script Anda rusak. Kalau setting disable-all-hooks bernilai true di luar managed settings, Claude Code hanya menjalankan status line yang berasal dari managed settings — dan bila di sana tidak ada, Anda tidak mendapat status line sama sekali.
Yang kedua adalah setting managed-hooks-only. Ketika sebuah organisasi menyetelnya, status line kustom Anda lenyap dalam senyap dan satu-satunya status line yang boleh Anda punya adalah yang disediakan administrator di managed settings. Kalau milik Anda hilang setelah sebuah kebijakan digulirkan alih-alih setelah sebuah pengeditan, hampir pasti itulah sebabnya, dan itu pertanyaan untuk pemilik managed settings Anda, bukan sebuah bug.
Ada setting terpisah untuk baris subagent, yang mengganti nama, deskripsi, dan jumlah token bawaan dengan format Anda sendiri. Perintahnya menerima setiap baris subagent yang terlihat sebagai satu objek JSON dan Anda menulis satu baris JSON per baris yang ingin ditimpa — termasuk model yang teresolusi per task, ukuran context window-nya, dan effort level-nya, sehingga Anda bisa menampilkan persentase konteks per agent yang sungguhan di panel agent.
Godaannya adalah menampilkan semua yang tersedia, dan hasilnya dinding angka yang tak dibaca siapa pun. Uji yang berguna adalah apakah sebuah nilai akan mengubah apa yang Anda lakukan dalam satu menit berikutnya.
Empat segmen yang sepadan dengan lebarnya:
| Segmen | Keputusan yang diinformasikannya |
|---|---|
| Persentase konteks | Apakah melakukan compact sekarang, di batas tugas, atau membiarkannya menyala di tengah tugas nanti |
| Cache read terhadap cache creation | Apakah ada yang membatalkan prefix Anda tiap giliran |
| Model dan effort | Apakah Anda masih di model yang Anda maksudkan satu jam lalu |
| Branch dan worktree | Terminal ini sebenarnya sesi paralel yang mana |
Setiap perintah cetak menjadi baris terpisah, jadi bar dua baris tidak butuh konfigurasi khusus. Kode escape ANSI standar bekerja di mana pun terminalnya mendukung, dan escape sequence hyperlink terminal membuat teks bisa diklik di terminal yang mendukungnya — dan begitulah cara Anda mendapat ID tiket di bar yang membuka tiketnya.
Layak diketahui sebelum Anda menginvestasikan waktu pada sebuah script: mengonfigurasi status line kustom membuat Claude Code berhenti menampilkan sebagian besar petunjuk keyboard di footer, termasuk petunjuk interrupt dan fallback shortcut. Kalau yang Anda inginkan hanya badge yang bisa diklik ketika sebuah pengenal muncul di percakapan, ada settings key terpisah untuk itu yang tidak menagih satu pun petunjuk tersebut.
Bangun bar terkecil yang menjawab pertanyaan yang terus membuat Anda menghentikan diri sendiri, lalu berhenti. Milik saya selebar empat segmen dan yang benar-benar mengubah perilaku saya adalah rasio cache, karena ia mengubah biaya yang tak terlihat menjadi angka yang bergerak di depan mata. Uji dengan JSON yang dipipa, simpan hasil apa pun yang lambat, dan baca lebarnya dari environment alih-alih menanyakannya ke terminal — itu sudah sebagian besar jalan menuju status line yang terus bekerja.
Sumber & bacaan lanjutan