Як налаштувати statusline Claude Code на VPS
Додайте statusLine до settings.json і виводьте hostname, каталог, git-гілку та модель під prompt, щоб не виконати команду не на тому VPS.
Що показує statusline у Claude Code
statusline у Claude Code — це рядок під запрошенням командного рядка, у якому відображається результат виконання написаного вами скрипту. Додайте блок statusLine до settings.json і вкажіть у ньому команду. Claude Code виконає цю команду, передасть їй стан сеансу у форматі JSON через стандартний ввід і виведе все, що команда запише у стандартний вивід.
Це весь опис взаємодії. Скрипт читає JSON зі стандартного вводу та виводить текст у стандартний вивід. Він виконується на вашому комп’ютері, і жоден виведений ним текст не надсилається моделі, тому токени не витрачаються.
На ноутбуці з одним проєктом це лише оформлення. На трьох серверах це захисний механізм. Кожен сеанс Claude Code має однаковий вигляд у кожному терміналі, тому чотири SSH-вікна без підписів можуть призвести до виконання міграції не на тому сервері. statusline, що починається з імені хоста, усуває цей тип помилок.
Де зберігається параметр statusLine у settings.json
Додайте його до користувацьких налаштувань у ~/.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, тому вона завжди відповідає каталогу, який показує панель.
Збережіть файл і зробіть його виконуваним:
chmod +x ~/.claude/statusline.shБіт виконання є обов’язковим. Claude Code запускає команду через shell, тому скрипт без +x завершується з помилкою Permission denied, не виводить даних у stdout, а рядок залишається порожнім без видимої помилки.
jq аналізує JSON у командному рядку, але не встановлений на чистому Ubuntu server:
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 mode і на кожному такті refreshInterval, якщо ви його налаштували. Оновлення відкладаються на 300 ms, тому серія змін запускає скрипт лише один раз. Панель приховується під час autocomplete, у меню довідки та в запитах дозволів, а потім знову відображається.
Чому ім’я хоста має бути на першому місці
Коли агенти працюють на кількох серверах, термінал — єдине, що повідомляє, де ви перебуваєте, але термінали можуть вводити в оману. Відкрийте друге з’єднання ssh з панелі tmux, і заголовок вікна часто збереже старе ім’я, оскільки його встановлює оболонка, яка не дізналася про перехід. Залиште Claude Code запущеним у від’єднаній сесії tmux на VPS і під’єднайтеся знову наступного дня — на екрані ніщо не відрізнятиме сервер складання від production-сервера.
Рядок стану відрізняється, оскільки його відтворює сам Claude Code окремо для кожної сесії на основі даних, які зберігає ця сесія. Він не може успадкуватися від неправильної панелі або залишитися застарілим через prompt оболонки, який не оновився. Він показує сервер, на якому агент записує файли.
Призначте кожному серверу власний колір, щоб розпізнавати його ще до читання. Додайте ці два рядки перед присвоєнням 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. Скопіюйте той самий скрипт на кожен сервер, і кожен із них позначатиме себе самостійно.
Каталог важливий із тієї самої причини. /srv/api і /srv/api-staging розташовані на відстані одного натискання клавіші в команді ssh, але наслідки їх використання можуть відрізнятися на цілий інцидент. Модель і гілка — ще два елементи, які варто залишити в рядку стану: модель показує, яку сесію ви відновили, а гілка — чи збирається агент виконати 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 у різних репозиторіях не можуть прочитати закешоване ім’я гілки один одного. За задумом сеанси залишаються ізольованими. Щоб передати роботу з одного сеансу іншому, потрібна явна дія. Саме для цього призначене надсилання повідомлення з одного сеансу Claude Code до іншого.
Є ще одне обмеження: tput cols не працює всередині скрипту statusline. Claude Code перехоплює вивід замість підключення скрипту до термінала, тому визначати ширину немає з чого. Перед запуском команди Claude Code встановлює змінні середовища COLUMNS і LINES у v2.1.153 і новіших версіях. Тому, коли потрібно визначити, скільки тексту виводити, читайте $COLUMNS.
Чому statusline залишається порожнім
На екрані нічого не з’являється. Перевірте біт виконання за допомогою ls -l ~/.claude/statusline.sh, а потім запустіть скрипт вручну з наведеними вище тестовими даними. Якщо в shell він виводить рядок, але в Claude Code нічого немає, почніть із claude --debug. Ця команда записує код завершення та stderr першого запуску statusline у поточному сеансі.
У журналі налагодження зазначено Status line command skipped: workspace trust not accepted. statusline виконує shell-команду, тому на нього поширюється той самий захист workspace trust, що й на hooks. Поки ви не підтвердите довіру до цього каталогу у відповідному діалозі, команда не запускатиметься. Це часто трапляється на VPS, де кожен новий clone розташований у каталозі, якого Claude Code ще не бачив. Перезапустіть Claude Code у цьому каталозі та підтвердьте довіру.
Усе порожнє, а disableAllHooks встановлено. "disableAllHooks": true у settings.json також вимикає statusline, оскільки це той самий механізм дозволу на виконання 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 до налаштувань проєкту репозиторію, з яким ви працюєте на цьому сервері, оскільки налаштування проєкту мають пріоритет над користувацькими налаштуваннями для цього каталогу.