SSD Nodes Learn Hosting plans →
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-08-30

Paano Mag-set Up ng Claude Code Statusline sa VPS

Ipakita ang hostname, directory, git branch, at model sa ilalim ng prompt gamit ang statusLine script, para malinaw kung aling VPS ang iyong ine-edit.

Ipinapakita ng statusline ng Claude Code

Ang statusline ng Claude Code ay isang row sa ilalim ng prompt na nagpapakita ng output ng script na isinulat mo. Magdagdag ng statusLine block sa settings.json at ituro ito sa isang command. Pinapatakbo ng Claude Code ang command na iyon, ipinapasa rito bilang JSON sa standard input ang state ng session, at ipinapakita ang anumang isinusulat ng command sa standard output.

Iyan ang buong contract. Binabasa ng script mo ang JSON mula sa stdin at nagpi-print ng text sa stdout. Tumatakbo ito sa iyong machine, at walang ipinapadala sa model mula sa anumang ipiniprint nito, kaya walang nagagamit na tokens.

Sa laptop na may isang project, dekorasyon lamang ito. Sa tatlong server, nagsisilbi itong safety rail. Pare-pareho ang hitsura ng bawat Claude Code session sa bawat terminal, kaya ang apat na SSH window na walang label ay maaaring magdulot ng migration sa maling machine. Kapag nagsisimula sa hostname ang statusline, naiiwasan ang ganitong uri ng pagkakamali.

Kung saan matatagpuan ang setting na statusLine sa settings.json

Ilagay ito sa user settings sa ~/.claude/settings.json. Nalalapat ito sa bawat project sa machine na iyon. Gumagana rin ang project settings sa .claude/settings.json sa loob ng isang repository, at iyon ang nangingibabaw para sa directory na iyon.

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

Ang type ay palaging "command". Ang value ng command ay ipinapadaan sa isang shell, kaya maaari itong path ng script o simpleng command. Tiyaking gumagana ang wiring bago ka magsulat ng script:

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

Simulan ang Claude Code at magpadala ng isang mensahe. Makikita na sa bar sa ilalim ng prompt ang maikling hostname ng server. Kung nananatili itong walang laman, ang problema ay nasa setting o sa trust dialog, hindi sa script mo. Basahin ang “Bakit nananatiling blangko ang statusline” sa ibaba.

May tatlong optional key na available simula Agosto 2026. Nagdaragdag ang padding ng horizontal spacing sa characters at ang default nito ay 0. Muling pinapatakbo ng refreshInterval ang command bawat N segundo bukod sa mga normal na trigger, na may minimum na 1. Gamitin lamang ito kapag may clock o ibang value sa line na nagbabago habang idle ang session. Pinipigilan ng hideVimModeIndicator ang built-in na text na -- INSERT -- kapag ang sarili mong script na ang nagre-render ng vim mode.

Anong data ang natatanggap ng statusline script?

Huwag magtiwala sa field list na nabasa mo kahit saan, kabilang ang page na ito. Kunin ang aktuwal na object na ipinapadala ng iyong bersyon. Sumulat ng pansamantalang script na nagse-save ng stdin sa isang file:

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

Ituro ang statusLine.command sa file na iyon, magsimula ng session, at magpadala ng isang mensahe. Binabasa ng bar ang captured. Tingnan ngayon kung ano ang natanggap:

jq . /tmp/statusline-input.json

Nasa iyo na ang eksaktong structure para sa iyong build, at maaari mo itong ulitin anumang oras na may mabago sa update.

Ang mga stable na bahagi, batay sa dokumentasyon noong August 2026, ay mga nested object at hindi flat key. Naglalaman ang model ng id at display_name. Naglalaman ang workspace ng current_dir at project_dir: ang current_dir ang kasalukuyang lokasyon ng session, ang project_dir ang lokasyon kung saan ito inilunsad, at nagkakaiba ang dalawang ito kapag nagbago ang working directory habang tumatakbo ang session. Ang top-level na cwd ay may kaparehong value ng workspace.current_dir. Naglalaman ang context_window ng mga bilang ng token at ng paunang nakalkulang used_percentage. Naglalaman ang cost ng total_cost_usd at mga duration counter. Stable ang session_id sa buong buhay ng session at natatangi sa bawat session, na mahalaga para sa caching sa susunod.

Tatlong panuntunan ang tumutulong para manatiling gumagana ang script kapag nagbago ang schema.

May mga key na wala, hindi null. Lumalabas lamang ang vim, agent, pr, worktree at effort kapag aktibo ang katumbas na feature. Kapag binasa ang .vim.mode gamit ang jq -r habang naka-off ang vim mode, ipinapakita ang literal na string na null, at ipinapakita ng bar ang null sa user. Idagdag ang // empty sa bawat selector upang walang maipakita kapag wala ang key.

May mga value na null sa simula. Null ang context_window.used_percentage at context_window.current_usage bago ang unang API response, at bumabalik sa null ang current_usage pagkatapos ng /compact hanggang sa mapunan itong muli ng susunod na call. Kaya kailangan ng context percentage sa bar ang // 0; kung hindi, babasahin nito ang null sa mga unang segundo ng bawat session. Bago mo ilagay ang numerong iyon sa bar, makatutulong na malaman kung paano aktuwal na napupuno ang context window.

Wala sa JSON ang git branch. Walang field na nag-uulat nito. Anumang branch na lumalabas sa bar ay galing sa script na mismong nagpapatakbo ng git.

Isang statusline script na nagde-degrade sa halip na mag-break

Ito ang bersyong maaaring i-copy-paste. Ipinapakita nito ang hostname, working directory, git branch, at model name. May fallback ang bawat field, kaya kahit isang walang laman na JSON object ay makakagawa pa rin ng kapaki-pakinabang na line.

#!/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"

Ang bawat read ay dumadaan sa field, na nagdaragdag ng // empty. Dahil dito, kapag pinalitan o inalis ang isang key, magiging empty string ito at magbibigay ng default ang susunod na line. Ang directory ay nagfa-fallback mula workspace.current_dir papunta sa cwd at pagkatapos ay sa $PWD. Kinukuha ang branch mula sa git -C "$DIR" sa halip na sa bare git, kaya palaging tugma ang branch sa directory na ipinapakita ng bar.

I-save ito, pagkatapos ay gawin itong executable:

chmod +x ~/.claude/statusline.sh

Hindi optional ang execute bit. Pinapatakbo ni Claude Code ang command sa pamamagitan ng shell, kaya mabibigo ang script na walang +x dahil sa Permission denied, walang mailalabas na stdout, at mananatiling blank ang row nang walang nakikitang error.

Ang jq ay nagpa-parse ng JSON sa command line at hindi naka-install sa bagong Ubuntu server:

sudo apt update && sudo apt install -y jq

Ituro ang setting sa script gamit ang unang settings.json block sa itaas.

Subukan ang script bago ito pagkatiwalaan

Patakbuhin ito nang dalawang beses nang manu-mano. Una, gamit ang normal na session object:

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

Makukuha mo ang hostname, kasunod ang /srv/api, at pagkatapos ang Opus. Walang lalabas na branch dahil malamang na hindi git repository ang /srv/api sa machine mo.

Ikalawa, ang degradation test. Ito ang karaniwang nilalaktawan:

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

Ang empty object ang pinakamasamang sitwasyong maaaring ibigay sa iyo ng pagbabago sa schema. Magpi-print pa rin ang line: ang hostname, ang kasalukuyang directory mula sa $PWD, at ang salitang claude kung saan dapat lumabas ang model name. Walang magka-crash at walang magpi-print ng null. Ang script na pumapasa sa test na ito ay nananatiling gumagana kapag pinalitan ang pangalan ng isang field, dahil para sa script mo, pareho lang ang renamed field at missing field.

Ano ang dapat mong makita

Nagre-render ang statusline sa sarili nitong row sa ibabaw ng built-in footer badges at hindi nito pinapalitan ang mga iyon. Sa gumaganang setup, isang row ito: ang maikling hostname na cyan, kasunod ang working directory na naka-collapse ang home directory mo sa ~, pagkatapos ang branch name na yellow kapag git repository ang directory, at panghuli ang model name na dimmed. Malapit ito sa web-01 ~/api main Opus, na may kulay ang apat na bahaging iyon.

Muling pinapatakbo ng row ang script kapag nagsisimula ang session, kasama ang resume, kapag may bagong assistant message, pagkatapos matapos ang /compact, kapag nagbago ang permission mode, kapag nag-toggle ang vim mode, at sa bawat refreshInterval tick kung nagtakda ka nito. Naka-debounce ang mga update nang 300 ms, kaya kapag sunod-sunod ang mga pagbabago, isang beses lang pinapatakbo ang script. Itinatago ang bar habang ginagamit ang autocomplete, help menu, at permission prompts, at pagkatapos ay bumabalik.

Bakit nauuna ang hostname

Kapag nagpapatakbo ka ng mga agent sa higit sa isang server, ang terminal lang ang nagsasabi kung nasaan ka, at maaaring mali ang ipinapakita ng terminal. Magbukas ng ikalawang ssh connection mula sa loob ng isang tmux pane, at kadalasang nananatili ang lumang pangalan sa window title dahil itinakda ito ng shell na hindi nalaman na lumipat ito. Iwanang tumatakbo ang Claude Code sa isang detached tmux session sa isang VPS at muling kumonekta makalipas ang isang araw. Walang makikita sa screen na naghihiwalay sa build server mula sa production box.

Iba ang statusline dahil mismong Claude Code ang nagre-render nito para sa bawat session, batay sa data na hawak ng session. Hindi ito namamana mula sa maling pane at hindi rin naiiwang luma dahil sa shell prompt na hindi nag-refresh. Ang ipinapakita nito ay ang box kung saan nagsusulat ng mga file ang agent.

Bigyan ng sariling kulay ang bawat server para makilala mo ito bago mo basahin ang pangalan. Dalawang linya ang ilagay bago ang LINE= assignment:

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

Gamitin naman ang ${HOST_COLOR} bilang kapalit ng ${CYAN}. Nagpi-print ang cksum ng checksum ng hostname, kaya palaging napupunta ang isang pangalan sa parehong kulay sa range na 31 hanggang 36, mula red hanggang cyan. Kopyahin ang parehong script sa bawat box para awtomatikong malagyan ng label ang bawat isa.

May dahilan ding isama ang directory. Magkalapit ng isang keystroke ang /srv/api at /srv/api-staging sa isang ssh command, pero malaki ang maaaring maging epekto ng pagkakaiba nila sa isang buong incident. Ang model at branch ang dalawa pang sulit isama sa limitadong espasyo: ipinapakita ng model kung aling session ang ipinagpatuloy mo, at ipinapakita ng branch kung magko-commit ang agent sa main.

Mas malinaw ang lahat ng ito sa maliit na screen dahil walang window title na maaasahan. Kung ganito ang setup mo, tingnan ang pagpapatakbo ng Claude Code mula sa phone.

Panatilihing mabilis ang script

Tumatakbo ang script sa bawat mensahe ng assistant, at kinakansela ng Claude Code ang kasalukuyang run kapag may bagong update. Kaya kapag mabagal ang script, lumalabas ang lumang text o walang text.

Ilang millisecond lang ang gastos ng bawat jq call. Ang mabagal na bahagi ay git: ang git status sa malaking repository na cold ang cache ay tumatagal ng daan-daang millisecond. Sadyang iniiwasan ng script sa itaas ang git status at tinatawag nito ang git branch --show-current, na nagbabasa ng .git/HEAD at agad na nagbabalik ng resulta.

Kung magdadagdag ka ng mas mabigat na operasyon, i-cache ito sa isang file at i-refresh bawat ilang segundo. Gamitin ang session bilang key ng file:

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

Gamitin ang session_id, hindi ang $$. Ang $$ ay process ID ng script mo. Nag-iiba ito sa bawat invocation, kaya hindi kailanman nagkakaroon ng cache hit kapag ito ang ginamit na key, at babayaran mo ang buong cost sa bawat pagkakataon. Stable ang session_id sa buong session at naiiba ito sa bawat session. Dahil dito, hindi mababasa ng dalawang Claude Code session na nasa magkaibang repository ang naka-cache na branch name ng isa't isa. Sadyang ganoon ang isolation ng mga session. Kaya kailangan ng tahasang hakbang para maipasa ng isang session ang trabaho sa isa pa. Ito ang gamit ng pagpapadala ng mensahe mula sa isang Claude Code session papunta sa isa pa.

May isa pang limitasyon na dapat malaman: hindi gumagana ang tput cols sa loob ng statusline script. Kinukuha ni Claude Code ang output sa halip na i-attach ang script mo sa terminal, kaya walang masusukat para sa width detection. Itinatakda ni Claude Code ang mga environment variable na COLUMNS at LINES bago patakbuhin ang command, sa v2.1.153 at mas bago. Basahin ang $COLUMNS kapag kailangan mong magpasya kung gaano karaming text ang ipi-print.

Mananatiling walang laman ang statusline

Walang lumalabas. Suriin ang execute bit gamit ang ls -l ~/.claude/statusline.sh, pagkatapos ay patakbuhin nang mano-mano ang script gamit ang mock input sa itaas. Kung may nailalabas itong linya sa shell pero wala sa Claude Code, magsimula sa claude --debug. Nila-log nito ang exit code at stderr ng unang statusline run ng session.

Sinasabi ng debug log na Status line command skipped: workspace trust not accepted. Shell command ang ine-execute ng statusline, kaya saklaw ito ng kaparehong workspace trust gate ng hooks. Hangga't hindi mo tinatanggap ang trust dialog para sa directory na iyon, hindi tatakbo ang command. Karaniwan ito sa VPS, kung saan bawat bagong clone ay directory na hindi pa nakikita ng Claude Code. I-restart ang Claude Code sa directory na iyon at tanggapin ang dialog.

Walang laman ang lahat at naka-set ang disableAllHooks. Idi-disable din ng "disableAllHooks": true sa settings.json ang statusline dahil pareho itong shell-execution gate. Alisin ito o itakda sa false.

Inilalabas ng row ang null. Umabot ang jq selector sa key na nawawala o null, at inilalabas ng jq -r ang null bilang apat na character na null. Idagdag ang // empty para sa text at // 0 para sa mga numero.

Nawawalan ng laman ang row kaagad matapos mong i-edit ang script. Kapag may command na nag-e-exit nang non-zero o walang inilalabas, nagiging blank ang row. Karaniwang sanhi nito ang panghuling linyang tulad ng [ -n "$BRANCH" ] && LINE="...", na nag-e-exit ng 1 kapag walang laman ang branch at ginagamit ng buong script ang exit code nito. Panatilihing huli ang printf, o idagdag ang exit 0.

Lumilitaw bilang literal na text ang escape codes gaya ng \e]8;; sa bar. Gamitin ang printf '%b' sa halip na echo -e. Kailangan din ng mga clickable OSC 8 link ng terminal na sumusuporta sa mga ito, at maaaring alisin ng tmux o SSH ang mga sequence. Kaya mas ligtas ang plain colour sa remote box.

Napuputol ang kanang bahagi ng row. Magkasalo sa row na iyon ang system notifications at verbose-mode token counter mula sa kanan, kaya nawawala ang magkakapatong na bahagi kapag makitid ang terminal. Panatilihing maikli ang output. Para sa aktuwal na pagtutuos ng usage sa halip na numerong ipinapakita sa bar, tingnan ang kung paano nagbibilang ng tokens ang Claude Code.

FAQ

Saan nakalagay ang setting ng Claude Code statusline?

Nasa settings.json ito, bilang statusLine block na may type na nakatakda sa "command" at command na nakatakda sa script path o shell command. Nasa ~/.claude/settings.json ang user settings at nalalapat ang mga ito sa bawat project sa machine na iyon. Nasa .claude/settings.json ang project settings sa loob ng repository at mananaig ang mga ito para sa directory na iyon. Awtomatikong nagre-reload ang settings, pero makikita lamang ang pagbabago sa susunod na update trigger, gaya ng susunod mong mensahe.

Bakit blangko ang Claude Code statusline ko?

Apat na sanhi ang sumasaklaw sa halos lahat ng kaso. Walang execute bit ang script, kaya ibinabalik ng shell ang Permission denied at walang napupunta sa stdout. Hindi kailanman tinanggap ang workspace trust dialog, kaya nagla-log ang claude --debug ng Status line command skipped: workspace trust not accepted. Ang disableAllHooks ay true, kaya dini-disable nito ang statusline sa ilalim ng kaparehong gate. Maaari ring mag-exit ang script nang non-zero, na nagbablanko sa row. Subukan muna ito nang mano-mano: kailangang may mai-print ang echo '{}' | ~/.claude/statusline.sh.

Kasama ba sa statusline JSON ang git branch?

Hindi. Naglalaman ang JSON ng session state gaya ng model, workspace directories, context window numbers, at cost. Walang git information sa loob nito. Ang branch na nasa bar mo ay galing sa sarili mong script na tumatawag sa git branch --show-current. Ipasa ang directory mula sa JSON gamit ang git -C "$DIR" upang palaging tumugma ang branch sa directory na ipinapakita ng bar.

Kumokonsumo ba ng tokens o nagpapabagal sa session ang statusline?

Wala itong kinokonsumong tokens dahil lokal na tumatakbo ang script at hindi ipinapadala sa model ang output nito. Ikaw ang responsable sa bilis. Tumatakbo ang command sa bawat assistant message na may 300 ms debounce, at kinakansela ng Claude Code ang kasalukuyang run kapag may bagong update. Dahil dito, magpapakita ng stale text ang script na umaabot ng isang buong segundo. Iwasan ang git status sa malalaking repository, at i-cache sa file ang anumang mabagal, gamit ang session_id bilang key.

Paano ako magpapakita ng ibang statusline sa bawat server?

Gumamit ng isang script at hayaan itong basahin ang machine. Ini-print ng script sa itaas ang $HOSTNAME, na may hostname -s bilang fallback. Kaya kapag kinopya ang parehong file sa bawat box, tama nitong nalalagyan ng label ang bawat isa. Nagbibigay rin ang checksum colour trick ng sariling kulay sa bawat hostname. Kung kailangan ng ibang layout ng isang server, maglagay ng statusLine block sa project settings ng repository na ginagamit mo sa server na iyon. Nauuna ang project settings sa user settings para sa directory na iyon.