Привет, Хабр! Возможно, вы знаете меня по дайджестам проекта far2l, но сегодня хочу поделиться кое-чем другим. Это небольшая и очень полезная утилита и формат файлов для неё, которые родились из моей повседневной работы с AI-ассистентами (в том числе в процессе работы над тем же фаром). Штука получилась настолько удобной, что я решил поделиться ей с сообществом. Поехали!
Боль и страдания ручного копипаста
Думаю, многим здесь знаком этот цикл:
Вы: «Перепиши вот эту функцию, чтобы она обрабатывала ещё и такой-то случай».
AI: «Конечно! Вот обновлённый код…» (выдаёт красивый блок кода).
Вы: Вручную выделяете этот блок, переключаетесь в IDE, находите нужный файл и нужную функцию, аккуратно заменяете старый код на новый, поправляете отступы, которые почти всегда едут. Запускаете, видите ошибку, возвращаетесь к AI и повторяете всё заново.
Ручной копипаст — самое узкое место во всём процессе. Он отнимает время, утомляет и провоцирует ошибки. Да, есть платные плагины для IDE, позволяющие AI менять код самостоятельно, но они стоят денег, некоторые недоступны в РФ, а ещё мне удобнее самому решать, какие части кода проекта экспонировать нейронке, это сильно влияет на качество результата.
Конечно, все мы пробовали предлагать ИИ сразу генерировать patch-файлы, и, конечно, знаем, что файлы получаются битыми. Происходит это от того, что на входе сетка «видит» не байты, а токены, и сгенерировать верный с точностью до байта патч она не в состоянии.
Размышляя о том, как можно было бы упростить процесс, я вспомнил про систему обновлений форума Simple Machines. Там использовался семантический подход: вместо строгих инструкций «замени строку 4 на вот такую», файлы с обновлениями содержали семантические инструкции «найди вот этот блок кода, и допиши после него вот это». Интуиция подсказывала: такой патч ИИ сочинить будет куда проще!
Из этой идеи родился формат файлов .ap (AI-friendly Patch), который уже некоторое время существенно облегчает мою жизнь и экономит время.
Как устроен .ap?
Это простой, человекочитаемый YAML-файл. Формат использует несколько ключевых понятий:
действие, action: Что мы делаем? (REPLACE, INSERT_AFTER, INSERT_BEFORE, DELETE).
цель, target: Где мы это делаем?
фрагмент, snippet: Уникальный фрагмент кода, который нужно найти. Поиск «умный» — он игнорирует отступы и пустые строки
якорь, anchor (необязательно): Если snippet встречается в файле несколько раз (например, return result), можно указать «якорь» — более крупный и точно уникальный блок кода (скажем, сигнатура функции), внутри которого нужно искать snippet
На примере из README
Представим, что у нас есть простой файл greeter.py:
# greeter.py
def say_hello():
# Эту строку мы хотим изменить
print("Hello, world!")
Мы просим AI изменить приветствие (не забыв «скормить» ему спеку на .ap формат и инструкцию генерировать ответ именно в нём). Вместо нового блока кода он выдаёт нам вот такой файл (назовём его afix.ap — я обычно использую это имя, чтоб легко было найти патч вверху списка файлов в папке):
# afix.ap
version: "1.0"
changes:
- file_path: "greeter.py"
modifications:
- action: REPLACE
target:
snippet: 'print("Hello, world!")'
content: 'print("Hello, AI-powered Habr!")'
Запускаем патчер из командной строки:
python3 ap.py --patch afix.ap
И наш greeter.py автоматически обновляется:
# greeter.py
def say_hello():
# Эту строку мы хотим изменить
print("Hello, AI-powered Habr!")
И, разумеется, формат позволяет пропатчить (или создать с нуля) целую серию файлов. Больше никакого ручного поиска и копипаста! Вся рутина автоматизирована.
Как начать пользоваться?
Всё необходимое — в репозитории:
Сам скрипт-патчер
ap.py(в папкеimplementation)Файл со спецификацией формата
ap.md
Общаясь с AI, прикладываем к промпту содержимое ap.md и ставим задачу: «сгенерируй ответ в формате ap». Как минимум, Gemini 2.5 Pro отлично с этим справляются. Полученный .ap файл сохраняем себе и применяем скриптом ap.py.
Приглашаю обсуждать и тестировать!
Вот такая штука получилась. Я уже активно использую её в своих проектах, и она экономит мне кучу времени и нервов. Возможно, это только начало: наверняка и формат и утилиту можно улучшить.
Поэтому и делюсь этим с вами. Пробуйте, тестируйте, ломайте! Что если snippet будет слишком коротким? А что если он найдётся 10 раз? Как поведёт себя патчер с разными окончаниями строк (спойлер: я постарался это учесть)?
Буду рад любому фидбеку, идеям и, конечно, тикетам в багтрекере. Давайте вместе сделаем взаимодействие с AI-помощниками ещё чуточку удобнее!
Комментарии (25)

achekalin
12.10.2025 03:40Идея здравая и подход нравится. Но не очень ли громоздко? Вот эти обертки занимают немало, разве нет?
Надо будет попробовать на более-менее крупном применении, спасибо!

unxed Автор
12.10.2025 03:40Оверхед на YAML, конечно, имеется, и всё же несравнимый с генерацией файлов с исходниками целиком. Хотел, чтобы было человекочитаемо, чтобы сразу было видно, что делает патч, и правки в него легко внести можно было.
Спасибо за отзыв! Будет очень интересно услышать, как оно покажет себя на большом проекте. Именно такого фидбека сейчас и не хватает.

titulusdesiderio
12.10.2025 03:40Кто в 2025 ещё использует чат для кодинга? Абсолютно все современные IDЕ имеют ИИ инструментарий. А кроме этого существует ещё и консольные агенты.
Выглядит так, что сам придумал себе проблему - сам героически её решил.

kurdlyplot
12.10.2025 03:40Ну как бы джемини-про в чате бесплатный с контекстом 1кк. За его апи платить слишком дорого.

unxed Автор
12.10.2025 03:40Кстати, весь проект: спека, патчер и тесты сделан при помощи именно этой сетки

shukolza
12.10.2025 03:40Только вы не пишите слишком много, а то все вайбкодеры мира пойдут в AI studio и Гугл гайки закрутит и там

unxed Автор
12.10.2025 03:40Их сетки на моих диалогах с ними учатся, а я в итоге получаю очень качественный контент, так что обучение на диалогах со мной им ещё как полезно. Тут нет благотворительности со стороны Гугла

MikhailLukashov
12.10.2025 03:40А можно пояснение вот к этому:
Общаясь с AI, прикладываем к промпту содержимое
ap.mdи ставим задачу: «сгенерируй ответ в формате ap».Как это делается в командной строке? Или это можно использьовать только в IDE и браузере?

unxed Автор
12.10.2025 03:40some_ai_tool "(...описание задачи...) сгенерируй ответ в формате ap: $(cat ap.md)"

DmitryMikhin
12.10.2025 03:40А не сравнивал с тем, чтобы просить нейросеть сгенерить команды для sed, в целом он все подобные изменения может делать (вставка до, после, удаления, замены) и более лаконичный?
nidalee
Я думал, все уже перешли на агентов, которые либо сами правят файлы, либо пишут пулл реквесты.
Rive
Чем выше разнообразие, тем ниже риски что дополнительный компьют не удастся привлечь, если основные каналы его поставки заблокируют.
unxed Автор
Пробовал, не зашло. В Cursor неудобно работать с длинными сложными промптами, у встроенной модели маленькое контекстное окно, бесплатно доступный объем токенов быстро заканчивается и не обнуляется через время, и невозможно выбрать, какие именно части кода экспонировать сетке, а какие точно в этом диалоге не нужны (вместе с маленьким контекстным окном это катастрофа). Вернее, отдельные файлы исходников-то «прикладывать» к диалогу можно, а вот варианта сказать «используй в этом диалоге только их» нет (или надо пустой проект создавать под это). Для задачек класса «перекладывание JSONов» отличный, полагаю, инструмент. Но не для более сложного.
Агентский режим copilot с их консольной тулзой поближе, но это опять же только в платной версии и сложный промпт-инжиниринг всё равно удобнее в чате. А допускать его что-то коммитить в репозиторий сразу, без тестирования, я не готов — я даже Gemini своей любимой 2.5 Pro такое не доверил бы, слишком сырой код всё-таки генерируют они (с первой попытки, по крайней мере). И контекстное окно, опять-таки, маленькое
titulusdesiderio
Во первых: если критично "прятать" от LLM часть кода - есть cline в котором нет "индексации" кода и можно как раз точечно передавать только нужные файлы.
Во вторых: контекстное окно модели одинаковое и в IDE и в чате. От инструмента оно не зависит. Если вы жалуетесь на размер контекстного окна, то эти претензии актуальны и для чата. Разве что у чата интерфейс не удобный и приходится городить костыли вроде того, что в статье описан.
В третьих: что у вас за задачи такие, которым 1-2 млн контекстного окна мало? Это огромный массив текста, который человек будет читать десятки часов. Пару лет назад, когда окна были по паре десятков тысяч токенов, претензии были уместны. Но не в 2025 году. Но даже если это реально проблема - замена IDE на чат её никак не решает
unxed Автор
Всё так, cli-клиент решает проблему выбора файлов для экспонирования, остальные остаются. Контекстное окно от инструмента очень даже зависит, в colipot например я не могу использовать Gemini 2.5 Pro с её 2 млн токенов, а бесплатно я его как cli не могу использовать вовсе. Мне мало в первую очередь обычных для таких инструментов ~100к, потому что когда отлаживаешь сложный код, итераций цикла «внести изменения, собрать логи» может быть довольно много, разрастается объем быстро, а уже на 30-50% окна сетка начинает изрядно тупить и ошибаться почти постоянно, эффективное окно всегда меньше номинального. 1-2м тоже мало, конечно: решение сложных задач вроде исправления багов в запутанных legacy исходниках или разработку с нуля любых штук хотя бы немного сложнее тривиальных приходится рубить на несколько чатов. Мой максимум — что-то около 20 по одной задаче. Весь .ap формат: спека, патчер и тесты вместе с отладкой и шлифовкой потребовал 4 чатов с той же Gemini 2.5 Pro
titulusdesiderio
А Cline, RooCode, KiloCode и десятки их аналогов? Зачем останавливаться на единственном инструменте в котором нельзя?
Почему? Во первых у Gemini есть свой cli, а во вторых есть aider и десятки других клонов claudecode.
Конечно! И это относится к любому инструменту. Что Cursor, что Cline, что Claude Code. Ну как ваш формат помогает эту проблему решать? Благодаря нему можно ввести один диалог на 50 млн токенов с хорошим результатом? А если нет то чем плохо патч которым пользуются IDE? Только его не приходится копировать и вставлять, это происходит нативно
unxed Автор
Использование плагинов IDE не особо подходит, когда у тебя запрос не пара фраз, а страница-другая текста, а ещё туда 20 страниц логов прилагаются. А ещё я постоянно удаляю неудачные ответы ИИ, генерю заново, где-то редактирую промпты (и не только последний, а любой в диалоге), а где-то и его ответы. И ещё так получается атомарная история изменений, где всегда легко откатиться назад. Поэтому «неудобно работать с длинными сложными промптами» — тейк, с которого я начал. Однако если в каком-то из перечисленных вами редакторов это всё есть и сделано удобно, буду признателен за статью с обзором :)
Добавил в readme, что .ap не является «убийцей» ваших любимых редакторов, консольных клиентов и т.д. Эта штука для тех, кто предпочитает, чтобы генерация была отдельно, а редактирование кода отдельно. И тех, кому недоступны редакторы и консольные тулзы с сетками на 1-2 млн токенов по финансовым или политическим причинам
titulusdesiderio
В cline и десятках его форков и аналогов есть такое понятие как чекпоинты - возможность откатываться по истории коммуникации. При этом там на выбор: откатить только историю, только состояние файлов, и то и другое.
Как раз, когда к диалогу нужно кроме пары фраз добавлять ещё и файлы - чаты тупо требуют больше телодвижений по сравнению со всеми остальными альтернативами. Чаты просто не особо для этого предназначены. Чаты больше подходят для переписки. А для редактирования кода, как не удивительно, редакторы кода (:
В IDE вы можете передать LLM сразу несколько файлов, так же просто, как заменьшонить коллегу в корпоративном чате - через @. Через него же можно сразу целую директорию добавить в контекст.
Можно выделить часть лога и в один хоткей добавить именно эту часть, а не весь файл.
Более того, можно сказать ему самостоятельно запустить код и получить из stdio или из файла логи и их обработать. То есть ещё до появления самих логов, сказать ему как их обработать.
P.S. я не считаю проект плохим или что-то в этом роде. Задача которую вы решаете актуальна и решается каждым из упомянутых мною инструментов индивидуально. Более того, существуют отдельные LLM которые натренированы выполнять лишь одну задачу - применять изменения в формате, аналогичном вашему.
Я лишь удивлён что вы решаете её в отрыве от инструментов, которые решают её сейчас в рамках своей работы.