Statusline di Claude Code su un VPS: configurazione
Configura statusLine per mostrare host, directory, branch Git e modello sotto il prompt. Evita di confondere server SSH e di eseguire comandi sul VPS sbagliato.
Cosa mostra una statusline di Claude Code
Una statusline di Claude Code è una riga sotto il prompt che visualizza l’output di uno script scritto dall’utente. Si aggiunge un blocco statusLine a settings.json e lo si collega a un comando. Claude Code esegue il comando, gli invia lo stato della sessione in formato JSON tramite lo standard input e visualizza l’output prodotto dal comando sullo standard output.
Questo è l’intero contratto. Lo script legge JSON dallo standard input e stampa testo sullo standard output. Viene eseguito sulla macchina locale e ciò che stampa non viene inviato al modello, quindi non consuma token.
Su un laptop con un solo progetto è un elemento puramente decorativo. Su tre server è una protezione operativa. Ogni sessione di Claude Code appare allo stesso modo in ogni terminale; quattro finestre SSH senza etichette possono quindi portare a eseguire una migrazione sul server sbagliato. Una statusline che inizia con il nome host elimina questo tipo di errore.
Dove si trova l'impostazione statusLine in settings.json
Inseriscila nelle impostazioni utente in ~/.claude/settings.json. Questa posizione si applica a ogni progetto della macchina. Funzionano anche le impostazioni del progetto in .claude/settings.json all'interno di un repository, che hanno precedenza per quella directory.
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}type è sempre "command". Il valore command viene eseguito tramite una shell, quindi può essere il percorso di uno script oppure un comando semplice. Verifica il funzionamento del collegamento prima di scrivere qualsiasi script:
{
"statusLine": {
"type": "command",
"command": "hostname -s"
}
}Avvia Claude Code e invia un messaggio. La barra sotto il prompt ora mostra il nome host breve del server. Se rimane vuota, il problema riguarda l'impostazione oppure la finestra di dialogo relativa all'attendibilità, non lo script. Leggi la sezione "Perché la statusline rimane vuota" più avanti.
Ad agosto 2026 sono disponibili tre chiavi facoltative. padding aggiunge spaziatura orizzontale in caratteri e il valore predefinito è 0. refreshInterval riesegue il comando ogni N secondi, oltre ai normali trigger, con un minimo di 1. Usalo solo quando la riga mostra un orologio o un altro valore che cambia mentre la sessione rimane inattiva. hideVimModeIndicator nasconde il testo -- INSERT -- integrato quando lo script personalizzato visualizza già la modalità vim.
Quali dati riceve lo script della statusline?
Non fidarti di un elenco di campi trovato altrove, nemmeno in questa pagina. Acquisisci l'oggetto reale inviato dalla tua versione. Scrivi uno script temporaneo che salvi lo stdin in un file:
cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.shIndica quel file a statusLine.command, avvia una sessione e invia un messaggio. La barra legge captured. Ora controlla i dati ricevuti:
jq . /tmp/statusline-input.jsonIn questo modo ottieni la struttura esatta della tua build e puoi ripetere la verifica ogni volta che un aggiornamento modifica qualcosa.
Le parti stabili, secondo la documentazione disponibile ad agosto 2026, sono oggetti annidati e non chiavi piatte. model contiene id e display_name. workspace contiene current_dir e project_dir: current_dir indica la directory di lavoro corrente della sessione, project_dir quella da cui è stata avviata e i due valori differiscono quando la directory di lavoro cambia durante la sessione. Il campo di primo livello cwd contiene lo stesso valore di workspace.current_dir. context_window contiene i conteggi dei token e un valore used_percentage precalcolato. cost contiene total_cost_usd e i contatori della durata. session_id rimane stabile per tutta la sessione ed è univoco tra le sessioni, un aspetto importante per il caching successivo.
Tre regole aiutano a mantenere funzionante uno script anche quando cambia lo schema.
Alcune chiavi sono assenti, non null. vim, agent, pr, worktree e effort compaiono solo quando la funzione corrispondente è attiva. La lettura di .vim.mode con jq -r quando la modalità vim è disattivata stampa la stringa letterale null e la barra mostra al lettore null. Aggiungi // empty a ogni selettore, in modo che una chiave mancante non stampi nulla.
Alcuni valori sono null all'inizio. context_window.used_percentage e context_window.current_usage sono null prima della prima risposta dell'API, mentre current_usage torna a null dopo /compact finché la chiamata successiva non lo valorizza di nuovo. Una percentuale del contesto nella barra richiede quindi // 0; in caso contrario, nei primi secondi di ogni sessione viene letto null. Prima di visualizzare questo numero nella barra, è utile capire come viene effettivamente utilizzata la context window.
Il branch git non è presente nel JSON. Nessun campo lo riporta. Qualsiasi branch visualizzato nella barra proviene dallo script, che esegue direttamente git.
Uno script per la statusline che degrada senza interrompersi
Questa è la versione pronta da copiare e incollare. Stampa il nome host, la directory di lavoro, il branch Git e il nome del modello. Ogni campo ha un valore alternativo, quindi anche un oggetto JSON vuoto produce comunque una riga utilizzabile.
#!/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"Ogni lettura passa da field, che aggiunge // empty. Se una chiave è stata rinominata o rimossa, il risultato è quindi una stringa vuota e la riga successiva fornisce un valore predefinito. La directory passa da workspace.current_dir a cwd e infine a $PWD. Il branch viene ricavato da git -C "$DIR" anziché da un semplice git, quindi corrisponde sempre alla directory visualizzata dalla barra.
Salva il file, quindi rendilo eseguibile:
chmod +x ~/.claude/statusline.shIl bit di esecuzione è obbligatorio. Claude Code esegue il comando tramite una shell, quindi uno script senza +x termina con Permission denied, non produce output su stdout e lascia la riga vuota senza mostrare errori.
jq analizza JSON dalla riga di comando e non è installato su un server Ubuntu appena installato:
sudo apt update && sudo apt install -y jqImposta quindi la configurazione in modo che punti allo script, usando il primo blocco settings.json riportato sopra.
Testa lo script prima di considerarlo affidabile
Eseguilo manualmente due volte. Prima con un normale oggetto di sessione:
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/srv/api"},"session_id":"t1"}' | ~/.claude/statusline.shOttieni il nome host, quindi /srv/api e infine Opus. Non viene visualizzato alcun ramo, perché /srv/api sul tuo computer probabilmente non è un repository Git.
Secondo, esegui il test di degradazione, che spesso viene saltato:
echo '{}' | ~/.claude/statusline.shUn oggetto vuoto rappresenta il caso peggiore che una modifica allo schema possa produrre. La riga viene comunque visualizzata: il nome host, la directory corrente restituita da $PWD e la parola claude al posto del nome del modello. Non si verifica alcun arresto anomalo e non viene visualizzato nulla per null. Uno script che supera questo test continua a funzionare anche se un campo viene rinominato, perché per lo script un campo rinominato e un campo mancante sono lo stesso evento.
Cosa dovresti vedere
La statusline viene visualizzata su una riga separata sopra i badge del footer integrato e non li sostituisce. In una configurazione funzionante occupa una riga: prima compare l'hostname breve in ciano, poi la directory di lavoro con la home abbreviata in ~, quindi il nome del branch in giallo quando la directory è un repository git e infine il nome del modello attenuato. Il risultato è simile a web-01 ~/api main Opus, con questi quattro elementi colorati.
La riga riesegue lo script quando inizia una sessione, incluso il ripristino di una sessione, quando arriva un nuovo messaggio dell'assistente, dopo il completamento di /compact, quando cambia la modalità delle autorizzazioni, quando si attiva o disattiva la modalità vim e a ogni intervallo di refreshInterval, se ne hai configurato uno. Gli aggiornamenti sono sottoposti a debounce di 300 ms, quindi una serie ravvicinata di modifiche esegue lo script una sola volta. La barra viene nascosta durante il completamento automatico, nel menu della guida e nelle richieste di autorizzazione, quindi viene visualizzata di nuovo.
Perché il nome host viene prima
Quando mantieni agenti attivi su più server, il terminale è l'unico elemento che indica dove ti trovi, ma i terminali possono fornire informazioni errate. Apri una seconda connessione ssh dall'interno di un pannello tmux e il titolo della finestra spesso conserva il vecchio nome, perché il titolo è impostato da una shell che non ha rilevato lo spostamento. Lascia Claude Code in esecuzione in una sessione tmux scollegata su un VPS e riconnettiti il giorno dopo: sullo schermo non c'è nulla che distingua il server di build dal server di produzione.
La statusline è diversa perché viene generata direttamente da Claude Code per ogni sessione, usando i dati contenuti nella sessione stessa. Non può essere ereditata dal pannello sbagliato né rimanere obsoleta a causa di un prompt della shell che non è mai stato aggiornato. Indica il server sul quale l'agente sta scrivendo i file.
Assegna a ogni server un colore distinto, così puoi riconoscerlo prima ancora di leggere il nome. Inserisci queste due righe sopra l'assegnazione LINE=:
CODE=$(printf '%s' "$HOST" | cksum | cut -d' ' -f1)
HOST_COLOR=$(printf '\033[%dm' "$((31 + CODE % 6))")Usa quindi ${HOST_COLOR} al posto di ${CYAN}. cksum calcola un checksum del nome host, quindi ogni nome corrisponde sempre allo stesso colore nell'intervallo da 31 a 36, cioè dal rosso al ciano. Copia lo stesso script su ogni server: ciascuno mostrerà automaticamente la propria identità.
La directory è utile per lo stesso motivo. /srv/api e /srv/api-staging distano un solo tasto in un comando ssh, ma possono corrispondere a incidenti completamente diversi. Modello e branch sono gli altri due elementi per cui vale la pena usare spazio: il modello indica quale sessione hai ripreso, mentre il branch indica se l'agente sta per eseguire il commit su main.
Su uno schermo piccolo queste informazioni sono ancora più importanti, perché non puoi contare sul titolo della finestra. Se questa è la tua configurazione, consulta usare Claude Code da un telefono.
Mantieni veloce lo script
Lo script viene eseguito a ogni messaggio dell'assistente e Claude Code annulla un'esecuzione in corso quando arriva un nuovo aggiornamento. Se lo script è lento, quindi, mostra testo non aggiornato oppure non mostra alcun testo.
Ogni chiamata a jq richiede pochi millisecondi. git è la parte che rallenta: git status in un repository di grandi dimensioni con cache fredda richiede centinaia di millisecondi. Lo script precedente evita intenzionalmente git status e usa git branch --show-current, che legge .git/HEAD e restituisce subito il risultato.
Se aggiungi un'operazione più pesante, memorizza il risultato in un file e aggiornalo ogni pochi secondi. Usa la sessione come chiave del file:
CACHE="/tmp/statusline-$(field '.session_id')"Usa session_id, non $$. $$ è l'ID del processo dello script e cambia a ogni esecuzione, quindi una cache basata su questo valore non produce mai corrispondenze e il costo completo viene sostenuto ogni volta. session_id resta invariato per tutta la sessione e cambia tra sessioni diverse, quindi due sessioni di Claude Code in due repository non possono leggere il nome del branch memorizzato nella cache dell'altra sessione.
C'è un'altra limitazione da conoscere: tput cols non funziona all'interno di uno script statusline. Claude Code acquisisce l'output invece di collegare lo script al terminale, quindi non c'è una larghezza da rilevare. A partire da v2.1.153, Claude Code imposta le variabili d'ambiente COLUMNS e LINES prima di eseguire il comando. Leggi $COLUMNS quando devi decidere quanto testo stampare.
Perché la riga di stato resta vuota
Non compare nulla. Verifica il bit di esecuzione con ls -l ~/.claude/statusline.sh, quindi esegui manualmente lo script usando l'input simulato precedente. Se stampa una riga nella shell ma non in Claude Code, inizia da claude --debug, che registra il codice di uscita e lo stderr della prima esecuzione della riga di stato nella sessione.
Il log di debug indica Status line command skipped: workspace trust not accepted. La riga di stato esegue un comando shell, quindi è soggetta allo stesso controllo di attendibilità dell'area di lavoro degli hook. Finché non accetti la finestra di dialogo relativa all'attendibilità per quella directory, il comando non viene eseguito. Questo è comune su un VPS, dove ogni nuovo clone si trova in una directory che Claude Code non ha ancora rilevato. Riavvia Claude Code in quella directory e accetta la finestra di dialogo.
Tutto è vuoto e disableAllHooks è impostato. "disableAllHooks": true in settings.json disabilita anche la riga di stato, perché utilizza lo stesso controllo per l'esecuzione della shell. Rimuovilo oppure impostalo su false.
La riga stampa null. Un selettore jq ha raggiunto una chiave mancante o null e jq -r stampa null come i quattro caratteri null. Aggiungi // empty per il testo e // 0 per i numeri.
La riga diventa vuota subito dopo aver modificato lo script. Un comando che termina con un codice diverso da zero, oppure non stampa nulla, rende vuota la riga. La causa più comune è una riga finale come [ -n "$BRANCH" ] && LINE="...", che termina con codice 1 quando il ramo è vuoto e trasferisce il proprio codice di uscita all'intero script. Mantieni printf come ultima istruzione oppure aggiungi exit 0.
I codici di escape vengono visualizzati come testo letterale, ad esempio \e]8;; nella barra. Usa printf '%b' invece di echo -e. Anche i link OSC 8 cliccabili richiedono un terminale che li supporti; inoltre tmux o SSH possono rimuovere queste sequenze, quindi su un sistema remoto è più sicuro usare semplicemente i colori.
La parte destra della riga viene tagliata. Le notifiche di sistema e il contatore dei token della modalità dettagliata condividono la riga a partire da destra, quindi in un terminale stretto si sovrappongono. Mantieni breve l'output. Per un calcolo effettivo dell'utilizzo, invece di un numero visualizzato nella barra, consulta come Claude Code conta i token.
FAQ
Dove si trova l'impostazione della statusline di Claude Code?
Si trova in settings.json, in un blocco statusLine con type impostato su "command" e command impostato sul percorso di uno script o su un comando shell. Le impostazioni utente si trovano in ~/.claude/settings.json e si applicano a ogni progetto presente su quella macchina. Le impostazioni del progetto si trovano in .claude/settings.json all'interno del repository e hanno precedenza per quella directory. Le impostazioni vengono ricaricate automaticamente, ma una modifica diventa visibile solo al successivo evento di aggiornamento, ad esempio al messaggio successivo.
Perché la statusline di Claude Code è vuota?
Quattro cause spiegano quasi tutti i casi. Allo script manca il bit di esecuzione, quindi la shell restituisce Permission denied e non arriva nulla su stdout. La finestra di dialogo per l'attendibilità dell'area di lavoro non è mai stata accettata e claude --debug registra Status line command skipped: workspace trust not accepted. disableAllHooks è true, quindi la statusline viene disabilitata dalla stessa condizione. In alternativa, lo script termina con un codice diverso da zero e la riga resta vuota. Verificalo prima manualmente: echo '{}' | ~/.claude/statusline.sh deve stampare qualcosa.
Il JSON della statusline include il branch git?
No. Il JSON contiene lo stato della sessione, ad esempio il modello, le directory dell'area di lavoro, i valori relativi alla finestra di contesto e il costo. Non contiene informazioni su git. Il branch visualizzato nella barra viene ricavato dallo script, che deve eseguire git branch --show-current. Passa la directory dal JSON usando git -C "$DIR", così il branch corrisponde sempre alla directory mostrata dalla barra.
La statusline consuma token o rallenta la sessione?
Non consuma token, perché lo script viene eseguito localmente e il suo output non viene mai inviato al modello. La velocità dipende da te. Il comando viene eseguito a ogni messaggio dell'assistente con un debounce di 300 ms. Claude Code annulla un'esecuzione in corso quando arriva un nuovo aggiornamento. Di conseguenza, se lo script impiega un secondo intero, il testo visualizzato può essere obsoleto. Evita git status nei repository di grandi dimensioni e memorizza nella cache i dati lenti in un file indicizzato tramite session_id.
Come posso visualizzare una statusline diversa su ogni server?
Usa un solo script e lascia che rilevi la macchina. Lo script precedente stampa $HOSTNAME, usando hostname -s come fallback. Lo stesso file, copiato su ogni server, assegna quindi a ciascuno l'etichetta corretta. Inoltre, il meccanismo basato sul colore del checksum assegna a ogni hostname un colore distinto. Se un server richiede un layout diverso, inserisci un blocco statusLine nelle impostazioni del progetto del repository su cui lavori in quel server, perché le impostazioni del progetto hanno precedenza su quelle utente per quella directory.