
Claude Code — Скиллы которые реально срабатывают
Скиллы - одна из тех фич Claude Code которые кажутся простыми пока не пытаешься использовать их последовательно. Идея проста: напиши markdown файл с инструкциями, положи в нужную директорию - и Claude загружает его когда нужно, или вызываешь явно через slash команду. На практике это "когда нужно" - там где начинается интересное, и не всегда хорошо.
Что такое скиллы
Скиллы - markdown файлы с YAML frontmatter которые Claude Code загружает в контекст. Каждый скилл создаёт slash команду - напиши ~/.claude/skills/security-review/SKILL.md, получишь /security-review. Можешь вызвать напрямую, или Claude может вызвать автоматически когда разговор соответствует описанию скилла.
Сами скиллы Claude Code следуют открытому стандарту Agent Skills, который работает и в других AI-инструментах. Claude Code расширяет стандарт своими фичами: контроль инвокации, запуск в субагенте, инъекция динамического контекста. Это стоит держать в голове если планируешь переносить скиллы между инструментами - часть frontmatter будет работать только здесь.
Скиллы живут на четырёх уровнях:
| Уровень | Путь | Область действия |
|---|---|---|
| Enterprise | managed settings | Все пользователи в организации |
| Personal | ~/.claude/skills/<name>/SKILL.md |
Все твои проекты |
| Project | .claude/skills/<name>/SKILL.md |
Только этот проект |
| Plugin | <plugin>/skills/<name>/SKILL.md |
Где плагин включён |
Когда одно и то же имя скилла существует на нескольких уровнях - enterprise побеждает, потом personal, потом project. Это противоположность того что большинство ожидает - глобальные скиллы переопределяют проектные, не наоборот. Скилл на любом из этих уровней также переопределяет встроенный скилл с тем же именем: свой code-review в .claude/skills/ заменит собой bundled /code-review. Плагинные скиллы живут в неймспейсе plugin-name:skill-name и поэтому не конфликтуют вообще ни с кем.
Вложенные скиллы и монорепы
Project скиллы подхватываются не только из .claude/skills/ рабочей директории, но и из каждой родительской вплоть до корня репозитория. Плюс - из вложенных директорий по требованию: если Claude читает или правит файл в packages/frontend/, скиллы из packages/frontend/.claude/skills/ становятся доступны, даже если сессия стартовала в корне.
Если вложенный скилл совпадает по имени с корневым - оба остаются живы. Вложенный получает квалифицированное имя вида apps/web:deploy, его описание сообщает к какой директории он относится, и Claude выбирает вариант соответствующий файлам над которыми работает. /deploy запускает корневой; /apps/web:deploy - вложенный явно. Требует v2.1.203 или новее.
Ещё одна мелочь про которую полезно знать: Claude Code следит за директориями скиллов и подхватывает изменения SKILL.md внутри текущей сессии, без рестарта. Рестарт нужен только если создаёшь директорию скиллов верхнего уровня которой не было на старте сессии.
Анатомия скилла
Каждый скилл - директория с обязательным SKILL.md. Внутри файла две части: YAML frontmatter между маркерами --- и markdown инструкции.
---
name: pr-review
description: Reviews staged changes for correctness, test coverage, and consistency with project conventions. Use when the user asks for a code review or is about to open a PR.
---
Review the current changes:
1. Run `git diff --staged` to see what's changing.
2. Check that every modified function has a corresponding test change.
3. Flag any hardcoded values that should be environment variables.
4. Confirm the commit message matches the conventional commit format used in this repo.
Return findings as a short numbered list. If nothing to flag, say so explicitly.
Важная поправка к тому, что часто пишут (и что я сам раньше думал): поле name - это не slash команда. Slash команда берётся из имени директории. .claude/skills/deploy-staging/SKILL.md даёт /deploy-staging независимо от того что написано в name. Поле name - display label в листингах скиллов. Единственное исключение - корневой SKILL.md плагина, там имени директории скилла просто нет, и name действительно определяет команду.
Все поля frontmatter опциональны. Рекомендуется только description - его Claude читает чтобы решить загружать ли скилл автоматически. Это не документация для людей, даже если читается как она. Если description не указан - берётся первый параграф markdown содержимого.
Поддерживающие файлы опциональны но полезны:
.claude/skills/pr-review/
├── SKILL.md
├── reference.md
├── examples/good-review.md
└── scripts/validate.sh
Ссылайся на них явно из SKILL.md, чтобы Claude знал что в каждом файле и когда его грузить. Файлы в директории не загружаются автоматически - и это хорошо: большая API-спека не должна попадать в контекст каждый раз когда скилл срабатывает. Держи SKILL.md в пределах ~500 строк, остальное выноси.
Frontmatter: поля которые стоит знать
| Поле | Что делает |
|---|---|
description |
Что скилл делает и когда применять. Главный рычаг автовызова. |
when_to_use |
Дополнительный контекст: триггерные фразы, примеры запросов. Приклеивается к description в листинге. |
paths |
Glob-паттерны ограничивающие когда скилл активируется. Claude грузит его автоматически только при работе с подходящими файлами. |
disable-model-invocation |
true - только ты можешь вызвать скилл. Описание вообще не попадает в контекст. |
user-invocable |
false - только Claude может вызвать. Для фонового знания которое не является осмысленным действием для человека. |
allowed-tools |
Инструменты которые Claude может использовать без запроса разрешения пока скилл активен. |
disallowed-tools |
Инструменты убираемые из пула пока скилл активен. Сбрасывается на следующем твоём сообщении. |
context: fork |
Выполнить скилл в изолированном контексте субагента. |
agent |
Какой тип субагента использовать при context: fork - Explore, Plan, general-purpose или свой из .claude/agents/. |
model / effort |
Переопределить модель и уровень reasoning на время работы скилла. |
arguments / argument-hint |
Именованные позиционные аргументы и подсказка в автокомплите. |
hooks |
Хуки со скоупом жизненного цикла конкретно этого скилла. |
shell |
bash (по умолчанию) или powershell для инлайновых команд. |
paths - это, на мой взгляд, самое недооценённое поле. Раньше единственным способом ограничить слишком жадный скилл было disable-model-invocation: true, то есть отказ от автовызова вообще. Теперь можно сказать «активируйся только когда работаем с **/*.sql» и оставить автоматику включённой.
Подстановки в теле скилла
$ARGUMENTS- всё что передано при вызове$ARGUMENTS[N]или короткое$N- конкретный аргумент по индексу с нуля$name- именованный аргумент объявленный вarguments${CLAUDE_SKILL_DIR}- директория самого скилла; используй её чтобы ссылаться на собственные скрипты независимо от рабочей директории${CLAUDE_PROJECT_DIR}- корень проекта (v2.1.196+)${CLAUDE_SESSION_ID},${CLAUDE_EFFORT}- для логирования и адаптации инструкций под текущий уровень усилий
Если вызываешь скилл с аргументами, но $ARGUMENTS в теле нет - Claude Code просто допишет ARGUMENTS: <твой ввод> в конец, так что ввод не теряется.
И приятная мелочь: с v2.1.199 скиллы можно стакать в начале сообщения. /code-review /fix-issue 123 загрузит оба и передаст 123 как $ARGUMENTS каждому. Раскрытие останавливается на первом токене который не является инлайново вызываемым скиллом.
Динамический контекст - то ради чего стоит переписать половину своих скиллов
Синтаксис !`<command>` выполняет shell-команду до того как содержимое скилла уйдёт в модель. Вывод подставляется на место плейсхолдера. Claude видит только результат - он не запускает эту команду, она уже отработала.
---
name: pr-summary
description: Summarize changes in a pull request
context: fork
agent: Explore
allowed-tools: Bash(gh *)
---
## Pull request context
- PR diff: !`gh pr diff`
- PR comments: !`gh pr view --comments`
- Changed files: !`gh pr diff --name-only`
## Your task
Summarize this pull request...
Разница с обычным «попроси Claude запустить gh pr diff» принципиальная: данные приходят в промпт уже готовыми, без лишнего раунда инструментов и без шанса что модель решит что diff ей не нужен.
Пара граблей:
- Подстановка выполняется один раз по исходному файлу. Вывод команды вставляется как простой текст и повторно не сканируется - команда не может выдать плейсхолдер для следующего прохода.
- Инлайновая форма распознаётся только когда
!стоит в начале строки или сразу после пробела. ВKEY=!cmd`` плейсхолдер останется литеральным текстом. - Для многострочного используй блок открытый через
```!. - Отключается настройкой
"disableSkillShellExecution": true- полезно в managed settings, где пользователи не могут её переопределить.
Что реально контролирует автовызов
Claude решает загружать ли скилл автоматически на основе поля description (плюс when_to_use если оно есть). Это семантическое соответствие, не keyword matching - что звучит гибко но имеет конкретный недостаток: трудно предсказать или тестировать.
Есть символьный бюджет для листинга. Все имена скиллов всегда загружаются в контекст, но описания обрезаются чтобы уместиться в динамический лимит - он масштабируется как 1% контекстного окна модели. Каждая отдельная запись (description + when_to_use вместе) ограничена 1 536 символами независимо от бюджета.
Второй важный нюанс: когда листинг переполняется, Claude Code срезает описания начиная с наименее часто вызываемых скиллов. То есть скиллы которыми ты реально пользуешься сохраняют полный текст, а страдают редкие. Это лучше чем случайное обрезание, но означает что новый скилл в большой коллекции стартует в невыгодной позиции.
Диагностика:
/doctor- оценка стоимости листинга в контексте и крупнейшие вкладчики/context- строка Skills показывает размер листинга после применения бюджета, то есть ровно то что получает модель (до v2.1.196 она считала полный текст и могла показывать число в разы больше реального)--debug- при переполнении листинга в лог пишется предупреждение
Поднять бюджет можно настройкой skillListingBudgetFraction (например 0.02 = 2%) или переменной SLASH_COMMAND_TOOL_CHAR_BUDGET для фиксированного числа символов. Лимит на запись настраивается через skillListingMaxDescChars. Но более полезное исправление - писать более чёткие описания и держать общее количество скиллов низким. Это то же давление что и счётчик инструментов MCP серверов - оба конкурируют за один контекстный бюджет.
Чтобы предотвратить автовызов скилла полностью - добавь disable-model-invocation: true в frontmatter. Deployment и другие деструктивные воркфлоу всегда должны иметь это.
---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
---
Жизненный цикл содержимого скилла
Когда скилл вызывается, отрендеренное содержимое SKILL.md попадает в разговор одним сообщением и остаётся там до конца сессии. Claude Code не перечитывает файл на последующих ходах. Практический вывод: пиши руководство которое должно действовать на протяжении всей задачи как постоянные инструкции, а не как одноразовые шаги.
Что из этого следует:
- Повторный вызов скилла с идентичным отрендеренным содержимым больше не дублирует его - Claude Code добавляет короткую пометку что скилл уже загружен (с v2.1.202; раньше каждый повторный вызов приклеивал полную копию). Если содержимое отличается - аргументы поменялись, динамическая команда выдала новый вывод - контент приклеивается заново целиком.
- Автокомпакция переносит вызванные скиллы вперёд в пределах токенного бюджета: после суммаризации переприкрепляется последний вызов каждого скилла, по первые 5 000 токенов от каждого, с общим бюджетом 25 000 токенов. Заполняется от самого свежего вызова - значит старые скиллы могут выпасть целиком если ты за сессию вызвал много.
- Если кажется что скилл «перестал влиять» после первого ответа - содержимое почти наверняка на месте, просто модель выбирает другие инструменты. Усиливай
descriptionи инструкции, либо ставь хук если поведение должно быть детерминированным. После компакции большой скилл имеет смысл вызвать заново.
Подводные камни
Инверсия приоритетов
Порядок приоритетов - enterprise > personal > project - по-прежнему удивляет. Если у тебя глобальный ~/.claude/skills/deploy/SKILL.md и команда добавляет проектный deploy скилл с другими шагами для этого конкретного репо - проектный проигрывает.
# Не делай так - предполагает что project-level побеждает
~/.claude/skills/deploy/SKILL.md # глобальный deploy
.claude/skills/deploy/SKILL.md # предполагаемый project override - будет проигнорирован
# Делай так вместо этого
~/.claude/skills/deploy/SKILL.md # generic deploy scaffold
.claude/skills/deploy-staging/SKILL.md # project-specific
.claude/skills/deploy-prod/SKILL.md # project-specific с env контекстом
Оговорка которую нужно добавить: для вложенных директорий правило другое. Скилл в apps/web/.claude/skills/deploy/ не проигрывает корневому - он сосуществует с ним под именем /apps/web:deploy, и Claude сам выбирает вариант по файлам над которыми работает. Так что в монорепе разводить имена руками уже не обязательно.
Тихая проблема несоответствия
Скиллы которые должны автовызываться часто просто не срабатывают. Описание слишком расплывчатое, слишком длинное, или не соответствует тому как реально ведётся разговор. Предупреждений нет.
# Слишком расплывчато - Claude не знает когда применять
description: Helps with code quality and reviews
# Лучше - конкретное условие триггера, конкретная задача
description: Reviews staged changes for test coverage and conventional commit format. Use before opening a PR.
Отдельный случай который выглядит так же, но лечится иначе: битый YAML во frontmatter. Claude Code загрузит тело скилла с пустыми метаданными - /skill-name будет работать, а автовызова не будет никогда, потому что description для матчинга просто нет. Запусти с --debug чтобы увидеть ошибку парсинга.
Порядок диагностики: проверь что скилл вообще виден (спроси «What skills are available?»), проверь --debug на ошибки парсинга, вызови напрямую через /skill-name чтобы подтвердить что инструкции работают, и только потом дорабатывай описание.
Context bloat от always-loaded скиллов
Держи тело скилла лаконичным. Заявляй что делать, а не рассказывай как и почему. Тот же тест на краткость что и для содержимого CLAUDE.md.
Инструменты:
- Task скиллы - deployments, migrations, PR creation - почти всегда
disable-model-invocation: true. - Reference скиллы - conventions, patterns, API documentation - разумные кандидаты для автовызова, но их лучше ограничивать через
pathsвместо «или всегда, или никогда». - Длинный справочный материал - в поддерживающие файлы, не в тело.
Есть также взаимодействие с хуками: хук который запускает форматтер на каждой записи файла уже добавляет токенные накладные расходы. Наложи широко автовызывающийся скилл поверх этого - и per-turn стоимость быстро растёт.
Скиллы проекта - это вектор доверия
allowed-tools в скилле из .claude/skills/ репозитория вступает в силу после того как ты принял workspace trust dialog - так же как правила разрешений в .claude/settings.json. Скилл может выдать себе широкий доступ к инструментам. Ревьюй чужие project скиллы перед тем как доверять репозиторию.
skillOverrides: выключить скилл не трогая файл
Настройка skillOverrides управляет видимостью скиллов из твоих settings, а не из frontmatter самого скилла. Полезно для скиллов чей SKILL.md ты не хочешь править - закоммиченных в общий репозиторий или поставляемых MCP-сервером. Меню /skills пишет её за тебя: подсвети скилл, Space переключает состояния, Enter сохраняет в .claude/settings.local.json.
| Значение | Виден Claude | В меню / |
|---|---|---|
"on" |
Имя и описание | Да |
"name-only" |
Только имя | Да |
"user-invocable-only" |
Скрыт | Да |
"off" |
Скрыт | Скрыт |
{
"skillOverrides": {
"legacy-context": "name-only",
"deploy": "off"
}
}
"name-only" - хороший способ освободить бюджет листинга не удаляя скилл. Плагинные скиллы через skillOverrides не управляются, для них /plugin.
Если нужно резать доступ жёстче - есть правила разрешений: Skill(commit) для точного совпадения, Skill(review-pr *) для префикса с любыми аргументами, голый Skill в deny отключает все скиллы разом.
Встроенные скиллы которые стоит знать
Claude Code поставляется с набором bundled скиллов. Они prompt-based (не hardcoded), так что могут читать файлы, порождать агентов и адаптироваться к кодовой базе:
/batch <instruction>- разбивает большое изменение на параллельные единицы, порождает одного агента на единицу в изолированном git worktree, и открывает PR на единицу. Требует git репо./simplify [focus]- порождает трёх параллельных агентов ревью (переиспользование кода, качество, эффективность), агрегирует находки и применяет исправления. Передай фокус:/simplify focus on memory efficiency./code-review- ревью корректности, дополняет/simplify./loop [interval] <prompt>- запускает промпт повторно по расписанию пока сессия открыта./debug [description]- включает debug логирование mid-session и читает лог./claude-api- загружает справочный материал API для языка проекта. Также автовызывается когда обнаруживает Anthropic SDK import в коде./doctor- проверка конфигурации.
Отдельная тройка появилась недавно (требует v2.1.145+) и закрывает дыру между «тесты прошли» и «оно реально работает»:
/run- запустить приложение и провести по нему чтобы увидеть изменение в деле/verify- собрать и запустить приложение чтобы подтвердить что изменение делает то что должно, без опоры на тесты и тайпчек/run-skill-generator- научить/runи/verifyсобирать и запускать конкретно твой проект
/run и /verify работают без настройки: выводят способ запуска из типа проекта и из README, package.json или Makefile. Этот вывод становится ненадёжным как только проекту нужно что-то сверх стандартного запуска - база, env-файл, графическая сессия, многоэтапная сборка. /run-skill-generator вместо угадывания записывает рецепт: поднимает приложение с чистого окружения, фиксирует что сработало, и коммитит это как per-project скилл в .claude/skills/run-<name>/. Прогнать один раз на проект, и ещё раз если процесс сборки поменялся.
Различие между bundled скиллами и built-in slash командами (/compact, /clear, /cost) важно: built-in команды выполняют фиксированную логику и не могут быть кастомизированы. Bundled скиллы - prompt-based, и их можно переопределить создав скилл с тем же именем. Граница между этими двумя категориями двигается: /doctor был built-in командой, а с v2.1.205 стал bundled скиллом.
Отключить весь набор - настройка disableBundledSkills (/doctor остаётся доступным; скрывается отдельно через DISABLE_DOCTOR_COMMAND или "doctor": "off" в skillOverrides).
Как понять что скилл реально работает
То что скилл сработал говорит только что Claude его нашёл, а не что он сделал то что задумано. Меряй две вещи отдельно: вызывается ли скилл на тех промптах на которых должен, и совпадает ли вывод с ожидаемым когда вызывается.
Базовый способ - сравнение: собери несколько реалистичных промптов, прогони каждый в свежей сессии со скиллом и ещё раз с выключенным (через skillOverrides), сравни результаты. Свежая сессия принципиальна: остаточный контекст от написания скилла замаскирует дыры в самих инструкциях.
Для автоматизации этого цикла есть плагин skill-creator из официального маркетплейса:
/plugin install skill-creator@claude-plugins-official
/reload-plugins
Дальше просишь Claude оценить конкретный скилл. Плагин хранит тест-кейсы в evals/evals.json внутри директории скилла, прогоняет каждый в отдельном субагенте с чистым контекстом, пишет pass/fail с доказательствами в grading.json, агрегирует pass rate, время и токены с-скиллом против без-скилла в benchmark.json, умеет слепое A/B двух версий и - отдельно полезное - тюнинг описания: генерирует should-trigger и should-not-trigger промпты, меряет попадание и предлагает правки описания если скилл срабатывает не там.
Если бы я добавлял одну привычку из всего этого поста - это была бы вот эта. Тюнинг описания вслепую был самой утомительной частью работы со скиллами.
Советы
- Держи проектные скиллы в version control. Коммить
.claude/skills/в репо. - Один скилл - одна работа. Скилл который делает code review, генерирует commit message и проверяет coverage хуже чем три сфокусированных скилла.
- Имя директории - это команда. Не полагайся на
nameво frontmatter чтобы переименовать команду. - Используй динамический контекст вместо инструкций «запусти X».
!`git diff HEAD`в теле скилла надёжнее чем просьба сделать то же самое. - Ограничивай автовызов через
paths, а не через полное отключение. Это появилось недавно и решает старую дилемму. - Используй поддерживающие файлы для длинного справочного контента. Держи
SKILL.mdпод 500 строк. - Тестируй инструкции скилла вызовом напрямую.
/skill-nameобходит matching описания. Если скилл работает когда вызван вручную но не автоматически - описание нуждается в работе (или frontmatter битый - проверь--debug). - Добавь инвентарь скиллов в CLAUDE.md. Перечисли доступные кастомные скиллы и когда их использовать.
Итог
Скиллы требуют более обдуманной настройки чем документация подразумевает. Автовызов зависит полностью от качества описания, и тихий режим сбоя - где скилл просто не срабатывает - занимает время для диагностики в первый раз. Порядок приоритетов (глобальный бьёт проектный) удивит почти всех.
Общий принцип: используй project-level скиллы для командных воркфлоу, держи их сфокусированными и явно именованными, ставь disable-model-invocation: true на всё деструктивное, и дополняй автовызов инвентарём скиллов в CLAUDE.md.

Комментарии