Сторож контекста и лимитов Claude Code: statusline и хук
Разработка - Инструментарий разработчика
Файлы
ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний
Оформите подписку на компанию для решения рабочих задач
Оформить подписку и скачать решение со скидкойВы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
50.7-companion.zip: session_guard.py, settings.example.json, HANDOFF-template.md, учебные входы samples/, run_samples.py, замер measure-2026-10-08.md, READMEТем, кто ведёт длинные сессии Claude Code по проекту 1С: как скрипт читает размер контекста и лимиты, при каких порогах советует новую сессию и где его измерения кончаются. Запуски 05-08.10.2026, в том числе в настоящем клиенте; найдена и исправлена ошибка кодировки хука на Windows, замерена цена обращения при разном размере контекста.
- Строка состояния берёт
total_input_tokensи проценты лимитов из JSON Claude Code и кладёт лимиты в кеш для хука. - Хук считает контекст по последней ненулевой записи журнала основной ветки; новый запрос в это число не входит.
- Повтор совета подавляется по числовому уровню: второй уровень после второго молчит, даже если причина другая.
- Пороги 150, 250 и 400 тыс. токенов и 80% лимитов - политика скрипта, их стоит пересмотреть под свой процесс.
- На Windows хук в канале молчал из-за cp1251, а уровень уже записывался; найдено запуском в настоящем клиенте, исправление в четыре строки.
Счётчик контекста подсказывает момент для передачи задачи, а качество передачи проверяется первым ответом новой сессии.
Для кого: тем, кто ведёт длинные сессии Claude Code по проекту 1С и хочет видеть размер контекста и расход лимитов.
В длинной сессии по проекту 1С легко накопить историю, которую уже трудно пересказать: обсуждение ошибки, выгрузку модулей, результаты поиска, несколько вариантов исправления. Перед следующим запросом полезно увидеть размер входного контекста и понять, пора ли записать состояние задачи для продолжения. Я разобрала небольшой Python-скрипт session_guard.py, который показывает эти сведения в строке состояния и выдаёт совет через UserPromptSubmit.
У скрипта два режима. statusline принимает JSON от Claude Code, печатает строку и сохраняет сведения о лимитах. hook читает журнал текущей сессии, оценивает размер последнего входа основной ветки и предупреждает при переходе на более высокий уровень. Пороги заданы в токенах; отдельно учитывается доля занятого окна.
Оба режима я запустила 05.10.2026 на Windows 11, Python 3.12.10: строку состояния - на подготовленном JSON, хук - на журнале живой рабочей сессии Claude Code. 08.10.2026 хук сработал в настоящем клиенте claude -p, и этот запуск показал ошибку, которую прежние пробы скрывали: на Windows совет молчал из-за кодировки. Исправление и замер цены обращения при разном размере контекста разобраны ниже, оба результата в архиве. Имена полей сверила с документацией.
🧮 Какие величины измеряет сторож
Сначала я разделила входной контекст, лимиты подписки и денежную оценку. Их можно вывести в одной строке, но отвечают они на разные вопросы. Контекст описывает объём входа последнего обращения. Лимиты показывают использованную долю соответствующего периода. Денежное поле приходит отдельным значением и само по себе ничего не говорит о моменте исчерпания лимита.
В режиме строки состояния скрипт читает следующие поля:
Документация определяет total_input_tokens как вход последнего ответа, включая чтение и запись кеша; процент рассчитывается по входным токенам. Поля лимитов могут отсутствовать. Для подключения используются statusLine и командный хук. Эти имена сверены по справке строки состояния.
Суммировать размеры всех прошлых обращений для такой задачи бессмысленно. Тогда получилось бы накопленное потребление за историю, и после сокращения контекста показатель продолжил бы расти. В коде хука выбрана другая величина: последняя ненулевая сумма входных токенов подходящей записи журнала. Она даёт приближение к текущему размеру входа перед следующим запросом.
Проверку доли окна скрипт выполняет отдельно. Если окно известно, отношение tokens / window сравнивается с порогом. При небольшом окне эта проверка может сработать раньше порогов в абсолютных токенах. При большом окне абсолютные пороги сохраняют значение: длинную историю всё равно полезно зафиксировать в передаточной записке.
Из этого не следует конкретная стоимость ответа. В докстринге автор связывает размер истории с затратами, но в самом скрипте нет расчёта тарифа, распределения стоимости между видами токенов или сравнения двух сессий. Я использую его как индикатор состояния работы. Экономию в процентах не измеряла; цену обращения при разном размере контекста замерила отдельно, результат в разделе «Цена обращения».
🪧 Что показывает строка состояния
В режиме statusline скрипт читает один JSON из стандартного ввода. В конце он печатает одну строку, где части соединены разделителем. Размер входа округляется вниз до тысяч токенов, процент форматируется без дробной части. Если доступно денежное поле, оно выводится с двумя знаками после точки.
Основной фрагмент формирования строки выглядит так:
Здесь есть полезная разница между отсутствующим полем и нулём. Нулевой процент лимита выводится. Отсутствующий процент пропускается. Скрипт не подставляет вместо неизвестного лимита нулевое потребление, поэтому строка без 5ч не означает, что весь период свободен.
Перед выводом создаётся кеш, который понадобится второму режиму:
По умолчанию состояние хранится в пользовательском каталоге .claude/session-guard. Другой каталог задаётся переменной SESSION_GUARD_DIR. Имя кеша лимитов фиксировано: limits.json. Этот файл общий для всех сессий, использующих один каталог состояния. Размер окна в нём тоже общий, поэтому одновременная работа с разными окнами требует внимания.
В коде нет привязки кеша к session_id, модели или плану. Последняя строка состояния перезаписывает его. Если вы откроете две сессии с разными условиями, хук одной из них может получить сведения, сохранённые другой. Я бы начинала подключение с одной сессии и проверяла содержимое кеша при переходе между клиентами.
Ещё одна деталь касается процента. Запасной расчёт через dict.get применяется, когда ключа нет. Если ключ used_percentage присутствует со значением null, форматирование числа завершится исключением. Внешний обработчик скрипта подавит его, и строка останется пустой. Кеш при этом уже мог быть записан. Эту ситуацию стоит включить в локальную проверку, особенно перед первым ответом новой сессии.
🚦 Когда сторож предупреждает
Я выписала пороги прямо из функции оценки. Они отражают политику конкретного скрипта. Вы можете пересмотреть их под свои задачи после проверки, но при первом запуске лучше сохранить исходные значения и понять, какое условие срабатывает.
| Условие | Уровень | Действие в тексте совета |
|---|---|---|
| От 150 000 входных токенов | 1 | Держать HANDOFF.md в актуальном виде |
| От 250 000 входных токенов | 2 | Закончить текущую задачу и начать новую сессию |
| От 400 000 входных токенов | 3 | Начать новую сессию сейчас |
| Занято от 70% известного окна | 3 | Предупредить о приближении сжатия |
| Использовано от 80% пятичасового лимита | 2 | Отложить крупные задачи или перераспределить работу |
| Использовано от 80% недельного лимита | 2 | Сократить сессии и пересмотреть расход |
Числа в таблице взяты из констант, сравнения включают границу. На ровно 150 000 токенов первый уровень уже достигнут. Для абсолютных порогов выбирается текст самого высокого пройденного уровня. Советы по доле окна и лимитам добавляются отдельно.
Формулировки о подорожании и потере деталей в исходном совете шире измерений скрипта. Функция видит счётчики; фактическую потерю информации после сжатия она не проверяет. Я оставляю эти строки в листинге как текст исходного инструмента, а при настройке советую трактовать их как повод сохранить ход работы.
Пятичасовой или недельный лимит повышает уровень минимум до второго. Поэтому надпись «пора новую сессию» может появиться при небольшом контексте. Чтобы понять причину, смотрите остальные значения строки либо полный совет хука. Начало новой сессии само по себе не восстанавливает доступный лимит периода; скрипт такого действия не выполняет.
Оценка не учитывает время сброса лимитов. В кеше сохраняются только проценты и размер окна. Нет обратного отсчёта, вычисления оставшихся запросов или подбора модели по цене. Упоминание Sonnet/Haiku в исходном совете относится к организации работы автора; автоматического переключения модели в коде нет.
Разные причины предупреждения полезно обсуждать по-разному. При росте контекста вы готовите передачу задачи. При расходе лимита решаете, какие обращения нужны до обновления периода. Если одновременно сработали оба условия, короткая записка поможет продолжить позже без повторного чтения всего разговора.
🪝 Хук перед следующим запросом
Хук получает путь к журналу и идентификатор сессии. Затем он читает файл построчно. Повреждённые JSON-строки пропускаются, записи других типов игнорируются, боковые ветки исключаются. В расчёт попадают три поля usage.
Последняя запись с нулевой суммой не обнуляет результат: функция сохраняет предыдущую ненулевую сумму. Это важно при разборе неполного журнала. Если подходящих записей нет или файл недоступен, вернётся ноль. Такой результат означает отсутствие измерения в выбранном источнике; качество чтения журнала отдельным флагом не передаётся.
Событие запускается при отправке пользовательского запроса, поэтому хук оценивает предыдущий ответ. Будущий ввод и ещё не выполненные обращения в этом числе отсутствуют. Если вы вставляете большой текст, сторож не прогнозирует его вклад: поле prompt он не анализирует.
Документированный вход события содержит session_id и transcript_path. Для совета используются systemMessage и hookSpecificOutput.additionalContext с именем события UserPromptSubmit. Поля сверены по справке хуков.
Уровень предупреждения хранится в отдельном файле с именем сессии. Условие подавления повторов короткое:
После первого предупреждения второго уровня следующий второй уровень будет молчать. Даже если причина поменялась с размера контекста на недельный лимит. Подавление устроено по числовому уровню, без отдельной памяти для каждого условия. Снижение контекста также не сбрасывает сохранённый уровень.
Из этого следует ограничение после сжатия: если прежний максимум уже достигнут, повторное приближение к нему в той же сессии может пройти без нового совета. Строка состояния продолжит пересчитываться при вызове. Если вы рассчитываете только на хук, полезно помнить, что его молчание связано с памятью предупреждений.
Скрипт не блокирует запрос и сам ничего не выполняет: новую сессию не открывает, Git-команды не запускает. Пользователь получает сообщение, модель - дополнительный контекст с просьбой передать совет. Решение о переходе остаётся у вас.
🔌 Как подключить сторожа
Для подключения сохраните полный session_guard.py из архива в каталог tools вашего проекта. Затем добавьте настройки, сохранив уже существующие записи. Пример предполагает запуск из корня проекта и доступную команду python:
Это фрагмент для .claude/settings.json. Если рабочий каталог отличается, относительный путь может не разрешиться. Укажите путь к своему скрипту и проверьте его отдельным вызовом до подключения. Личные пути и настройки чужого проекта копировать не нужно.
Я бы проверяла подключение в два этапа. Сначала запуск из оболочки с контролируемым JSON, затем получение реальных полей от клиента. Первый этап проверяет форматирование и условия. Второй показывает, какие данные доступны в вашей сессии и где отображается сообщение.
Для PowerShell можно начать с входа, где нет измерений и нет лимитов:
Этот вызов печатает пустую строку с кодом выхода 0 и записывает кеш с пустыми лимитами. Интерфейс Claude Code он не проверяет. Для опытов задайте отдельный каталог через SESSION_GUARD_DIR, чтобы не подменить кеш рабочей сессии.
Вход с заполненными полями:
ctx 26% (260k) · 5ч 12% · нед 3% · $1.23 · → пора новую сессию
Строку и хук я проверила в самом интерфейсе 08.10.2026. Сначала на новом сеансе: после ответа под полем ввода появилась строка «ctx 5% (47k) · 5ч 7% · нед 59% · $0.08». Затем я довела контекст сеанса на дешёвой модели до 271 тыс. токенов запросом claude -p --resume и открыла тот же сеанс в claude --resume с этими настройками. Снимок экрана ниже.
Окно Claude Code 2.1.294 в панели терминала, 08.10.2026: совет хука («UserPromptSubmit says»), ответ модели и под полем ввода строка «ctx 28% (281k) · 5ч 11% · нед 60% · $0.47 · → пора новую сессию». Снимок экрана вырезан из окна без изменений.
Надпись «→ пора новую сессию» появилась на пороге из таблицы выше. Числа в кадре различаются по делу: хук считает контекст до отправки сообщения (271 тыс.), строка состояния берёт вход последнего ответа (281 тыс.). Текст совета дошёл до модели: она пересказала его в ответе, а на запросе с контекстом 208 тыс. токенов сделала то же с советом первого уровня.
Тот же вход с "used_percentage":null в context_window дал пустую строку и код 0: исключение форматирования подавлено, как описано выше.
Затем проверьте вход, сохранённый из вашей установки. Сопоставьте total_input_tokens с тем, что попало в строку. Посмотрите, появились ли проценты лимитов и как ведёт себя строка до первого ответа. Отдельно проверьте отсутствующие поля и null: именно на границе этих случаев могут проявиться ошибки форматирования.
Хук я запустила на журнале своей рабочей сессии: на вход подала JSON с session_id, transcript_path и hook_event_name. Функция чтения журнала вернула 265 926 токенов, хук напечатал совет второго уровня:
{"systemMessage": "Сторож сессии (≈265 тыс. токенов контекста): контекст больше 250 тыс. токенов: ... рекомендую закончить текущую задачу и начать новую сессию. ...", "hookSpecificOutput": {"hookEventName": "UserPromptSubmit", "additionalContext": "..."}}
В файле состояния появилась запись {"level": 2, "tokens": 265926, ...}. Повторный запуск с тем же входом не напечатал ничего: уровень 2 уже записан, и подавление повторов сработало.
Те же запуски в настоящем клиенте показали ошибку, которую оболочка скрывала. 08.10.2026 я подключила хук к claude -p и довела контекст сеанса до 208 тыс. токенов. Клиент передал хуку session_id, transcript_path, cwd, prompt_id, permission_mode, hook_event_name и prompt, число токенов по журналу совпало с суммой usage последнего ответа (2 + 39 633 + 70 = 39 705 на проверочном журнале). Совет при этом не появился, хотя в файле состояния уже стоял уровень 1.
Причина в кодировке. На Windows вывод в канал идёт в cp1251, символ «≈» из текста совета в ней отсутствует, при печати возникает исключение, и внешний обработчик его гасит. Уровень к этому моменту уже записан в файл. Дальше хук молчал бы весь сеанс. В прежних пробах в окружении стояла PYTHONIOENCODING, поэтому ошибка не проявлялась. В версию из архива добавлены строки в начале запуска:
После исправления клиент принял ответ хука: событие hook_response вернулось со статусом success и кодом 0. run_samples.py теперь не задаёт PYTHONIOENCODING: на прежней версии скрипта он показывает отсутствие вывода, на новой печатает совет.
Для хука нужен реальный transcript_path, доступный процессу Python. Если журнал не читается, число токенов станет нулевым. Если лимиты есть в кеше, они всё равно могут вызвать совет. Поэтому одно успешное уведомление ещё не подтверждает исправность чтения журнала: нужно сверить и число контекста.
Кеш считается свежим менее шести часов. На самой границе срока он уже отбрасывается. Здесь проверяется возраст записи, без обращения к сервису и без учёта момента сброса конкретного лимита. Процент, сохранённый перед обновлением периода, способен остаться в кеше до следующей строки состояния или истечения этого срока.
В докстринге исходного инструмента облачный режим описан как работа хука без строки состояния. В такой сессии лимиты плана сторожу недоступны: скрипт получает их только через кеш, который заполняет строка состояния. Хук в облачной сессии я не запускала, сведения о нём здесь взяты из описания автора инструмента. Для вашего окружения это проверяется одним запуском: нужны команда python, доступ к журналу по пути transcript_path и тестовый вызов хука с этим путём.
📝 Как передать задачу в новую сессию
При предупреждении первого уровня я бы записала состояние задачи до продолжения исследования. Для проекта 1С ценность записки определяется тем, можно ли восстановить решение без догадок. Нужны воспроизведение ошибки, подтверждённые факты и ближайшее действие.
В исходном совете фигурируют series/HANDOFF.md и series/00-bible.md. Это пути конкретного проекта. В вашей работе файл передачи может называться HANDOFF.md, а правила проекта храниться в другом документе. Сторож ничего из этого не создаёт и не проверяет наличие файлов.
Шаблон записки, адаптированный к смыслу исходного совета:
Я отделила бы в таком файле план от выполненного действия. Если вы только собирались проверить права роли, новая сессия должна увидеть это как незавершённую проверку. Формулировка «права проверены» без результата опаснее длинной истории: она переносит неверную уверенность в следующий диалог.
Для ошибки обмена полезно сохранить способ воспроизведения и обезличенный результат. Для изменения модуля нужны имя объекта и конкретное поведение, которое должно измениться. Для исследования документации запишите источник и границы сделанного вывода. Значения секретов в передаточной записке не нужны.
Предложение «закоммитить и слить» присутствует в исходном HOWTO как инструкция рабочего процесса автора. Сам Python-скрипт этих операций не выполняет. При адаптации текста совета сверяйте его с правилами вашего проекта и текущим разрешением на изменения. Порог контекста не даёт дополнительных полномочий ассистенту.
После подготовки записки откройте новую сессию и попросите прочитать её вместе с правилами проекта. Проверьте первое изложение задачи: оно должно совпасть с сохранённым состоянием. Если ассистент пропустил ограничение, исправьте понимание до следующего действия. Это проверка передачи, которую счётчик токенов заменить не может.
💸 Цена обращения
В докстринге сторожа размер истории связан с затратами, поэтому я проверила это замером. 08.10.2026 в одном сеансе claude -p --resume (модель claude-haiku-5-5) я отправляла одно и то же короткое сообщение при контексте 40, 73 и 208 тыс. токенов, а между ними добавляла большие тексты. Поле total_cost_usd в выводе клиента накопительное за сеанс, поэтому цену отдельного обращения к модели я считала как разность двух соседних значений. Сравнивала только обращения с прогретым кешем, где новая запись в кеш не превышала 70 токенов.
| Размер контекста, токенов | Цена короткого обращения | На один прочитанный токен |
|---|---|---|
| 39 633 | 0,00041 $ | 1,0·10S15;S12; $ |
| 73 436 | 0,00074 $ | 1,0·10S15;S12; $ |
| 208 320 | 0,01047 $ | 5,0·10S15;S12; $ |
| 208 360 | 0,01047 $ | 5,0·10S15;S12; $ |
До 73 тыс. токенов цена растёт пропорционально размеру контекста. На 208 тыс. каждый токен стоит в пять раз дороже. Это совпадает с границей 200 тыс. токенов и похоже на ступень цены для длинного контекста; с публичным тарифом я эти цифры не сверяла. Обращения, в которых кеш записывается заново, дороже: запись 67 тыс. токенов обошлась примерно в 0,07 $. После долгой паузы кеш остыл, и обращение, которое записало заново 246 тыс. токенов, обошлось примерно в 0,27 $: простой между запросами тоже влияет на цену. Таблица всех восьми обращений лежит в архиве, файл measure-2026-10-08.md.
Пороги сторожа, 150 и 250 тыс. токенов, лежат по разные стороны от этой границы. Совпадет ли она с тарифом вашей модели, нужно смотреть отдельно. Выводы ограничены одним сеансом, одной моделью и прогретым кешем. Процент экономии от перехода на новую сессию я не измеряла.
🧭 Ограничения
Скрипт запущен из оболочки на подготовленных входах, на журнале одной живой сессии и в настоящем клиенте claude -p. Строка состояния и совет хука показаны в окне Claude Code (рисунок выше): консольный клиент версии 2.1.294 в панели терминала. Другие клиенты и версии не проверялись. Сравнения расходов до и после перехода на новую сессию нет.
Оценка контекста зависит от структуры журнала. Читается последняя ненулевая запись основной ветки; новый запрос ещё не учтён. При недоступном файле функция возвращает ноль. После сокращения истории сохранённый максимум предупреждений не сбрасывается автоматически.
Кеш лимитов общий для каталога состояния, живёт менее шести часов и может устареть раньше. Он не содержит времени сброса, модели или идентификатора сессии. Запись файлов подавляет ошибки файловой системы; при неудаче состояние предупреждений может не сохраниться. Одновременные записи не защищены блокировкой или атомарной заменой.
Внешний обработчик подавляет большинство исключений и завершает процесс с кодом ноль. Это помогает не прервать обычную работу, но затрудняет обнаружение ошибки. Неверный режим запуска обработан иначе: выводится строка использования. Нулевой код выхода в рабочем режиме не подтверждает, что измерения успешно прочитаны.
Влияние длины контекста на качество ответа и на точность после сжатия не измеряла. Цену обращения замерила один раз на одной модели. Хук в облачных сессиях не запускала. Отсутствующие лимиты и денежные поля остаются неизвестными. Пороги из скрипта требуют оценки под ваш процесс и не гарантируют завершение задачи до исчерпания периода.
📚 Источники
- Claude Code: настройка строки состояния. Имена
statusLine,context_window,rate_limitsи денежного поля. - Claude Code: справка хуков. Вход
UserPromptSubmitи формат передачи сообщения. - Исходный
session_guard.py: функцииstatusline,context_from_transcript,assess,hook; константы порогов и срока кеша. Существенные фрагменты разобраны в тексте, полный скрипт - в архиве к статье. - Предшественники на Infostart: ИИ-агент в 1С-разработке: как не сжечь токены и получить рабочий результат (Николай Маеров, 19.06.2026); Паттерн экономии токенов в Claude Code на правке больших файлов (Sorm, 28.05.2026). Здесь разобран конкретный сторож с двумя режимами и границами его измерений.
📎 Файл к статье
В архиве к статье - 50.7-companion.zip: полный session_guard.py, образец настроек settings.example.json, шаблон HANDOFF-template.md из статьи, учебные входы для строки состояния и хука, run_samples.py для пробного запуска, вывод прогона 08.10.2026, таблица замера цены обращения и README. Сначала запустите python run_samples.py, затем подключите скрипт в своём проекте и проверьте отдельным вызовом. Текст совета адаптируйте: в нём упомянуты файлы нашего проекта.
Вступайте в нашу телеграмм-группу Инфостарт