У меня небольшой бюджет на AI-ассистент — $20 в месяц. Хватает, но только если понимаешь как работает тарификация. Я потратил время чтобы разобраться что именно ест токены, и написал framework который пытается решить эти проблемы. Расскажу про оба.
Как формируется контекст
Каждый запрос к модели стоит денег пропорционально размеру контекста — всего что модель читает перед ответом. В Cursor контекст состоит из нескольких слоёв:
Файлы которые вы явно указали через
@Файлы которые Cursor подтянул автоматически как связанные
Содержимое
.cursor/context/— если естьПравила из
.cursor/rules/— если естьПроиндексированное содержимое проекта
Последний пункт — главная проблема. По умолчанию Cursor индексирует всё в директории проекта. В Go проекте это vendor/ с зависимостями, .git/ с историей, dist/, логи. Реальный код занимает процент от этого.
.cursorignore работает как .gitignore — говорит Cursor что не трогать. После его настройки индексируется только то что нужно.
Почему Agent Mode дорогой
В Agent Mode Cursor может создавать и редактировать файлы. Но есть особенность: при каждом File Edit контекст перечитывается заново. Не один раз за задачу — а для каждого изменения отдельно.
Когда AI исправляет баг, он обычно создаёт два файла: исправленный код и тест. Это два перечитывания контекста. Нормально.
Проблема в том что AI по своей инициативе часто создаёт дополнительные файлы: описание что было сделано, чеклист, саммари изменений. Я видел как одна задача порождала 11 File Edits вместо двух. При контексте в 100K токенов это 1.1M токенов входа вместо 200K.
Есть механизм Prompt Caching — повторное чтение одного и того же контекста стоит дешевле. Но кэш работает только если контекст не меняется между запросами. Каждый новый файл меняет контекст — кэш инвалидируется, платишь полную цену снова.
Запрет на создание лишних файлов через .cursor/rules/ решает это напрямую: AI создаёт только код и тест, всё остальное запрещено правилами которые Cursor применяет автоматически.
Кеш на стороне платформы и почему он не всегда помогает
Anthropic поддерживает Prompt Caching на уровне API. Если вы отправляете одинаковый контекст в нескольких запросах подряд — повторное чтение кешированной части стоит значительно дешевле.
Но у этого кеша есть TTL — он живёт около 30 минут без обращения. Если вы ушли на кофе, отвлеклись на встречу, вернулись через час — кеш протух. Следующий запрос снова читает весь контекст по полной цене.
Это не баг, это особенность архитектуры. Практический вывод: при маленьком бюджете лучше не рассчитывать на кеш как на стабильную экономию. Лучше изначально держать контекст маленьким — тогда и цена каждого запроса меньше, и потеря кеша не так болезненна.
Потеря контекста при смене модели
Cursor Composer — stateless. У каждого разговора нет памяти о предыдущих. Когда меняешь модель — начинаешь с чистого листа.
Это важно если используешь разные модели для разных задач. Дорогая модель для анализа архитектуры, дешёвая для рутинных задач — логичная стратегия. Но если дешёвая модель не видит что делала дорогая, приходится объяснять контекст заново.
Решение через файловую структуру: дорогая модель пишет результаты анализа в файл, дешёвая читает этот файл через @. Контекст не теряется при смене модели — он хранится на диске, а не в памяти сессии.
.cursor/ ├── analysis/ │ └── project-map.md # Opus написал один раз └── plans/ └── tasks/ └── task-003.md # Haiku читает и выполняет
Проблема большого плана
Когда задач много, появляется соблазн держать весь план в одном файле и тянуть его через @ в каждый промпт.
При выполнении задачи №7 модель читает задачи 1-6 которые уже сделаны, и задачи 8-20 которые ещё не актуальны. Это лишние токены при каждом запросе.
Вторая проблема — план устаревает. Анализ написан в начале: "функция ProcessOrder, строка 47". После первых задач строки сдвинулись, что-то переименовано. Модель работает по устаревшим координатам и ошибается.
Разделение на маленькие файлы решает первое: при выполнении задачи в контексте только её файл — 15-20 строк, не весь план на 300.
Для второго — снапшоты. Но сначала стоит понять саму проблему подробнее, потому что это ключевой момент.
Opus анализирует проект и создаёт карту:
## service.go — 150 строк ### Функции: - `ProcessOrder` (~строка 47) — обрабатывает заказ - `withdrawAndDeposit` (~строка 124) — списание и пополнение
На основе этого Sonnet создаёт план. Задача task-003 выглядит так:
## Функция `withdrawAndDeposit` (~строка 124)
Выполняем задачи 001 и 002. В ходе task-001 рефакторим service.go — разбиваем большую функцию, добавляем обработку ошибок. Файл вырастает со 150 до 220 строк.
Теперь ситуация такая:
В плане написано: В реальном коде: withdrawAndDeposit withdrawAndDeposit ~строка 124 ~строка 187 ← сдвинулась на 63 строки
Когда приходит время task-003, модель идёт к строке 124, видит там что-то другое и либо ошибается, либо тратит токены на повторный поиск. Чем больше задач выполнено — тем сильнее план расходится с реальностью.
Снапшоты решают это так. После каждого git commit запускается скрипт:
# snapshot-state.sh DATE=$(date '+%Y-%m-%d %H:%M') CHANGED=$(git diff --name-only HEAD) echo "## $DATE" >> .cursor/snapshots/changes.md echo "$CHANGED" | while read f; do lines=$(wc -l < "$f") echo "- $f ($lines строк)" >> .cursor/snapshots/changes.md done
После task-001 в changes.md появляется запись:
## 2026-02-23 14:30 - src/mascot/service.go (220 строк) - src/mascot/service_test.go (45 строк)
Это просто лог. Сам по себе он ничего не делает.
Важное происходит в run-next-task.txt — перед выполнением следующей задачи промпт читает этот лог и обновляет файл только следующей задачи:
Прочитай .cursor/snapshots/changes.md. service.go изменился. Задача task-003 ссылается на этот файл. Найди актуальное расположение функции withdrawAndDeposit и обнови строку в task-003.md. Остальные задачи не трогай.
Модель открывает service.go, находит withdrawAndDeposit на строке 187, обновляет task-003.md. Задача выполняется по актуальным координатам.
Ключевое здесь — обновляется только следующая задача, не весь план. Переписывать весь план при каждом изменении было бы дорого и медленно.
Как это запускается: анализ и план
Прежде чем выполнять задачи, нужно понять что вообще делать. Framework начинается с двух шагов.
Анализ проекта. Промпт 01-analyze-project.txt запускается один раз с Opus. Он сначала выполняет bash-скрипты локально — собирает структуру проекта, количество строк, список TODO — и использует этот вывод как контекст. Потом читает сам код и создаёт файл .cursor/analysis/project-map.md:
## service.go — 150 строк | оценка 4/10 ### Функции: - `withdrawAndDeposit` (~строка 124) — списание и пополнение - `ProcessOrder` (~строка 47) — обрабатывает заказ ### Проблемы: - [КРИТИЧНО] нет DB-транзакции между GetBalance и UpdateBalance - [ВАЖНО] функция ProcessOrder больше 50 строк, сложно тестировать
Это карта проекта. Она не меняется — создаётся один раз и служит исходником для следующего шага.
Создание плана. Промпт 02-create-plan.txt запускается с Sonnet. Он читает карту и создаёт два вида файлов.
Первый — индекс optimization-plan.md, просто список ссылок:
## Очередь - [ ] task-001 — утечка горутин в retry (03-fix-simple-bug, Haiku, ~$0.03) - [ ] task-002 — валидация параметров (05-refactor, Haiku, ~$0.12) - [ ] task-003 — race condition в withdrawAndDeposit (03-fix-simple-bug, Sonnet, ~$0.15)
Второй — отдельный файл для каждой задачи в .cursor/plans/tasks/. Эти файлы и есть суть хранения контекста: каждый содержит всё что нужно для выполнения одной задачи — конкретный файл, конкретную функцию, конкретное решение. Индекс — это только ссылки на них, сами задачи живут отдельно.
Такое разделение нужно именно для контроля контекста: при выполнении задачи модель читает только её маленький файл, не весь план целиком.
Как работает run-next-task под капотом
Основной промпт framework'а run-next-task.txt — это последовательность bash команд которые Cursor выполняет сам в Agent Mode:
Шаг 1: найти задачу
grep -m 1 '^\- \[ \]' .cursor/plans/optimization-plan.md
Возвращает первую строку без ✅, из неё берётся номер задачи.
Шаг 2: прочитать файл задачи
cat .cursor/plans/tasks/task-003.md
Файл содержит проблему, путь к файлу, имя функции, конкретное решение, какой промпт использовать.
Шаг 3: прочитать сам промпт
cat .cursor/scripts/prompts/05-refactor.txt
Промпт содержит конкретные инструкции для типа задачи: что создать, что не создавать, как запустить тесты.
Шаг 4: прочитать целевой код
cat src/mascot/types.go
Шаг 5: выполнить Модель следует инструкциям из промпта, используя детали из файла задачи.
Шаг 6: зафиксировать
bash .cursor/scripts/bash/snapshot-state.sh git commit -m "feat: add input validation"
Шаг 7: закрыть задачу
mv .cursor/plans/tasks/task-003.md .cursor/plans/done/task-003.md
В индексе ставится ✅, проверяется следующая задача по changes.md.
Вся эта цепочка запускается одним промптом. Контекст при этом минимальный: файл задачи (15-20 строк) + целевой файл кода + base.md который Cursor читает автоматически.
Установка в проект
Framework распространяется как репозитарий на гитхабе. После клониования:
cd your-go-project bash /path/to/framework/setup.sh bash test-framework.sh
setup.sh копирует всю структуру .cursor/ в ваш проект, создаёт .cursorignore, копирует промпты, bash-скрипты и test-framework.sh.
test-framework.sh проверяет что всё на месте — структура папок, все промпты, скрипты, содержимое .cursorignore. Выдаёт список ✅ и ❌ по каждому пункту. Если что-то не так — сразу видно что именно.
После установки в корне проекта появляется:
your-project/ ├── .cursorignore ├── test-framework.sh ├── GUIDE.md └── .cursor/ ├── rules/optimization.mdc # правила — запрет лишних файлов ├── context/base.md # описание проекта — заполнить под себя ├── analysis/ # сюда Opus запишет карту проекта ├── plans/ │ ├── optimization-plan.md # индекс задач │ ├── tasks/ # файлы задач │ └── done/ # выполненные ├── snapshots/changes.md # лог изменений кода └── scripts/ ├── bash/ # скрипты анализа └── prompts/ # все промпты
Единственное что нужно сделать руками — заполнить .cursor/context/base.md. В архиве есть готовый пример для Go + Clean Architecture, обычно достаточно поменять название проекта и цель.
Эту проблему решают и другие
Пока я разбирался с токенами, наткнулся на Get Shit Done — framework для Claude Code который решает ту же проблему деградации контекста, но с другой стороны.
Их подход: оркестратор + subagents. Главная сессия остаётся лёгкой и только координирует. Тяжёлую работу делают subagents — каждый стартует с чистым контекстом, выполняет одну задачу, записывает результат в файл (SUMMARY.md, STATE.md) и умирает. Следующий subagent читает эти файлы и продолжает. Основная сессия никогда не деградирует.
Это та же центральная идея — контекст живёт в файлах, а не в памяти сессии. Только у GSD это автоматизировано на уровне multi-agent оркестрации, а у меня реализовано вручную через промпты в Cursor.
Где расходимся: GSD не контролирует что загружается в контекст subagent при старте. Если в проекте нет аналога .cursorignore — subagent получает раздутый контекст из vendor/ и .git/ с первого же запроса. Мой framework решает именно этот пласт: что попадает в контекст, сколько это стоит, как не платить за мусор. GSD про это не говорит вообще.
Они скорее дополняют друг друга чем конкурируют. GSD — система управления проектом. Мой framework — оптимизация затрат внутри Cursor.
Результаты на тестовом проекте
Я прогнал framework на Go сервисе около 1500 строк — несколько багов, валидация параметров, тесты, godoc.
Фаза |
Без framework |
С framework |
|---|---|---|
Анализ |
~$5 |
~$2 |
4 бага |
~$4 |
~$0.12 |
Рефакторинг |
~$3 |
~$0.15 |
3 теста |
~$2 |
~$0.54 |
Документация |
~$2 |
~$0.40 |
Итого |
~$16 |
~$3.21 |
Цифры получились ожидаемыми — каждый компонент экономит на своём. Но это один тестовый проект в контролируемых условиях. Насколько это воспроизводится на других проектах с другим кодом — непонятно.
Вопросы которые возникнут
— У Cursor есть RAG, он сам индексирует проект и находит нужные файлы. Зачем тогда вся эта структура?
RAG в Cursor действительно работает — он умеет находить релевантные файлы по семантическому сходству. Но это не то же самое что явный контроль контекста.
Во-первых, RAG решает поиск, но не решает проблему объёма. Если проект не огорожен .cursorignore, поиск идёт по всему включая vendor/ и .git/. Найденные файлы всё равно попадают в контекст и стоят токенов.
Во-вторых, RAG — это вероятностный поиск. Он находит то что семантически похоже на запрос. Файловая структура .cursor/ — это детерминированный контекст: конкретный файл задачи, конкретный промпт, конкретный целевой файл. Никакой случайности в том что попадёт в контекст.
В-третьих, RAG не решает проблему потери контекста между моделями и между сессиями. Результат анализа который Opus записал в файл — он там и лежит. RAG-индекс при смене модели начинается заново.
— В Cursor есть встроенный режим планирования. Почему не использовать его?
Встроенный режим плана в Cursor удобен для небольших задач — попросил, получил список шагов, подтвердил. Но у него есть ограничения.
Он работает в рамках одного разговора. Как только сессия закончилась или модель сменилась — план исчез. Нет персистентности между сессиями.
Кроме того, встроенный план не решает проблему устаревания. Если план создан в начале работы и задачи выполняются несколько дней — он всё равно будет указывать на старые строки и функции.
Файлы задач в .cursor/plans/tasks/ живут на диске независимо от сессий, моделей и перезапусков Cursor.
— Кеш же должен спасать, зачем тогда минимизировать контекст?
Кеш на стороне платформы живёт около 30 минут. Если не успел продолжить работу до истечения TTL — кеш протух, следующий запрос снова платный в полную цену. Маленький контекст стоит меньше и при попадании в кеш, и при промахе.
— Это работает только для Go?
Структура .cursor/ и принципы — универсальны. Bash-скрипты для анализа и промпты — написаны под Go. Для другого языка нужно адаптировать промпты и скрипты, структура остаётся той же.
— В промптах и файлах задач указаны конкретные модели — Haiku, Sonnet, Opus. Это обязательно?
Нет, это рекомендации фреймворка основанные на балансе цена/качество для типичных задач. Haiku для простых багов, Sonnet для рефакторинга, Opus для первоначального анализа — это не правила, а отправная точка.
Перед каждой задачей вы сами выбираете модель в Cursor. Если хотите перестраховаться и взять Sonnet там где стоит Haiku — никто не запрещает. Если у вас другой бюджет или другие предпочтения — слушайте себя. Модели в файлах задач просто подсказывают что авторы framework'а использовали бы в этой ситуации.
— А если у меня не Clean Architecture?
base.md — это просто описание вашего проекта. Можно описать любую структуру. Clean Architecture там как пример, не как требование.
Если у вас есть Go проект и желание проверить — буду рад обратной связи в комментариях. Особенно интересно где не работает как ожидается и насколько цифры отличаются от моих.
Комментарии (15)

Pusk1
23.02.2026 22:00Статья отличная. Для уменьшения контекста ещё помогает писать код максимально независимыми модулями сверху вниз. Прямо аля паскаль. И тогда можно открывать как проект папку с отдельным модулем, в котором только тесты и сам модуль + что - то вложенное в него. Так и дешевле и быстрее, более красиво по архитектуре.
Но есть более качественное и универсальное решение.
Я тоже долго без него мучился и изголялся. И даже Sonet при отладке выходил дороговато. А потом стал платить 60 вместо 20 и как то веселей стало работать. Особенно при проверке гипотез или дебаге. Через пару месяцев упёрся, что мне не хватает и 60. Теперь у меня корпоративный аккаут и это не совсем мои проблемы в рамках разумного, конечно.

rkazmin Автор
23.02.2026 22:00К сожалению у меня нет корпоративного аккаунта... :((. Поэтому приходитьяс оганичивать себя в опытах, экономя токены

criminalist
23.02.2026 22:00Нужен уже гибридный подход, локальная модель которая будет экономить токены, формировать нужный участок кода скармливать его уже платное, но тут опять скорость, для простых задач например прочитать файл выкусить участок кода и показать ai плат6ой, было бы не плохо

aladkoi
23.02.2026 22:00Какая то жесть написана. Стоит claude code с подпиской за "копейки" на glm модель . Нет никаких лимитов на запросы. Claude code делает все тоже, что и курсор, контекст сессии не теряется даже после ее окончания или перезагрузки компа. Есть их локальная история по проекту , с которой claude умеет работать. Правильно выбранный инструмент и его настройка снимает все проблемы.

inetstar
23.02.2026 22:00Как обходите блокировку? Через переменные среды и прокси? Говорят клод банит даже платные аккаунты.

LionMuzzle
23.02.2026 22:00Я тоже столкнулся. Жрёт токеты как не в себя. Но вы пишете не совсем правду:
Если не создавать .cursorignore, то по умолчанию будут включены в игнор лист все пути из вашего .gitignore. Вот тут написано это, и показан дополнительный обширный список того, что исключается, даже .git там указан: https://cursor.com/ru/docs/context/ignore-files#-5
Планы можно сохранять персистентно. Во-первых, они и так не удаляются, они просто лежат в домашней папке. Во-вторых, в плане можно нажать на три точки и выбрать Save to workspace, чтобы перенести его в папку проекта внутрь папки .cursor. Вот тут написано: https://cursor.com/ru/docs/get-started/quickstart#
И ещё от меня. В последнее время стал пользоваться моделью auto, и заметил на моем очень большом веб-проекте, что она ведёт себя довольно хорошо. Я сравнивал с opus и sonet. Меня этот режим сильно удивил. В бюджете аккаунта режим auto тарифицируется отдельно, и упереться в лимит у меня пока не получилось. https://cursor.com/dashboard?tab=spending
У меня:
Auto + Composer: 5%
Consumed by Auto and Composer models.
API: 47%
Consumed by other models.

dmiche
23.02.2026 22:00Авто стала чудо как хороша. С летом вообще не сравнить. Хотя ровно сегодня попал под какую-то более кондовую. Возможно тестят чего-то новое.
А вообще doc-first рулит. Начинать с документации. Поддерживать ее, чтобы не разъезжалась стало необременительно, а архитектурный документ нынче ценнее кода.

Lashadkach
23.02.2026 22:00
План за 20 мне показался скорее ознакомительным, а вот за 60 хорошо себя показывает на крупном проекте. Свежая composer 1.5 работает гораздо лучше 1.0 от курсора и теперь не особо и нужно использовать codex/opus или сильно экономить токены при условии использования всех модов.Так же заметил для себя что сформировать план, затем через ask определить корректировки и внести их снова через plan мод тоже не хило экономит токены. И в целом ask мод который отрезает возможности преждевременно создавать файлы очень полезен в целях экономии.
Во многом задача ИИ это снизить когнитивную нагрузку и повысить за счёт этого продуктивность, поэтому писать скрипты для инструмента ИИ вообще считаю оверхедом, даже для оптимизации токенов. Уж лучше использовать бесплатные модели в браузере, скармливая им модули проекта.
Ну и заголовок статьи байтит, а прямого и структурированного ответа на вопрос "что с этим можно сделать?" в статье не нашёл, хотя очень хотелось :D

serjeant
23.02.2026 22:00Есть ещё вот такая удобная штука:
https://github.com/vanzan01/cursor-memory-bank
а к ней в связку платный плагин https://supercode.sh/ru. Правда после обновления курсора он перестал у меня работать и поддержка не отвечает...
iafilin
Могу ошибаться, но если ввести правило, чтобы модель думала и рассуждала на английском, а планы и ответы давала на русском, то вероятно это тоже своего рода оптимизация расходов, ведь токены для кириллицы дороже, чем для латиницы.
rkazmin Автор
Интересная гипотеза. Я поинтересовался ИИ, он подтверждает что
В рамках нового исследования Cursor-Probe я хочу посмотреть, влияет ли формат промпта (XML против обычного текста) на качество кода у слабых моделей. Я хочу проверить, станет ли Haiku реже ошибаться в логике, если загнать её в жесткие рамки структуры, или же это никак не поможет её "интеллекту".
В рамках Cursor-Probe я проверю разницу между кириллицей и латиницей как побочный фактор..
AlexanderMatveev
Текстовый запрос на русском это капля в море, он сразу переводится на английский, модель "думает" на английском и переводит текстовый ответ на русский, чтобы показать вам