Ponytail: ИИ-агент, который не пишет лишнего кода
Разбираем инструмент ponytail для Claude Code: как настроить агента, чтобы он предлагал готовые решения вместо нового кода и не изобретал велосипеды.
Что такое ponytail и зачем он нужен
Что такое ponytail и зачем он нужен
Claude Code по умолчанию склонен писать код. Попроси его добавить логирование в приложение — и он накидает middleware, создаст новый файл, подключит зависимости. Иногда это оправданно, чаще — нет. В реальной разработке большая часть задач решается не новым кодом, а правильным использованием того, что уже есть в репозитории, в стандартной библиотеке или в документации фреймворка.
Ponytail — это набор agent-skills для Claude Code, который переключает агента из режима «написать решение» в режим «предложить готовое решение». Агент перестаёт изобретать велосипеды и начинает смотреть в сторону существующих модулей, конфигов и стандартных инструментов. Для инженера, который ценит предсказуемость конфигураций, это разница между стабильной системой и постоянным рефакторингом чужого кода.
Принцип «ленивого сеньора»
Опытный сеньор редко пишет код с нуля. Сначала он проверяет, не решена ли задача уже в проекте: есть ли подходящий сервис, утилита или конфигурация. Только если ничего подходящего нет, он пишет новый код — и даже тогда старается максимально переиспользовать существующее.
Ponytail кодирует этот подход в системном промпте Claude Code. Агент получает набор навыков, которые заставляют его:
- искать готовое решение в репозитории перед тем, как предложить новый код;
- предлагать стандартные инструменты фреймворка вместо самописных обёрток;
- объяснять, почему существующее решение подходит, а не генерировать код «на всякий случай».
Пример. Пользователь просит добавить проверку здоровья сервиса. Обычный Claude Code может предложить новый HTTP-хендлер, маршрут и контроллер. Ponytail-агент с большей вероятностью укажет на уже подключённый мониторинг или встроенный health-check фреймворка:
yaml# Пример навыка ponytail (упрощённо)
name: prefer-existing-solution
description: |
Before writing new code, search the repository for existing
implementations, utilities, or configuration that solve the task.
If found, propose reusing it instead of creating new files.
rules:
- Check /src, /lib, /internal for similar logic.
- Prefer standard library over third-party packages.
- Prefer framework built-ins over custom middleware.
Настройка такого навыка обычно сводится к добавлению файла в репозиторий или подключению готового набора из сообщества. Если вы уже работали с навыками из репозитория mattpocock/skills, принцип будет знаком — см. Навыки для ИИ-агентов из репозитория mattpocock/skills.
Чем отличается от обычного Claude Code
Обычный Claude Code оптимизирован на помощь в написании кода. Он охотно генерирует новые файлы, функции, конфиги — даже когда задача решается настройкой существующего компонента. Это удобно для прототипирования, но в продакшене приводит к разрастанию кодовой базы и поддержке самописных велосипедов.
Ponytail накладывает на агента ограничения, которые меняют его поведение:
| Ситуация | Обычный Claude Code | Claude Code с ponytail |
|---|---|---|
| Добавить логирование | Напишет новый middleware и подключит библиотеку | Укажет на встроенный логгер фреймворка или существующий модуль |
| Реализовать валидацию | Создаст новую схему и валидатор | Предложит использовать уже подключённую библиотеку или стандартные средства |
| Настроить мониторинг | Напишет скрипт сбора метрик | Укажет на существующий экспортер или конфиг Prometheus |
Практический пример. Допустим, нужно ограничить частоту запросов к API. Обычный агент предложит написать rate-limiter на Redis с eigener очередью и скриптом на Lua. Ponytail-агент сначала проверит, не есть ли в проекте уже готовый мидлвар или не поддерживает ли это API-шлюз из коробки:
bash# Вместо нового кода — проверка существующего решения
grep -r "rate" --include="*.go" --include="*.py" --include="*.js" .
# или
ls internal/middleware/
Если ничего не найдено — только тогда агент переходит к написанию кода, но уже с контекстом о том, что существующих решений нет.
Это отличие не в том, что ponytail запрещает писать код. Он просто меняет приоритет: сначала существующее, потом новое. Для команды, которая поддерживает продакшен несколько лет, это разница между кодовой базой, которую легко читать, и набором самописных обёрток вокруг стандартных инструментов.
Если вы только начинаете настраивать навыки для Claude Code, полезно ознакомиться с инструкцией по подключению навыков из mattpocock/skills — там описан базовый workflow, который применим и к ponytail: Подключение навыков из mattpocock/skills к ИИ-агенту.
Установка и подключение к Claude Code
Установка и подключение к Claude Code
Требования и порядок установки
Ponytail — это навык (agent-skill) для Claude Code, который меняет поведение агента: вместо того чтобы писать новый код с нуля, он ищет готовое решение в вашем репозитории или предлагает использовать существующие паттерны. Для меня, как для человека, который терпеть не может «решений на коленке», это именно то, что нужно — меньше самодеятельности, больше предсказуемости.
Перед установкой убедитесь, что у вас есть:
- Claude Code (версия не ниже той, которая поддерживает agent-skills — проверьте в официальной документации Anthropic);
- Node.js 18+ и npm, если ставите через пакетный менеджер;
- Доступ к репозиторию с проектом, где агент будет работать.
Установка занимает пару минут. Сначала клонируем репозиторий с навыком:
bashgit clone https://github.com/ponytail-ai/ponytail.git ~/.claude/skills/ponytail
Затем подключаем его в конфигурации Claude Code. Открываем файл ~/.claude/settings.json (или создаём, если ещё нет) и добавляем секцию с навыками:
json{
"agentSkills": [
{
"name": "ponytail",
"path": "~/.claude/skills/ponytail",
"enabled": true
}
]
}
Сохраняем файл и перезапускаем Claude Code. Агент подхватит навык автоматически — дополнительных действий не требуется.
С практической точки зрения, я всегда проверяю, что навык действительно подгрузился, прежде чем переходить к работе. Проще всего сделать это через команду списка навыков:
bashclaude code --list-skills
В выводе должен появиться ponytail со статусом active. Если его там нет — перепроверьте путь в settings.json и права доступа к директории с навыком.
Первая проверка работы агента
После установки стоит убедиться, что Ponytail ведёт себя так, как ожидается. Главное отличие от обычного Claude Code — агент не должен предлагать написать новый компонент или функцию, если в репозитории уже есть что-то подходящее.
Попросите агента реализовать типовую задачу. Например:
Добавь обработку ошибок в API-роут пользователей, используя существующие паттерны в проекте.
Если Ponytail настроен правильно, он не придумает новую обёртку над ошибками с нуля, а покажет вам готовый фрагмент из кодовой базы или предложит адаптировать существующий middleware. Пример ответа может выглядеть так:
В репозитории уже есть обработчик ошибок в src/middleware/errorHandler.ts.
Используйте его в роуте пользователей:
```typescript
import { errorHandler } from '@/middleware/errorHandler';
router.get('/users/:id', errorHandler, async (req, res) => {
// ...
});
Хотите, чтобы я подключил этот middleware к вашему роуту?
Это и есть суть Ponytail — агент предлагает готовое решение вместо изобретения велосипеда. Если вы видите, что агент начинает писать новый код с нуля, хотя в проекте есть аналоги, значит, что-то пошло не так. Проверьте, что навык включён в `settings.json`, и попробуйте переформулировать запрос, явно указав на использование существующих паттернов.
Ещё один момент, на который я обращаю внимание: Ponytail работает лучше всего в проектах с чёткой структурой и документированным кодом. Если ваш репозиторий похож на свалку, агент не сможет найти готовое решение и может откатиться к обычному поведению. В этом случае начните с наведения порядка — вынесите повторяющийся код в общие модули, опишите интерфейсы, и тогда агент начнёт предлагать по-настоящему полезные готовые решения.
Если хотите углубиться в работу с навыками для ИИ-агентов, посмотрите связанные материалы: [подключение навыков из mattpocock/skills к ИИ-агенту](/guides/podklyuchenie-navykov-iz-mattpocockskills-k-ii-agentu-hzm1mi) и [навыки для ИИ-агентов из репозитория mattpocock/skills](/guides/navyki-dlya-ii-agentov-iz-repozitoriya-mattpocockskills-l4nry8).
## Как заставить агента не писать лишнего кода
Как заставить агента не писать лишнего кода
Когда Claude Code берётся за задачу, его первый импульс — написать код. Агент видит пустой файл и сразу хочет заполнить его новыми функциями, классами, скриптами. В большинстве случаев это избыточно. В репозитории уже есть решение, или в экосистеме языка есть библиотека, которая делает то же самое, но надёжнее и с тестами. Моя задача как инженера — не запрещать агенту писать код, а научить его сначала смотреть вокруг.
Если вы подключаете навыки к агенту через ponytail, имеет смысл посмотреть, как это делают в других проектах — например, в репозитории [mattpocock/skills](/guides/navyki-dlya-ii-agentov-iz-repozitoriya-mattpocockskills-l4nry8) или в руководстве по [подключению навыков к ИИ-агенту](/guides/podklyuchenie-navykov-iz-mattpocockskills-k-ii-agentu-hzm1mi). Там уже есть заготовки, которые можно адаптировать под правило «сначала поиск, потом реализация».
### Поиск готового решения в репозитории
Прежде чем просить агента написать функцию, проверьте, не лежит ли она уже в репозитории под другим названием.
На практике так и происходит: в проекте есть утилита для форматирования дат, но агент не знает о её существовании и пишет свою. Чтобы этого избежать, нужно явно прописать в инструкциях агента правило: сначала поиск, потом реализация.
Пример навыка для ponytail:
```yaml
# .ponytail/skills/code-reuse.yaml
name: code-reuse
description: "Ищите готовое решение в репозитории перед написанием нового кода"
rules:
- before_writing_code:
- run: grep -r "format_date" --include="*.ts" --include="*.js" --include="*.py" .
- run: rg -l "parse_date|to_iso" src/ lib/ pkg/
- if_found:
action: reuse
message: "Найдено существующее решение: {file}. Используйте его вместо нового кода."
- if_not_found:
action: proceed
message: "Готового решения не найдено. Можно реализовать новое."
Если вы хотите проверить это вручную перед тем, как дать задание агенту, используйте команду:
bash# Ищем существующие реализации похожей логики
rg -l "format_date|parse_date|to_iso" src/ lib/ pkg/
С практической точки зрения, этот шаг экономит время на код-ревью. Если агент написал свою функцию, а в репозитории уже есть аналогичная, ревьюверу придётся тратить время на объяснение, зачем дублировать логику. Лучше сразу направить агента к существующему коду.
Использование библиотек вместо самописных функций
Если в репозитории решения нет, следующим шагом должен быть поиск в экосистеме языка. Агент часто изобретает велосипед: пишет свой парсер CSV, свою обёртку над HTTP, свою валидацию email. В большинстве случаев для этого уже есть библиотека.
Пример навыка для ponytail:
yaml# .ponytail/skills/library-first.yaml
name: library-first
description: "Предпочитайте готовые библиотеки самописным функциям"
rules:
- before_implementing:
- check: package.json / requirements.txt / go.mod
- search: npm, pypi, pkg.go.dev
- preferred_action:
- add_dependency
- import_and_use
- forbidden_without_approval:
- writing_custom_http_client
- writing_custom_csv_parser
- writing_custom_date_formatter
Как это выглядит в работе. Агенту нужно отправить уведомление в Slack при ошибке. Без правила он напишет свой HTTP-клиент на Node.js:
typescript// Плохо: агент написал свой HTTP-клиент
export async function sendSlackNotification(webhookUrl: string, message: string) {
const response = await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: message }),
});
if (!response.ok) {
throw new Error(`Slack API error: ${response.status}`);
}
}
С правилом library-first агент предложит использовать существующую библиотеку:
typescript// Хорошо: используется готовая библиотека
import { WebClient } from '@slack/web-api';
const slack = new WebClient(process.env.SLACK_TOKEN);
export async function sendSlackNotification(channel: string, message: string) {
await slack.chat.postMessage({ channel, text: message });
}
Разница не только в количестве кода. Готовая библиотека уже обрабатывает повторные запросы, rate limiting, таймауты и обработку ошибок. Самописный fetch придётся дорабатывать каждый раз, когда Slack изменит API или добавит новые ограничения.
Если мы посмотрим на опыт работы с большими репозиториями, предсказуемость конфигурации важнее краткости кода. Когда агент использует библиотеку, любой разработчик может открыть package.json и понять, откуда взялся функционал. Когда агент пишет свой велосипед, функционал спрятан внутри неочевидной функции, которую ещё нужно найти и прочитать.
Главное правило — агент не должен писать код, пока не проверит репозиторий и не поищет библиотеку. Это не ограничивает его возможности, а делает изменения предсказуемыми. Код, который не написан, не требует поддержки, не ломается при рефакторинге и не нуждается в тестах.
Ограничения подхода и когда он не подходит
Ограничения подхода и когда он не подходит
Ponytail перекладывает акцент с написания кода на подбор и адаптацию готовых решений. Для типовых задач — подключение базы, раздача статики, аутентификация через OAuth — это экономит время. Но подход не универсален. Агент может предложить решение, которое работает в общем случае, но не подходит под вашу инфраструктуру, или просто не найти подходящего навыка в репозитории.
Когда всё же приходится писать код с нуля
Во-первых, когда бизнес-логика не укладывается в готовые шаблоны. Ponytail опирается на навыки (agent-skills) — готовые фрагменты и паттерны. Если ваша задача специфична, например, интеграция с внутренним API контрагента или нестандартная обработка платежей, агент не найдёт подходящего навыка и либо предложит что-то близкое, но нерабочее, либо промолчит.
С практической точки зрения, вот как выглядит граница. Допустим, вы просите агента добавить endpoint для загрузки файлов. Ponytail может подтянуть навык из репозитория mattpocock/skills и сгенерировать код на Express с multer:
typescriptimport express from 'express';
import multer from 'multer';
const router = express.Router();
const upload = multer({ dest: 'uploads/' });
router.post('/upload', upload.single('file'), (req, res) => {
res.json({ path: req.file?.path });
});
export default router;
Это работает, пока вам не понадобится валидировать mime-тип, ограничить размер файла и сохранить метаданные в свою таблицу documents с внешним ключом на пользователя. В этот момент готовое решение становится препятствием: проще переписать с нуля, чем вырезать лишнее из чужого шаблона.
Во-вторых, когда важна предсказуемость и размер зависимости. Готовый навык может тянуть за собой тяжелую библиотеку, которая не оправдана для вашей задачи. Например, агент предлагает подключить полноценный фреймворк для очередей, хотя вам достаточно простого setTimeout с ретраями. В продакшене каждый лишний пакет — это потенциальная уязвимость и дополнительное время на обновления.
В-третьих, когда код работает в примере, но не в вашей среде. Агент не знает, что у вас за прокси, какая версия Node.js и какие переменные окружения. Он может предложить конфиг, который требует правки:
yaml# .ponytailrc — пример ограничения навыков
skills:
allowed:
- http-client
- postgres-query
blocked:
- code-generation
- scaffold-project
Если вы заблокируете генерацию нового кода, агент не сможет выйти за рамки доступных навыков. Это полезно для контроля, но в момент, когда нужен нестандартный скрипт миграции, придётся либо снимать ограничение, либо писать код вручную.
Наконец, отладка. Когда агент предлагает готовое решение, вы не всегда понимаете, почему оно не работает. Логи не помогают, потому что вы не писали этот код. В такой ситуации быстрее сесть и написать свою реализацию, чем тратить час на чтение чужого кода, сгенерированного нейросетью.
Если вы уже подключали навыки из mattpocock/skills, вы знаете, что навыки покрывают типичные сценарии. Но они не заменяют понимание системы. Когда задача выходит за рамки шаблона, пишите код сами — и документируйте, почему готовое решение не подошло.
Часто задаваемые вопросы
Чем ponytail отличается от обычного Claude Code?
Обычный Claude Code склонен писать код с нуля: новый middleware, отдельный файл, лишние зависимости. Ponytail переключает агента в режим поиска готового решения — он сначала смотрит в репозиторий, стандартную библиотеку и документацию фреймворка. С практической точки зрения это разница между «написать велосипед» и «воспользоваться тем, что уже лежит в проекте». Для меня главное здесь — предсказуемость конфигураций.
Нужно ли готовить репозиторий специальным образом?
Не нужно переписывать код под ponytail. Агент ищет то, что уже есть: модули, утилиты, конфиги, встроенные механизмы фреймворка. Если в проекте беспорядок и дублирование, ponytail не вылечит архитектуру, но поможет не усугублять её новым кодом. Во‑первых, наведите порядок в существующих абстракциях, а потом подключайте агента.
Что делать, если подходящего решения в репозитории нет?
Ponytail не запрещает писать новый код, он только откладывает этот момент. Если агент не находит подходящего модуля или стандартного инструмента, он предложит решение — но с обоснованием, почему существующие варианты не подошло. С точки зрения инженера это здорово: вы видите не просто код, а аргументированный отказ от переиспользования.
Подходит ли ponytail для новых проектов?
В новом проекте ещё нет накопленного кода, поэтому агенту нечего переиспользовать. Ponytail всё равно полезен: он заставит Claude Code смотреть в сторону стандартной библиотеки и встроенных средств фреймворка вместо самописных обёрток. Если мы посмотрим на типичный старт проекта, большая часть проблем возникает именно из‑за лишнего кода на раннем этапе.
Как понять, что ponytail работает?
Сравните ответы агента до и после подключения навыков. Обычный Claude предложит новый файл и маршрут, ponytail-агент укажет на уже подключённый мониторинг или встроенный health‑check. Если в ответе появляется ссылка на существующий модуль и объяснение, почему он подходит — значит, навык сработал.