Мы платили 39 000 токенов за то, чтобы поправить кнопку

Продолжение истории про то, как мы делали Cursor-агента членом команды. В прошлый раз я рассказывал, как обкладывал проект правилами, hooks и доками. Теперь — про счёт, который за это пришёл, и как мы срезали его на 64%, ничего не сломав.
Симптом
Мобильное приложение, команда из шести человек. За год проект оброс: большой каталожный раздел, оффлайн-режим, гостевой доступ, сложная форма с предзаполнением, iOS home widgets, OTA-обновления, вендорные Expo skills. И параллельно рос слой, который заставляет агентов писать код как мы: CLAUDE.md, AGENTS.md, правила Cursor, доменные документы хрупких зон, hooks.
Каждый новый кусок документации решал реальную проблему. Проблема была в том, что все они грузились всегда.
Симптомы выглядели так:
Открываешь новый чат с агентом, пишешь «поправь отступ у кнопки на карточке» — и контекст уже заполнен наполовину до твоего вопроса.
Проценты использования модели в Cursor заканчивались подозрительно быстро для объёма реально сделанной работы.
Крупные задачи проходили через несколько циклов суммаризации. А суммаризация — это когда агент забывает половину того, о чём вы с ним договорились двадцать минут назад, и вы обнаруживаете это по результату.
Контекст заканчивался посреди задачи. Не на сложной — на обычной.
Я довольно долго считал это ценой качества. Логика простая: правила работают, агент пишет в нашем стиле, hooks не дают сломать нативку — значит, толстый контекст это плата за порядок. Оказалось, нет. Оказалось, я платил за дубли.
Что мы вообще измеряли
Прежде чем резать, надо было понять, сколько весит проектный слой. Тут сразу оговорка, потому что это первое, о чём спросят.
Метод грубый: 1 токен ≈ 4 байта UTF-8. Это не замер настоящим токенизатором модели и не то, что показывает Cursor Usage. Реальный fixed prompt в IDE ещё включает каталог инструментов и MCP, историю чата и много чего служебного.
Почему так: мне нужна была не точность, а воспроизводимость на одних и тех же артефактах. Размер файла на диске — метрика, которую можно померить из консоли, сравнить до и после, и которую сможет повторить любой читатель в своём репозитории за минуту. Токенизатор дал бы более честное абсолютное число и ровно такое же относительное изменение. Меня интересовало относительное.
Мерил я ровно тот слой, которым управляю: CLAUDE.md, AGENTS.md, правила в .cursor/rules/, каталог skills. То, что добавляет сама IDE, — не моя зона ответственности, и срезать её я не могу.
Счёт «до»
Always-on пакет — то, что грузится почти в каждый чат
Файл | Байты |
|---|---|
70 287 | |
9 352 | |
| 8 632 |
| 4 831 |
| 5 452 |
| 3 354 |
Итого | 101 908 (~25 500 токенов) |
Один CLAUDE.md — 69% пакета. Семьдесят килобайт. Файл, который начинался как «короткий контекст продукта для аналитиков», за год превратился в свалку: шаблоны постановки задач, длиннющий раздел «что ломает PR», карта «где что лежит», продублированная из правил и доменных доков.
Лёгкая правка .ts или .tsx
К always-on добавляется главный кодекс проекта — app-core.mdc с glob на все TypeScript-файлы:
Байты | ~токены | |
|---|---|---|
Always-on | 101 908 | ~25 500 |
| 53 071 | ~13 300 |
Итого на лёгкой TS-задаче | 154 979 | ~38 700 |
Вот он, заголовок статьи. Тридцать девять тысяч токенов фиксированного слоя, чтобы поправить отступ. В одном файле на 417 строк лежали правила про гостевой режим, промпты главной страницы, сложную форму, каталожный раздел, оффлайн, виджеты и OTA — всё сразу, независимо от того, что вы трогаете.
Skills
Двадцать шесть записей в skills-lock.json, каталог .agents/skills/ на 1.1 МБ, 27 папок. Это вендорные Expo skills — полезная штука, справочник по EAS и Expo API. Но их описания попадают в system prompt каталогом: чем больше skills, тем длиннее «меню» на каждом ходу. Самый тяжёлый — expo-skill-eval на 148 КБ, eval-харнесс, который в продуктовой разработке не нужен вообще.
Никто не выбирал «поставить 26 skills». Поставили пакет целиком, потому что так проще.
Что я понял не сразу
Две вещи, и обе неприятные.
Первая: много документации — не всегда хорошо. Это звучит банально, пока вы не оказываетесь автором семидесяти килобайт, каждый абзац которых когда-то был написан по делу. Каждый отдельный кусок защищаем. Проблема не в содержании — в том, что всё это грузится независимо от задачи. Документация хороша, когда она приходит в нужный момент. Всегда — это не «нужный момент», это «все моменты сразу».
Вторая, и она специфична для нашего случая: автоматизация мелких задач меняет экономику контекста.Когда агент решает две крупные фичи в день, фиксированный слой в 39k амортизируется — задача всё равно длинная. Когда у вас автоматический pipeline, который закрывает десяток мелких багов в день, каждый в отдельном чате, вы платите этот фиксированный оверхед десять раз за день. Я строил автоматизацию мелких задач и не подумал, что именно она делает фиксированный слой главной статьёй расходов.
Что сделали: четыре фазы
Фаза 1. CLAUDE.md становится индексом
Идея простая: CLAUDE.md — это оглавление, а не учебник. Стек, ключевые сущности, индекс доменных доков, топ-5 hard bans, команды проверки. Всё.
Что уехало:
шаблоны постановки задач и критериев приёмки для аналитиков → в
docs/for-analysts.md, который грузится, только когда он нужен;длинный раздел «что ломает PR» → он и так продублирован в
AGENTS.md;карта «где что лежит» → дубль правил и доменных доков.
Результат: 70 287 → 16 049 байт, −77%. 409 строк → 114.
Замечу: аналитики от этого не пострадали, они получили свой отдельный файл, который читают люди, а не грузит каждая агентская сессия.
Фаза 2. Сплит главного кодекса по globs
Тот самый файл на 417 строк разрезан:
core остаётся на
**/*.{ts,tsx}— структура компонентов, импорты и алиасы, ссылка на тему, навигация, картинки, нативные баны. То, что верно для любой правки в проекте;домены вынесены в отдельные
domain-*.mdcс path-globs: гость, промпты главной, форма создания, каталог, оффлайн, виджеты, OTA, email-авторизация, фото профиля.
Теперь правило про каталожный раздел подтягивается, когда агент трогает его файлы, и не подтягивается, когда он правит кнопку в профиле.
Результат: core 53 071 → 15 328 байт, −71%. 417 строк → 255.
Сумма всех доменных domain-*.mdc — около 24 КБ, но они больше никогда не грузятся все сразу.
Отдельно завёл docs/agent-rules-map.md — человекочитаемую карту «зона → правило → доменный док». Иначе через месяц сам не вспомнишь, где что лежит.
Фаза 3. Гигиена alwaysApply и прополка skills
Прошёлся по правилам с флагом alwaysApply: true и задал каждому один вопрос: оно правда нужно в каждой задаче?
integration-docs-sync.mdc— нет. Оно про синхронизацию доков при крупной интеграции. Перевёл на globs:app.config.js,plugins/**,eas.json, env-файлы,package.json. Когда агент правит кнопку, правило про интеграции ему не нужно.expo-vendor-skills.mdc— да, оставил always, но сжал с 3 354 до 1 423 байт. Оно страхует от того, что вендорные skills потянут Expo Router и React Query, которых у нас нет. Короткое и высокоценное.theme-colors.mdcиagent-workflow.mdc— оставил без изменений, про них ниже.
Skills прополол по критерию «гарантированно не понадобится в этом проекте»: выкинул eval-харнесс, hosting, app clips, brownfield, DOM-компоненты, web-to-native, миграцию модулей, feedback-скилл.
Результат: lock 26 → 18 записей, каталог 1.1 МБ → 716 КБ (−35%), папок 27 → 19.
Фаза 4. Привычки и защита от отката
Оптимизация, которая держится на дисциплине одного человека, живёт до первого аврала. Поэтому:
docs/agent-chat-habits.md— новый чат на каждую задачу, обращение к файлам через@pathвместо пересказа, Ask вместо Agent там, где ничего не надо менять;context-sync.mdc— при смене конвенции обновляется пара: доменное правило и соответствующий доменный док, плюс карта. Иначе они разъедутся, и мы получим два источника правды — худшее, что может быть после одного слишком толстого;stop-hooks напоминают об этом: при крупной интеграции и при правке файлов из пары.
Счёт «после»
Always-on
До | После | Δ | |
|---|---|---|---|
Байты | 101 908 | 40 823 | −59.9% |
~токены | ~25 500 | ~10 200 | ≈ −15 300 на чат |
Лёгкая UI/TS-задача
До | После | Δ | |
|---|---|---|---|
Байты | 154 979 | 56 151 | −63.8% |
~токены | ~38 700 | ~14 000 | ≈ −24 700 |
До: ████████████████████████████████████████ ~39k
После:██████████████ ~14kЗадача в хрупкой зоне
Самое интересное. Задача в самой сложной зоне теперь тянет always-on + core + её domain-*.mdc = 58 286 байт, ~14 600 токенов.
То есть работа в самой сложной зоне проекта сейчас легче по контексту, чем раньше была любая правка одной строки.
Чего мы сознательно не резали
Оптимизация без этого раздела превращается в вредительство.
Hooks. Запреты на запись в нативное дерево и соседний бэкенд, stop-hook с обязательными lint и type-check. Enforce в рантайме стоит ноль токенов и работает лучше, чем три абзаца текста с просьбой. Это главный вывод предыдущей статьи, и оптимизация его только подтвердила: дешёвое качество — это гарантии среды, а не объём инструкций.
Правило про цвета — осталось always. Цвета из Figma мимо темы — самая частая ошибка, а правило короткое. Высокая ценность на байт.
Правило рабочего процесса — осталось always. Финал сдачи, «Как тестировать», вердикт по OTA. Это то, что структурирует ответ агента на каждой задаче.
Доменные доки. Никуда не делись, просто приходят по требованию, когда агент в соответствующей зоне.
Что изменилось в работе
Качество осталось прежним. PR от агентов проходят ревью так же, как проходили, hooks ловят то же, что ловили, в хрупких зонах регрессий не прибавилось — за всё время после оптимизации я ни разу не поймал момент «раньше было лучше».
А вот что изменилось заметно:
Контекст перестал заканчиваться посреди задачи. Раньше обычная правка стартовала с половиной заполненного окна, и на длинной задаче агент уходил в суммаризацию — то есть терял половину договорённостей и делал не то. Теперь окно почти пустое к моменту, когда вы задаёте вопрос, и на задачу целиком его хватает.
Проценты использования модели перестали таять. Один и тот же лимит теперь закрывает существенно больше реальной работы: на каждом ходу мы не платим за двадцать пять тысяч токенов правил, из которых к задаче относится дай бог пятая часть.
Автоматика стала дешевле в разы. Мелкие баги закрываются в отдельных чатах, десяток в день — это десяток фиксированных слоёв. Срезав 25 тысяч токенов с каждого, мы срезали их со всего pipeline.
Правила стали точнее. Это неожиданный побочный эффект сплита: раньше агент получал кодекс на 417 строк, где правила про оффлайн, лиги, виджеты и гостевой режим лежали вперемешку, — и правило, относящееся к его задаче, тонуло среди восьми чужих. Теперь он видит ровно то доменное правило, в зоне которого работает.
Почему я не ждал падения качества: оно в нашей схеме держится на трёх вещах, и ни одну я не тронул — hooks, которые физически не дают сделать неправильное; доменные доки, приходящие точно в своей зоне; точечные правила по globs. Срезаны были дубли и то, что грузилось не вовремя: вычитание шума, а не сигнала.
Строгого A/B я не ставил — не прогонял один и тот же набор задач на двух конфигурациях. Но когда экономишь две трети контекста и при этом не можешь вспомнить ни одного случая, где стало хуже, вывод достаточно очевиден.
Что забрать себе
Если у вас в репозитории есть CLAUDE.md, AGENTS.md или .cursorrules, потратьте одну минуту:
wc -c CLAUDE.md AGENTS.md .cursor/rules/*.mdcСложите то, что грузится всегда, поделите на 4 — получите порядок в токенах. Дальше три вопроса к каждому файлу:
Это нужно в каждой задаче? Если нет — globs или отдельный файл по требованию.
Это уже написано в другом месте? Дубли в трёх файлах не делают правило в три раза убедительнее, они делают контекст в три раза толще.
Это для людей или для агента? Шаблоны для аналитиков, онбординг, длинные объяснения «почему мы так решили» — для людей. Люди читают файл целиком один раз. Агент читает его каждый раз.
И главное, что я бы сказал себе год назад: правила — не единственный способ управлять агентом, и самый дорогой из них. Hooks стоят ноль токенов. Globs стоят ноль токенов, когда файл не подходит. Хорошая структура проекта стоит ноль токенов. Текст в always-on — единственное, за что вы платите на каждом ходу, поэтому там должно остаться только то, что действительно нужно всегда.
Предыдущая статья — про hooks, safe-list и Telegram-бота, который превращает задачу в Notion в готовый PR. Если соберусь с силами, следующая будет про то, как всё это выглядит в enterprise, где процесс спускают сверху.
Буду рад, если поделитесь своими цифрами до/после — интересно, у всех ли CLAUDE.md вырастает до семидесяти килобайт, или это только у меня.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.