Claude Code Statuszeile auf einem VPS einrichten
Mit statusLine zeigt Claude Code Hostname, Verzeichnis, Git-Branch und Modell unter dem Prompt. So erkennen Sie den richtigen VPS vor riskanten Befehlen.
Was eine Claude Code-Statuszeile anzeigt
Eine Claude Code-Statuszeile ist eine Zeile unter der Eingabeaufforderung. Sie zeigt die Ausgabe eines von Ihnen erstellten Skripts an. Sie fügen einen statusLine-Block zu settings.json hinzu und verweisen darin auf einen Befehl. Claude Code führt diesen Befehl aus, übergibt den Sitzungsstatus als JSON über die Standardeingabe und gibt alles aus, was der Befehl auf die Standardausgabe schreibt.
Das ist der gesamte Vertrag. Ihr Skript liest JSON von stdin und gibt Text auf stdout aus. Es läuft auf Ihrem Computer. Nichts von seiner Ausgabe wird an das Modell gesendet. Dadurch entstehen keine Token-Kosten.
Auf einem Laptop mit einem Projekt ist das nur Dekoration. Auf drei Servern ist es eine Sicherheitsmaßnahme. Jede Claude Code-Sitzung sieht in jedem Terminal gleich aus. Vier nicht beschriftete SSH-Fenster können deshalb dazu führen, dass eine Migration auf dem falschen Server ausgeführt wird. Eine Statuszeile, die mit dem Hostnamen beginnt, verhindert diese Art von Fehler.
Wo die Einstellung statusLine in settings.json steht
Legen Sie sie in den Benutzereinstellungen unter ~/.claude/settings.json ab. Sie gilt dann für jedes Projekt auf diesem Rechner. Projekteinstellungen unter .claude/settings.json innerhalb eines Repositorys funktionieren ebenfalls. Sie haben für dieses Verzeichnis Vorrang.
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}type ist immer "command". Der Wert command wird über eine Shell ausgeführt. Er kann daher ein Skriptpfad oder ein einfacher Befehl sein. Prüfen Sie die Verbindung, bevor Sie ein Skript schreiben:
{
"statusLine": {
"type": "command",
"command": "hostname -s"
}
}Starten Sie Claude Code und senden Sie eine Nachricht. Die Leiste unter der Eingabeaufforderung zeigt nun den kurzen Hostnamen des Servers an. Wenn sie leer bleibt, liegt das Problem an der Einstellung oder am Vertrauensdialog, nicht an Ihrem Skript. Lesen Sie weiter unten den Abschnitt „Warum die Statuszeile leer bleibt“.
Ab August 2026 gibt es drei optionale Schlüssel. padding fügt horizontalen Abstand in Zeichen hinzu und verwendet standardmäßig 0. refreshInterval führt den Befehl zusätzlich zu den normalen Auslösern alle N Sekunden erneut aus. Der Mindestwert ist 1. Das benötigen Sie nur, wenn die Zeile eine Uhr oder einen anderen Wert anzeigt, der sich ändert, während die Sitzung untätig bleibt. hideVimModeIndicator unterdrückt den integrierten Text -- INSERT --, wenn Ihr eigenes Skript den vim-Modus bereits darstellt.
Welche Daten empfängt das Statusline-Skript?
Vertrauen Sie keiner Feldliste, die Sie irgendwo lesen, auch nicht dieser Seite. Erfassen Sie das tatsächliche Objekt, das Ihre Version sendet. Schreiben Sie ein temporäres Skript, das stdin in einer Datei speichert:
cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.shVerweisen Sie statusLine.command auf diese Datei, starten Sie eine Sitzung und senden Sie eine Nachricht. Die Leiste liest captured. Sehen Sie sich nun die empfangenen Daten an:
jq . /tmp/statusline-input.jsonDamit haben Sie die genaue Struktur für Ihren Build. Sie können dies jederzeit wiederholen, wenn ein Update etwas ändert.
Die stabilen Teile sind laut Dokumentation vom August 2026 verschachtelte Objekte und keine flachen Schlüssel. model enthält id und display_name. workspace enthält current_dir und project_dir: current_dir bezeichnet das aktuelle Arbeitsverzeichnis der Sitzung, project_dir das Verzeichnis, in dem sie gestartet wurde. Die beiden Werte unterscheiden sich, sobald sich das Arbeitsverzeichnis während der Sitzung ändert. Das oberste cwd enthält denselben Wert wie workspace.current_dir. context_window enthält die Tokenanzahlen sowie einen vorab berechneten used_percentage. cost enthält total_cost_usd und Dauerzähler. session_id bleibt während der gesamten Sitzung stabil und ist sitzungsübergreifend eindeutig. Das ist später für das Caching wichtig.
Drei Regeln sorgen dafür, dass ein Skript auch bei Änderungen am Schema funktioniert.
Einige Schlüssel fehlen und sind nicht null. vim, agent, pr, worktree und effort erscheinen nur, wenn die entsprechende Funktion aktiv ist. Wenn Sie .vim.mode mit jq -r auslesen, während der vim-Modus deaktiviert ist, wird die Zeichenfolge null ausgegeben. Ihre Leiste zeigt dem Benutzer dann null. Fügen Sie jedem Selektor // empty hinzu, damit bei einem fehlenden Schlüssel überhaupt nichts ausgegeben wird.
Einige Werte sind anfänglich null. context_window.used_percentage und context_window.current_usage sind vor der ersten API-Antwort null. current_usage wird nach /compact wieder auf null gesetzt, bis der nächste Aufruf den Wert erneut einträgt. Eine Kontextanzeige in der Leiste benötigt daher // 0. Andernfalls liest sie in den ersten Sekunden jeder Sitzung null. Bevor Sie diese Zahl in einer Leiste anzeigen, sollten Sie wissen, wie das Kontextfenster tatsächlich gefüllt wird.
Der Git-Branch steht nicht im JSON. Es gibt kein Feld, das ihn meldet. Jeder Branch in Ihrer Leiste stammt daher aus dem Skript, das selbst git ausführt.
Eine Statuszeile, die bei Änderungen degradiert statt auszufallen
Dies ist die Version zum Kopieren und Einfügen. Sie gibt Hostnamen, Arbeitsverzeichnis, Git-Branch und Modellnamen aus. Für jedes Feld gibt es einen Fallback. Selbst ein leeres JSON-Objekt erzeugt daher weiterhin eine nutzbare Zeile.
#!/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"Jeder Lesezugriff läuft über field. Dabei wird // empty angehängt. Ein umbenannter oder entfernter Schlüssel ergibt dadurch eine leere Zeichenfolge. In der nächsten Zeile wird dann ein Standardwert verwendet. Das Verzeichnis fällt von workspace.current_dir auf cwd und anschließend auf $PWD zurück. Der Branch wird über git -C "$DIR" statt über ein einfaches git ermittelt. Dadurch entspricht der Branch immer dem Verzeichnis, das die Leiste anzeigt.
Speichern Sie die Datei und machen Sie sie anschließend ausführbar:
chmod +x ~/.claude/statusline.shDas Ausführungsrecht ist erforderlich. Claude Code führt den Befehl über eine Shell aus. Ein Skript ohne +x schlägt daher mit Permission denied fehl, gibt nichts auf stdout aus und die Zeile bleibt ohne sichtbaren Fehler leer.
jq analysiert JSON auf der Kommandozeile und ist auf einem frisch installierten Ubuntu-Server nicht vorhanden:
sudo apt update && sudo apt install -y jqVerweisen Sie anschließend in der Einstellung auf das Skript. Verwenden Sie dafür den ersten settings.json-Block oben.
Das Skript testen, bevor Sie ihm vertrauen
Führen Sie es zweimal von Hand aus. Zuerst mit einem normalen Sitzungsobjekt:
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/srv/api"},"session_id":"t1"}' | ~/.claude/statusline.shDer Hostname, dann /srv/api und anschließend Opus werden ausgegeben. Es erscheint kein Branch, weil /srv/api auf Ihrem Rechner wahrscheinlich kein Git-Repository ist.
Anschließend folgt der Degradationstest, den viele überspringen:
echo '{}' | ~/.claude/statusline.shEin leeres Objekt ist der schlimmste Fall, den eine Schemaänderung erzeugen kann. Die Zeile gibt weiterhin den Hostnamen, das aktuelle Verzeichnis aus $PWD und an der Stelle des Modellnamens das Wort claude aus. Es tritt kein Fehler auf, und null wird nicht ausgegeben. Ein Skript, das diesen Test besteht, übersteht die Umbenennung eines Felds, weil ein umbenanntes und ein fehlendes Feld für das Skript dasselbe Ereignis sind.
Was Sie sehen sollten
Die Statuszeile wird in einer eigenen Zeile über den integrierten Footer-Badges angezeigt und ersetzt diese nicht. Bei einer funktionierenden Konfiguration enthält sie eine Zeile: den kurzen Hostnamen in Cyan, danach das Arbeitsverzeichnis, wobei Ihr Home-Verzeichnis zu ~ verkürzt wird, anschließend den Branchnamen in Gelb, wenn das Verzeichnis ein Git-Repository ist, und schließlich den abgedunkelten Modellnamen. Das Ergebnis ähnelt web-01 ~/api main Opus, wobei diese vier Bestandteile eingefärbt sind.
Die Zeile führt Ihr Skript erneut aus, wenn eine Sitzung startet, einschließlich beim Fortsetzen einer Sitzung, wenn eine neue Assistant-Nachricht eintrifft, nachdem /compact abgeschlossen ist, wenn sich der Berechtigungsmodus ändert, wenn der Vim-Modus umgeschaltet wird und bei einem refreshInterval-Intervall, falls Sie eines festlegen. Aktualisierungen werden 300 ms lang entprellt. Dadurch führt eine Folge von Änderungen das Skript nur einmal aus. Die Leiste wird während der Autovervollständigung, im Hilfemenü und bei Berechtigungsabfragen ausgeblendet und anschließend wieder angezeigt.
Warum der Hostname an erster Stelle steht
Wenn Sie Agents auf mehreren Servern ausführen, zeigt Ihnen nur das Terminal, wo Sie sich befinden. Terminals können jedoch einen falschen Eindruck vermitteln. Öffnen Sie innerhalb eines tmux-Fensters eine zweite ssh-Verbindung, bleibt im Fenstertitel häufig der alte Name stehen, weil der Titel von einer Shell gesetzt wird, die den Wechsel nicht erkannt hat. Lassen Sie Claude Code in einer getrennten tmux-Sitzung auf einem VPS ausführen und stellen Sie die Verbindung einen Tag später wieder her, bietet die Bildschirmausgabe keinen Hinweis darauf, ob Sie sich auf dem Build-Server oder auf dem Produktionssystem befinden.
Die Statuszeile ist anders, weil Claude Code sie für jede Sitzung selbst aus den in dieser Sitzung verfügbaren Daten erzeugt. Sie kann weder vom falschen Fenster geerbt werden noch veraltet bleiben, weil eine Shell-Eingabeaufforderung nicht aktualisiert wurde. Sie zeigt an, auf welchem System der Agent Dateien bearbeitet.
Vergeben Sie für jeden Server eine eigene Farbe. So erkennen Sie ihn, bevor Sie den Namen lesen. Fügen Sie die folgenden zwei Zeilen oberhalb der Zuweisung LINE= ein:
CODE=$(printf '%s' "$HOST" | cksum | cut -d' ' -f1)
HOST_COLOR=$(printf '\033[%dm' "$((31 + CODE % 6))")Verwenden Sie anschließend ${HOST_COLOR} anstelle von ${CYAN}. cksum gibt eine Prüfsumme des Hostnamens aus. Dadurch wird ein bestimmter Name immer derselben Farbe im Bereich von 31 bis 36 zugeordnet, also Rot bis Cyan. Kopieren Sie dasselbe Script auf jedes System. Dann beschriftet sich jedes System selbst.
Das Verzeichnis ist aus demselben Grund wichtig. /srv/api und /srv/api-staging liegen in einem ssh-Befehl nur einen Tastendruck auseinander, können sich in ihrer Auswirkung jedoch um einen ganzen Vorfall unterscheiden. Modell und Branch sind die beiden weiteren Informationen, die den Platz wert sind: Das Modell zeigt, welche Sitzung Sie fortgesetzt haben, und der Branch zeigt, ob der Agent gleich nach main committen wird.
Auf einem kleinen Bildschirm ist das besonders hilfreich, weil kein Fenstertitel als Ausweichmöglichkeit vorhanden ist. Wenn Sie dieses Setup verwenden, lesen Sie Claude Code von einem Smartphone aus steuern.
Das Skript muss schnell sein
Ihr Skript wird bei jeder Assistentenantwort ausgeführt. Claude Code bricht eine laufende Ausführung ab, sobald ein neues Update eintrifft. Ein langsames Skript zeigt daher veralteten Text oder überhaupt keinen Text an.
Jeder Aufruf von jq kostet einige Millisekunden. git ist der langsame Teil: git status benötigt in einem großen Repository bei einem kalten Cache mehrere hundert Millisekunden. Das obige Skript vermeidet git status absichtlich und verwendet git branch --show-current. Dieser Befehl liest .git/HEAD und liefert sofort ein Ergebnis.
Wenn Sie etwas aufwendigeres hinzufügen, speichern Sie das Ergebnis in einer Datei zwischen und aktualisieren Sie diese alle paar Sekunden. Verwenden Sie die Sitzung als Bestandteil des Dateinamens:
CACHE="/tmp/statusline-$(field '.session_id')"Verwenden Sie session_id, nicht $$. $$ ist die Prozess-ID Ihres Skripts. Sie ist bei jeder Ausführung anders. Ein Cache mit diesem Schlüssel wird daher nie getroffen, und die vollständigen Kosten fallen bei jedem Aufruf an. session_id bleibt während der gesamten Sitzung stabil und unterscheidet sich zwischen Sitzungen. Dadurch können zwei Claude-Code-Sitzungen in zwei Repositories nicht den zwischengespeicherten Branchnamen der jeweils anderen Sitzung lesen. Sitzungen bleiben absichtlich so voneinander isoliert. Damit eine Sitzung Arbeit an eine andere übergibt, ist daher ein bewusster Schritt erforderlich. Dafür ist das Senden einer Nachricht von einer Claude-Code-Sitzung an eine andere vorgesehen.
Beachten Sie außerdem eine weitere Einschränkung: tput cols funktioniert nicht innerhalb eines Statusline-Skripts. Claude Code erfasst die Ausgabe, statt Ihr Skript an das Terminal anzuhängen. Daher gibt es für die Breitenbestimmung nichts zu messen. Claude Code setzt die Umgebungsvariablen COLUMNS und LINES vor der Ausführung des Befehls. Dies gilt ab v2.1.153. Lesen Sie $COLUMNS, wenn Sie entscheiden müssen, wie viel Text ausgegeben werden soll.
Die Statuszeile bleibt leer
Es wird überhaupt nichts angezeigt. Prüfen Sie das Ausführungsbit mit ls -l ~/.claude/statusline.sh und führen Sie das Skript anschließend manuell mit der obigen Testeingabe aus. Wenn es in der Shell eine Zeile ausgibt, aber nicht in Claude Code, beginnen Sie mit claude --debug. Dieser Befehl protokolliert den Exit-Code und die Standardfehlerausgabe des ersten Statuszeilenaufrufs der Sitzung.
Das Debug-Log meldet Status line command skipped: workspace trust not accepted. Die Statuszeile führt einen Shell-Befehl aus und unterliegt daher derselben Workspace-Trust-Sperre wie Hooks. Der Befehl wird erst ausgeführt, wenn Sie den Trust-Dialog für dieses Verzeichnis bestätigen. Das kommt auf einem VPS häufig vor, weil jeder neue Clone ein Verzeichnis ist, das Claude Code noch nicht kennt. Starten Sie Claude Code in diesem Verzeichnis neu und bestätigen Sie den Dialog.
Alles bleibt leer und disableAllHooks ist gesetzt. "disableAllHooks": true in settings.json deaktiviert ebenfalls die Statuszeile, weil es dieselbe Shell-Ausführungssperre ist. Entfernen Sie die Einstellung oder setzen Sie sie auf false.
Die Zeile gibt null aus. Ein jq-Selektor hat einen fehlenden oder null-Wert erreicht, und jq -r gibt null als die vier Zeichen null aus. Fügen Sie für Text // empty und für Zahlen // 0 hinzu.
Die Zeile bleibt direkt nach einer Änderung am Skript leer. Ein Befehl, der mit einem Fehlercode endet oder nichts ausgibt, leert die Zeile. Die häufigste Ursache ist eine letzte Zeile wie [ -n "$BRANCH" ] && LINE="...". Sie beendet das Skript mit 1, wenn der Zweig leer ist, und übernimmt diesen Exit-Code für das gesamte Skript. Lassen Sie printf als letzten Befehl stehen oder fügen Sie exit 0 hinzu.
Escape-Codes werden als Text angezeigt, beispielsweise \e]8;; in der Leiste. Verwenden Sie printf '%b' anstelle von echo -e. Anklickbare OSC-8-Links benötigen außerdem ein Terminal, das diese unterstützt. tmux oder SSH können die Sequenzen entfernen. Auf einem Remote-System ist einfache Farbausgabe daher die sicherere Wahl.
Die rechte Seite der Zeile wird abgeschnitten. Systembenachrichtigungen und der Tokenzähler im ausführlichen Modus verwenden diese Zeile ebenfalls von rechts. Bei einem schmalen Terminal kommt es dadurch zu Überlagerungen. Halten Sie die Ausgabe kurz. Eine genaue Abrechnung der Nutzung statt einer Zahl in der Leiste finden Sie unter wie Claude Code Token zählt.
FAQ
Wo befindet sich die Einstellung für die Statuszeile von Claude Code?
In settings.json als statusLine-Block mit type auf "command" und command auf einen Skriptpfad oder einen Shell-Befehl gesetzt. Die Benutzereinstellungen befinden sich in ~/.claude/settings.json und gelten für jedes Projekt auf diesem Rechner. Die Projekteinstellungen befinden sich in .claude/settings.json innerhalb des Repositorys und haben für dieses Verzeichnis Vorrang. Die Einstellungen werden automatisch neu geladen. Eine Änderung wird jedoch erst beim nächsten Aktualisierungstrigger sichtbar, beispielsweise bei Ihrer nächsten Nachricht.
Warum bleibt meine Statuszeile von Claude Code leer?
Fast alle Fälle lassen sich auf vier Ursachen zurückführen. Dem Skript fehlt das Ausführungsbit. Deshalb gibt die Shell Permission denied zurück, und stdout bleibt leer. Der Dialog zur Bestätigung des Workspace-Vertrauens wurde nicht akzeptiert. In diesem Fall protokolliert claude --debug den Wert Status line command skipped: workspace trust not accepted. Oder disableAllHooks ist auf true gesetzt. Dadurch wird die Statuszeile unter derselben Bedingung deaktiviert. Alternativ beendet sich das Skript mit einem Status ungleich 0, wodurch die Zeile leer bleibt. Testen Sie das Skript zuerst manuell: echo '{}' | ~/.claude/statusline.sh muss eine Ausgabe erzeugen.
Enthält das JSON der Statuszeile den Git-Branch?
Nein. Das JSON enthält Sitzungsdaten wie das Modell, die Workspace-Verzeichnisse, die Werte des Kontextfensters und die Kosten. Es enthält keine Git-Informationen. Ein Branch in Ihrer Statusleiste wird von Ihrem eigenen Skript ausgegeben, das git branch --show-current aufruft. Übergeben Sie das Verzeichnis aus dem JSON mit git -C "$DIR". Dadurch entspricht der Branch immer dem Verzeichnis, das die Statusleiste anzeigt.
Verbraucht die Statuszeile Tokens oder verlangsamt sie die Sitzung?
Sie verbraucht keine Tokens, weil das Skript lokal ausgeführt wird und seine Ausgabe nie an das Modell gesendet wird. Für die Geschwindigkeit sind Sie selbst verantwortlich. Der Befehl wird bei jeder Assistentennachricht mit einer Verzögerung von 300 ms ausgeführt. Claude Code bricht einen laufenden Durchlauf ab, sobald eine neue Aktualisierung eintrifft. Wenn ein Skript eine ganze Sekunde benötigt, zeigt die Statuszeile daher veralteten Text an. Vermeiden Sie git status in großen Repositorys und speichern Sie langsame Ergebnisse in einer Datei zwischen, deren Schlüssel session_id ist.
Wie zeige ich auf jedem Server eine andere Statuszeile an?
Verwenden Sie ein Skript und lassen Sie es den Rechner auslesen. Das obige Skript gibt $HOSTNAME aus und verwendet hostname -s als Fallback. Wenn Sie dieselbe Datei auf jeden Server kopieren, wird jeder Server korrekt bezeichnet. Der Farbmechanismus auf Basis der Prüfsumme weist jedem Hostnamen außerdem eine eigene Farbe zu. Wenn ein Server ein anderes Layout benötigt, fügen Sie in den Projekteinstellungen des Repositorys auf diesem Server einen statusLine-Block ein. Projekteinstellungen haben für dieses Verzeichnis Vorrang vor den Benutzereinstellungen.