SSD Nodes Learn 🎉 VPS от $4.99/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-07

Настройка statusLine в Claude Code на VPS

Узнайте, как настроить отображение имени хоста, пути и ветки Git в строке состояния Claude Code. Инструкция по редактированию settings.json для защиты от ошибок на серверах.

Что отображает строка состояния Claude Code

Строка состояния Claude Code — это строка под приглашением командной строки, в которой выводится результат работы вашего скрипта. Вы добавляете блок statusLine в settings.json и указываете путь к команде. Claude Code выполняет эту команду, передает ей состояние сессии в формате JSON через стандартный поток ввода (stdin) и выводит всё, что команда записывает в стандартный поток вывода (stdout).

Это и есть весь принцип работы. Ваш скрипт считывает JSON из stdin и выводит текст в stdout. Он выполняется на вашей машине, и всё, что он выводит, не отправляется модели, поэтому токены не расходуются.

На ноутбуке с одним проектом это лишь элемент оформления. На трех серверах — это средство безопасности. Каждая сессия Claude Code выглядит одинаково в любом терминале, поэтому четыре окна SSH без меток — это способ совершить ошибку при миграции, выполнив действия не на том сервере. Строка состояния, начинающаяся с имени хоста, исключает подобные ошибки.

Где находится параметр statusLine в settings.json

Добавьте его в пользовательские настройки по пути ~/.claude/settings.json, которые применяются ко всем проектам на этой машине. Также можно использовать настройки проекта в .claude/settings.json внутри репозитория; они имеют приоритет для данной директории.

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

type всегда имеет значение "command". Значение command выполняется через оболочку, поэтому это может быть путь к скрипту или обычная команда. Проверьте работоспособность связки перед написанием скрипта:

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

Запустите Claude Code и отправьте одно сообщение. В строке под полем ввода теперь отображается короткое имя хоста сервера. Если она остается пустой, проблема в настройке или диалоговом окне доверия, а не в вашем скрипте. Прочтите раздел "Почему статусная строка остается пустой" ниже.

По состоянию на август 2026 года доступны три необязательных ключа. padding добавляет горизонтальный отступ в символах, значение по умолчанию — 0. refreshInterval перезапускает команду каждые N секунд в дополнение к обычным триггерам, с минимумом в 1; это нужно только в том случае, если строка отображает часы или другие данные, меняющиеся во время простоя сессии. hideVimModeIndicator подавляет встроенный текст -- INSERT --, если ваш собственный скрипт уже выводит режим vim.

Какие данные получает скрипт статус-строки?

Не доверяйте списку полей, который вы где-либо прочитали, включая эту страницу. Захватите реальный объект, который отправляет ваша версия. Напишите временный скрипт, который сохраняет 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

У вас есть точная структура для вашей сборки, и вы можете повторить это в любой момент, когда обновление что-то изменит.

Стабильные части, согласно документации на август 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.

Скрипт для статус-строки с механизмом деградации вместо сбоев

Это версия для копирования. Скрипт выводит имя хоста, текущую рабочую директорию, ветку 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 запускает команду через оболочку, поэтому скрипт без +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. Скрипт, прошедший этот тест, выдержит переименование поля, так как для вашего скрипта переименованное поле и отсутствующее поле — это одно и то же событие.

Что вы должны увидеть

Строка состояния отображается в отдельной строке над встроенными значками нижнего колонтитула и не заменяет их. В работающей конфигурации это одна строка: короткое имя хоста (cyan), затем рабочий каталог с сокращенным домашним путем до ~, далее имя ветки (yellow), если каталог является git-репозиторием, и затем имя модели (dimmed). Результат должен быть близок к web-01 ~/api main Opus, с использованием этих четырех цветов.

Строка перезапускает ваш скрипт при начале сессии (включая возобновление), при получении нового сообщения от ассистента, после завершения /compact, при изменении режима прав доступа, при переключении режима vim и по тику refreshInterval, если вы его настроили. Обновления имеют задержку (debounce) в 300 мс, поэтому серия быстрых изменений запускает скрипт только один раз. Панель скрывается во время автодополнения, отображения меню справки и запросов прав доступа, а затем возвращается.

Почему имя хоста должно быть первым

Когда вы запускаете агенты на нескольких серверах, терминал — это единственное, что указывает на ваше местоположение, но терминалы могут вводить в заблуждение. Откройте второе соединение ssh из панели tmux, и заголовок окна часто сохраняет старое имя, так как заголовок задается оболочкой, которая «не знает» о смене контекста. Оставьте Claude Code запущенным в отсоединенной сессии tmux на VPS и вернитесь к ней через день — на экране не будет ничего, что отличало бы сервер сборки от продуктового сервера.

Строка состояния отличается тем, что она отрисовывается самим Claude Code для каждой сессии на основе данных, которыми эта сессия располагает. Она не может быть унаследована от другой панели или остаться неактуальной из-за того, что приглашение оболочки не обновилось. Она всегда указывает на тот сервер, на котором агент выполняет запись файлов.

Назначьте каждому серверу свой цвет, чтобы узнавать его до того, как вы прочитаете текст. Добавьте две строки перед присвоением LINE=:

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

Затем используйте ${HOST_COLOR} вместо ${CYAN}. cksum выводит контрольную сумму имени хоста, поэтому конкретное имя всегда соответствует одному и тому же цвету в диапазоне от 31 до 36 (от красного до голубого). Скопируйте этот скрипт на каждый сервер, и каждый из них будет помечать себя автоматически.

Директория занимает свое место по той же причине. /srv/api и /srv/api-staging находятся на расстоянии одного нажатия клавиши в команде ssh, но их последствия могут привести к серьезному инциденту. Модель и ветка — это еще два параметра, заслуживающих места в строке: модель показывает, какую сессию вы возобновили, а ветка сообщает, собирается ли агент выполнить коммит в 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 не работает внутри скрипта строки состояния. Claude Code перехватывает вывод вместо подключения вашего скрипта к терминалу, поэтому функции определения ширины нечего измерять. Начиная с версии v2.1.153, Claude Code устанавливает переменные окружения COLUMNS и LINES перед выполнением команды, поэтому считывайте $COLUMNS, когда вам нужно определить объем выводимых данных.

Почему строка состояния остается пустой

Ничего не отображается. Проверьте бит исполнения с помощью ls -l ~/.claude/statusline.sh, затем запустите скрипт вручную, используя тестовые входные данные, приведенные выше. Если скрипт выводит строку в оболочке, но не в Claude Code, начните с claude --debug: эта команда записывает в лог код завершения и stderr первого запуска строки состояния в сессии.

В отладочном логе указано Status line command skipped: workspace trust not accepted. Строка состояния выполняет команду оболочки, поэтому она находится под тем же контролем доверия к рабочей области, что и хуки. Пока вы не подтвердите диалоговое окно доверия для этой директории, команда не будет запущена. Это часто случается на VPS, где каждый новый клон — это директория, которую Claude Code еще не видел. Перезапустите Claude Code в этой директории и подтвердите диалог.

Все пусто, и задано disableAllHooks. Параметр "disableAllHooks": true в settings.json также отключает строку состояния, так как он использует тот же механизм контроля выполнения команд. Удалите его или установите значение 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 делят эту строку с правой стороны, и в узком терминале происходит наложение. Делайте вывод коротким. Для точного учета использования, а не простого числа на панели, см. как Claude Code считает токены.

FAQ

Где хранятся настройки строки состояния Claude Code?

В settings.json, в виде блока statusLine, где type установлено в "command", а command содержит путь к скрипту или команду оболочки. Пользовательские настройки находятся в ~/.claude/settings.json и применяются ко всем проектам на данной машине. Настройки проекта располагаются в .claude/settings.json внутри репозитория и имеют приоритет для этой директории. Настройки обновляются автоматически, но изменения становятся видны только при следующем триггере обновления, например, при отправке следующего сообщения.

Почему строка состояния Claude Code пуста?

Почти всегда причина кроется в одном из четырех факторов. У скрипта отсутствует бит исполнения, поэтому оболочка возвращает Permission denied и в stdout ничего не попадает. Диалоговое окно доверия к рабочей области не было подтверждено, и claude --debug записывает в лог Status line command skipped: workspace trust not accepted. Параметр disableAllHooks имеет значение true, что отключает строку состояния через тот же механизм. Либо скрипт завершается с ненулевым кодом, что приводит к очистке строки. Сначала протестируйте скрипт вручную: echo '{}' | ~/.claude/statusline.sh должен выводить хоть что-то.

Включает ли JSON строки состояния ветку git?

Нет. JSON содержит состояние сессии, такое как модель, рабочие директории, показатели контекстного окна и стоимость. Никакие данные в нем не сообщают о git. Ветка в вашей строке состояния появляется благодаря вашему собственному скрипту, вызывающему git branch --show-current. Передавайте директорию из JSON с помощью git -C "$DIR", чтобы ветка всегда соответствовала директории, отображаемой в строке.

Потребляет ли строка состояния токены или замедляет сессию?

Она не потребляет токены, так как скрипт выполняется локально, а его вывод никогда не отправляется модели. Скорость зависит от вас. Команда выполняется при каждом сообщении помощника с задержкой в 300 мс, и Claude Code отменяет текущий запуск при поступлении нового обновления, поэтому скрипт, выполняющийся целую секунду, будет отображать устаревший текст. Избегайте git status в больших репозиториях и кэшируйте любые медленные операции в файле, используя session_id в качестве ключа.

Как отобразить разную строку состояния на каждом сервере?

Используйте один скрипт и позвольте ему считывать данные машины. Приведенный выше скрипт выводит $HOSTNAME с hostname -s в качестве резервного значения, поэтому один и тот же файл, скопированный на каждый сервер, будет корректно помечать каждый из них, а трюк с цветом на основе контрольной суммы придаст каждому имени хоста свой цвет. Если для одного сервера требуется другой макет, добавьте блок statusLine в настройки проекта того репозитория, с которым вы работаете на этой машине, так как настройки проекта переопределяют пользовательские настройки для данной директории.