Configurer une statusline Claude Code sur un VPS
Ajoutez l’hôte, le répertoire, la branche Git et le modèle sous l’invite. Le script statusLine lit l’état JSON sur stdin et affiche sa sortie sur stdout.
Ce qu’affiche la statusline de Claude Code
La statusline de Claude Code est une ligne située sous l’invite. Elle affiche la sortie d’un script que vous écrivez. Vous ajoutez un bloc statusLine à settings.json et vous lui indiquez une commande. Claude Code exécute cette commande, lui transmet l’état de la session au format JSON sur l’entrée standard, puis affiche tout ce que la commande écrit sur la sortie standard.
C’est tout le contrat. Votre script lit le JSON sur stdin et écrit du texte sur stdout. Il s’exécute sur votre machine. Rien de ce qu’il affiche n’est envoyé au modèle. Il ne consomme donc aucun token.
Sur un ordinateur portable avec un seul projet, c’est de la décoration. Sur trois serveurs, c’est une protection. Toutes les sessions Claude Code se ressemblent dans chaque terminal. Quatre fenêtres SSH sans libellé suffisent donc à appliquer une migration sur le mauvais serveur. Une statusline qui commence par le nom d’hôte élimine ce type d’erreur.
Emplacement du paramètre statusLine dans settings.json
Ajoutez-le à vos paramètres utilisateur dans ~/.claude/settings.json. Il s’applique alors à tous les projets de cette machine. Les paramètres du projet dans .claude/settings.json, à l’intérieur d’un dépôt, fonctionnent également et sont prioritaires pour ce répertoire.
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}type vaut toujours "command". La valeur command est exécutée par un shell. Elle peut donc être un chemin de script ou une commande simple. Vérifiez le fonctionnement de la configuration avant d’écrire un script :
{
"statusLine": {
"type": "command",
"command": "hostname -s"
}
}Lancez Claude Code et envoyez un message. La barre située sous l’invite affiche maintenant le nom d’hôte court du serveur. Si elle reste vide, le problème vient du paramètre ou de la boîte de dialogue de confiance, pas de votre script. Consultez la section « Pourquoi la statusline reste vide » ci-dessous.
Trois clés facultatives existent depuis août 2026. padding ajoute un espacement horizontal en caractères et vaut par défaut 0. refreshInterval relance la commande toutes les N secondes, en plus des déclencheurs normaux, avec un minimum de 1. Utilisez-la uniquement lorsque la ligne affiche une horloge ou une autre valeur qui change pendant que la session reste inactive. hideVimModeIndicator masque le texte -- INSERT -- intégré lorsque votre propre script affiche déjà le mode vim.
Quelles données le script de statusline reçoit-il ?
Ne faites confiance à aucune liste de champs que vous lisez ailleurs, y compris sur cette page. Capturez l’objet réel envoyé par votre version. Écrivez un script temporaire qui enregistre stdin dans un fichier :
cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.shPointez statusLine.command vers ce fichier, démarrez une session et envoyez un message. La barre lit captured. Examinez ensuite les données reçues :
jq . /tmp/statusline-input.jsonVous disposez ainsi de la structure exacte utilisée par votre build. Vous pouvez recommencer à tout moment si une mise à jour la modifie.
Les éléments stables, d’après la documentation disponible en août 2026, sont des objets imbriqués plutôt que des clés plates. model contient id et display_name. workspace contient current_dir et project_dir : current_dir indique le répertoire courant de la session, project_dir celui depuis lequel elle a été lancée, et les deux diffèrent dès que le répertoire de travail change pendant la session. Le cwd de niveau supérieur contient la même valeur que workspace.current_dir. context_window contient les compteurs de tokens ainsi qu’un used_percentage précalculé. cost contient total_cost_usd et les compteurs de durée. session_id reste stable pendant toute la session et est unique entre les sessions, ce qui est important pour la mise en cache ultérieure.
Trois règles permettent à un script de rester compatible malgré les changements de schéma.
Certaines clés sont absentes, et non nulles. vim, agent, pr, worktree et effort n’apparaissent que lorsque la fonctionnalité correspondante est active. Lire .vim.mode avec jq -r lorsque le mode vim est désactivé affiche la chaîne littérale null, et votre barre affiche null à l’utilisateur. Ajoutez // empty à chaque sélecteur afin qu’une clé absente n’affiche rien.
Certaines valeurs sont nulles au début. context_window.used_percentage et context_window.current_usage sont nulles avant la première réponse de l’API, et current_usage redevient nul après /compact, jusqu’à ce que l’appel suivant le renseigne à nouveau. Un pourcentage de contexte affiché dans la barre nécessite donc // 0 ; sinon, il affiche null pendant les premières secondes de chaque session. Avant d’afficher ce nombre dans une barre, il est utile de comprendre comment la fenêtre de contexte se remplit réellement.
La branche git ne figure pas dans le JSON. Aucun champ ne l’indique. Toute branche affichée dans votre barre provient de l’exécution de git par votre script.
Une script de statusline qui se dégrade au lieu de tomber en erreur
Voici la version à copier-coller. Elle affiche le nom d’hôte, le répertoire courant, la branche Git et le nom du modèle. Chaque champ a une valeur de repli. Même un objet JSON vide produit donc une ligne utilisable.
#!/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"Chaque lecture passe par field, qui ajoute // empty. Ainsi, une clé renommée ou supprimée produit une chaîne vide, puis la ligne suivante fournit une valeur par défaut. Le répertoire utilise successivement workspace.current_dir, cwd, puis $PWD comme valeurs de repli. La branche provient de git -C "$DIR" et non d’un simple git. Elle correspond donc toujours au répertoire affiché par la barre.
Enregistrez le fichier, puis rendez-le exécutable :
chmod +x ~/.claude/statusline.shLe bit d’exécution est obligatoire. Claude Code exécute la commande via un shell. Un script sans +x échoue avec Permission denied, ne produit aucune sortie standard et laisse la ligne vide, sans erreur visible.
jq analyse le JSON sur la ligne de commande. Il n’est pas installé sur un serveur Ubuntu fraîchement installé :
sudo apt update && sudo apt install -y jqPointez ensuite le paramètre vers le script en utilisant le premier bloc settings.json ci-dessus.
Tester le script avant de lui faire confiance
Exécutez-le deux fois manuellement. D’abord avec un objet de session normal :
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/srv/api"},"session_id":"t1"}' | ~/.claude/statusline.shVous obtenez le nom d’hôte, puis /srv/api, puis Opus. Aucune branche ne s’affiche, car /srv/api sur votre machine n’est probablement pas un dépôt git.
Ensuite, effectuez le test de dégradation, celui que beaucoup de personnes ignorent :
echo '{}' | ~/.claude/statusline.shUn objet vide est le pire cas qu’une modification de schéma puisse vous transmettre. La ligne s’affiche toujours : le nom d’hôte, le répertoire courant fourni par $PWD et le mot claude à la place du nom du modèle. Rien ne plante et rien n’affiche null. Un script qui réussit ce test résiste au renommage d’un champ, car pour votre script, un champ renommé et un champ manquant correspondent au même événement.
Ce que vous devez voir
La ligne d’état s’affiche sur sa propre ligne, au-dessus des badges de pied de page intégrés, et ne les remplace pas. Dans une configuration fonctionnelle, elle tient sur une ligne : le nom d’hôte court en cyan, puis le répertoire de travail, avec votre répertoire personnel réduit à ~, puis le nom de la branche en jaune lorsque le répertoire est un dépôt git, et enfin le nom du modèle en atténué. Le résultat doit ressembler à web-01 ~/api main Opus, avec ces quatre éléments colorés.
La ligne réexécute votre script au démarrage d’une session, y compris lors d’une reprise, à l’arrivée d’un nouveau message de l’assistant, après la fin de /compact, lorsque le mode d’autorisation change, lorsque le mode vim est activé ou désactivé, et à chaque intervalle de refreshInterval si vous en configurez un. Les mises à jour sont regroupées pendant 300 ms : une série de changements déclenche donc une seule exécution du script. La barre est masquée pendant la saisie semi-automatique, l’affichage de l’aide et les demandes d’autorisation, puis réapparaît.
Pourquoi le nom d’hôte doit apparaître en premier
Lorsque plusieurs serveurs exécutent des agents, le terminal est le seul élément qui indique où vous vous trouvez. Or les terminaux peuvent être trompeurs. Ouvrez une deuxième connexion ssh depuis un volet tmux : le titre de la fenêtre conserve souvent l’ancien nom, car il est défini par un shell qui n’a pas détecté le changement. Laissez Claude Code s’exécuter dans une session tmux détachée sur un VPS, puis rattachez-vous à cette session le lendemain : rien à l’écran ne permet de distinguer le serveur de build du serveur de production.
La ligne d’état est différente, car Claude Code la génère lui-même pour chaque session, à partir des données détenues par cette session. Elle ne peut pas être héritée du mauvais volet ni rester obsolète à cause d’une invite shell qui n’a pas été actualisée. Elle indique le serveur sur lequel l’agent écrit les fichiers.
Attribuez une couleur propre à chaque serveur afin de le reconnaître avant même de lire son nom. Ajoutez ces deux lignes au-dessus de l’affectation LINE= :
CODE=$(printf '%s' "$HOST" | cksum | cut -d' ' -f1)
HOST_COLOR=$(printf '\033[%dm' "$((31 + CODE % 6))")Utilisez ensuite ${HOST_COLOR} à la place de ${CYAN}. cksum affiche une somme de contrôle du nom d’hôte. Un nom donné correspond donc toujours à la même couleur parmi les valeurs 31 à 36, du rouge au cyan. Copiez le même script sur chaque serveur : chacun affichera automatiquement son identité.
Le répertoire est utile pour la même raison. /srv/api et /srv/api-staging ne demandent qu’une touche de différence dans une commande ssh, mais leurs conséquences peuvent séparer deux incidents complètement différents. Le modèle et la branche sont les deux autres informations qui méritent cet espace. Le modèle indique quelle session vous avez reprise, et la branche indique si l’agent est sur le point de valider des modifications dans main.
Un petit écran rend toutes ces informations encore plus importantes, car vous ne pouvez pas compter sur le titre de la fenêtre. Si c’est votre configuration, consultez piloter Claude Code depuis un téléphone.
Optimiser la vitesse du script
Votre script s’exécute à chaque message de l’assistant, et Claude Code annule l’exécution en cours lorsqu’une nouvelle mise à jour arrive. Un script lent affiche donc un texte obsolète, voire aucun texte.
Chaque appel à jq coûte quelques millisecondes. git est la partie qui ralentit : git status dans un dépôt volumineux avec un cache froid prend des centaines de millisecondes. Le script ci-dessus évite volontairement git status et appelle git branch --show-current, qui lit .git/HEAD et renvoie immédiatement le résultat.
Si vous ajoutez une opération plus lourde, mettez son résultat en cache dans un fichier et actualisez-le toutes les quelques secondes. Utilisez la session comme clé :
CACHE="/tmp/statusline-$(field '.session_id')"Utilisez session_id, pas $$. $$ est l’ID de processus de votre script. Il est différent à chaque exécution. Un cache indexé sur cet ID n’est donc jamais utilisé et vous payez le coût complet à chaque fois. session_id reste stable pendant toute la session et diffère d’une session à l’autre. Deux sessions Claude Code dans deux dépôts ne peuvent donc pas lire le nom de branche mis en cache par l’autre session. Les sessions restent isolées de cette manière par conception. Pour qu’une session transmette du travail à une autre, il faut donc une action explicite. C’est le rôle de l’envoi d’un message d’une session Claude Code à une autre.
Une autre limite mérite d’être connue : tput cols ne fonctionne pas dans un script de statusline. Claude Code capture la sortie au lieu d’attacher votre script au terminal. La détection de la largeur n’a donc rien à mesurer. Claude Code définit les variables d’environnement COLUMNS et LINES avant d’exécuter la commande, à partir de la version v2.1.153. Lisez $COLUMNS lorsque vous devez déterminer la quantité de texte à afficher.
Pourquoi la statusline reste vide
Rien ne s’affiche. Vérifiez le bit d’exécution avec ls -l ~/.claude/statusline.sh, puis exécutez le script manuellement avec l’entrée simulée ci-dessus. S’il affiche une ligne dans le shell, mais pas dans Claude Code, commencez par claude --debug, qui journalise le code de sortie et la sortie d’erreur de la première exécution de la statusline de la session.
Le journal de débogage indique Status line command skipped: workspace trust not accepted. La statusline exécute une commande shell. Elle est donc soumise au même mécanisme de confiance de l’espace de travail que les hooks. Tant que vous n’avez pas accepté la boîte de dialogue de confiance pour ce répertoire, la commande ne s’exécute pas. Ce cas est fréquent sur un VPS, où chaque nouveau clone se trouve dans un répertoire que Claude Code n’a pas encore rencontré. Redémarrez Claude Code dans ce répertoire et acceptez la boîte de dialogue.
Tout est vide et disableAllHooks est défini. "disableAllHooks": true dans settings.json désactive également la statusline, car il s’agit du même mécanisme d’autorisation pour l’exécution de commandes shell. Supprimez-le ou définissez-le sur false.
La ligne affiche null. Un sélecteur jq a atteint une clé absente ou nulle, et jq -r affiche null sous la forme des quatre caractères null. Ajoutez // empty pour le texte et // 0 pour les nombres.
La ligne devient vide juste après la modification du script. Une commande qui se termine avec un code différent de zéro ou qui n’affiche rien rend la ligne vide. La cause habituelle est une dernière ligne comme [ -n "$BRANCH" ] && LINE="...", qui renvoie 1 lorsque la branche est vide et donne ce code de sortie à l’ensemble du script. Conservez printf en dernière ligne ou ajoutez exit 0.
Les codes d’échappement s’affichent sous forme de texte littéral, par exemple \e]8;; dans la barre. Utilisez printf '%b' à la place de echo -e. Les liens OSC 8 cliquables nécessitent également un terminal compatible. tmux ou SSH peut supprimer ces séquences. Une couleur simple est donc plus sûre sur un serveur distant.
Le côté droit de la ligne est tronqué. Les notifications système et le compteur de tokens du mode verbeux partagent cette ligne depuis la droite, et un terminal étroit ne dispose pas de suffisamment d’espace pour les afficher sans chevauchement. Limitez la longueur de la sortie. Pour un suivi précis de l’utilisation, plutôt qu’un nombre affiché dans une barre, consultez comment Claude Code compte les tokens.
FAQ
Où se trouve le paramètre de la statusline de Claude Code ?
Dans settings.json, sous la forme d’un bloc statusLine avec type défini sur "command" et command défini sur le chemin d’un script ou sur une commande shell. Les paramètres utilisateur se trouvent dans ~/.claude/settings.json et s’appliquent à tous les projets de cette machine. Les paramètres du projet se trouvent dans .claude/settings.json, dans le dépôt, et sont prioritaires pour ce répertoire. Les paramètres sont rechargés automatiquement, mais une modification ne devient visible qu’au prochain déclenchement de la mise à jour, par exemple à votre prochain message.
Pourquoi la statusline de Claude Code est-elle vide ?
Quatre causes couvrent presque tous les cas. Le script n’a pas le bit d’exécution, donc le shell renvoie Permission denied et rien n’est écrit sur stdout. La boîte de dialogue de confiance de l’espace de travail n’a jamais été validée, et claude --debug journalise Status line command skipped: workspace trust not accepted. disableAllHooks vaut true, ce qui désactive la statusline avec le même contrôle. Sinon, le script se termine avec un code différent de zéro, ce qui vide la ligne. Testez-le d’abord manuellement : echo '{}' | ~/.claude/statusline.sh doit afficher quelque chose.
Le JSON de la statusline contient-il la branche git ?
Non. Le JSON contient l’état de la session, notamment le modèle, les répertoires de l’espace de travail, les valeurs de la fenêtre de contexte et le coût. Il ne contient aucune information sur git. La branche affichée dans votre barre vient de votre propre script, qui appelle git branch --show-current. Transmettez-lui le répertoire depuis le JSON avec git -C "$DIR", afin que la branche corresponde toujours au répertoire affiché par la barre.
La statusline consomme-t-elle des tokens ou ralentit-elle la session ?
Elle ne consomme aucun token, car le script s’exécute localement et sa sortie n’est jamais envoyée au modèle. La rapidité dépend de votre script. La commande s’exécute à chaque message de l’assistant avec un debounce de 300 ms, et Claude Code annule une exécution en cours lorsqu’une nouvelle mise à jour arrive. Un script qui prend une seconde entière affiche donc un texte obsolète. Évitez git status dans les grands dépôts et mettez en cache dans un fichier tout ce qui est lent, en utilisant session_id comme clé.
Comment afficher une statusline différente sur chaque serveur ?
Conservez un seul script et laissez-le identifier la machine. Le script ci-dessus affiche $HOSTNAME, avec hostname -s comme valeur de repli. Le même fichier copié sur chaque serveur identifie donc correctement chaque machine, et l’astuce de couleur basée sur la somme de contrôle attribue à chaque nom d’hôte sa propre couleur. Si un serveur nécessite une mise en page différente, ajoutez un bloc statusLine dans les paramètres du projet du dépôt utilisé sur cette machine, car les paramètres du projet sont prioritaires sur les paramètres utilisateur pour ce répertoire.