Cara Set Statusline Claude Code di VPS
Gunakan tetapan statusLine untuk memaparkan hostname, direktori, dan cawangan git pada prompt Claude Code. Elakkan kesilapan pelayan dengan skrip output stdout yang mudah.
Apa yang dipaparkan oleh statusline Claude Code
Statusline Claude Code ialah baris di bawah prompt yang memaparkan output skrip yang anda tulis. Anda menambah blok statusLine ke settings.json dan menghalakannya kepada sesuatu arahan. Claude Code menjalankan arahan tersebut, menghantar status sesi kepadanya sebagai JSON melalui input standard, dan mencetak apa sahaja yang ditulis oleh arahan tersebut ke output standard.
Itu sahaja kontraknya. Skrip anda membaca JSON pada stdin dan mencetak teks pada stdout. Ia berjalan pada mesin anda dan tiada apa yang dicetaknya dihantar kepada model, jadi ia tidak menggunakan sebarang token.
Pada komputer riba dengan satu projek, ini hanyalah hiasan. Pada tiga pelayan, ia merupakan langkah keselamatan. Setiap sesi Claude Code kelihatan sama dalam setiap terminal, jadi empat tetingkap SSH tanpa label adalah punca migrasi tersalah masuk ke pelayan yang salah. Statusline yang bermula dengan hostname menamatkan risiko kesilapan jenis itu.
Lokasi tetapan statusLine dalam settings.json
Letakkan tetapan ini dalam tetapan pengguna anda di ~/.claude/settings.json, yang akan terpakai pada setiap projek dalam mesin tersebut. Tetapan projek di .claude/settings.json di dalam repositori juga boleh digunakan, dan ia akan mengatasi tetapan global bagi direktori tersebut.
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}type sentiasa bernilai "command". Nilai command akan dijalankan melalui shell, jadi ia boleh berupa laluan skrip atau arahan biasa. Pastikan sambungan berfungsi sebelum anda menulis sebarang skrip:
{
"statusLine": {
"type": "command",
"command": "hostname -s"
}
}Mulakan Claude Code dan hantar satu mesej. Bar di bawah prompt kini akan memaparkan nama hos pendek pelayan tersebut. Jika ia kekal kosong, masalahnya terletak pada tetapan atau dialog kepercayaan, bukan pada skrip anda. Baca "Mengapa statusline kekal kosong" di bawah.
Terdapat tiga kunci pilihan setakat Ogos 2026. padding menambah jarak mendatar dalam aksara dan nilai lalainya ialah 0. refreshInterval menjalankan semula arahan setiap N saat sebagai tambahan kepada pencetus biasa, dengan nilai minimum 1; anda hanya perlukan ini jika baris tersebut memaparkan jam atau sesuatu yang berubah semasa sesi melahu. hideVimModeIndicator menyembunyikan teks -- INSERT -- terbina dalam apabila skrip anda sendiri sudah memaparkan mod vim.
Apakah data yang diterima oleh skrip statusline?
Jangan percaya senarai medan yang anda baca di mana-mana, termasuk halaman ini. Tangkap objek sebenar yang dihantar oleh versi anda. Tulis skrip sementara yang menyimpan stdin ke dalam fail:
cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.shHalakan statusLine.command ke fail tersebut, mulakan sesi, dan hantar satu mesej. Bar tersebut membaca captured. Sekarang lihat apa yang sampai:
jq . /tmp/statusline-input.jsonAnda mempunyai bentuk yang tepat untuk binaan anda, dan anda boleh mengulanginya pada bila-bila masa apabila kemas kini mengubah sesuatu.
Bahagian yang stabil, seperti yang didokumenkan pada Ogos 2026, adalah objek bersarang dan bukannya kunci rata. model memegang id dan display_name. workspace memegang current_dir dan project_dir: current_dir ialah tempat sesi berada sekarang, project_dir ialah tempat ia dilancarkan, dan kedua-duanya berbeza sebaik sahaja direktori kerja berubah di pertengahan sesi. cwd peringkat atas membawa nilai yang sama seperti workspace.current_dir. context_window memegang kiraan token serta used_percentage yang telah dikira terlebih dahulu. cost memegang total_cost_usd dan pembilang tempoh. session_id adalah stabil sepanjang hayat sesi dan unik merentas sesi, yang penting untuk caching kemudian.
Tiga peraturan memastikan skrip kekal berfungsi merentas perubahan skema.
Sesetengah kunci tiada, bukannya null. vim, agent, pr, worktree dan effort hanya muncul apabila ciri yang sepadan aktif. Membaca .vim.mode dengan jq -r semasa mod vim dimatikan akan mencetak rentetan literal null, dan bar anda menunjukkan null kepada pembaca. Tambahkan // empty pada setiap pemilih, supaya kunci yang hilang tidak mencetak apa-apa langsung.
Sesetengah nilai adalah null pada peringkat awal. context_window.used_percentage dan context_window.current_usage adalah null sebelum respons API pertama, dan current_usage kembali kepada null selepas /compact sehingga panggilan seterusnya mengisinya semula. Oleh itu, peratusan konteks pada bar memerlukan // 0, atau ia akan membaca null untuk beberapa saat pertama setiap sesi. Sebelum anda meletakkan nombor itu pada bar, adalah berguna untuk mengetahui bagaimana tetingkap konteks sebenarnya diisi.
Cawangan git tidak terdapat dalam JSON. Tiada medan yang melaporkannya. Sebarang cawangan pada bar anda datang daripada skrip anda yang menjalankan git sendiri.
Skrip baris status yang merosot dengan anggun dan tidak terhenti
Ini adalah versi salin-tampal. Ia mencetak nama hos, direktori kerja, cawangan git dan nama model. Setiap medan mempunyai sandaran (fallback), jadi walaupun objek JSON kosong, ia tetap menghasilkan baris yang boleh 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 bacaan melalui field, yang menambah // empty, jadi kunci yang dinamakan semula atau dialih keluar akan menghasilkan rentetan kosong dan baris seterusnya membekalkan nilai lalai. Direktori disandarkan daripada workspace.current_dir kepada cwd kepada $PWD. Cawangan diambil daripada git -C "$DIR" dan bukannya git kosong, supaya cawangan sentiasa sepadan dengan direktori yang dipaparkan oleh bar tersebut.
Simpan fail tersebut, kemudian jadikan ia boleh laku:
chmod +x ~/.claude/statusline.shBit laku (execute bit) adalah wajib. Claude Code menjalankan arahan melalui shell, jadi skrip tanpa +x akan gagal dengan Permission denied, tidak menghasilkan stdout, dan baris tersebut kekal kosong tanpa ralat yang kelihatan.
jq menghuraikan JSON pada baris arahan dan tidak dipasang pada pelayan Ubuntu yang baharu:
sudo apt update && sudo apt install -y jqKemudian, halakan tetapan kepada skrip tersebut, menggunakan blok settings.json pertama di atas.
Uji skrip sebelum anda mempercayainya
Jalankan skrip sebanyak dua kali secara manual. Pertama, gunakan objek sesi biasa:
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/srv/api"},"session_id":"t1"}' | ~/.claude/statusline.shAnda akan mendapat nama hos, diikuti oleh /srv/api, kemudian Opus. Tiada cawangan (branch) dipaparkan, kerana /srv/api pada mesin anda mungkin bukan repositori git.
Kedua, ujian degradasi, iaitu ujian yang sering diabaikan oleh pengguna:
echo '{}' | ~/.claude/statusline.shObjek kosong adalah senario terburuk yang boleh berlaku akibat perubahan skema. Baris tersebut masih dicetak: nama hos, direktori semasa daripada $PWD, dan perkataan claude di tempat nama model sepatutnya berada. Tiada apa-apa yang terhenti (crash) dan tiada apa-apa yang mencetak null. Skrip yang melepasi ujian ini mampu bertahan jika sesuatu medan dinamakan semula, kerana bagi skrip anda, medan yang dinamakan semula dan medan yang hilang adalah peristiwa yang sama.
Apa yang sepatutnya anda lihat
Statusline dipaparkan pada barisnya sendiri di atas lencana pengaki (footer badges) terbina dalam dan tidak menggantikannya. Pada persediaan yang berfungsi, ia terdiri daripada satu baris: nama hos pendek dalam warna sian, diikuti direktori kerja dengan direktori rumah anda diringkaskan kepada ~, kemudian nama cawangan dalam warna kuning apabila direktori tersebut merupakan repositori git, dan seterusnya nama model yang dimalapkan. Sesuatu yang hampir dengan web-01 ~/api main Opus, dengan empat bahagian tersebut berwarna.
Baris ini menjalankan semula skrip anda apabila sesi bermula, termasuk penyambungan semula (resume), apabila mesej pembantu baharu tiba, selepas /compact selesai, apabila mod kebenaran berubah, apabila mod vim bertukar, dan pada detik refreshInterval jika anda menetapkannya. Kemas kini dinyahlantun (debounced) pada 300 ms, jadi perubahan yang berlaku serentak hanya menjalankan skrip sekali sahaja. Bar tersebut disembunyikan semasa autolengkap, menu bantuan, dan gesaan kebenaran, kemudian dipaparkan semula.
Mengapa hostname perlu diletakkan di hadapan
Apabila anda menjalankan ejen pada lebih daripada satu pelayan, terminal adalah satu-satunya petunjuk lokasi anda, dan terminal boleh mengelirukan. Buka sambungan ssh kedua dari dalam anak tetingkap tmux dan tajuk tetingkap sering mengekalkan nama lama, kerana tajuk tersebut ditetapkan oleh shell yang tidak mengesan perubahan lokasi. Biarkan Claude Code berjalan dalam sesi tmux yang dipisahkan pada VPS dan sambung semula sehari kemudian, tiada apa-apa pada skrin yang membezakan pelayan binaan (build server) daripada kotak pengeluaran (production box).
Baris status adalah berbeza kerana ia dirender oleh Claude Code sendiri, bagi setiap sesi, daripada data yang disimpan oleh sesi tersebut. Ia tidak boleh diwarisi daripada anak tetingkap yang salah atau dibiarkan lapuk oleh prompt shell yang tidak pernah disegarkan. Apa yang dipaparkannya ialah kotak tempat ejen menulis fail.
Berikan setiap pelayan warnanya sendiri supaya anda mengenalinya sebelum membacanya. Dua baris, diletakkan di atas tugasan LINE=:
CODE=$(printf '%s' "$HOST" | cksum | cut -d' ' -f1)
HOST_COLOR=$(printf '\033[%dm' "$((31 + CODE % 6))")Kemudian gunakan ${HOST_COLOR} sebagai ganti ${CYAN}. cksum mencetak checksum bagi hostname, jadi nama tertentu sentiasa dipetakan kepada warna yang sama dalam julat 31 hingga 36, iaitu merah hingga sian. Salin skrip yang sama ke setiap kotak dan setiap satu akan melabelkan dirinya sendiri.
Direktori mendapat tempatnya atas sebab yang sama. /srv/api dan /srv/api-staging hanya dipisahkan oleh satu ketukan kekunci dalam arahan ssh, namun kesannya boleh menyebabkan insiden yang besar. Model dan cawangan (branch) adalah dua lagi maklumat yang berbaloi dengan ruang yang digunakan: model memberitahu anda sesi mana yang anda sambung semula, dan cawangan memberitahu anda sama ada ejen akan melakukan commit ke main.
Skrin kecil menjadikan semua ini lebih jelas, kerana tiada tajuk tetingkap untuk dijadikan sandaran. Jika itu persediaan anda, lihat mengendalikan Claude Code daripada telefon.
Pastikan skrip berjalan pantas
Skrip anda berjalan pada setiap mesej pembantu, dan Claude Code membatalkan pelaksanaan yang sedang berjalan apabila kemas kini baharu tiba. Oleh itu, skrip yang perlahan akan memaparkan teks yang lapuk atau tiada teks langsung.
Setiap panggilan jq mengambil masa beberapa milisaat. git merupakan bahagian yang menjadi perlahan: git status dalam repositori yang besar dengan cache sejuk mengambil masa ratusan milisaat. Skrip di atas sengaja mengelakkan git status dan memanggil git branch --show-current, yang membaca .git/HEAD dan kembali serta-merta.
Jika anda menambah sesuatu yang lebih berat, simpan dalam fail dan segarkan semula setiap beberapa saat. Gunakan kunci fail berdasarkan sesi:
CACHE="/tmp/statusline-$(field '.session_id')"Gunakan session_id, bukan $$. $$ ialah ID proses skrip anda, yang berbeza pada setiap panggilan, jadi cache yang dikunci dengannya tidak akan pernah mencapai hit dan anda menanggung kos penuh setiap kali. session_id adalah stabil untuk keseluruhan sesi dan berbeza antara sesi, jadi dua sesi Claude Code dalam dua repositori tidak boleh membaca nama cawangan yang dicache oleh satu sama lain. Sesi kekal terasing secara reka bentuk, jadi untuk memindahkan kerja daripada satu sesi ke sesi lain memerlukan langkah yang disengajakan, iaitu tujuan bagi menghantar mesej daripada satu sesi Claude Code ke sesi yang lain.
Satu lagi had yang perlu diketahui: tput cols tidak berfungsi di dalam skrip statusline. Claude Code menangkap output tersebut dan bukannya melampirkan skrip anda pada terminal, jadi pengesanan lebar tidak mempunyai apa-apa untuk diukur. Claude Code menetapkan pemboleh ubah persekitaran COLUMNS dan LINES sebelum menjalankan arahan, dalam v2.1.153 dan seterusnya, jadi baca $COLUMNS apabila anda perlu menentukan jumlah teks yang ingin dicetak.
Mengapa bar status kekal kosong
Tiada apa-apa yang dipaparkan. Semak bit laksana dengan ls -l ~/.claude/statusline.sh, kemudian jalankan skrip secara manual menggunakan input olok-olok di atas. Jika ia mencetak baris pada shell tetapi tidak dalam Claude Code, mulakan dengan claude --debug, yang merekodkan kod keluar dan stderr bagi larian bar status pertama dalam sesi tersebut.
Log nyahpepijat menyatakan Status line command skipped: workspace trust not accepted. Bar status melaksanakan arahan shell, jadi ia tertakluk kepada kawalan kepercayaan ruang kerja yang sama seperti cangkuk (hooks). Selagi anda tidak menerima dialog kepercayaan untuk direktori tersebut, arahan itu tidak akan berjalan. Ini perkara biasa pada VPS, di mana setiap klon baharu merupakan direktori yang belum pernah dilihat oleh Claude Code. Mulakan semula Claude Code dalam direktori tersebut dan terima dialog berkenaan.
Semuanya kosong dan disableAllHooks ditetapkan. "disableAllHooks": true dalam settings.json turut melumpuhkan bar status, kerana ia menggunakan kawalan pelaksanaan shell yang sama. Buang tetapan tersebut atau tetapkan kepada false.
Baris mencetak null. Pemilih jq mencapai kunci yang tiada atau null, dan jq -r mencetak null sebagai empat aksara null. Tambahkan // empty untuk teks dan // 0 untuk nombor.
Baris menjadi kosong sejurus selepas anda menyunting skrip. Arahan yang keluar dengan status bukan sifar, atau tidak mencetak apa-apa, akan mengosongkan baris tersebut. Punca lazim ialah baris terakhir seperti [ -n "$BRANCH" ] && LINE="...", yang keluar dengan status 1 apabila cawangan kosong dan membawa kod keluar keseluruhan skrip bersamanya. Pastikan printf berada di kedudukan terakhir, atau tambahkan exit 0.
Kod escape dipaparkan sebagai teks literal seperti \e]8;; pada bar. Gunakan printf '%b' sebagai ganti echo -e. Pautan OSC 8 yang boleh diklik juga memerlukan terminal yang menyokongnya, dan tmux atau SSH mungkin membuang jujukan tersebut, jadi warna biasa adalah pilihan yang lebih selamat pada mesin jauh.
Bahagian kanan bar terpotong. Pemberitahuan sistem dan pembilang token mod verbose berkongsi baris tersebut dari sebelah kanan, dan terminal yang sempit akan menyebabkan pertindihan hilang. Pastikan output anda ringkas. Untuk pengiraan penggunaan sebenar dan bukannya sekadar nombor pada bar, lihat bagaimana Claude Code mengira token.
FAQ
Di manakah tetapan statusline Claude Code disimpan?
Dalam settings.json, sebagai blok statusLine dengan type ditetapkan kepada "command" dan command ditetapkan kepada laluan skrip atau arahan shell. Tetapan pengguna berada di ~/.claude/settings.json dan terpakai untuk setiap projek pada mesin tersebut. Tetapan projek berada di .claude/settings.json di dalam repositori dan akan diutamakan untuk direktori tersebut. Tetapan dimuat semula secara automatik, tetapi perubahan hanya akan kelihatan pada pencetus kemas kini seterusnya, seperti mesej anda yang berikutnya.
Mengapakah statusline Claude Code saya kosong?
Empat punca merangkumi hampir semua kes. Skrip kehilangan bit pelaksanaan, jadi shell mengembalikan Permission denied dan tiada apa-apa yang sampai ke stdout. Dialog kepercayaan ruang kerja tidak pernah diterima, dan claude --debug mencatat Status line command skipped: workspace trust not accepted. disableAllHooks adalah true, yang melumpuhkan statusline di bawah kawalan yang sama. Atau skrip keluar dengan kod bukan sifar, yang mengosongkan baris tersebut. Uji secara manual dahulu: echo '{}' | ~/.claude/statusline.sh mesti mencetak sesuatu.
Adakah JSON statusline menyertakan cawangan git?
Tidak. JSON membawa status sesi seperti model, direktori ruang kerja, nombor tetingkap konteks dan kos. Tiada apa-apa di dalamnya yang melaporkan git. Cawangan pada bar anda datang daripada skrip anda sendiri yang memanggil git branch --show-current. Hantarkan direktori daripada JSON dengan git -C "$DIR", supaya cawangan sentiasa sepadan dengan direktori yang dipaparkan oleh bar tersebut.
Adakah statusline menggunakan token atau melambatkan sesi?
Ia tidak menggunakan sebarang token, kerana skrip berjalan secara setempat dan outputnya tidak pernah dihantar kepada model. Kelajuan adalah tanggungjawab anda. Arahan tersebut berjalan pada setiap mesej pembantu dengan debounce 300 ms, dan Claude Code membatalkan pelaksanaan yang sedang berjalan apabila kemas kini baharu tiba, jadi skrip yang mengambil masa satu saat penuh akan memaparkan teks yang lapuk. Elakkan git status dalam repositori yang besar, dan cache apa-apa yang perlahan dalam fail yang dikunci pada session_id.
Bagaimanakah cara saya memaparkan statusline yang berbeza pada setiap pelayan?
Gunakan satu skrip dan biarkan ia membaca mesin tersebut. Skrip di atas mencetak $HOSTNAME dengan hostname -s sebagai sandaran, jadi fail yang sama yang disalin ke setiap kotak melabelkan setiap satu dengan betul, dan helah warna checksum memberikan setiap hostname warnanya sendiri. Jika satu pelayan memerlukan susun atur yang berbeza, letakkan blok statusLine dalam tetapan projek bagi repositori yang anda kerjakan pada kotak tersebut, memandangkan tetapan projek mengatasi tetapan pengguna untuk direktori itu.