Як налаштувати statusline Claude Code на VPS
Додайте statusLine до ~/.claude/settings.json і виводьте hostname, поточний каталог, git-гілку та модель, щоб не виконати команду не на тому сервері.
Що показує statusline Claude Code
statusline Claude Code — це рядок під запрошенням командного рядка, у якому відображається результат роботи написаного вами скрипту. Додайте блок statusLine до settings.json і вкажіть у ньому команду. Claude Code виконає цю команду, передасть їй стан сеансу у форматі JSON через стандартний ввід і виведе все, що команда записала у стандартний вивід.
Це весь опис взаємодії. Скрипт читає JSON зі стандартного вводу та виводить текст у стандартний вивід. Він працює на вашому комп’ютері, і дані, які він виводить, не передаються моделі, тому токени не витрачаються.
На ноутбуці з одним проєктом це лише оформлення. На трьох серверах це засіб захисту від помилок. Кожен сеанс Claude Code у кожному терміналі виглядає однаково, тому чотири SSH-вікна без підписів можуть призвести до виконання міграції не на тому сервері. Рядок statusline, який починається з імені хоста, усуває цей тип помилок.
Де в settings.json розташований параметр statusLine
Додайте його до користувацьких налаштувань у ~/.claude/settings.json. Вони застосовуються до кожного проєкту на цьому комп’ютері. Налаштування проєкту в .claude/settings.json у межах репозиторію також працюють і мають пріоритет для цього каталогу.
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}type завжди має значення "command". Значення command виконується через shell, тому це може бути шлях до скрипту або звичайна команда. Перш ніж писати скрипт, перевірте, чи працює зв’язка:
{
"statusLine": {
"type": "command",
"command": "hostname -s"
}
}Запустіть Claude Code і надішліть одне повідомлення. Панель під запитом тепер містить коротке ім’я хоста сервера. Якщо вона залишається порожньою, проблема в параметрі або діалоговому вікні довіри, а не у вашому скрипті. Див. нижче розділ «Чому statusline залишається порожнім».
Станом на August 2026 доступні три необов’язкові ключі. padding додає горизонтальний інтервал у символах і за замовчуванням має значення 0. refreshInterval повторно запускає команду кожні N секунд на додаток до звичайних тригерів. Мінімальне значення — 1. Використовуйте це лише тоді, коли рядок містить годинник або інше значення, яке змінюється під час простою сесії. hideVimModeIndicator вимикає вбудований текст -- INSERT --, якщо ваш скрипт уже відображає режим vim.
Які дані отримує скрипт statusline?
Не довіряйте списку полів, який ви прочитали будь-де, зокрема на цій сторінці. Перехопіть фактичний об’єкт, який надсилає ваша версія. Створіть тимчасовий скрипт, що зберігає stdin у файл:
cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.shВкажіть statusLine.command цей файл, запустіть сеанс і надішліть одне повідомлення. Рядок стану читає captured. Тепер перегляньте отримані дані:
jq . /tmp/statusline-input.jsonТепер ви маєте точну структуру для своєї збірки. Повторюйте цю перевірку щоразу, коли оновлення щось змінює.
Стабільні частини, описані станом на August 2026, є вкладеними об’єктами, а не пласкими ключами. model містить id і display_name. workspace містить current_dir і project_dir: current_dir — це поточний каталог сеансу, project_dir — каталог, з якого сеанс запущено. Вони відрізняються після зміни робочого каталогу під час сеансу. Об’єкт верхнього рівня cwd містить те саме значення, що й workspace.current_dir. context_window містить кількість токенів і попередньо обчислене значення used_percentage. cost містить total_cost_usd і лічильники тривалості. session_id залишається незмінним протягом усього сеансу та є унікальним для різних сеансів, що важливо для подальшого кешування.
Три правила допомагають скрипту працювати після змін схеми.
Деякі ключі відсутні, а не мають значення null. vim, agent, pr, worktree і effort з’являються лише тоді, коли активна відповідна функція. Читання .vim.mode за допомогою jq -r, коли режим vim вимкнено, виводить буквальний рядок null, і ваш рядок стану показує читачеві null. Додавайте // empty до кожного селектора, щоб за відсутності ключа нічого не виводилося.
Деякі значення спочатку дорівнюють null. context_window.used_percentage і context_window.current_usage мають значення null до першої відповіді API, а current_usage знову набуває значення null після /compact, доки наступний виклик не заповнить його повторно. Тому для відсотка використання контексту в рядку стану потрібне // 0. Інакше протягом перших секунд кожного сеансу він читає null. Перш ніж додавати це число до рядка стану, варто зрозуміти як насправді заповнюється контекстне вікно.
Гілка git не входить до JSON. Жодне поле її не передає. Будь-яка гілка в рядку стану з’являється тому, що ваш скрипт сам запускає git.
Скрипт statusline, який деградує, а не завершується з помилкою
Це готова до копіювання версія. Вона виводить ім’я хоста, робочий каталог, гілку git і назву моделі. Для кожного поля передбачено запасне значення, тому навіть порожній JSON-об’єкт повертає придатний для використання рядок.
#!/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"Кожне читання виконується через field, який додає // empty. Тому перейменований або видалений ключ повертає порожній рядок, а наступний рядок підставляє значення за замовчуванням. Для каталогу передбачено послідовний відкат від workspace.current_dir до cwd і потім до $PWD. Гілка визначається через git -C "$DIR", а не через звичайний git, тому вона завжди відповідає каталогу, який показує statusline.
Збережіть файл, а потім зробіть його виконуваним:
chmod +x ~/.claude/statusline.shПрапорець виконання є обов’язковим. Claude Code запускає команду через shell, тому скрипт без +x завершується з Permission denied, нічого не виводить у stdout, і рядок залишається порожнім без видимої помилки.
jq розбирає JSON у командному рядку й не встановлений на чистому сервері Ubuntu:
sudo apt update && sudo apt install -y jqПотім укажіть у налаштуванні цей скрипт, використовуючи перший блок settings.json вище.
Перевірте скрипт, перш ніж йому довіряти
Запустіть його вручну двічі. Спочатку зі звичайним об’єктом сеансу:
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/srv/api"},"session_id":"t1"}' | ~/.claude/statusline.shВи отримуєте ім’я хоста, потім /srv/api, а потім Opus. Гілка не відображається, оскільки /srv/api на вашому комп’ютері, імовірно, не є git-репозиторієм.
Далі виконайте тест на погіршення — саме його часто пропускають:
echo '{}' | ~/.claude/statusline.shПорожній об’єкт — найгірший випадок, який може виникнути через зміну схеми. Рядок усе одно виводить ім’я хоста, поточний каталог із $PWD і слово claude на місці назви моделі. Нічого не завершується аварійно, і нічого не виводить null. Скрипт, який проходить цей тест, витримує перейменування поля, оскільки для скрипту перейменоване поле та відсутнє поле є тією самою подією.
Що ви маєте побачити
Рядок стану відображається в окремому рядку над вбудованими бейджами нижнього колонтитула й не замінює їх. У робочій конфігурації це один рядок: коротке ім’я хоста блакитного кольору, потім робочий каталог зі скороченим домашнім каталогом до ~, далі назва гілки жовтого кольору, якщо каталог є git-репозиторієм, і назва моделі приглушеного кольору. Результат має бути приблизно таким, як web-01 ~/api main Opus, із цими чотирма кольоровими елементами.
Рядок повторно запускає ваш скрипт під час запуску сеансу, зокрема після відновлення, коли надходить нове повідомлення асистента, після завершення /compact, під час зміни режиму дозволів, перемикання vim-режиму та на кожному такті refreshInterval, якщо ви його налаштували. Оновлення відкладаються на 300 ms, тому серія змін запускає скрипт лише один раз. Рядок приховується під час автодоповнення, у меню довідки та під час запитів дозволу, а потім знову відображається.
Чому ім’я хоста має бути першим
Якщо агенти працюють на кількох серверах, термінал — єдине, що показує, де ви перебуваєте, але термінали можуть вводити в оману. Відкрийте друге ssh-з’єднання з панелі tmux, і заголовок вікна часто збереже старе ім’я, оскільки його встановлює shell, який не дізнався про перехід. Залиште Claude Code запущеним у від’єднаній сесії tmux на VPS, повторно під’єднайтеся через день — і ніщо на екрані не відрізнятиме сервер збірки від production-сервера.
Statusline працює інакше, оскільки Claude Code формує її окремо для кожної сесії на основі даних цієї сесії. Вона не успадковується від іншої панелі й не залишається застарілою через prompt shell, який не оновився. Вона показує сервер, на якому агент записує файли.
Призначте кожному серверу власний колір, щоб розпізнавати його ще до читання тексту. Два рядки додайте перед присвоєнням LINE=:
CODE=$(printf '%s' "$HOST" | cksum | cut -d' ' -f1)
HOST_COLOR=$(printf '\033[%dm' "$((31 + CODE % 6))")Потім використовуйте ${HOST_COLOR} замість ${CYAN}. cksum виводить checksum імені хоста, тому певне ім’я завжди відповідає одному кольору в діапазоні від 31 до 36 — від червоного до cyan. Скопіюйте той самий script на кожен сервер, і кожен сервер позначатиме себе сам.
Каталог потрібен з тієї самої причини. /srv/api і /srv/api-staging відрізняються одним натисканням клавіші в команді ssh, але наслідки для інциденту можуть бути зовсім різними. Model і branch — ще два значення, для яких варто залишити місце: model показує, яку сесію ви відновили, а branch — чи збирається агент виконати commit у main.
На малому екрані це ще важливіше, оскільки немає заголовка вікна, на який можна було б орієнтуватися. Якщо ви працюєте саме так, дивіться як керувати Claude Code з телефона.
Прискорте виконання скрипту
Ваш скрипт запускається під час кожного повідомлення асистента, а Claude Code скасовує поточний запуск, коли надходить нове оновлення. Тому повільний скрипт виводить застарілий текст або не виводить нічого.
Кожен виклик jq займає кілька мілісекунд. Повільною є частина git: git status у великому репозиторії з холодним кешем займає сотні мілісекунд. Наведений вище скрипт навмисно не використовує git status і викликає git branch --show-current, який читає .git/HEAD та одразу повертає результат.
Якщо ви додаєте важчу операцію, кешуйте її результат у файлі й оновлюйте файл кожні кілька секунд. Прив’яжіть файл до сеансу:
CACHE="/tmp/statusline-$(field '.session_id')"Використовуйте session_id, а не $$. $$ — це ідентифікатор процесу вашого скрипту. Він змінюється під час кожного запуску, тому кеш із таким ключем ніколи не використовується повторно, і повна операція виконується щоразу. session_id залишається незмінним протягом усього сеансу й відрізняється між сеансами, тому два сеанси Claude Code у двох репозиторіях не зможуть прочитати назву гілки з кешу один одного.
Є ще одне обмеження: tput cols не працює всередині скрипту statusline. Claude Code захоплює вивід замість підключення скрипту до термінала, тому визначати ширину немає з чого. У версіях v2.1.153 і новіших Claude Code встановлює змінні середовища COLUMNS і LINES перед виконанням команди. Тому, коли потрібно визначити обсяг виводу, зчитуйте $COLUMNS.
Рядок стану залишається порожнім
На екрані взагалі нічого не з’являється. Перевірте біт виконання за допомогою ls -l ~/.claude/statusline.sh, а потім запустіть скрипт вручну з наведеними вище тестовими вхідними даними. Якщо в shell він виводить рядок, але в Claude Code — ні, почніть із claude --debug. Ця команда записує код завершення та stderr першого запуску рядка стану в межах сеансу.
У журналі налагодження зазначено Status line command skipped: workspace trust not accepted. Рядок стану виконує shell-команду, тому на нього поширюється та сама перевірка довіри до робочого простору, що й на hooks. Поки ви не підтвердите довіру для цього каталогу у відповідному діалоговому вікні, команда не запускатиметься. Це часто трапляється на VPS, де кожен новий clone розташований у каталозі, якого Claude Code ще не бачив. Перезапустіть Claude Code у цьому каталозі та підтвердьте довіру.
Усе порожнє, а disableAllHooks встановлено. Параметр "disableAllHooks": true у settings.json також вимикає рядок стану, оскільки це той самий механізм дозволу виконання shell-команд. Видаліть його або встановіть значення false.
Рядок виводить null. Селектор jq звернувся до ключа, якого немає або значення якого дорівнює null, а jq -r виводить null як чотири символи null. Додайте // empty для текстових значень і // 0 для чисел.
Рядок стає порожнім одразу після редагування скрипту. Команда, яка завершується з ненульовим кодом або нічого не виводить, очищає рядок. Зазвичай причина полягає в останньому рядку на кшталт [ -n "$BRANCH" ] && LINE="...": якщо гілка порожня, він завершується з кодом 1, і весь скрипт успадковує цей код завершення. Залиште printf останнім або додайте exit 0.
Керівні escape-послідовності відображаються як звичайний текст, наприклад \e]8;; на панелі. Використовуйте printf '%b' замість echo -e. Для клікабельних посилань OSC 8 також потрібен термінал, який їх підтримує. Крім того, tmux або SSH можуть видаляти ці послідовності, тому на віддаленому сервері безпечніше використовувати звичайний колір.
Праву частину рядка обрізано. Системні сповіщення та лічильник токенів у verbose mode займають цей рядок праворуч, а у вузькому терміналі виникає перекриття. Скоротіть вивід. Щоб отримати точний облік використання, а не лише число на панелі, див. як Claude Code підраховує токени.
FAQ
Де зберігається параметр statusline у Claude Code?
У settings.json як блок statusLine, де type має значення "command", а command — шлях до скрипту або shell-команда. Користувацькі параметри зберігаються в ~/.claude/settings.json і застосовуються до всіх проєктів на цій машині. Параметри проєкту зберігаються в .claude/settings.json у репозиторії та мають пріоритет для цього каталогу. Параметри перезавантажуються автоматично, але зміна стане видимою лише під час наступного тригера оновлення, наприклад після наступного повідомлення.
Чому statusline у Claude Code порожній?
Майже всі випадки пояснюються чотирма причинами. Скрипт не має біта виконання, тому shell повертає Permission denied, і stdout залишається порожнім. Діалог підтвердження довіри до робочого простору не було прийнято, а claude --debug записує Status line command skipped: workspace trust not accepted. disableAllHooks має значення true, що вимикає statusline за тієї самої умови. Або скрипт завершується з ненульовим кодом, через що рядок стає порожнім. Спочатку перевірте скрипт вручну: echo '{}' | ~/.claude/statusline.sh має щось вивести.
Чи містить JSON statusline гілку git?
Ні. JSON містить стан сеансу, зокрема модель, каталоги робочого простору, номери контекстного вікна та вартість. Даних про git у ньому немає. Гілка в панелі з’являється завдяки власному скрипту, який викликає git branch --show-current. Передайте каталог із JSON через git -C "$DIR", щоб гілка завжди відповідала каталогу, показаному в панелі.
Чи споживає statusline токени або сповільнює сеанс?
Токени не споживаються, оскільки скрипт запускається локально, а його вивід ніколи не передається моделі. За швидкодію відповідаєте ви. Команда запускається після кожного повідомлення асистента з debounce 300 ms, а Claude Code скасовує поточний запуск, коли надходить нове оновлення. Тому скрипт, який виконується цілу секунду, показує застарілий текст. У великих репозиторіях уникайте git status і кешуйте повільні операції у файлі з ключем на основі session_id.
Як показувати різний statusline на кожному сервері?
Використовуйте один скрипт і дайте йому зчитувати дані про машину. Наведений вище скрипт виводить $HOSTNAME, використовуючи hostname -s як резервне значення. Тому один і той самий файл, скопійований на кожен сервер, правильно позначає кожен із них, а прийом із кольором контрольної суми надає кожному hostname власний колір. Якщо для одного сервера потрібне інше компонування, додайте блок statusLine до параметрів проєкту репозиторію, з яким ви працюєте на цьому сервері, оскільки параметри проєкту мають пріоритет над користувацькими параметрами для цього каталогу.