Ботинок и карандаш https://bootandpencil.com bootandpencil.com Fri, 26 Sep 2025 13:27:03 +0000 ru-RU hourly 1 https://wordpress.org/?v=6.8.3 https://bootandpencil.com/wp-content/uploads/2021/10/cropped-logo_icon-3-1-32x32.png Ботинок и карандаш https://bootandpencil.com 32 32 Немного о вайбкодинге https://bootandpencil.com/lifestyle/vibecoding/ Thu, 25 Sep 2025 12:08:43 +0000 https://bootandpencil.com/?p=51320 Читать далее]]> Выскажусь по теме, которая некоторое время назад была хайповой, пока она, вроде бы, совсем не протухла.

DISCLAIMER: в этой области сейчас всё очень быстро меняется, поэтому высока вероятность, что этот текст устареет сразу после публикации (если не до).

Для читателей, совсем далёких от мира информационных технологий, коротко поясню: вайбкодинг — это когда программирует не программист, а нейросеть.

Идея в том, чтобы взять какой-нибудь Codex / Claude Code / Qwen Code / Cline / Roo / Augment / Gemini CLI / Cursor / Windsurf / Trae / Aider (их очень много сейчас всяких-разных) и сказать ему что-то вроде «дорогая ГПТ-шка, напиши мне второй фейсбук, который сделает меня богатым, но только без багов», а та как возьмёт, да как напишет…

Напишет что-то.

И я даже затрудняюсь определиться, какое из этих слов выделить: да, это будет «что-то» (скорее всего, не то, не так и не тогда), с другой стороны, оно всё-таки будет.

Оказывается, правильно создавать технический долг тоже нужно учиться 🙁

Set and setting

Для тех, кто пришёл сюда из поисковика, скажу, что я не IT-специалист, я психолог, поэтому включайте скептицизм на максимум.

Ну, и минутка рекламы, как же без этого: покупайте наших слонов (ну, то есть психологические сессии).

Тестировал я всё нижеперечисленное на нескольких небольших проектах (в основном в духе «тут дёрнем одну API-шку, там — другую»), самый крупный из которых на момент написания имеет порядка 30 тысяч строк кода.

Как оно на кодовых базах с миллионами строк — без понятия, поскольку не имел удовольствия попробовать.

Язык — Python, из которого я упорно пытаюсь сделать что-то статически типизированное, навешивая все линтеры / тайп-чекеры, до которых могу дотянуться (вот такое извращение, почему не взять сразу что-то статически типизированное — я не отвечу, ибо «так сложилось исторически» ©).

Кто / что?

Я пробовал разные инструменты и по итогу в качестве основной рабочей лошадки выбрал Claude Code.

Почему?

Во-первых, тарифная политика: за 100 USD ты получаешь не самого плохого агента в режиме «сколько-то сообщений каждые 5 часов».

На практике это означает, что где-то часа полтора — два можно активно вайбкодить, потом нужно ждать ещё часа три.

Во-вторых, Claude Code действительно неплохо умеет дёргать разного рода внешние инструменты: MCP-серверы (см. ниже), утилиты командной строки, кастомные скрипты и прочее подобное.

В-третьих, как бы ни ругали в августе — сентябре Sonnet 4 (это основная рабочая LLM в Claude Code), на мой взгляд, она всё ещё неплоха.

Поскольку основной практический опыт у меня именно с Claude Code (Sonnet 4), писать буду про него.

При этом могу сказать, что концептуально остальные не сильно отличаются, а вот в конкретных деталях другие агенты могут быть радикально иными. Но я постараюсь объяснять сами принципы и закономерности, не сильно привязываясь к деталям реализации.

Чем я ещё пользуюсь?

Google Gemini CLI — для множественных быстрых, но не слишком заковыристых правок.

Нужно поправить кучу тестов после рефакторинга? Это сюда. Требуется поменять интерфейсы, но лениво юзать sed? Вполне подойдёт.

Осознал, что надо бы поменять зависимость в криво спроектированном коде? Норм задача.

В интернетах часто говорят, что Gemini невообразимо прекрасен на сложных задачах. В режиме LLM для Zen MCP (см. далее) версия 2.5-pro мне и правда очень зашла.

А вот в режиме гугловского агента (собственно, Gemini CLI) — не особенно: не слушается, инструментами пользуется криво, контекст хоть и большой, но расплывается.

OpenAI Codex — для планирования и сложных задач (наряду с режимом планирования и моделью Opus 4.1 в Claude Code).

Умная, часто видит косяки, которых не замечает Sonnet 4 (дефолтная LLM в Claude Code), но хуже UX/UI, а также использование инструментов (ниже постараюсь объяснить, чего я к этим инструментам так прицепился).

How much is the fish?

На момент написания статьи вся это радость съедает ежемесячно:

1. Claude Code (Max 5x) — 100 USD.
2. ChatGPT Plus — 20 USD.
3. Google Workspace на двух пользователей — 28 USD.

Итого — 148 USD (или 12 400 RUR, или 400 GEL — по курсу на момент написания).

Жируют психолухи, да.

Вайбкодинг [не]работает. До некоторой степени

Насколько хорошим получается код? Скажем так, он однозначно лучше, чем мой.

Хорош ли он? На мой вкус, не очень.

Что конкретно с ним не так? Сложно объяснить, но в основном это — эклектичность. Причём у меня не получилось от неё избавиться никакими средствами ни на каком сочетании агента и модели.

Вроде всё под один стандарт, но в одном месте передаётся параметр, а в другом — словарь с параметрами, в третьем — кортеж, а в четвёртом — вообще датакласс — и всё это для (по сути своей) одной операции — передачи настроек.

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

Оптимистичный взгляд на явление


Разумеется, сколько-нибудь вменяемого разработчика агент с LLM-кой в заднице не заменит: кожаный программист sed’ом и awk’ом редактирует быстрее самых быстрых моделей, пишет единообразно, не смешивает подходы и… сто́ит намного дороже.

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

Подвох, разумеется, есть — в словах «правильно выстроенный процесс».

Garbage in — garbage out

Тут мы подходим к основному вопросу: можно ли, совсем нифига не понимая в разработке, что-то написать чистым вайбкодингом?

Всё так, Карпатый не даст соврать

К сожалению, для меня ответ оказался отрицательным: какие-то, хотя бы даже самые базовые познания на уровне «отличаю компилятор от переменной» (лисперы гусары, молчать!), всё же потребуются.

Поэтому я даже не знаю, для кого предназначен этот текст: кто знает, тот и так знает, а новичку он всё равно ничего не даст, кроме иллюзии понимания.

В контексте вайбкодинга нейросеть (не люблю термин ИИ) целесообразно рассаматривать как преобразователь текстов: на вход вы подаёте один набор текстов (ваш запрос, уже написанный код и так далее), на выходе получаете другой (например, несколько *.py-файлов).

И качество выходного текста напрямую зависит не только от модели, но и от того, что было подано на вход (собственно, отсюда и подзаголовок), то есть от контекста.

Контекст важен

Что в данном случае входит в понятие контекста?

Много чего: ваш промпт (что конкретно вы запрашиваете), история диалога (о чём вы говорили с агентом), структура папок проекта, имена файлов, комментарии в коде, сам код, имена переменных и функций и так далее.

В вайбкодинге, как бы странно это ни прозвучало, очень важны строгость, придирчивость и перфекционизм.

Ни в коем случае нельзя допускать, чтобы агент отходил от принятых в вашей среде / стеке технологий лучших практик: одна маленькая «оплошность» (например, Any в сигнатуре метода) может настроить агента на генерацию гораздо худшего кода, чем он на самом деле способен.

Грубо говоря, он постоянно смотрит на уже имеющийся код и, если видит там несовершенства, «понимает, что тут такое прокатывает» (на самом деле, конечно, нифига он не понимает, а просто праймится на повышение вероятностей продуцирования чего-то похожего на то, что подано на вход, но как метафора — вполне пойдёт).

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

Поэтому с самого начала нужно озаботиться тем, чтобы всё было правильно: организация в файловой системе, документация, тесты, CI/CD, codestyle и прочее.

Если у вас есть существующая кодовая база и вы хотите её «до-вайбкодить», не делайте этого, пожалуйста, одумайтесь! приведите её в порядок перед тем, как запускать туда агента а там, глядишь, и вайбкодить перехочется.

Мне нравится идея о том, что LLM (большая языковая модель) — это множитель: если в кодовой базе баги и косяки, их станет больше, если идеальный код — то всё не так плохо.

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

До некоторой степени этому можно противостоять, и первым шагом является выбор правильной архитектуры разрабатываемого приложения.

Гексагональная архитектура

Мне больше всего понравилось вайбкодить в парадигме гексагональной архитектуры.

Да, она избыточна, многословна, усложняет многое без необходимости, но, с другой стороны, концептуально проста (вот реально — для дураков сделано) и дисциплинирует, а именно эти качества крайне важны для агента.

В интернете полно материалов о том, что это такое, и почему оно неприменимо к реальной жизни но опишу кратко основную идею для тех, кому лениво гуглить: это такой способ написания программы, где мы стараемся очень чётко разграничивать, что мы делаем и как мы это делаем (ооооочень упрощённо, конечно же).

В теории это позволяет потом, когда понадобится (YAGNI такой: «ну да, пошёл я на хер») поменять это самое «как», сохранив неизменным «что».

Вообще, такое можно достичь многими способами, но эта самая гексагональная архитектура, во-первых, известна (а значит можно писать более короткие промпты), во-вторых, распространена в обучающих нейросеть данных (а значит, велика вероятность, что LLM осилит), в-третьих, стандартизирована и, главное, буквально заставляет агента писать чуть более вменяемо, чем если предоставить ему полную свободу.

Почему так происходит? Потому что автоматические проверки на соблюдение целостности слоёв просто банят совсем уж плохой код (см. далее).

Это очень ригидная структура, в которой шаг влево-вправо является нарушением, и часто нарушением, которое легко поймать автоматически.

Она не очень-то допускает разные способы сделать что-либо, поэтому мы можем до некоторой степени рассчитывать на то, что, если агент её не нарушил, то и код там хоть немного похож на что-то разумное (просто потому, что в противном случае, скорее всего, мы бы поймали нарушение).

Итак, за основу берём гексагональную архитектуру (просто за неимением лучшего для данного применения) и некоторый набор «хороших практик».

Теперь нужно как-то сообщить об этом агенту.

CLAUDE.md

Способов сделать это существует достаточно много — рассматриваемый здесь файл CLAUDE.md, флаг —append-system-prompt, output styles, включение нужной информации непосредственно в [каждый] промпт, наконец.

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

У меня в практике прижился именно файл CLAUDE.md в корне проекта. Кстати, в подпапках могут быть свои файлы CLAUDE.md, они все «суммируются».

Рекомендуется делать этот файл структурированным и достаточно коротким, но у меня фактически прижился совсем другой — 63 пункта правил, 15 000 символов размером.

Правила созданы, чтобы их нарушать (c) Claude Code

Знаю, что это неправильно, но другие испробованные мной варианты сильно хуже. Следует ли Claude всем этим правилам на практике? Конечно же, нет.

Наивно было бы думать, что можно вот так просто сказать: «Claude, пиши хорошо», — и он всё сделает.

Зачем же тогда отъедать столько контекста? Чтобы получалось пнуть Claude легко и достаточно надёжно в сторону того, что делать, а что нет.

Пишешь ему, что, например, моки у нас запрещены, и он такой: «Точно, это нарушение пункта #9 Claude.md» (и некоторое время на самом деле не использует моки, а без такого файла — использует).

Сам по себе мой CLAUDE.md откровенно плох, но он и не создан, чтобы работать в отрыве от остальных инструментов, в сочетании с которыми он может полностью проявить свою полезность.

Claude строит из себя послушного исполнителя

В ходе экспериментов я однажды просто попросил Claude в каждом ответе повторять все положения Claude.md (заодно прописал такую инструкцию в самом файле), и это сработало: он почти всё это выполнял, но контекст и токены заканчивались очень быстро, поэтому пришлось от этой практики отказаться.

После я сколько-то (довольно много) раз попытался исправить / написать другой / скачать готовый CLAUDE.md, но всё всегда заканчивалось одинаково: либо он разрастался до размеров текущего, либо же работал даже хуже, чем этот, что заставило меня пересмотреть подход: вместо того, чтобы пытаться уговорить Claude писа́ть, как мне нужно, — попытаться принудить его к этому.

Но промпты как таковые (включая автоматически добавляемые из CLAUDE.md) не очень хороши в качестве средств принуждения, тут нужны дополнительные инструменты.

TODO

Одним из таких инструментов, встроенных в Claude Code, является мой любимый список TODO. Он до некоторой степени решает проблему ограниченности размера контекстного окна — не полностью, не всегда, но всё же.

7.1 Ограниченность контекстного окна и его переполнение

Здесь, к сожалению, нам придётся прервать линейное повествование и ненадолго отойти в сторону, чтобы поговорить о переполнении контекстного окна.

Любая LLM имеет ограниченние на объём контекста, который она способна воспринимать (от 64K токенов у старых моделей до 2M у лидеров по этому показателю).

Токен в данном случае — это (очень упрощённо и неправильно) символ или несколько символов (зависит от настроек и вида токенайзера). Например, слово «например» может быть представлено разным количеством токенов — от 1 до 8.

Но для простоты в грубых прикидках можно считать, что токен равен символу (не придирайтесь, я же говорю, что это очень грубая прикидка).

Так вот, модель может воспринимать не более N символов (то есть токенов) одновременно. Эта величина называется «ёмкостью контекстного окна» (или — для краткости — просто «контекстным окном»).

Почему это так важно? Потому что LLM, как мы помним, работает в режиме «подали текст на вход — получили текст на выходе».

Никаких возможностей ведения связного диалога, когда собеседники помнят, о чём было сказано ранее, здесь не предусмотрено: выходной текст зависит только от входного (но не от сказанного ранее).

Но человеки привыкли не так: им гораздо удобнее ссылаться на ранее сказанное и вести связные диалоги. Как же быть?

Инженеры не стали сильно заморачиваться и решили проблему просто: на вход LLM каждый раз подаётся весь диалог с самого начала — реплики пользователя, ответы LLM, копипаста (если была таковая), — вся история пихается на вход модели.

Одни опрашивали, а другие измеряли

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

Что делать?

И правда, что же делать? Есть несколько вариантов.

Во-первых, можно просто принудительно завершать диалог при достижении лимита контекстного окна. Точнее, даже немного заранее. Тут всё просто: проблемы нет, поскольку мы никогда не столкнёмся с «тотальной забывчивостью относительно предыдущих реплик» со стороны модели.

Но на практике это не очень удобно: если проблема большая, приходится каждый раз посвящать модель в курс дела заново;

Во-вторых, можно сделать окно скользящим: допустим, у нас есть контекстное окно на 100 реплик (да, оно не в репликах измеряется, но для простоты давайте примем, что там столько токенов, сколько соотвтествует ста репликам).

Когда реплик становится 101, на вход подаются реплики со второй по стопервую, а первая «забывается».

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

В-третьих, при достижении лимита можно кратко пересказать содержание предыдущей беседы и подать на вход этот пересказ вместе с новыми репликами. Именно этот способ и используется в Claude Code (и много где ещё).

Наконец-то добираемся до TODO

Так вот, получается, что раз в некоторое (нужно сказать, достаточно небольшое, особенно если общаться с Claude по-русски) время всё сказанное заменяется на некоторый пересказ.

Этот процесс называется сжатием контекста. И, разумеется, при таком сжатии очень часто теряется важная информация: пересказ далеко не всегда фокусируется на том, что действительно нужно было бы сохранить.

В частности, Claude может забывать, какую задачу он решает, какие-то правила, корректировки, которые вы ему дали и так далее.

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

Есть два ответа: правильный и мой.

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

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

Вот так это выглядит:

To do, or not to do, that is the question!

Соответственно, вы можете попросить Claude создать очень детальное TODO, в котором будут содержаться не только шаги, но и все нужные для их прохождения данные, и он это сделает. Таким образом, самое важное переживёт даже множественное сжатие контекста.

Режим планирования

При создании TODO для задачи в Claude Code целесообразно использовать т.н. режим плнирования, предварительно выбрав «Opus plan mode» в меню, вызываемом командой /model:

Opus, не magnum

Что это означает: у Anthropic («производителя» Claude Code) есть несколько серий моделей, из которых самые «умные» и «продвинутые» входят в серию «Opus». И вот этот самый «Opus» будет использоваться в режиме планирования.

У читателя наверняка возникнут вопросы:
Что за режим планирования?
А почему бы не использовать этот Opus всегда, раз он такой клёвый?

Начну с последнего, ответ там банальный: слишком быстро заканчиваются токены, выделенные по тарифу. На стобаксовом тарифе это буквально три — пять коротких диалогов.

А вот с режимом планирования всё немного интереснее: в этом режиме агент не может ничего менять. То есть вероятность того, что Claude напишет откровенную фигню вам в кодовую базу, в этом режиме равна нулю — поскольку он жёстко read-only.

Это позволяет спокойно обсудить с моделью дальнейшие действия, не опасаясь, что какие-то изменения будут внесены (если вы разрешили Claude редактировать ваши файлы без запроса, чтобы не отвлекаться постоянно на «можно ли отредактировать файлик?»).

Вторая фишка режима планирования — это то, что в результате его работы, как ни странно, создаётся план: модель старается хоть немного «сначала подумать, а потом уже делать» (чего ей порой сильно не хватает в обычном режиме).

Никто до этого не говорил мне, что я так умён и во всём прав. Люблю Claude!

Дальше можно попросить Claude создать очень детальный TODO с сохранением всех деталей, имен файлов и сведений о том, что и где поменять, чтобы они не потерялись при сжатии контекста.

И вот уже агент следует одобренному вами плану. Поздравляю, вы восхитительны!

Заклинание Ultrathink

Эта фишка работает только в Claude Code. Можно к любому промпту добавить слово «Ultrathink», и модель выделит максимально возможное количество токенов на рассуждения.

А чем больше токенов выделено на рассуждения, тем тщательнее модель «думает» прежде, чем ответить.

Опять о своих бабах думает?!

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

А вообще, Ultrathink — не единственное доступное заклинание:

"think": 4,000 tokens
"megathink": 10,000 tokens
"ultrathink": maximum budget

Я всегда использую Ultrathink, мне его cc-sessions (см. далее) установил на все беседы, я и доволен.

Хуки

Итак, у нас есть файл CLAUDE.md, который инструктирует Claude по основным вопросам мироздания, TODO-список, в котором хранится самое важное и которому не страшны сжатия контекста, а также режим «сначала думай, потом делай» (через Plan Mode + Ultrathink).

Ну, теперь-то Claude будет писать нормально? Правда?

Разумеется, нет.

Дело в том, что ничто в этом мире не заставляет (пока что) Claude следовать плану и предписаниям. Не, он, конечно, тренирован на это, но на практике далеко не всегда делает так.

И, что самое неприятное, у него нет механизмов самоконтроля. Если вы его отправили писать парсер, а он отвлёкся и решил отрефакторить модель данных, он будет делать это.

Хуже того: если он, например, правит ошибку с наследованием, он может напихать в код исправления кучу Any (что уже считается у меня ошибкой, ибо плохо обрабатывается анализаторами типов).

В результате нередко оказывается, что, исправляя одну проблему, Claude создаёт ещё десяток.

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

Собственно, именно поэтому генеративный код и не любят.

И сколько ни проси Claude так не делать, он выдаст своё коронное «You’re absolutely right!» и продолжит хренорезить.

Решение? Проверять написанное им немедленно после написания.

То есть нужна какая-то штука, которая будет запускать проверку (ну, или что угодно ещё) сразу после того, как Claude что-то написал.

Это и есть хук.

Хук — это такая фиговина, которая отслеживает определённые события (например, Claude прочитал файл или Claude пометил задачу как решённую), запуская некоторый скрипт / программу / команду, как только целевое событие произойдёт.

Самый главный хук: «А не херню ли я только что написал?»

У меня установлено несколько разных хуков на разные события. Самый важный из них срабатывает на событие «после записи в файл».

Работает он так: проверяет, редактирует ли Claude тот же файл, что и раньше. Если да, то не превысило ли число правок заданный лимит (10) и не запускалась ли проверка слишком давно. Если да, запускается проверка файла, который Claude редактирует.

Если нет (то есть Claude переключился на другой файл), то проверки запускаются на оба файла: старый, чтобы не получилось так, что Claude накосячил и бросил, и новый, чтобы убедиться, что в нём не совсем фигня написана.

Выглядит это всё примерно так:

Пойман с поличным

Здесь как раз Claude переключился с одного файла на другой, и сейчас хук сообщает ему, что он накосячил в обоих 🙂

Именно этот хук позволил мне продвигаться в вайбкодинге до стадий, до которых иными средствами я добраться не мог.

Самый назойливый хук: «Редактируй правильно! Пиши правильно».

Этот хук гораздо проще. Он запускается каждый раз, когда Claude что-то записывает, и талдычит ему одно и то же: не пытаться скрыть проблемы (он это любит), использовать символический редактор Serena MCP (см. далее) для редактирования, чтобы экономить токены, не использовать Any и моки, а также не допускать недо-/оверинжиниринга.

Вот так это выглядит:

Ну, выброси, наконец, уже ёлку!

Здесь как раз видно, что Claude не использовал символический редактор, хук ему напомнил, и Claude принял поправку, пообещав дальше использовать Serena, когда закончит текущую серию правок (спойлер: обещание сдержал).

Остальные хуки: DAIC, «проверь себя» и «не говори гоп, пока не прыгнешь».

Есть у меня ещё несколько хуков, коротко расскажу о каждом.

Во-первых, это хуки, относящиеся к запуску DAIC-проверки от cc-sessions. Об этой системе будет рассказано ниже, тут просто упомяну, что она тоже через хуки работает.

Во-вторых, хук, срабатывающий на событие «Claude пометил одну из задач в TODO как завершённую».

Он напоминает Claude, что, собственно, делать это нужно после проверки, решена ли задача, а не до и не вместо (как любит Claude), заставляя агента таки посмотреть, а действительно ли он решил проблему (спойлер: с первого раза, как правило, нет).

В-третьих, хук, который автоматически запускается, когда Claude заканчивает некоторую итерацию и ожидает действий пользователя (то есть совсем в конце работы над каким-то куском).

Он просто запускает процесс проверки кодовой базы и, если найдены какие-то проблемы, сообщает об этом Claude (а тот уже решает, что с этим делать).

Делай, что я сказал! cc-sessions

Хуки прекрасны и решают многие проблемы с агентом, однако они достаточно бесполезны, если агент делает не то, что от него требуется (пусть даже самым лучшим образом).

Для того, чтобы такого не было, я использую cc-sessions.

Вообще говоря, существует довольно много менеджеров сессий (1, 2, 3, 4, 5, 6) для Claude Code, каждый из которых обещает супер-удобство и почти идеальный код на выходе.

Но cc-sessions выделяется уже на этапе маркетинга, честно предупреждая, что результат будет всратым. Чуть менее всратым, чем без, но всё же.

Когда реклама не врёт

И в данном случае маркетинг не обманывает: система действительно заставляет Claude писать чуть менее всрато — просто за счёт того, что не даёт ему растекаться мыслею по древу.

Она буквально висит на основных хуках и заставляет Claude сосредотачиваться только на том, о чём его попросил пользователь.

А ещё она переключает режим дискуссии (когда Claude не может ничего редактировать) и режим имплементации (когда Claude может записывать файлы).

Таким образом, процесс работы с агентом структурируется:

1. В режиме дискуссии планируем, обсуждаем, исследуем, согласовываем задачу.

2. В режиме имплементации — реализовываем ровно то, о чём договорились (не больше и не меньше).

3. Повторяем, пока не достигнем цели (или пока не надоест).

Когда DAIC держит тебя за… за что там надо держать Клода, он ведь нейросеть?!

Звучит очень просто, но избавляет от кучи проблем вида «я отвлёкся на звонок, а Claude натворил фигни». При этом агент вполне остаётся агентным в рамках согласованной задачи и не требует обращать на него внимание по каждой мелочи.

В результате процесс становится более предсказуемым и управляемым, и при минимальной положительной вменяемости пользователя это делает код чуть менее плохим.

Линтеры: проверки и перепроверки

А как мы, собственно, определяем, хороший у нас код или плохой? Нет, понятно, что он нагенерённый, а значит, по определению отстойный, но вот как понять, насколько именно?

Ответ на этот вопрос однозначен: автоматически и воспроизводимо. Идея в том, чтобы у Claude была возможность посмотреть, в чём именно и где он накосячил.

Отчасти это решается хуками (см. выше), но основные проверки происходят перед коммитом и пушем.

На данный момент используются следующие категории проверок (тут будет длинный список, уберу под спойлер), но простое перечисление оставлю тут: mypy, pylint, pyright, sonar, semgrep, radon, coderabbit.

Развёрнутый список проверок

1. Форматирование кода.

Black: автоматическое форматирование кода.
Ruff: комплексный линтер с автоисправлениями (импорты, например, пофиксить).
trailing-whitespace, end-of-file-fixer: обрабатывают лишние / недостающие пробелы и пустые строки.

2. Проверка типов (да, я знаю про Typescript!)

MyPy: классический инструмент статической проверки типов, со —strict режимом.
Pyright: дополнительная проверка типов, более придирчивый инструмент.
No Any Types: кастомный скрипт, следящий, чтобы не было Any.

3. Общее качество кода

Pylint: комплексный анализ качества (максимально 30 операторов, 7 аргументов у функций, не больше 10 веток в условиях).
Function Length Check: отдельный кастомный скрипт, реализующий ограничение на длину функций — до 30 строк.
Module Size Check: тоже кастомный скрипт, который проверяет длину модулей: почти все модули ≤400 строк, инфраструктурные модули ≤600 строк.
Vulture: отслеживает мёртвый код (который не используется).
SonarCloud: инкрементальный и полный анализ проекта, 6500 разных проверок, по заверениям производителя.
Coderabbit: ещё одна проверялка широкого профиля с подсказками для LLM-агента.

4. Безопасность

Bandit: сканирование уязвимостей безопасности.
detect-secrets: поиск секретов с baseline файлом.
Semgrep: семантический анализ с кастомными правилами.

5. Архитектурные ограничения: формальная проверка корректности архитектуры

Import Linter: проверка архитектурных границ между слоями (например, убеждается, что доменные модули не импотрируют инфраструктуру).
No shared.logging (через semgrep): запрет прямого использования логгеров вне адаптера (Claude очень любит нарушать этот запрет, поэтому отдельная проверка).
No aiofiles in upper layers (тоже через semgrep): инкапсуляция операций ввода-вывода в инфраструктурном слое.
BaseHttpApiAdapter enforcement (и снова через semgrep): обязательное наследование для HTTP адаптеров.

6. Проверка сложности кода

Radon Complexity: цикломатическая сложность ≤10 (grade B).
Maintainability Index: отслеживание индекса сопровождаемости — кастомный скрипт, который следит, чтобы она сильно не падала.
Pragma No Cover Discipline: контроль исключений проверок (чтобы не было слишком широких).

7. Проверка на запрещённые паттерны:

No Mocks (CLAUDE.md #9): запрет unittest.mock, pytest_mock.
No Stdlib Logging (CLAUDE.md #54): только structlog через LoggingPort.
No httpx in adapters: инкапсуляция HTTP транспорта.
No direct sanitizer usage: использование SecretSanitizationPort.

[свернуть]

В совокупности эти инструменты позволяют получать довольно интересный эмерджентный эффект.

Эмерджентность: 1+1=3

Прости меня, читатель, за столь пошлый подзаголовок, я действительно не смог придумать ничего лучшего.

О чём сказать-то хотел: большинство проверок носят сугубо формальный характер: проверяется количество строк, порядок импортов, наличие / остутствие определённых последовательностей строк.

И Claude пытается соответствовать этим сугубо формальным требованиям (ну, то есть писать соответствующий им код).

А вот дальше начинается интересное: в процессе этих попыток он снижает избыточность, повышает переиспользование, применяет паттерны и лучшие практики (хотя напрямую его никто к этому не принуждает).

То есть мы выставляем «количественные» требования, а получаем «качественные» улучшения (ну, относительно того, что было бы без, конечно же, не нужно думать, что там всё суперкруто).

Когда б вы знали, из какого сора… (c)

Мне нравится наблюдать за этим: правила буквально в тиски зажимают Claude и заставляют код принимать более-менее приемлемую форму.

MCP

Наверняка читатель уже догадался о том, что код, написанный Claude, проходит все эти извращённые проверки далеко не с первого раза.

А это означает, что попыток предпринимается множество. Что в свою очередь ведёт к достаточно сильному расходу токенов.

И вот тут в дело вступает она — Serena.

Serena — это один из многочисленных MCP-серверов. А MCP — это model context protocol: технология, позволяющая LLM-агенту использовать какие-то инструменты.

Этих самых MCP-серверов существует великое множество (1, 2, 3): некоторые из них очень полезны, другие — нишевые штуки, третьи — откровенный шлак, который делает хуже.

Serena, по мнению многих (и я с ними согласен), безусловно относится к первой категории.

Serena MCP

Зачем нужна Serena? Для экономии токенов. В норме Claude, чтобы отредактировать файл, нужно прочесть его содержимое (или его часть, если известно заранее, в каких примерно строках находится искомое).

Serena же позволяет избежать этого: редактура производится не на уровне «найди, где в файле находится функция foo, в ней пятую строку замени на другую», а на уровне «поменяй функцию foo».

Разница в том, что в первом случае Claude должен знать содержимое файла (а значит — потратить токены на его «узнавание»), а во втором — просто имя функции / класса / переменной.

Экономия получается весьма существенной: при использовании Serena стобаксового тарифа мне хватает примерно на несколько часов, как было сказано выше, а без неё — токены заканчиваются минут через 40.

Экономим на MCP: mcp-funnel и meta-mcp

Serena позволяет экономить токены. Но она же, как и всякий MCP-сервер, их тратит.

Проблема в том, что MCP-инструмент должен как-то сообщить агенту о своём существовании и о том, как именно им, этим инструментом, пользоваться.

Для этого MCP-инструмент снабжается описанием, которое автоматически добавляется в контекстное окно при подключении инструмента. То есть какое-то количество токенов будет тратиться просто по факту подключения mcp-сервера.

Вот пример не самого большого описания реального инструмента:

Больше контекстное окно — больше мусора поместится!

Как видите, это некоторое количество текста.

Кто-то скажет, что фигня, но на реддите довольно часто народ отписывается, что mcp-серверы съедают у них чуть ли не половину контекстного окна (это очень много).

Особенно досадно, если большое описание имеет инструмент, который вы (точнее ваш Claude-агент) в рабочем процессе не используете.

Для решения этой проблемы я использую два инструмента: mcp-funnel и meta-mcp.

Оба они являются агрегаторами MCP-серверов: в Claude прописываются они, а уже к ним подключаются реальные MCP-серверы.

При этом агент видит инструменты подключенных серверов так, словно сами серверы подключены к нему непосредственно.

Но основная фишка не в этом, а в том, что оба они, и mcp-funnel, и meta-mcp, позволяют отключать ненужные инструменты. У первого это делается через правку конфига, у второго через тыкание кнопочек в WebUI:

К-Н-О-П-О-Ч-К-И!!!1111

То есть можно оставить только то, что реально используется:

Двенадцать избранных, все совпадения случайны

Почему два инструмента? Так исторически сложилось: Meta-MCP у меня обслуживает докеризированные серверы (у меня и на хосте, и в докере создан один путь — /usr/local/dev-projects/, и в контейнерах примонтирована как раз хостовая папка, поэтому пути работают и доступ к файлам из докера — есть), а mcp-funnel — то, что запускается локально.

Не могу сказать, что они оба — строгая необходимость, но пока у меня организовано так, чуть позже приведу в порядок, оставив только один из них (не решил ещё, какой именно).

Ну, а дальше, раз уж мы заговорили об MCP-серверах, расскажу ещё о двух, которыми реально пользуюсь хотя бы иногда.

И оба они, как ни странно, по большому счёту служат одной цели: подрядить в помощь Claude другие LLM.

Эффект эхо-камеры, и как с ним бороться

Почему вообще возникает желание добавить к Claude другую LLM? Потому, что все они (LLM-ки) порой не в состоянии «правильно подумать» и «посмотреть на проблему с нужной стороны».

И Sonnet 4, основная «рабочая лошадка» Claude Code на момент написания этого текста, совсем не является исключением.

Будучи оставленной наедине с собой, она иногда впадает в цикл, в котором фиксит одну проблему, порождает этим другие, затем фиксит их, возвращая первую и добавляя ещё сколько-то — и так по кругу.

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

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

Собственно, это и есть борьба с эффектом эхо-камеры, когда мы не даём модели множить собственные ошибки, заставляя сверяться её с иными мнениями.

Точнее, «не даём» здесь не совсем уместно, правильнее сказать «несколько препятствуем этому», поскольку ситуации, когда даже несколько разных моделей (Sonnet, o3, Grok-3, Gemini-2.5-pro) пропускали один и тот же важный аспект, я видел.

Но всё же они относительно редки.

Zen MCP

И первая штука, позволяющая удобно выстраивать взаимодействие между несколькими моделями, о которой хочется сказать, это Zen MCP.

У него достаточно много инструментов: дебаггер, код-ревью, планировщик и много чего ещё (это некий промпт-гайдинг Sonnet + подключение внешней модели).

Он поддерживает несколько провайдеров — Google, OpenAI, Openrouter, xAI, один кастомный провайдер — и очень много моделей.

Среди множества инструментов отмечу три, которыми сам пользовался довольно часто:

1. Challenge: это когда модель (внешняя, например, Grok) «проверяет на прочность» утверждение пользователя или агента. Если вас вконец задолбало соглашательство Claude, используйте этот инструмент.

2. Chat: тут всё просто — Claude обращается к внешней модели за консультацией. Модель можно указать, а можно отдать выбор самому Claude — как вам удобнее.

3. Consensus: здесь Claude обращается сразу к нескольким внешним моделям, стараясь получить некоторое решение, с которым согласятся все.

Опять же, можно указать, какие модели это будут, можно даже указать их позицию (например, LLaMa-4 — за, Qwen — нейтральный, а Kimi — против). Но можно и не указывать, отдав решение самому Claude.

Разумеется, всё это не бесплатно: для того, чтобы внешние модели работали, необходимо предоставить соответствующие API-ключи, а вызовы будут тарифицироваться по расценкам провайдеров.

Но если сильно всем этим не злоупотреблять, то бюджет достаточно легко ограничивается несколькими десятками долларов в месяц.

gemini-cli MCP

Этот MCP интересен тем, что Google сейчас достаточно агрессивно продвигает свою Gemini, и это приводит к тому, что тарифы на неё бывают достаточно приятными (включая бесплатный).

У меня есть Google Workspace (для других целей), и туда входит некоторое количество использования Gemini Pro.

Обходится мне это в 14 USD на человека в месяц, а лимита по Gemini хватает либо на несколько часов интенсивного вайбкодинга в сутки, либо на практически неограниченное количество консультаций для Claude (вот реально ни разу не упёрся тут в лимиты).

Собственно, этот MCP является банальной обёрткой над CLI-утилитой gemini, и можно полностью обходиться без него, вызывая CLI-программу gemini напрямую (или приказывая Claude вызвать её), но если ваш рабочий процесс предполагает интенсивное использование MCP, то есть и такая форма.

Возможности примерно те же: задать вопрос, показать файл и так далее.

English, motherfucker! Do you speak it?

Говоря об экономии токенов, нельзя не отметить тот факт, что их расход зависит от того, на каком языке идёт общение.

И здесь английский оказывается более выгодным выбором.

Во-первых, там в среднем слова и фразы короче, чем в русском (а мы помним, что чем больше букв/символов, тем больше токенов).

Во-вторых, в ряде случаев количество токенов, которое тратится на один символ, для английского ниже, чем для русского.

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

В более спокойное время я разговариваю с ним на рунглише в целях экономии. Он понимает.

Разницы именно в качестве рассуждений и решений на этих двух языках я не заметил.

Интеграционные тесты на реальных данных

Под конец напишу ещё об одной штуке, которая мне кажется важной для хоть немного успешного вайбкодинга.

Ни в коем случае нельзя позволять модели писать юнит-тесты с моками.

Во-первых, они получаются у неё очень хрупкими и на каждое минимальное изменение кода ломаются.

Во-вторых, модель просто мокает всё, и тесты теряют смысл: она фактически пишет отдельную логику и моками / патчами меняет тестируемый код. Тесты зелёные, но проверяется примерно ничего.

Поэтому я предпочитаю максимально использовать тестирование с реальными данными и реальными вызовами внешних API.

А когда это невозможно — вместо моков использую фейковые реализации нужных интерфейсов с предсказуемым поведением. При необходимости поднимаю минимальный ASGI-сервер с нужными эндпоинтами.

Да, это несколько сложнее (в том числе и для модели), но окупается тем, что код оказывается реально протестированным.

А теперь — все вместе, дружно позовём Дедушку Мороза

Понимаю, что такое сумбурное изложение вряд ли способствует целостному восприятию всей картины, поэтому попробую ещё раз кратко описать, как вся эта фигня взаимодействует.

Итак, представим себе, что мы решили повайбкодить. Запускаем Claude Code, создаём задачу в cc-sessions.

Затем пишем, чего хотим сделать, включаем режим планирования с мощной моделью Opus. При необходимости корректируем план.

Если непонятно, что делать, используем Zen MCP и/или gemini-cli MCP для того, чтобы опросить другие модели: возможно, они придумают что-то интересное.

Если не помогло, открываем codex на нашей кодовой базе и консультируемся с ним.

В общем, так или иначе, правдами или неправдами — приходим к плану, который нас устраивает.

Дальше просим Claude создать очень детальное TODO, которое сохранит все нужные технические подробности при сжатии контекста.

После этого Claude попросит разрешить ему перейти в режим имплементации (за это отвечает cc-sessions). Разрешаем.

Claude пишет код, хук сразу же проверяет его на самые распространённые ошибки и, если они обнаруживаются, требуют от Claude их исправить.

Такие же проверки запускаются, когда Claude помечает задачу как выполненную.

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

Затем Claude переключается в режим дискуссии, который не даёт ему вносить нежелательные изменения.

Когда Claude закончит, просим его сделать commit и push. Эти операции запускают свои, более строгие и полные, проверки.

Скорее всего, с первого раза они не пройдут. Просим Claude составить TODO на решение. По запросу разрешаем перейти в режим имплементации.

При необходимости делаем ревью в Sonar Cloud.

Claude пишет фиксы, хуки проверяют, не наделал ли Claude новых ошибок, заставляя его сразу же добиваться приемлемого (хотя бы по формальным критериям) качества нового кода.

Повторяем (возможно, несколько раз с такими же циклами исправлений) попытку сделать commit и push. Добиваемся прохождения соответствующих проверок.

Помечаем задачу как выполненную в cc-sessions и переходим к следующей.

Вот такой нехитрый рабочий процесс позволяет получать из Claude хоть чуть -чуть юзабельный код.

И нафига весь этот геморрой?

Конечно, если ты умный и быстрый, вероятно, ты напишешь всё руками быстрее и качественнее. Это круто, но, к сожалению, не все так могут.

Всё же, по моим оценкам, Claude пишет и быстрее, и лучше, чем я.

С другой стороны, справедливым будет вопрос о том, почему не, например, Codex?

Ответ простой: codex при таком интенсивном использовании дороже.

Но дело не только в этом: на длинных сложных правках codex всё же работает хуже, чем Claude, обвешанный хуками и MCP-шками.

А построить такую же систему для Codex у меня не получилось (на момент написания текста там ещё не было хуков).

Возможно, имеет смысл попробовать прикрутить к приложению Claude Code нейросеть от OpenAI и протестировать этот гибрид, но я так ещё не пробовал.

Поэтому, каким бы плохим ни был этот процесс (и его результат), лучших опций для себя я пока всё равно не вижу.

Кто-то скажет, что я так и не научусь программировать, и я даже соглашусь.

Очень грустная картинка

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

И да, этот пайплайн рассчитан на генерацию стрёмного скучного тривиального коммерческого кода. Что-то продвинутое на нём не напишешь.

Но бо́льшая часть программистов именно такое и пишут. И ничего, живут как-то.

Файлы

Не думаю, что оно кому-то потребуется, но к таким постам принято прикладывать ссылку на гитхаб с настройками и скриптами, и в данном случае я предпочту не нарушать традицию.

Каждая кухарка способна деплоить в продакшн!

Доводить это до тиражируемого продукта мне лениво (это просто копия с рабочего репозитория), поэтому, весьма вероятно, у вас оно не сработает без допиливания, но основные принципы я описал, и если они вам близки, не сложно доработать недостающее тем же самым Claude.

————

P.s.: ни одна GPT-шка в процессе написания этого текста не пострадала 🙂

]]>
Шопоголизм, беспорядочные связи и другие способы стать умнее https://bootandpencil.com/notes/%d1%88%d0%be%d0%bf%d0%be%d0%b3%d0%be%d0%bb%d0%b8%d0%b7%d0%bc-%d0%b1%d0%b5%d1%81%d0%bf%d0%be%d1%80%d1%8f%d0%b4%d0%be%d1%87%d0%bd%d1%8b%d0%b5-%d1%81%d0%b2%d1%8f%d0%b7%d0%b8-%d0%b8-%d0%b4%d1%80%d1%83%d0%b3%d0%b8%d0%b5-%d1%81%d0%bf%d0%be%d1%81%d0%be%d0%b1%d1%8b-%d1%81%d1%82%d0%b0%d1%82%d1%8c-%d1%83%d0%bc%d0%bd%d0%b5%d0%b5/ Mon, 20 Jan 2025 22:55:04 +0000 https://bootandpencil.com/?p=51285 Читать далее]]> Некоторые люди (их довольно много) мечтают о «когнитивных бустерах» — волшебных таблетках, упражнениях, практиках и прочих штуках, которые могли бы помочь «стать умнее». 

Но почему-то в списке фантазий достаточно редко упоминается вещь, которая с наибольшей вероятностью (если речь не идёт о каких-либо заболеваниях) может дать целевой эффект: о снижении общей фрустрации и степени самоподавления. 

Возможно, дело в том, что построить эффективную систему воплощения этих взаимоисключающих (на первый взгляд) концепций в реальной жизни гораздо сложнее, чем принять препарат или потратить несколько часов (а то и меньше) на тренировки. 

Но далеко не всегда для получения ощутимого результата требуется решить эту задачу во всей полноте.

Часто простое устранение нескольких факторов, вызывающих фоновую фрустрацию, раздражение или необходимость чрезмерно контролировать поведение, неожиданно даёт ощутимый результат. 

Нередко решение проблем в одной сфере (например, в межличностных отношениях) может дать существенный прирост эффективности в другой (например, в работе). 

Другой характерный пример — разрешение вялотекущего конфликта с родственниками может положительно сказаться на способности высыпаться по ночам, а она приведёт повышению способности усваивать новый материал в учебной деятельности. 

Таким образом, иногда бывает целесообразным сначала каким-то образом снизить общий уровень недовольства (и / или повысить уровень удовлетворённости), а уже после этого браться за решение более сложных задач. 

В этом смысле действия, традиционно оцениваемые как деструктивные, — пищевые срывы, эпизоды «шопоголизма» или спонтанной агрессии, беспорядочные связи или рискованное поведение, — могут приводить к полезным результатам. 

Можно даже сформулировать некоторое эвристическое правило: если нечто в значительной степени снижает фрустрацию и / или повышает удовлетворённость, оно полезно. 

Загвоздка лишь в том, чтобы корректно определить, обладает ли оно этими качествами на самом деле.

]]>
Нас грызут, — а мы крепчаем (нет) https://bootandpencil.com/notes/%d0%bd%d0%b0%d1%81-%d0%b3%d1%80%d1%8b%d0%b7%d1%83%d1%82-%d0%b0-%d0%bc%d1%8b-%d0%ba%d1%80%d0%b5%d0%bf%d1%87%d0%b0%d0%b5%d0%bc-%d0%bd%d0%b5%d1%82/ Mon, 06 Jan 2025 21:24:13 +0000 https://bootandpencil.com/?p=51271 Читать далее]]> Корректно оказанная помощь — помогает: делает лучше, чем было бы без неё. Или, с другой стороны, без корректной деятельной помощи часто бывает хуже, чем с ней.

Однако почему-то это простое утверждение довольно часто вызывает у некоторых людей очень выраженную негативную реакцию.

«Вот у меня троюродного племянника до сорока лет содержали, а он так за ум и не взялся, пока мать не умерла»

Здесь упор делается на то, что пока герою повествования помогали, он был «плох», а потом стал «хорош», и именно потому, что помогать перестали.

Такие «жизненные истории», призванные продемонстрировать бесполезность (а то и вред) деятельной помощи, достаточно распространены.

Часто они идут ещё и в комплекте с рассказами о том, что некоторая жёсткость, суровость или даже жестокость по отношению к субъекту — приводят к его, субъекта, «улучшению» (и в терминах эффективности, и в контексте этических качеств).

Удобное мировоззрение.

Жаль, что неверное.

Чудес не бывает.

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


И его более успешная социальная адаптация после смерти матери произошла не благодаря тому, что халява закончилась, а благодаря снижению нагрузки.

Те же самые люди могут, например, осудить дальнюю знакомую, которая «ленилась», пока «её содержал богатый папик», и которая «исправилась» после расставания с ним.

Однако при проговаривании полного контекста «внезапно» (нет) обнаруживается, что этот же самый благодетель нефигово так её абьюзил.

Можно с уверенностью утверждать, что прогресс (порой достаточно значительный) в самостоятельности, компетентности и работоспособности, на который так любят ссылаться в подобных рассказах, обычно обусловлен именно прекращением / снижением нагрузки, которую этот самый «спонсор» содержал.

Положительный эффект имеет не снижение уровня заботы, а устранение (или уменьшение количества) насилия. Впрочем, второе нередко пытаются выдать за первое.

Но если нам кажется, что где-то помощь сделала хуже, значит это была не помощь, и мы просто не знаем какой-то стрёмной изнанки.

И наоборот, если кому-то после прекращения предоставления ресурсов стало лучше, значит ресурсы предоставлялись на таких условиях, что ну бы его на фиг.

И улучшение вызвано тем, что эти условия перестали выполняться (а не тем, что ништяки перестали поступать).

Давайте делать более корректную атрибуцию.

——

Продвинутый читатель спросит: а как же инвалидизация (не путать с инвалидацией), инфантилизация и прочее подобное?

А никак.

Если речь идёт именно о помощи (а не о насилии, которое за неё пытаются выдать), то проблем с инфантилизацией не будет.

Как отличить одно от другого?

В общем случае — непонятно, но есть не самая плохая эвристика: ни принятие, ни отказ от помощи не грозит негативными последствиями в форме прямых воздействий предлагающего её.

То есть если некто боится принять помощь (или отказаться от неё), считая, что предлагающий обидится / сломается / растревожится / разозлится, скорее всего, предлагается не помощь, а что-то иное под её видом (и не факт даже, что «предлагается», а не, например, «навязывается»).

Как и всякая эвристика, оценка на основе ощущений того, кому предложили помощь, не является абсолютно надёжной: контрпримеры подобрать довольно легко, но всё же она лучше, чем полное отсутствие способов различения «корректной» и «некорректной» помощи (которая и не помощь-то вовсе).

И, как и всякая эвристика, она может быть полезна, только если желающие ей воспользоваться будут «включать голову» при её применении.

Да и вообще, как бы ни хотелось сторонникам вульгарного волюнтаризма, проблемы с «инфантилизацией за счёт слишком благоприятных условий» встречаются нечасто (если вообще встречаются).

И если уж что-то и можно назвать «фактором инфантилизации», то как раз сам вульгарный / наивный волюнтаризм: слепая вера в то, что «надо просто взять и сделать, и всё будет» вместо анализа контекста и выявления закономерностей с последующей адаптацией к ним и преобразованием контекста — штука, которую, будь она обнаружена в ком-то другом, сами эти сторонники, вероятно, клеймили бы «инфантильностью» и «несерьёзностью».

]]>
Ненависть к себе и ощущение собственной недостаточности https://bootandpencil.com/notes/%d0%bd%d0%b5%d0%bd%d0%b0%d0%b2%d0%b8%d1%81%d1%82%d1%8c-%d0%ba-%d1%81%d0%b5%d0%b1%d0%b5-%d0%b8-%d0%be%d1%89%d1%83%d1%89%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d0%be%d0%b1%d1%81%d1%82%d0%b2%d0%b5%d0%bd%d0%bd%d0%be%d0%b9-%d0%bd%d0%b5%d0%b4%d0%be%d1%81%d1%82%d0%b0%d1%82%d0%be%d1%87%d0%bd%d0%be%d1%81%d1%82%d0%b8/ Sat, 04 Jan 2025 20:08:28 +0000 https://bootandpencil.com/?p=51266 Читать далее]]> Ненависть к себе и ощущение собственной недостаточности — достаточно сложные феномены. Частично они могут быть редуцированы с использованием рационализаций в духе КПТ: 

«я не буду себя корить за то, что провалил дедлайн, ведь это заставит меня тревожиться и грустить, а я в этом состоянии работаю хуже».

Но, увы, лишь частично. 

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

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

Они устраняются сразу (или почти сразу) после того, как вообще появились.

Остальное же так просто не убирается.

К сожалению, это один из тех часто встречающихся в терапии случаев, когда проблема и её решение лежат в совершенно отличных друг от друга контекстах: первое — это некое ощущение, отношение и оценка (собственно, ненависть к себе), второе — имеет иную природу.

Несмотря на то, что идея «как-то, — например, волевым решением, — изменить оценку себя и отношение к себе» может даже показаться логичной, такой подход обречён на провал в средне- и долгосрочной перспективе (наивный волюнтаризм вообще не очень-то работает).

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

Есть только одно средство борьбы с указанными явлениями, обладающее приемлемой эффективностью: проживание опыта успешного достижения поставленных эмоционально значимых целей. 

Причём важны все аспекты:

1. Если цель не является эмоционально значимой, способ работать не будет. Многим, наверное, знаком такой сценарий диалога:

— Я ничего не могу, у меня ничего не получается, я ничтожество. 
— Ну как ничего?! Вон, смотри, ты самостоятельно посрал, а ещё в детстве шнурки завязывать научился, да и мне ноешь без посторонней помощи.

Если вы были в такой ситуации на стороне обратившегося за поддержкой, вероятно, вы представляете насколько фрустрирующим, раздражающим и далёким от того, что возможно было бы воспринять как помощь, является подобный опыт.

А всё почему? Потому, что туда, где требуется достижение именно значимой (для самого обратившегося) цели, КПТ-шник некто пытается засунуть иную, незначимую, тривиально достижимую на текущем уровне функционирования субъекта.

Да ещё и утверждает, что это не он бессердечная сволочь, а у жалующегося на проблемы когнитивные искажения 🙂

2. Если цель не является поставленной, то есть нечто сделано, но сделано случайно, как побочный результат других процессов, то опереться на такой опыт не получится: он не даст возможности атрибутировать успех к себе и своим свойствам («мне просто повезло», «оно случайно вышло» и тому подобные возражения), а значит — не сможет стать основанием для пересмотра оценок субъектом самого себя.

3. Если цель просто не была достигнута, то вообще не имеет смысла рассматривать данный опыт как нечто, способное внести прямой вклад в отказ человека от того, чтобы себя ненавидеть. Более того, достижение цели должно быть реальным, без «злых джиннов» и «фарисейских трюков» в духе «ты же всегда хотела заниматься боевыми искусствами, вот теперь муж тебя бьёт, твоё желание сбылось».

4. Наконец, если цель была поставлена, наделена эмоциональной значимостью, была успешно достигнута (и ничто из связанного с ней не было обесценено в процессе), однако всё это произошло в мире фантазий, описываемый здесь способ работать не будет.

Опыт, обладающий целевыми характеристиками, требуется не представить, не нафантазировать, не нагаллюцинировать, а именно актуально пережить: на таких уровнях напряжения, при которых можно говорить о том, что человек себя ненавидит, различные «письма обидчику», «практики мысленного перепроживания» и «символические отыгрывания» уже не работают.

Паранойя не даёт поверить в происходящее, и правильно делает: фантазии и моделирование — прекрасные штуки, которые можно даже использовать, чтобы способствовать возникновению и проживанию целевого опыта, но ими невозможно его заменить.

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

То есть всё довольно грустно: для того, чтобы перестать себя ненавидеть и считать себя «недостаточным», — на самом деле перестать, а не просто научиться хорошо делать вид, что этого нет, — нужно получить нечто, как правило недоступное тому, у кого такие проблемы вообще могут возникнуть (ведь если бы оно было доступно, проблема бы не просуществовала достаточно долго).

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

В этом смысле действительно работающие подходы, к сожалению противоречат мейнстримному психологическому нарративу: если человеку не нравится что-то, наиболее терапевтически полезным будет перестать испытывать на себе влияние этой штуки (а не «принять» и «смириться»). 

Если же он переживает фрустрацию, наиболее эффективным будет удовлетворение соответствующих потребностей. 

Увы, это не всегда возможно, но стремиться целесообразно именно к таким интервенциям.

]]>
Обманчивая очевидность https://bootandpencil.com/notes/%d0%be%d0%b1%d0%bc%d0%b0%d0%bd%d1%87%d0%b8%d0%b2%d0%b0%d1%8f-%d0%be%d1%87%d0%b5%d0%b2%d0%b8%d0%b4%d0%bd%d0%be%d1%81%d1%82%d1%8c/ Fri, 03 Jan 2025 12:20:00 +0000 https://bootandpencil.com/?p=51255 Наиболее «интересные» с терапевтической точки зрения убеждения, идеи, модели, концепции и эмоциональные реакции находятся там, где, как нам кажется, «всё очевидно» и «думать не о чем».

«Очевидно, что родителей нужно любить». 

«Очевидно, что мужчина должен зарабатывать». 

«Очевидно, что брак — это союз мужчины и женщины». 

«Очевидно, что необходимо выполнять распоряжения руководства и действовать в интересах бизнеса». 

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

Но если субъект считает некий тезис, имеющий для него достаточно высокое эмоциональное значение, самоочевидным, то фокус его внимания, скорее всего, не концентрируется на этом убеждении. 

Свет разума не проникает в тёмные подвалы, скрытые за «очевидностью». Психика не вычищает их от устаревших и неверных представлений, суждений и ассоциаций. 

Вот и оказывается, что в целом весьма разумный человек может придерживаться воззрений, не соответствующих действительности. А достаточно этичный в других отношениях субъект — призывать к причинению страданий.

В «очевидностях» часто прячутся реликты прошлых времён (детства и юности, например), унаследованные из семьи происхождения установки и прочие мешающие эффективному функционированию психики штуки. 

Поэтому если где-то в терапии возникает слово «очевидно», целесообразно остановиться в рассуждениях и рассмотреть текущий контекст ооооочень внимательно.

]]>
Смерть Эго как возможная альтернатива суициду https://bootandpencil.com/notes/%d1%81%d0%bc%d0%b5%d1%80%d1%82%d1%8c-%d1%8d%d0%b3%d0%be-%d0%ba%d0%b0%d0%ba-%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%b0%d1%8f-%d0%b0%d0%bb%d1%8c%d1%82%d0%b5%d1%80%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%b0-%d1%81%d1%83%d0%b8%d1%86%d0%b8%d0%b4%d1%83/ Tue, 31 Dec 2024 11:47:00 +0000 https://bootandpencil.com/?p=51251 Читать далее]]> При анализе суицидального поведения может быть полезно задаться вопросом о том, кого именно человек хочет убить.

Казалось бы, ответ очевиден: себя, просто по определению.

Однако не всё так просто. И дело не в том, что это может быть случаем перенаправленной агрессии, когда из страха, этических соображений, эмпатии или по каким-то иным причинам — осознавая это или нет — субъект подменяет цель, ставя на место объекта своей агрессии самого себя.

В этой заметке речь о другом аспекте: какую именно конструкцию — ментальную или физическую — хотелось бы уничтожить.

Дело в том, что нередко при ближайшем рассмотрении оказывается, что человек жаждет не физического разрушения собственного тела, не тотального небытия, а «всего лишь» смерти Эго.

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

Неопределимое в полной мере, это явление ассоциировано с такими феноменами, как субъективное переживание физической смерти (без собственно физической смерти), ощущение «тотальной потери себя», достаточно сильная дезориентация и дезорганизация, выход за пределы принятой человеком аксиоматики (этической, метафизической и прочих форм и видов).

Смерть Эго также имеет непосредственное отношение к таким процессам, как изменение, развитие и — если не бояться пафосных формулировок — перерождение.

С какой-то точки зрения смерть Эго может выглядеть как «событие меньшего масштаба» по сравнению с физической смертью, но так бывает далеко не всегда.

Случается, что человек не способен посмотреть на это таким образом, и физическая смерть воспринимается им как явление, тождественное смерти Эго (и наоборот).

В таких ситуациях идея придирчивого, скрупулёзного анализа корректности выбранного для убийства объекта может быть достаточно продуктивна: если некто хочет испытать смерть Эго, то не обязательно добиваться этого физическим самоубийством, существует немалое количество альтернативных способов.

Пережить смерть Эго можно в состояниях изменённого сознания, при существенных эмоциональных потрясениях, в результате выполнения разного рода ментальных упражнений («практик»), через погружение в острый психоз.

Да, некоторые из этих способов могут показаться по меньшей мере экстравагантными, но обычно всё же они менее инвазивны, чем прямые попытки суицида.

Написанное выше покрывает лишь небольшую часть возможных ситуаций и не должно использоваться как руководство к действию, однако в некоторых случаях работы с людьми, имеющими высокий уровень суицидального риска, данный подход может быть полезен (при правильном и аккуратном применении).

Фишка его в том, что он разрешает суицидальные стремления не путём использования какой-то формы подавления — и связанных с ним «теневых» побочных эффектов, — а через прямое уточнение и достаточно полное удовлетворение имеющегося запроса.

Если пытаться подвести итог, можно остановиться на следующей формулировке: «Суицидальность часто ассоциируют со страхом изменений, говоря о желании убить себя как о способе их избежать, однако в некоторых случаях она может представлять ровно противоположное — выраженную, но неосознаваемую волю к тому, чтобы поменять себя и/или контекст достаточно существенно».

]]>
Телеологическое мышление https://bootandpencil.com/notes/%d1%82%d0%b5%d0%bb%d0%b5%d0%be%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%be%d0%b5-%d0%bc%d1%8b%d1%88%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5/ Thu, 26 Dec 2024 10:53:00 +0000 https://bootandpencil.com/?p=51249 Читать далее]]> ​Говоря об эмоциональной и социальной зрелости как о чём-то желательном (особенно в контексте психотерапии), люди противопоставляют её инфантильности. 

Разграничение этих явления проводят с помощью таких понятий, как «ответственность», «эгоцентризм», «импульсивность» или «эмпатия». 

Однако каждое из этих качеств (и их произвольные комбинации) в значительной степени выраженности могут быть присущи как «зрелым», так и «инфантильным» людям.

Более точным классификатором может выступить склонность к телеологическому мышлению — убеждение, согласно которому, всё в мире происходит для какой-то цели, —  или его отсутствие.

Понятие «цели» неявно включается в себя контексты субъектности и агентности, поэтому обычно в быту люди, склонные к этому самому типу мышления, достаточно быстро переходят к прямому антропоцентризму: «всегда есть кто-то, для кого происходят те или иные процессы, существуют феномены и так далее». 

Ребёнок может воздержаться от табакокурения потому, что мама будет ругать. Зрелый  человек сделает то же самое из соображений сохранения здоровья, экономии или эстетических представлений (если сделает, конечно). 

Достаточно надёжным критерием высокого уровня «зрелости» личности является способность рассуждать не в категориях вида «кому-то это понравится и они накажут / вознаградят», а с использованием описания объективных физических и социальных процессов и закономерностей, а также вызываемых ими последствий. 

Способность принять решение, не проецируя на кого-то (родителя, партнёра и так далее) функцию конечной инстанции, раздающей наказания и поощрения, а исходя из прогнозируемых последствий — фундаментальное отличие эмоционально зрелой личности.

]]>
Здоровое поведение в нездоровых обстоятельствах https://bootandpencil.com/notes/%d0%b7%d0%b4%d0%be%d1%80%d0%be%d0%b2%d0%be%d0%b5-%d0%bf%d0%be%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-%d0%bd%d0%b5%d0%b7%d0%b4%d0%be%d1%80%d0%be%d0%b2%d1%8b%d1%85-%d0%be%d0%b1%d1%81%d1%82%d0%be%d1%8f%d1%82%d0%b5%d0%bb%d1%8c%d1%81%d1%82%d0%b2%d0%b0%d1%85/ Wed, 25 Dec 2024 10:43:00 +0000 https://bootandpencil.com/?p=51247 ​Вести себя здоровым образом в нездоровых обстоятельствах — нездоровая реакция. 

Если контекст, в котором формировался ребёнок, не был «нормальным» (что бы это ни значило), то некоторая его девиантность / необычность — максимально «нормальное» (в хорошем смысле этого слова) развитие событий. 

Дети, — а точнее — выросшие из них взрослые, — сохранившие видимость «нормальности» в травмирующих условиях, обычно имеют бо́льшую степень травмированности, чем те, кто дезадаптировался явным образом. 

«Почему нельзя просто жить нормальную жизнь обычного человека?». 

Честный ответ: потому, что без подготовки и некоторой перенастройки психики она вас разрушит. 

Да, это относится далеко не ко всем, но те, к кому оно не относится, обычно не задаются подобными вопросами.

]]>
Ставки повышаются https://bootandpencil.com/notes/%d1%81%d1%82%d0%b0%d0%b2%d0%ba%d0%b8-%d0%bf%d0%be%d0%b2%d1%8b%d1%88%d0%b0%d1%8e%d1%82%d1%81%d1%8f/ Mon, 23 Dec 2024 10:33:00 +0000 https://bootandpencil.com/?p=51244 Читать далее]]> ​Если некоторая форма поведения и / или целый класс психических феноменов, например, агрессия, сексуальность, любопытство или игра был подавлен (как правило, в детстве), но в целом психике удалось «сохранить себя», она попытается «отыграть всё обратно». 

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

Сложно дать универсальное правило, по которому можно было бы вычислить конкретную форму, но некие общие закономерности всё же есть. 

Описываются они так: в результате этого «целевого» кризиса человек окажется перед выбором аналогичным тому, в котором некогда (и снова — обычно в детстве) он выбор «отключение части себя». 

При этом уровень эмоционального напряжения обязательно будет сопоставим с тем, который был «там» — в обстоятельствах, в которых психика дезактивировала какую-то свою часть. 

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

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

В случае «отключенного любопытства» это может быть всепоглощающая влюблённость в кого-то, для кого наличие этого качества в партнёре является экзистенциально важным. 

Обобщая, можно утверждать, что, во-первых, это будет ситуация достаточно сильного напряжения (чтобы вообще было уместно задумываться об использование чего-то, маркированного как «неприемлемое»)

Во-вторых, не совсем однозначная: в ней придётся принять какую-то долю агентности на себя, иначе это не будет «включением ранее выключенного», интеграции подавленного и непроявленного не произойдёт. 

В-третьих, там гарантированно не будет никаких гарантий успеха. Наоборот — там будет максимальная неопределённость и риск потерять если не всё, то очень многое и важное. 

Можно ли отказаться от того, чтобы «включать выключенное»? 

Можно. 

Но есть два «но»: 

a) Если не доведётся умереть раньше, психика вернёт человека в ситуацию аналогичного выбора, и нет способа этого избежать, оставаясь живым достаточно долго;  

b) С каждым разом ставки повышаются. И повышаются они быстрее, чем готовность субъекта рисковать. Это всегда будет чем-то, к чему он не будет готов. 

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

]]>
Собака бывает кусачей только от жизни собачьей https://bootandpencil.com/notes/%d1%81%d0%be%d0%b1%d0%b0%d0%ba%d0%b0-%d0%b1%d1%8b%d0%b2%d0%b0%d0%b5%d1%82-%d0%ba%d1%83%d1%81%d0%b0%d1%87%d0%b5%d0%b9-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%be%d1%82-%d0%b6%d0%b8%d0%b7%d0%bd%d0%b8-%d1%81%d0%be%d0%b1%d0%b0%d1%87%d1%8c%d0%b5%d0%b9/ Thu, 19 Dec 2024 10:24:00 +0000 https://bootandpencil.com/?p=51240 Читать далее]]> Раздражительность и «фоновая агрессивность» в людях бывает достаточно неприятна. Находиться (и, — тем более, — взаимодействовать близко) с таким человеком может быть сложно. 

Его хочется обвинить, атаковать, отодвинуть от себя. Такие реакции логичны, сложно за них осуждать кого-либо. Немногие способны проявлять эмпатию в ответ на агрессию. 

Но почему раздражительные люди раздражительны? Легко списать на скверный характер, но это не будет содержательным ответом. 

Как правило, общая раздражительность является — в той или иной форме — проявлением недостаточной ресурсности. 

Иногда состояние озлобленности — единственный способ заставить себя функционировать хоть как-то, используя неприкосновенный запас сил. 

Зачем его использовать, если он неприкосновенный? 

Незачем, просто другого нет: это как займы при низком уровне дохода — субъект, возможно, и рад бы не лезть в долги, но денег на выживание тупо не хватает. 

Иногда раздражительность является ответом не на актуальную перегрузку, а на обоснованное (!) ожидание того, что перегрузка случится, и количество сил, требуемых для решения задач, возрастёт настолько, что придётся израсходовать упомянутый выше запас. 

Это похоже на ситуацию с микрозаймами: можно долго рассказывать человеку о том, что не надо было брать кредит под большой процент, но у него вряд ли есть машина времени, чтобы вернуться в прошлое и всё исправить. 

А в текущий момент у него есть расходы, есть обязательства, и для их покрытия ему требуются средства здесь-и-сейчас. Да, пото́м это будет дорого сто́ить, но первая задача — дожить до этого самого «пото́м». 

Аналогия, хоть и кривая, но работает и дальше: в случае финансовой закредитованности предусмотрены процедуры банкротства. 

В случае перерасхода эмоциональных ресурсов — тоже (депрессия, апатия, уход в себя или чего похуже). 

Туда, в это состояние, очень не хочется, и психика пытается совершить отчаянные попытки не оказываться в состоянии «дефолта». 

И злость / раздражительность здесь является одним из немногих доступных средств: она и внешних агентов с их запросами оттолкнёт, и самого человека заставит мобилизоваться (если повезёт, и там резервы не израсходованы). 

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

И всё становится хуже. 

Решения? Не попадать в ситуации истощения. 

Что делать, если попал? Получать вливание ресурсов снаружи, «опора на себя» и «самодосточность» на данном этапе — непозволительная роскошь, они прекрасны сами по себе, но «не по карману» тому, кто в такой ситуации оказался.

]]>