SSD Nodes Learn 🎉 VPS mulai $5.50/bln
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-13

Cara Membuat Statusline Claude Code di VPS

Pelajari pengaturan statusLine Claude Code untuk menampilkan hostname, direktori, branch Git, dan model dari output skrip di bawah prompt, agar server yang diedit selalu tepat.

Yang ditampilkan statusline Claude Code

Statusline Claude Code adalah baris di bawah prompt yang menampilkan output dari skrip yang Anda tulis. Tambahkan blok statusLine ke settings.json, lalu arahkan blok tersebut ke sebuah perintah. Claude Code menjalankan perintah itu, mengirimkan status sesi dalam format JSON melalui standard input, lalu menampilkan apa pun yang ditulis perintah tersebut ke standard output.

Hanya itu kontraknya. Skrip Anda membaca JSON dari stdin dan menampilkan teks ke stdout. Skrip berjalan di komputer Anda. Tidak ada output yang dikirim ke model, sehingga tidak menggunakan token.

Pada laptop dengan satu project, fitur ini hanya bersifat dekoratif. Pada tiga server, fitur ini menjadi pengaman. Setiap sesi Claude Code terlihat sama di setiap terminal. Karena itu, empat jendela SSH tanpa label dapat menyebabkan migrasi diterapkan pada server yang salah. Statusline yang diawali hostname mencegah kesalahan tersebut.

Lokasi pengaturan statusLine di settings.json

Tempatkan di pengaturan pengguna pada ~/.claude/settings.json, yang berlaku untuk setiap project di mesin tersebut. Pengaturan project pada .claude/settings.json di dalam repository juga dapat digunakan dan memiliki prioritas untuk direktori tersebut.

{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh"
  }
}

type selalu berupa "command". Nilai command dijalankan melalui shell, sehingga dapat berupa path skrip atau perintah biasa. Pastikan integrasinya berfungsi sebelum menulis skrip apa pun:

{
  "statusLine": {
    "type": "command",
    "command": "hostname -s"
  }
}

Jalankan Claude Code dan kirim satu pesan. Baris di bawah prompt sekarang menampilkan hostname singkat server. Jika tetap kosong, masalahnya ada pada pengaturan atau dialog trust, bukan pada skrip Anda. Baca bagian "Mengapa statusline tetap kosong" di bawah.

Tersedia tiga kunci opsional per August 2026. padding menambahkan jarak horizontal dalam karakter dan nilai bawaannya adalah 0. refreshInterval menjalankan ulang perintah setiap N detik selain trigger normal, dengan minimum 1. Gunakan ini hanya jika baris menampilkan jam atau sesuatu yang berubah saat sesi dalam keadaan idle. hideVimModeIndicator menyembunyikan teks bawaan -- INSERT -- saat skrip Anda sendiri sudah menampilkan mode vim.

Data apa yang diterima skrip statusline?

Jangan mempercayai daftar field yang Anda baca di mana pun, termasuk di halaman ini. Ambil objek aktual yang dikirim oleh versi Anda. Tulis skrip sementara yang menyimpan stdin ke sebuah file:

cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.sh

Arahkan statusLine.command ke file tersebut, mulai sebuah sesi, lalu kirim satu pesan. Bar membaca captured. Sekarang periksa data yang diterima:

jq . /tmp/statusline-input.json

Anda memiliki struktur yang tepat untuk build Anda, dan dapat mengulanginya kapan pun pembaruan mengubah sesuatu.

Bagian yang stabil, sebagaimana didokumentasikan pada Agustus 2026, berupa objek bertingkat, bukan key datar. model berisi id dan display_name. workspace berisi current_dir dan project_dir: current_dir menunjukkan lokasi sesi saat ini, project_dir menunjukkan lokasi saat sesi dijalankan, dan keduanya berbeda setelah direktori kerja berubah di tengah sesi. cwd tingkat teratas membawa nilai yang sama seperti workspace.current_dir. context_window berisi jumlah token serta used_percentage yang telah dihitung sebelumnya. cost berisi total_cost_usd dan penghitung durasi. session_id tetap sama selama sesi berlangsung dan unik di antara sesi, sehingga penting untuk caching nantinya.

Tiga aturan berikut menjaga skrip tetap berfungsi saat skema berubah.

Beberapa key tidak ada, bukan bernilai null. vim, agent, pr, worktree, dan effort hanya muncul saat fitur yang sesuai aktif. Membaca .vim.mode dengan jq -r ketika mode vim nonaktif akan mencetak string literal null, dan bar Anda menampilkan null kepada pembaca. Tambahkan // empty ke setiap selector agar key yang tidak ada sama sekali tidak mencetak apa pun.

Beberapa nilai pada awalnya null. context_window.used_percentage dan context_window.current_usage bernilai null sebelum respons API pertama, dan current_usage kembali menjadi null setelah /compact sampai panggilan berikutnya mengisinya kembali. Karena itu, persentase konteks pada bar memerlukan // 0; jika tidak, bar akan membaca null selama beberapa detik pertama setiap sesi. Sebelum menampilkan angka tersebut pada bar, Anda perlu memahami cara pengisian context window yang sebenarnya.

Branch git tidak ada di JSON. Tidak ada field yang melaporkannya. Branch apa pun pada bar berasal dari skrip Anda sendiri yang menjalankan git.

Skrip statusline yang tetap berjalan saat data tidak tersedia

Berikut versi yang dapat langsung disalin dan ditempel. Skrip ini menampilkan hostname, direktori kerja, cabang git, dan nama model. Setiap bidang memiliki nilai pengganti, sehingga objek JSON kosong pun tetap menghasilkan baris yang dapat digunakan.

#!/bin/bash
# ~/.claude/statusline.sh
input=$(cat)

# Read one field. Prints nothing when the key is missing or null.
field() { printf '%s' "$input" | jq -r "$1 // empty" 2>/dev/null; }

HOST=$(hostname -s 2>/dev/null)
[ -z "$HOST" ] && HOST="host"

DIR=$(field '.workspace.current_dir')
[ -z "$DIR" ] && DIR=$(field '.cwd')
[ -z "$DIR" ] && DIR="$PWD"

MODEL=$(field '.model.display_name')
[ -z "$MODEL" ] && MODEL="claude"

SHORT="$DIR"
if [ -n "$HOME" ]; then
  case "$DIR" in
    "$HOME") SHORT="~" ;;
    "$HOME"/*) SHORT="~/${DIR#"$HOME"/}" ;;
  esac
fi

BRANCH=""
if git -C "$DIR" rev-parse --git-dir >/dev/null 2>&1; then
  BRANCH=$(git -C "$DIR" branch --show-current 2>/dev/null)
  [ -z "$BRANCH" ] && BRANCH="detached"
fi

CYAN=$'\033[36m'
YELLOW=$'\033[33m'
DIM=$'\033[2m'
RESET=$'\033[0m'

LINE="${CYAN}${HOST}${RESET} ${SHORT}"
[ -n "$BRANCH" ] && LINE="${LINE} ${YELLOW}${BRANCH}${RESET}"
LINE="${LINE} ${DIM}${MODEL}${RESET}"

printf '%s\n' "$LINE"

Setiap pembacaan dilakukan melalui field, yang menambahkan // empty. Dengan begitu, key yang diganti nama atau dihapus menghasilkan string kosong, lalu baris berikutnya memberikan nilai default. Direktori menggunakan workspace.current_dir, kemudian cwd, lalu $PWD sebagai fallback. Cabang diambil dari git -C "$DIR", bukan dari git langsung, sehingga cabang selalu sesuai dengan direktori yang ditampilkan oleh baris status.

Simpan skrip tersebut, lalu jadikan executable:

chmod +x ~/.claude/statusline.sh

Bit execute wajib diaktifkan. Claude Code menjalankan perintah melalui shell. Karena itu, skrip tanpa +x gagal dengan Permission denied, tidak menghasilkan stdout, dan baris status tetap kosong tanpa error yang terlihat.

jq digunakan untuk memproses JSON pada command line dan tidak terinstal pada server Ubuntu baru:

sudo apt update && sudo apt install -y jq

Kemudian arahkan pengaturan ke skrip tersebut menggunakan blok settings.json pertama di atas.

Uji skrip sebelum mengandalkannya

Jalankan skrip tersebut dua kali secara manual. Pertama, gunakan objek sesi normal:

echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/srv/api"},"session_id":"t1"}' | ~/.claude/statusline.sh

Hostname ditampilkan, kemudian /srv/api, lalu Opus. Tidak ada percabangan yang muncul karena /srv/api pada mesin Anda mungkin bukan repositori git.

Kedua, lakukan uji degradasi. Uji inilah yang sering dilewati:

echo '{}' | ~/.claude/statusline.sh

Objek kosong adalah kasus terburuk yang dapat diberikan oleh perubahan skema. Baris tersebut tetap menampilkan hostname, direktori saat ini dari $PWD, dan kata claude pada bagian yang seharusnya berisi nama model. Tidak ada yang mengalami crash dan tidak ada null yang ditampilkan. Skrip yang lulus uji ini tetap berfungsi ketika sebuah field diganti namanya karena bagi skrip Anda, field yang diganti nama dan field yang tidak ada merupakan peristiwa yang sama.

Yang harus Anda lihat

Baris status ditampilkan pada barisnya sendiri di atas lencana footer bawaan dan tidak menggantikannya. Pada konfigurasi yang berfungsi, baris ini memuat hostname singkat dalam warna cyan, kemudian direktori kerja dengan direktori home yang dipersingkat menjadi ~, lalu nama branch dalam warna kuning jika direktori tersebut merupakan repositori git, dan terakhir nama model yang diredupkan. Tampilannya kurang lebih seperti web-01 ~/api main Opus, dengan keempat bagian tersebut diberi warna.

Baris ini menjalankan ulang skrip saat sesi dimulai, termasuk saat melanjutkan sesi, saat pesan assistant baru diterima, setelah /compact selesai, saat mode izin berubah, saat vim mode diaktifkan atau dinonaktifkan, dan pada interval refreshInterval jika Anda menetapkannya. Pembaruan ditunda selama 300 ms, sehingga serangkaian perubahan hanya menjalankan skrip satu kali. Bilah status disembunyikan selama autocomplete, menu bantuan, dan prompt izin, lalu ditampilkan kembali.

Mengapa hostname harus ditampilkan terlebih dahulu

Saat Anda menjalankan agent di lebih dari satu server, terminal adalah satu-satunya petunjuk tentang lokasi Anda, dan terminal dapat menyesatkan. Buka koneksi ssh kedua dari dalam pane tmux, lalu judul jendela sering kali tetap menggunakan nama lama karena judul tersebut ditetapkan oleh shell yang tidak mengetahui bahwa lokasinya telah berubah. Biarkan Claude Code berjalan dalam sesi tmux detached di VPS dan lakukan reattach sehari kemudian. Tidak ada elemen di layar yang membedakan server build dari server production.

Statusline berbeda karena dirender oleh Claude Code sendiri untuk setiap sesi, berdasarkan data yang disimpan sesi tersebut. Statusline tidak dapat diwarisi dari pane yang salah atau tetap usang karena prompt shell yang tidak pernah diperbarui. Informasi yang ditampilkan adalah server tempat agent menulis file.

Gunakan warna yang berbeda untuk setiap server agar Anda dapat mengenalinya sebelum membaca namanya. Tambahkan dua baris berikut di atas assignment LINE=:

CODE=$(printf '%s' "$HOST" | cksum | cut -d' ' -f1)
HOST_COLOR=$(printf '\033[%dm' "$((31 + CODE % 6))")

Kemudian gunakan ${HOST_COLOR} sebagai pengganti ${CYAN}. cksum mencetak checksum hostname. Dengan demikian, nama tertentu selalu dipetakan ke warna yang sama dalam rentang 31 hingga 36, yaitu merah hingga cyan. Salin script yang sama ke setiap server agar masing-masing server menampilkan identitasnya sendiri.

Direktori memiliki fungsi yang sama pentingnya. /srv/api dan /srv/api-staging hanya berjarak satu penekanan tombol dalam perintah ssh, tetapi dampaknya dapat membedakan dua insiden yang sepenuhnya berbeda. Model dan branch adalah dua informasi lain yang layak menggunakan ruang statusline. Model menunjukkan sesi yang Anda lanjutkan, sedangkan branch menunjukkan apakah agent akan melakukan commit ke main.

Layar yang kecil membuat semua ini semakin penting karena tidak ada judul jendela yang dapat dijadikan petunjuk. Jika itu konfigurasi Anda, lihat mengendalikan Claude Code dari ponsel.

Jaga agar skrip tetap cepat

Skrip Anda berjalan pada setiap pesan assistant, dan Claude Code membatalkan proses yang sedang berjalan ketika pembaruan baru tiba. Karena itu, skrip yang lambat dapat menampilkan teks yang sudah usang atau tidak menampilkan teks sama sekali.

Setiap pemanggilan jq memerlukan beberapa milidetik. git adalah bagian yang menjadi lambat: git status pada repositori besar dengan cache dingin memerlukan waktu ratusan milidetik. Skrip di atas sengaja menghindari git status dan memanggil git branch --show-current, yang membaca .git/HEAD lalu segera mengembalikan hasil.

Jika Anda menambahkan proses yang lebih berat, simpan hasilnya dalam file cache dan perbarui setiap beberapa detik. Gunakan session sebagai kunci file:

CACHE="/tmp/statusline-$(field '.session_id')"

Gunakan session_id, bukan $$. $$ adalah ID proses skrip Anda. Nilainya berbeda pada setiap pemanggilan, sehingga cache yang menggunakan nilai ini sebagai kunci tidak pernah cocok dan seluruh biaya proses harus dibayar setiap kali. session_id tetap sama selama seluruh session dan berbeda antar-session. Dengan demikian, dua session Claude Code dalam dua repositori tidak dapat membaca nama branch yang tersimpan dalam cache satu sama lain.

Ada satu batasan lain yang perlu diketahui: tput cols tidak berfungsi di dalam skrip statusline. Claude Code menangkap output tersebut, bukan menghubungkan skrip Anda ke terminal, sehingga deteksi lebar tidak memiliki nilai yang dapat diukur. Pada v2.1.153 dan versi yang lebih baru, Claude Code menetapkan variabel lingkungan COLUMNS dan LINES sebelum menjalankan perintah. Karena itu, baca $COLUMNS ketika Anda perlu menentukan jumlah teks yang akan ditampilkan.

Baris status tetap kosong

Tidak ada apa pun yang muncul. Periksa bit eksekusi dengan ls -l ~/.claude/statusline.sh, lalu jalankan skrip secara manual menggunakan input tiruan di atas. Jika skrip mencetak baris di shell tetapi tidak di Claude Code, mulai dengan claude --debug, yang mencatat kode keluar dan stderr dari eksekusi statusline pertama dalam sesi.

Log debug berisi Status line command skipped: workspace trust not accepted. Statusline menjalankan perintah shell, sehingga tunduk pada gate kepercayaan workspace yang sama seperti hook. Perintah tersebut tidak akan berjalan sampai Anda menyetujui dialog kepercayaan untuk direktori itu. Hal ini umum terjadi pada VPS karena setiap clone baru merupakan direktori yang belum pernah dilihat Claude Code. Jalankan ulang Claude Code di direktori tersebut dan setujui dialognya.

Semuanya kosong dan disableAllHooks diatur. "disableAllHooks": true dalam settings.json juga menonaktifkan statusline karena merupakan gate eksekusi shell yang sama. Hapus pengaturan tersebut atau atur ke false.

Baris mencetak null. Selector jq menemukan key yang tidak ada atau bernilai null, dan jq -r mencetak null sebagai empat karakter null. Tambahkan // empty untuk teks dan // 0 untuk angka.

Baris menjadi kosong tepat setelah Anda mengedit skrip. Perintah yang keluar dengan status nonzero atau tidak mencetak apa pun akan mengosongkan baris. Penyebab yang umum adalah baris terakhir seperti [ -n "$BRANCH" ] && LINE="...", yang keluar dengan status 1 saat branch kosong dan menyebabkan seluruh skrip menggunakan kode keluar tersebut. Biarkan printf tetap menjadi baris terakhir, atau tambahkan exit 0.

Kode escape tampil sebagai teks literal, seperti \e]8;; pada baris. Gunakan printf '%b' sebagai pengganti echo -e. Tautan OSC 8 yang dapat diklik juga memerlukan terminal yang mendukungnya, dan tmux atau SSH dapat menghapus rangkaian tersebut. Karena itu, warna biasa merupakan pilihan yang lebih aman pada server remote.

Sisi kanan baris terpotong. Notifikasi sistem dan penghitung token mode verbose menggunakan baris yang sama dari sisi kanan, sehingga terminal yang sempit mengalami tumpang tindih. Buat output tetap singkat. Untuk pencatatan penggunaan yang sebenarnya, bukan sekadar angka pada baris, lihat cara Claude Code menghitung token.

FAQ

Di mana pengaturan statusline Claude Code berada?

Pengaturan tersebut berada di settings.json, sebagai blok statusLine dengan type yang ditetapkan ke "command" dan command yang ditetapkan ke path skrip atau perintah shell. Pengaturan pengguna berada di ~/.claude/settings.json dan berlaku untuk setiap proyek pada mesin tersebut. Pengaturan proyek berada di .claude/settings.json di dalam repositori dan memiliki prioritas untuk direktori tersebut. Pengaturan dimuat ulang secara otomatis, tetapi perubahan baru terlihat pada pemicu pembaruan berikutnya, seperti pesan Anda berikutnya.

Mengapa statusline Claude Code saya kosong?

Hampir semua kasus disebabkan oleh empat hal. Skrip tidak memiliki bit eksekusi, sehingga shell mengembalikan Permission denied dan tidak ada keluaran yang masuk ke stdout. Dialog kepercayaan workspace belum pernah disetujui, dan claude --debug mencatat Status line command skipped: workspace trust not accepted. disableAllHooks bernilai true, yang menonaktifkan statusline melalui pemeriksaan yang sama. Atau, skrip keluar dengan kode non-nol sehingga baris tersebut kosong. Uji skrip secara manual terlebih dahulu: echo '{}' | ~/.claude/statusline.sh harus mencetak sesuatu.

Apakah JSON statusline menyertakan branch git?

Tidak. JSON tersebut memuat status sesi, seperti model, direktori workspace, angka jendela konteks, dan biaya. JSON tersebut tidak memuat informasi git. Branch pada bar Anda berasal dari skrip Anda sendiri yang memanggil git branch --show-current. Teruskan direktori dari JSON menggunakan git -C "$DIR" agar branch selalu sesuai dengan direktori yang ditampilkan bar.

Apakah statusline menggunakan token atau memperlambat sesi?

Statusline tidak menggunakan token karena skrip berjalan secara lokal dan keluarannya tidak pernah dikirim ke model. Kecepatan menjadi tanggung jawab Anda. Perintah tersebut dijalankan pada setiap pesan assistant dengan debounce 300 ms. Claude Code membatalkan proses yang sedang berjalan ketika pembaruan baru tiba. Karena itu, skrip yang memerlukan waktu hingga satu detik akan menampilkan teks yang sudah usang. Hindari git status pada repositori besar, dan simpan hasil apa pun yang lambat ke dalam file yang menggunakan session_id sebagai kunci.

Bagaimana cara menampilkan statusline yang berbeda pada setiap server?

Gunakan satu skrip dan biarkan skrip tersebut membaca informasi mesin. Skrip di atas mencetak $HOSTNAME dengan hostname -s sebagai fallback. Dengan demikian, file yang sama dapat disalin ke setiap server dan memberi label yang benar pada masing-masing server. Trik warna checksum juga memberikan warna tersendiri untuk setiap hostname. Jika salah satu server memerlukan tata letak yang berbeda, tambahkan blok statusLine pada pengaturan proyek repositori yang Anda gunakan di server tersebut, karena pengaturan proyek mengesampingkan pengaturan pengguna untuk direktori itu.