SSD Nodes Learn Hosting plans →
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-28

Claude Code statusLine: jak dodać pasek stanu w terminalu

Konfiguracja statusLine w pliku settings.json pozwala wyświetlać nazwę hosta, katalog i branch git w Claude Code. Dowiedz się, jak uniknąć błędów na serwerach VPS przez skrypt.

Co oznacza pasek stanu Claude Code

Pasek stanu Claude Code to wiersz pod wierszem poleceń, który wyświetla wynik działania napisanego przez użytkownika skryptu. Należy dodać blok statusLine do settings.json i wskazać w nim odpowiednie polecenie. Claude Code uruchamia to polecenie, przesyła do niego stan sesji w formacie JSON na standardowe wejście i drukuje wszystko, co polecenie wypisze na standardowe wyjście.

To cała zasada działania. Skrypt odczytuje JSON ze standardowego wejścia i wypisuje tekst na standardowe wyjście. Działa on lokalnie na maszynie, a jego dane wyjściowe nie są przesyłane do modelu, więc nie generuje to kosztów w tokenach.

Na laptopie z jednym projektem jest to jedynie element dekoracyjny. Na trzech serwerach stanowi zabezpieczenie. Każda sesja Claude Code wygląda identycznie w każdym terminalu, więc cztery okna SSH bez etykiet to prosty sposób na wykonanie migracji na niewłaściwej maszynie. Pasek stanu rozpoczynający się od nazwy hosta eliminuje tego typu błędy.

Gdzie znajduje się ustawienie statusLine w settings.json

Należy umieścić je w ustawieniach użytkownika w ~/.claude/settings.json, co ma zastosowanie do każdego projektu na danej maszynie. Ustawienia projektu w .claude/settings.json wewnątrz repozytorium również działają i mają pierwszeństwo dla danego katalogu.

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

type to zawsze "command". Wartość command jest wykonywana przez powłokę, więc może to być ścieżka do skryptu lub zwykłe polecenie. Przed napisaniem jakiegokolwiek skryptu należy sprawdzić, czy połączenie działa:

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

Uruchom Claude Code i wyślij jedną wiadomość. Pasek pod promptem wyświetla teraz krótką nazwę hosta serwera. Jeśli pozostaje pusty, problemem jest ustawienie lub okno dialogowe zaufania, a nie skrypt. Przeczytaj sekcję "Dlaczego pasek statusu pozostaje pusty" poniżej.

Na sierpień 2026 istnieją trzy opcjonalne klucze. padding dodaje odstępy poziome w znakach, a jego wartością domyślną jest 0. refreshInterval uruchamia polecenie ponownie co N sekund niezależnie od standardowych wyzwalaczy, z minimum 1; jest to przydatne tylko wtedy, gdy wiersz wyświetla zegar lub inny element zmieniający się podczas bezczynności sesji. hideVimModeIndicator wyłącza wbudowany tekst -- INSERT --, gdy własny skrypt renderuje już tryb vim.

Jakie dane otrzymuje skrypt paska stanu?

Nie należy polegać na listach pól z jakiejkolwiek dokumentacji, w tym z tej strony. Należy przechwycić rzeczywisty obiekt wysyłany przez używaną wersję. W tym celu należy utworzyć tymczasowy skrypt zapisujący stdin do pliku:

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

Skieruj statusLine.command na ten plik, uruchom sesję i wyślij jedną wiadomość. Pasek odczytuje captured. Teraz sprawdź, co zostało odebrane:

jq . /tmp/statusline-input.json

W ten sposób uzyskasz dokładną strukturę dla swojej kompilacji; procedurę można powtórzyć w dowolnym momencie po aktualizacji, która mogła wprowadzić zmiany.

Stabilne elementy, zgodnie z dokumentacją z sierpnia 2026, to obiekty zagnieżdżone, a nie płaskie klucze. model zawiera id oraz display_name. workspace zawiera current_dir oraz project_dir: current_dir wskazuje bieżącą lokalizację sesji, project_dir wskazuje lokalizację początkową, a wartości te różnią się po zmianie katalogu roboczego w trakcie sesji. Klucz najwyższego poziomu cwd przechowuje tę samą wartość co workspace.current_dir. context_window zawiera liczby tokenów oraz wstępnie obliczone used_percentage. cost zawiera total_cost_usd oraz liczniki czasu trwania. session_id jest stałe przez cały czas trwania sesji i unikalne dla każdej sesji, co ma znaczenie dla późniejszego buforowania.

Trzy zasady pozwalają utrzymać skrypt w działaniu mimo zmian schematu.

Niektóre klucze są nieobecne, a nie puste (null). vim, agent, pr, worktree oraz effort pojawiają się tylko wtedy, gdy odpowiadająca im funkcja jest aktywna. Odczytanie .vim.mode za pomocą jq -r przy wyłączonym trybie vim powoduje wypisanie dosłownego ciągu null, a pasek wyświetla użytkownikowi null. Należy dodać // empty do każdego selektora, aby brakujący klucz nie powodował wyświetlenia żadnej wartości.

Niektóre wartości są początkowo puste (null). context_window.used_percentage oraz context_window.current_usage przyjmują wartość null przed pierwszą odpowiedzią API, a current_usage wraca do stanu null po /compact do momentu ponownego wypełnienia przez kolejne wywołanie. Procentowy wskaźnik kontekstu na pasku wymaga zatem // 0, w przeciwnym razie przez pierwsze sekundy sesji będzie wyświetlane null. Przed umieszczeniem tej liczby na pasku warto zapoznać się z informacją jak faktycznie wypełnia się okno kontekstowe.

Gałąź git nie znajduje się w JSON. Żadne pole jej nie raportuje. Każda gałąź widoczna na pasku pochodzi ze skryptu, który samodzielnie wykonuje git.

Skrypt paska stanu z mechanizmem degradacji zamiast awarii

Poniżej znajduje się wersja gotowa do skopiowania. Skrypt wyświetla nazwę hosta, bieżący katalog roboczy, gałąź git oraz nazwę modelu. Każde pole posiada mechanizm zastępczy, dzięki czemu nawet pusty obiekt JSON pozwala na wygenerowanie poprawnej linii.

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

Każdy odczyt przechodzi przez field, który dołącza // empty, więc zmiana nazwy lub usunięcie klucza skutkuje pustym ciągiem znaków, a kolejna linia dostarcza wartość domyślną. Katalog jest pobierany w kolejności: workspace.current_dir, następnie cwd, a na końcu $PWD. Gałąź pochodzi z git -C "$DIR", a nie z surowego git, dzięki czemu gałąź zawsze odpowiada katalogowi wyświetlanemu na pasku.

Zapisz plik, a następnie nadaj mu uprawnienia do wykonywania:

chmod +x ~/.claude/statusline.sh

Bit wykonywania nie jest opcjonalny. Claude Code uruchamia polecenie przez powłokę, więc skrypt bez +x kończy się niepowodzeniem z błędem Permission denied, nie generuje wyjścia na stdout, a wiersz pozostaje pusty bez widocznego komunikatu o błędzie.

jq służy do parsowania JSON w wierszu poleceń i nie jest instalowane domyślnie na czystym serwerze Ubuntu:

sudo apt update && sudo apt install -y jq

Następnie wskaż skrypt w ustawieniach, korzystając z pierwszego bloku settings.json powyżej.

Przetestuj skrypt przed wdrożeniem

Uruchom go dwukrotnie ręcznie. Najpierw przy użyciu standardowego obiektu sesji:

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

Otrzymasz nazwę hosta, a następnie /srv/api oraz Opus. Żadna gałąź nie zostanie wyświetlona, ponieważ /srv/api na Twojej maszynie prawdopodobnie nie jest repozytorium git.

Następnie przeprowadź test degradacji, który jest często pomijany:

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

Pusty obiekt to najgorszy przypadek, jaki może wystąpić przy zmianie schematu. Wiersz nadal wyświetla: nazwę hosta, bieżący katalog z $PWD oraz słowo claude w miejscu nazwy modelu. Nic nie ulega awarii i nie jest wyświetlane null. Skrypt, który przechodzi ten test, przetrwa zmianę nazwy pola, ponieważ dla skryptu zmiana nazwy pola i jego brak to to samo zdarzenie.

Co powinno być widoczne

Linia statusu jest renderowana w osobnym wierszu nad wbudowanymi odznakami stopki i nie zastępuje ich. W poprawnie działającej konfiguracji jest to jeden wiersz: krótka nazwa hosta w kolorze cyjan, następnie katalog roboczy ze skróconą ścieżką do katalogu domowego jako ~, potem nazwa gałęzi w kolorze żółtym, jeśli katalog jest repozytorium git, a na końcu przyciemniona nazwa modelu. Wynik powinien być zbliżony do web-01 ~/api main Opus, z tymi czterema elementami w odpowiednich kolorach.

Wiersz uruchamia skrypt ponownie przy rozpoczęciu sesji, w tym przy jej wznawianiu, po otrzymaniu nowej wiadomości od asystenta, po zakończeniu /compact, przy zmianie trybu uprawnień, przy przełączeniu trybu vim oraz przy tyknięciu refreshInterval, jeśli zostało ustawione. Aktualizacje są opóźniane o 300 ms (debouncing), więc seria zmian powoduje jednokrotne uruchomienie skryptu. Pasek ukrywa się podczas autouzupełniania, wyświetlania menu pomocy oraz monitów o uprawnienia, a następnie powraca.

Dlaczego nazwa hosta powinna znajdować się na początku

Gdy agenci działają na więcej niż jednym serwerze, terminal jest jedynym źródłem informacji o lokalizacji, a terminale bywają mylące. Otwarcie drugiego połączenia ssh wewnątrz panelu tmux często skutkuje zachowaniem starej nazwy w tytule okna, ponieważ tytuł jest ustawiany przez powłokę, która nie otrzymała informacji o zmianie kontekstu. Pozostawienie Claude Code uruchomionego w odłączonej sesji tmux na VPS i ponowne podłączenie się po dniu sprawia, że na ekranie nic nie odróżnia serwera budowania od maszyny produkcyjnej.

Pasek stanu działa inaczej, ponieważ jest renderowany bezpośrednio przez Claude Code dla każdej sesji na podstawie danych, które ta sesja przechowuje. Nie może zostać odziedziczony z niewłaściwego panelu ani stać się nieaktualny przez monit powłoki, który nie został odświeżony. Informuje on dokładnie o maszynie, na której agent zapisuje pliki.

Przypisz każdemu serwerowi własny kolor, aby rozpoznawać go przed przeczytaniem nazwy. Dwie linie, umieszczone powyżej przypisania LINE=:

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

Następnie użyj ${HOST_COLOR} zamiast ${CYAN}. cksum wypisuje sumę kontrolną nazwy hosta, dzięki czemu dana nazwa zawsze mapuje się na ten sam kolor z zakresu 31 do 36, czyli od czerwonego do cyjanu. Skopiuj ten sam skrypt na każdą maszynę, a każda z nich oznaczy się samodzielnie.

Katalog zajmuje swoje miejsce z tego samego powodu. /srv/api i /srv/api-staging dzieli jedno naciśnięcie klawisza w poleceniu ssh, a w skutkach dzieli je cały incydent. Model i gałąź to dwa kolejne elementy warte zajmowanego miejsca: model informuje, którą sesję wznowiono, a gałąź wskazuje, czy agent zamierza dokonać commita do main.

Mały ekran sprawia, że wszystko to staje się bardziej istotne, ponieważ nie ma tytułu okna, na którym można polegać. Jeśli taka jest Twoja konfiguracja, zobacz obsługa Claude Code z telefonu.

Utrzymanie szybkości działania skryptu

Skrypt uruchamia się przy każdej wiadomości asystenta, a Claude Code przerywa trwające wykonanie, gdy nadejdzie nowa aktualizacja. Wolny skrypt powoduje zatem wyświetlanie nieaktualnego tekstu lub jego brak.

Każde wywołanie jq kosztuje kilka milisekund. Część git jest najbardziej czasochłonna: git status w dużym repozytorium z zimną pamięcią podręczną zajmuje setki milisekund. Powyższy skrypt celowo unika git status i wywołuje git branch --show-current, który odczytuje .git/HEAD i zwraca wynik natychmiast.

W przypadku dodawania cięższych operacji, należy buforować wyniki w pliku i odświeżać je co kilka sekund. Klucz pliku powinien być powiązany z sesją:

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

Należy używać session_id, a nie $$. $$ to identyfikator procesu skryptu, który jest inny przy każdym wywołaniu, więc pamięć podręczna oparta na tym kluczu nigdy nie przyniesie trafienia i za każdym razem generuje pełny koszt operacji. session_id jest stałe dla całej sesji i unikalne dla różnych sesji, dzięki czemu dwie sesje Claude Code w dwóch repozytoriach nie mogą odczytać nawzajem swoich nazw gałęzi. Sesje są z założenia odizolowane, więc przekazanie pracy między nimi wymaga celowego działania, do czego służy wysyłanie wiadomości z jednej sesji Claude Code do drugiej.

Warto znać jeszcze jedno ograniczenie: tput cols nie działa wewnątrz skryptu linii statusu. Claude Code przechwytuje wyjście zamiast dołączać skrypt do terminala, więc wykrywanie szerokości nie ma punktu odniesienia. Claude Code ustawia zmienne środowiskowe COLUMNS oraz LINES przed uruchomieniem polecenia (w wersji v2.1.153 i nowszych), dlatego należy odczytywać $COLUMNS w celu określenia ilości danych do wyświetlenia.

Dlaczego pasek stanu pozostaje pusty

Nic się nie wyświetla. Sprawdź bit wykonywalności za pomocą ls -l ~/.claude/statusline.sh, a następnie uruchom skrypt ręcznie, używając powyższych przykładowych danych wejściowych. Jeśli skrypt wypisuje linię w powłoce, ale nie w Claude Code, zacznij od claude --debug, co zarejestruje kod wyjścia oraz stderr pierwszego uruchomienia paska stanu w sesji.

Dziennik debugowania zawiera Status line command skipped: workspace trust not accepted. Pasek stanu wykonuje polecenie powłoki, więc podlega tym samym ograniczeniom zaufania obszaru roboczego co hooki. Dopóki nie zaakceptujesz okna dialogowego zaufania dla tego katalogu, polecenie nie zostanie uruchomione. Jest to częste zjawisko na serwerach VPS, gdzie każdy nowy klon jest katalogiem, którego Claude Code jeszcze nie rozpoznał. Uruchom ponownie Claude Code w tym katalogu i zaakceptuj okno dialogowe.

Wszystko jest puste, a disableAllHooks jest ustawione. Opcja "disableAllHooks": true w pliku settings.json również wyłącza pasek stanu, ponieważ korzysta z tej samej bramy wykonywania powłoki. Usuń ją lub ustaw na false.

Wiersz wypisuje null. Selektor jq dotarł do klucza, który nie istnieje lub ma wartość null, a jq -r wypisuje null jako cztery znaki null. Dodaj // empty dla tekstu oraz // 0 dla liczb.

Wiersz staje się pusty zaraz po edycji skryptu. Polecenie, które kończy się niezerowym kodem wyjścia lub nic nie wypisuje, czyści wiersz. Typową przyczyną jest końcowa linia typu [ -n "$BRANCH" ] && LINE="...", która zwraca kod 1, gdy gałąź jest pusta, co wpływa na kod wyjścia całego skryptu. Umieść printf na końcu lub dodaj exit 0.

Kody sterujące wyświetlają się jako tekst jawny, taki jak \e]8;; na pasku. Użyj printf '%b' zamiast echo -e. Klikalne linki OSC 8 wymagają terminala, który je obsługuje; tmux lub SSH mogą usuwać te sekwencje, dlatego na zdalnych maszynach bezpieczniejszym wyborem jest zwykły kolor.

Prawa strona wiersza jest ucięta. Powiadomienia systemowe oraz licznik tokenów w trybie verbose współdzielą ten wiersz od prawej strony, a zbyt wąski terminal powoduje nakładanie się elementów. Utrzymuj dane wyjściowe w krótkiej formie. Aby uzyskać dokładne rozliczenie użycia, zamiast liczby na pasku, zobacz jak Claude Code zlicza tokeny.

FAQ

Gdzie znajduje się ustawienie paska stanu Claude Code?

W settings.json, jako blok statusLine z type ustawionym na "command" oraz command ustawionym na ścieżkę do skryptu lub polecenie powłoki. Ustawienia użytkownika znajdują się w ~/.claude/settings.json i dotyczą każdego projektu na danej maszynie. Ustawienia projektu znajdują się w .claude/settings.json wewnątrz repozytorium i mają pierwszeństwo dla danego katalogu. Ustawienia przeładowują się automatycznie, ale zmiana staje się widoczna dopiero przy kolejnym wyzwalaczu aktualizacji, na przykład przy następnej wiadomości.

Dlaczego mój pasek stanu Claude Code jest pusty?

Cztery przyczyny obejmują niemal wszystkie przypadki. Skrypt nie posiada bitu wykonywalności, więc powłoka zwraca Permission denied i nic nie trafia do stdout. Okno dialogowe zaufania do obszaru roboczego nie zostało zaakceptowane, a claude --debug loguje Status line command skipped: workspace trust not accepted. disableAllHooks ma wartość true, co wyłącza pasek stanu w ramach tego samego mechanizmu. Lub skrypt kończy działanie z kodem wyjścia innym niż zero, co powoduje wyczyszczenie wiersza. Przetestuj to ręcznie: echo '{}' | ~/.claude/statusline.sh musi wypisać cokolwiek.

Czy JSON paska stanu zawiera gałąź git?

Nie. JSON przenosi stan sesji, taki jak model, katalogi obszaru roboczego, liczby okna kontekstowego oraz koszt. Nic w nim nie raportuje stanu git. Gałąź na pasku pochodzi z własnego skryptu wywołującego git branch --show-current. Przekaż katalog z JSON za pomocą git -C "$DIR", aby gałąź zawsze odpowiadała katalogowi wyświetlanemu na pasku.

Czy pasek stanu zużywa tokeny lub spowalnia sesję?

Nie zużywa tokenów, ponieważ skrypt działa lokalnie, a jego wyjście nigdy nie jest wysyłane do modelu. Szybkość działania zależy od użytkownika. Polecenie uruchamia się przy każdej wiadomości asystenta z opóźnieniem 300 ms (debounce), a Claude Code anuluje trwające uruchomienie, gdy nadejdzie nowa aktualizacja, więc skrypt trwający pełną sekundę wyświetli nieaktualny tekst. Unikaj git status w dużych repozytoriach i buforuj wszelkie wolne operacje w pliku kluczowanym przez session_id.

Jak wyświetlić inny pasek stanu na każdym serwerze?

Utrzymuj jeden skrypt i pozwól mu odczytywać informacje o maszynie. Powyższy skrypt wypisuje $HOSTNAME z hostname -s jako wartością domyślną, więc ten sam plik skopiowany na każdą maszynę poprawnie etykietuje każdą z nich, a sztuczka z kolorem sumy kontrolnej nadaje każdej nazwie hosta własny kolor. Jeśli jeden serwer wymaga innego układu, umieść blok statusLine w ustawieniach projektu repozytorium, w którym pracujesz na tej maszynie, ponieważ ustawienia projektu nadpisują ustawienia użytkownika dla danego katalogu.