SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-25

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

Настройте отображение hostname, пути и git-ветки в Claude Code через параметр statusLine. Это предотвратит случайные изменения на сервере при работе в нескольких SSH-сессиях.

Что отображает строка состояния 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 выполняется через оболочку (shell), поэтому это может быть путь к скрипту или обычная команда. Проверьте работоспособность связки перед написанием любого скрипта:

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

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

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

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

FAQ

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

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

Почему статуслайн Claude Code пуст?

Почти всегда причина кроется в одном из четырех факторов. У скрипта отсутствует бит исполнения, поэтому shell возвращает 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 мс (debounce), и Claude Code отменяет текущий запуск при поступлении нового обновления, поэтому скрипт, выполняющийся целую секунду, будет отображать устаревший текст. Избегайте git status в больших репозиториях и кэшируйте любые медленные операции в файле, используя session_id в качестве ключа.

Как отобразить разный статуслайн на каждом сервере?

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