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

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

Репозиторий rpa-skills на GitHub
Репозиторий rpa-skills на GitHub

Но обо всём по порядку, для начала покажу, как создавать скилы по уму.

Анатомия Skill

Скил часто принимают за одинокий markdown-файл, сиречь промт, на деле же это папка, внутри которой мы можем обнаружить SKILL.md с YAML-заголовком и телом-инструкцией.

Вот небольшой пример такого файла:

---
name: название-скила
description: >
  Краткое описание, необходимое для progressive disclosure
---

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

Рядом с файлом SKILL.md иногда добавляют опциональные директории references/ со справочниками (тоже Markdown-файлы) и scripts/ со скриптами, а также прочие ассеты по вашему усмотрению.

<skill>/
├─ SKILL.md     # заголовок + инструкции
├─ references/  # справочники, читаются по требованию
├─ scripts/     # детерминированные скрипты
└─ README.md    # это уже для людей

При старте сессии харнес подтягивает только name и description всех скилов и добавляет эту информацию в специальную секцию системного промта, обычно это тег <SKILLS> или нечто похожее.

Тело SKILL.md читается при активации благодаря механизму progressive disclosure (прогрессивное раскрытие, агент подгружает данные в контекст, но только когда модель явно запрашивает скил, либо юзер пишет команду вызова скила), а справочники и прочая статика читаются моделью по мере необходимости.

Три шага прогрессивного раскрытия, от витрины скилов до чтения справочников
Три шага прогрессивного раскрытия, от витрины скилов до чтения справочников

Главное не забывать о том, что каждый токен скила конкурирует с историей диалога, поэтому к телу скила стоит применять те же best practices, что и к AGENTS.md, то есть тушку скила стараемся делать до 500 строк, тяжёлое выносим в references/, а ссылки на файлы помещаем в SKILL.md в виде справочника.

---
name: скил-с-индексом
description: >
  Краткое описание, необходимое для progressive disclosure
---

Тело скила, внутри которого будет список ссылок с относительными
путями (относительно файла SKILL.md, разумеется) к файлам в
директории `references/` вроде такого:

- [файл 1](references/файл-1.md)
- [файл 2](references/файл-2.md)
- [инструкция](references/инструкция.md)

И так далее.

Кстати, не обязательно делать ссылки в виде индекса, нам ничто
не мешает добавлять их внутри [текста](references/текст.md), главное,
чтобы путь был валиден.

И не объясняйте модели при помощи скила, что такое PDF, git или юнит-тест, она это знала до вас. В скил должно идти только то, чего модель знать не может, то есть бизнес-цели, ваши флоу, ваш порядок действий, какие MCP вызывать и как, какие CLI вызывать и для чего и так далее и тому подобное.

Подробнее можно почитать на странице открытого стандарта описания скилов.

agentskills.io, открытый стандарт Agent Skills
agentskills.io, открытый стандарт Agent Skills

Skill и Rule

Скил не единственный способ объяснить агенту, что и как делать.

Есть ещё специальные файлы агентных инструкций: CLAUDE.md у Claude Code, есть открытый стандарт AGENTS.md для всех, .cursor/rules у Cursor, .codex/rules/ у Codex и так далее, у всех агентов свои пути и свои нюансы создания правил.

Разница в том, когда они попадают в контекст.

Например, в сравнении rules и skills на примере Cursor это показано так - “Rules with alwaysApply: true are injected into every prompt regardless of relevance”, тогда как “Skills only load when the agent decides the task is relevant”. То есть правило висит в каждом запросе всегда, а скил подтягивается, только когда задача совпала с его описанием.

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

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

Пишите скилы на английском

Ещё один неочевидный способ экономии токенов, про который многие почему-то забывают.

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

Порядок величины такой - на актуальных моделях русский текст стоит примерно вдвое дороже английского. Короткое английское “contract” укладывается в один токен, а русское “разработка” - в два-три, “программирование” - в три-четыре. Разбор с цифрами по токенизаторам есть в посте Кириллица в LLM: почему русский язык в нейросетях стоит дороже и работает медленнее, у токенизатора cl100k_base на 100 тысяч токенов словаря приходится всего 435 на комбинации кириллицы, у o200k_base от GPT-4o их уже 4660, в десять раз больше, но англоязычный текст всё равно выигрывает.

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

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

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

Description для автоматизации

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

Давайте небольшой пример приведу, сравним описания скилов rpa-feat и rpa-bugfix:

rpa-feat: “Add a feature strictly by BDD… Requires a clear feature description.”

rpa-bugfix: “Fix a bug with a reproduction test first… Requires a clear bug description.”

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

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

Практики от Anthropic

Как говорится, если разработчик не справляется с задачей, то настаёт крайняя мера - чтение документации. Если уж надумали собирать свои скилы, то рекомендую начать с прочтения официального гайда Anthropic (перевод) в X/Твиттере, там даны дельные советы, которые я проверил на своём маркетплейсе rpa-skills.

  • Степени свободы под задачу. У Anthropic есть метафора про робота “narrow bridge with cliffs on both sides” против “open field with no hazards”. Там, где ошибка дорогая и порядок жёсткий, пишем точную инструкцию без вариантов, где путей много - даём направление и доверяем модели. К примеру, скил rpa-bugfix у меня выдаёт агенту жёсткие рельсы (тест, фикс, полный прогон, порядок неизменен), а скил logika больше похож на открытое поле.

  • Детерминированное - в скрипты. Хрупкие и повторяющиеся операции надёжнее вынести в скрипт и положить в папку scripts/, чем каждый раз просить модель генерить код. Правило Anthropic - “solve, don’t punt”, скрипт сам обрабатывает свои ошибки и не прячет магических констант навроде TIMEOUT = 42 (в доках их зовут “voodoo constants”), иначе модель начнёт “творчески” свой скил чинить.

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

  • Имена скилов в форме герундия (то есть -ingовое окончание), например: processing-pdfs, analyzing-spreadsheets, а не просто helper и utils, по имени должно быть сразу понятно, что скил делает, так его сложнее спутать с соседями.

  • Один дефолт вместо кучи вариантов. “Avoid offering too many options” рекомендует нам не вываливать пять библиотек модели на выбор, а дать ей одну основную и запасной вариант на случай форс-мажора. Лишняя вариативность только сбивает модель с толку.

Подробности в best practices на сайте Anthropic.

Проверяем скил сабагентом

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

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

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

Вопроса к прогону три:

  1. Активировался ли скил сам, без слеш-команды? Если нет, допиливаем description.

  2. Где сабагент ошибся? Каждая проблема это недоработка в инструкции.

  3. Сделал ли он то, что должен, с учётом данных из скила, или нечто похожее по мотивам?

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

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

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

Из Skill в Plugin

Сам по себе скил в маркетплейс не положить, сначала его нужно оформить как плагин.

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

Оформляется плагин просто, для Claude Code рядом со SKILL.md добавляется директория .claude-plugin/, а в ней манифест plugin.json с метаданными - имя, версия, описание, автор, лицензия и ключевые слова.

Вот, например, манифест из моего rpa-init:

{
  "name": "rpa-init",
  "version": "1.0.0",
  "description": "Warm up context on a repository...",
  "author": { ... },
  "license": "MIT",
  "keywords": ["onboarding", "repository", "context", "workflow"],
  "category": "workflow"
}

Тонкость одна, поле name в plugin.json должно совпадать с name из SKILL.md, а версию при изменениях бампаем синхронно и там и там, чтобы ничего не разъезжалось, однако, нам ничего не мешает прикрутить хуки или воспользоваться девопсовскими штучками.

У Codex манифест свой, лежит он в .codex-plugin/plugin.json, структура почти та же, только путь до скилов задаётся отдельным полем skills и добавляется блок interface с витринными данными для каталога плагинов:

{
  "name": "rpa-init",
  "version": "1.0.0",
  "description": "Warm up context on a repository...",
  "author": { ... },
  "license": "MIT",
  "skills": "./",
  "interface": {
    "displayName": "rpa-init",
    "shortDescription": "Warm up repo context: study code/docs/tests, set up env, run tests, report.",
    "developerName": "...",
    "category": "Developer Tools"
  }
}

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

Свой маркетплейс за вечер

Тема, которую на Хабре толком никто не раскрывал.

Маркетплейс это каталог плагинов, витрина, по которой агент узнаёт, какие плагины существуют, какие у них версии и откуда их ставить. Громкое слово пусть не пугает, никакого бэкенда, магазина и биллинга за ним нет, только JSON-файл со списком плагинов и ссылками на их источники.

Маркетплейс не хранит скилы внутри себя, его marketplace.json просто ссылается на директории в которых лежат файлы plugin.json, будь то отдельные репозитории на GitHub или папки внутри монорепы. Именно так и собран мой каталог, каждая запись указывает на репозиторий скила, а тот уже несёт свой манифест и свою версию.

Схема каталога rpa-skills, агенты ходят в marketplace.json, а тот ссылается на репозитории плагинов
Схема каталога rpa-skills, агенты ходят в marketplace.json, а тот ссылается на репозитории плагинов

Маркетплейс плагинов для Claude Code это обычный git-репозиторий с одним файлом .claude-plugin/marketplace.json. Никакой регистрации и модерации, а распространять каталог может кто угодно.

Внутри имя каталога, владелец и список плагинов со ссылками на источники:

{
  "name": "rpa-skills",
  "owner": { ... },
  "plugins": [
    {
      "name": "rpa-init",
      "source": { "source": "github", "repo": "EvilFreelancer/rpa-init" },
      "version": "1.0.0"
    }
  ]
}

Подключение двухшаговое, как в любом сторе:

# Сначала подключаем стор
/plugin marketplace add EvilFreelancer/rpa-skills

# Потом ставим нужный плагин
/plugin install rpa-init@rpa-skills

Источником может быть GitHub (owner/repo), произвольный git-URL с веткой через #ref, локальный путь или URL до marketplace.json. Области установки - user для всех своих проектов, project для текущего проекта. При установке Claude Code показывает context cost, сколько токенов плагин добавит к каждому ходу. Рекомендую периодически заглядывать в эту стату.

В Codex всё плюс минус то же самое, только манифест каталога лежит в .agents/plugins/marketplace.json, а команда подключения маркетплейса вводится через командную строку:

codex plugin marketplace add EvilFreelancer/rpa-skills

Дальше запускаем codex, открываем /plugins, находим там вкладку своего каталога и ставим нужное. Клодовский marketplace.json Codex тоже умеет читать как легаси-фолбэк, так что сработает любая из двух точек входа.

А вот у Cursor удалённого маркетплейса нет вовсе, он ищет скилы только по директориям, поэтому в каталоге rpa-skills я добавил скрипт install.sh, клонирующий скилы в ~/.agents/skills.

Внешние маркетплейсы

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

Самая крупная это skills.sh, директория и лидерборд скилов от команды Vercel. Работает она через опенсорсный CLI skills, который умеет ставить скилы почти в три десятка агентов, от Claude Code и Codex до Gemini CLI и Copilot:

# поиск по каталогу
npx skills find "formal logic"

# установка скила из репозитория owner/repo
npx skills add EvilFreelancer/logika

# а с флагом -g скил встанет глобально, а не в текущий проект
npx skills add EvilFreelancer/logika -g

Самое интересное, что никакой регистрации и формы сабмита у skills.sh нет, вы “платите” иначе, площадка собирает “анонимную” телеметрию установок CLI, и как только ваш публичный репозиторий со SKILL.md начинают ставить через npx skills add, он сам появляется в каталоге и ползёт вверх по лидерборду.

Лидерборд skills.sh, почти миллион установок на весь каталог
Лидерборд skills.sh, почти миллион установок на весь каталог

Для нашего рынка есть NeuralDeep Skills, российский каталог скилов, MCP-серверов и CLI-тулов, заточенный под локальные сервисы, там живут скилы для Яндекса, 1С, Битрикс24, GigaChat, Wildberries, Ozon и Авито.

Каталог NeuralDeep, скилы и MCP-серверы вокруг российских сервисов
Каталог NeuralDeep, скилы и MCP-серверы вокруг российских сервисов

У него свой CLI с похожим синтаксисом:

# поиск по каталогу
npx skillsbd search 1c

# установка скила
npx skillsbd add Nikolay-Shirokov/cc-1c-skills/1c-enterprise-skills

Скил приезжает в директорию .skills/ проекта, откуда его читают Claude Code, Cursor, Copilot и Cline. В отличие от skills.sh здесь есть модерация, свой скил добавляется через форму на сайте с авторизацией через GitHub, зато и мусора в каталоге меньше, а у проверенных скилов бывают пометки “выбор редакции”.

Отдельного упоминания заслуживает валидатор скилов. Скармливаете ему ссылку на GitHub-репозиторий или просто содержимое файла, а он проверяет, корректно ли всё оформлено и совместимо ли со стандартами популярных агентов.

Умеет валидировать SKILL.md по открытому стандарту (лимиты и формат полей name и description), plugin.json для Claude Code, marketplace.json целиком, AGENTS.md для Codex и правила .mdc для Cursor, причём всё считается прямо в браузере, запрос уходит из него напрямую в GitHub. Удобно прогонять свой скил или каталог перед публикацией, вместо того чтобы ловить ошибки оформления по одному агенту за раз.

Валидатор NeuralDeep проверяет SKILL.md, plugin.json и marketplace.json на соответствие стандартам
Валидатор NeuralDeep проверяет SKILL.md, plugin.json и marketplace.json на соответствие стандартам

Есть и другие площадки навроде SkillsMP, она работает как агрегатор, сама индексирует публичные репозитории со SKILL.md на GitHub, специально загружать туда ничего не нужно, достаточно нормального README и тегов в репозитории.

Ложка дёгтя

Чужой скил выполняется с правами вашего агента, то есть от вашего имени. На Хабре уже разбирали случай, когда установленный по совету из YouTube скил через prompt injection утащил данные пользователя. Поэтому перед установкой читаем SKILL.md глазами, заглядываем в scripts/ и смотрим, куда скил ходит и зачем. Эту задачу можно например доверить кодовому агенту.

Вторая ложка дёгтя, один и тот же скил на разных моделях может работать по-разному. В best practices Anthropic прямо советует гонять скил на всей линейке моделей и задавать разные вопросы, хватает ли Haiku подсказок, достаточно ли ясен скил для Sonnet, не переобъясняет ли он очевидное для Opus. Спецы из Tessl померили это на бенчмарках, скил, отлаженный под Opus, может показывать посредственные результаты на Haiku, эффект сильно зависит от модели. А исследование SkillsBench на пуле разных задач показало, что скилы в среднем поднимают долю успешных прогонов примерно на 16 процентных пунктов, но разброс по доменам огромный, где-то скил решает, а где-то почти не влияет.

С кодовыми агентами та же история. Стандарт SKILL.md один, но каждый харнес расширяет его своими полями фронт-маттера, и скил, завязанный на такие расширения, молча теряет часть поведения в чужом агенте, файл грузится, а специфичные поля просто игнорируются. Это ещё одна причина валидировать скил сабагентами на разных моделях и разных кодовых агентах от разных поставщиков, у меня это Claude Code, Codex, Cursor и OpenCode (с on-premise моделями), и допиливать инструкции до состояния, когда скил везде работает одинаково.

Послесловие

Изначально rpa-skills был монорепой, но я распилил его, каждый скил уехал в собственный репозиторий со своими версиями, а каталог стал агрегатором со ссылками. Единственный неочевидный момент в такой схеме - каталог следует за скилами и никогда не ведёт. Бампнули версию в репозитории скила, тем же коммитом обновили её в marketplace.json каталога, в целом это не проблема и легко автоматизируется хуками или рулесами в AGENTS.md.

Благодарю за прочтение. Если тема близка, заходите на мой Telegram-канал Pavel Zloi, пишу там про on-prem модельки, серверы, агентов и прочие радости агентной жизни.

Комментарии (0)