Каждое утро повторяется один и тот же ритуал: вспомнить, что вы вчера сделали, посмотреть, что осталось незакоммиченным, и сформулировать три пункта для команды. Данные для этого отчёта лежат прямо под рукой — в git-истории и рабочем дереве, — но собираются они руками, каждый раз заново, и что-нибудь обязательно забывается.
Это идеальная форма для скилла: процедура фиксированная, источник данных известен, результат нужен в одном и том же формате. В этом уроке мы соберём скилл /standup от наивной версии до рабочей и по дороге разберём, почему каждое решение принято именно так. После урока вы сможете превращать в скиллы собственные ежедневные ритуалы.
Что уже умеем / что добавим
Вы уже знаете, из чего состоит скилл: директория, файл SKILL.md, YAML-frontmatter и markdown-инструкции. Знаете, что тело скилла попадает в контекст только при вызове, а имя команды берётся из имени директории. Теперь мы применим это к живой задаче и добавим главный приём этого урока — динамический контекст: команды, которые выполняются до того, как содержимое уйдёт модели.
Что вы узнаете в рамках статьи
- Как выбрать задачу, из которой получится полезный скилл
- Чем плоха инструкция «посмотри, что я делал» без данных
- Как встроить вывод git-команд в тело скилла через
!команда`` - Зачем скиллу
allowed-tools,|| trueиdisable-model-invocation - Как быстро итерировать по скиллу и где его хранить
Ключевые термины
- Динамический контекст — синтаксис
!команда``, при котором команда выполняется до отправки содержимого скилла модели, а её вывод занимает место плейсхолдера. - Плейсхолдер — место в теле скилла, куда подставляется результат: вывод команды или значение аргумента.
- Инвокация скилла — один запуск скилла: подстановка динамических данных, рендер содержимого и передача его модели.
allowed-tools— список инструментов, которыми можно пользоваться без запроса разрешения в течение хода, вызвавшего скилл.disable-model-invocation— поле frontmatter, запрещающее Claude загружать скилл самостоятельно; остаётся только ручной вызов/имя.
Наивная версия: инструкция без данных
Начнём с самого очевидного варианта. Создаём директорию и кладём в неё файл:
mkdir -p ~/.claude/skills/standup
$EDITOR ~/.claude/skills/standup/SKILL.md
---
description: Собирает стендап-отчёт за рабочий день
---
Посмотри, что я делал сегодня в этом репозитории, и собери стендап:
что сделано, над чем идёт работа, что мешает.
Формально это работает. Практически — разочаровывает. Claude приходится самому догадываться, откуда взять данные: он выберет какие-то git-команды, возможно не те, возможно с другими границами по времени. Завтра он выберет другие. Результат нестабилен от запуска к запуску, а на сбор данных тратится несколько лишних ходов. Вы описали цель, но не описали процедуру, хотя процедура вам как раз известна.
Рабочая версия: данные приходят раньше модели
Правильное решение — вшить команды прямо в тело скилла. Синтаксис !`команда` выполняет команду до того, как содержимое отправится модели, и подставляет вывод на место плейсхолдера. Claude получает уже готовые данные, а не задание их добыть.
---
description: Собирает стендап-отчёт за день по git-истории
argument-hint: [период]
disable-model-invocation: true
allowed-tools: Bash(git log *) Bash(git status *) Bash(git branch *)
---
## Текущая ветка
!`git branch --show-current || true`
## Коммиты за сегодня
!`git log --since=midnight --author="you@example.com" --oneline || true`
## Незавершённая работа
!`git status --short || true`
## Инструкции
Составь стендап-отчёт по данным выше, строго в трёх разделах:
«Сделано», «В работе», «Блокеры». В «Сделано» — по одному пункту
на смысловую задачу, а не на каждый коммит. В «В работе» — изменённые
файлы и текущая ветка. В «Блокеры» — пиши «нет», если ничего не мешает.
Если коммитов за период нет, так и скажи, не выдумывай активность.
Важная деталь синтаксиса: ! распознаётся, только если стоит в начале строки или сразу после пробельного символа. Запись вида BRANCH=!`git branch --show-current` командой не считается — плейсхолдер останется литеральным текстом. Если команд подряд несколько, удобнее блок, открытый ```!:
## Окружение
```!
git branch --show-current
git status --short
```
Инженерные решения во frontmatter
Каждая строка frontmatter здесь появилась не для красоты.
disable-model-invocation: true — стендап нужен по расписанию человека, а не тогда, когда Claude решил, что момент подходящий. Побочный выигрыш: описание скилла перестаёт занимать место в контексте, потому что модели оно больше не нужно для выбора.
allowed-tools — обязательная строка, а не рекомендация. Внедрённые команды никогда не спрашивают разрешение. Если проверка разрешений вернула не «allow», вся инвокация прерывается с сообщением вида Shell command permission check failed for pattern "..." — отчёта вы не увидите вовсе. Предодобрение снимает вопрос.
|| true — страховка от падения. Неуспешная команда прерывает не свой плейсхолдер, а всю инвокацию: Claude вообще не получает содержимое скилла, вы получаете Shell command failed for pattern "...". Тонкость: для поисковых и сравнивающих команд код возврата 1 считается нормальным результатом, а коды 2 и выше — ошибкой. Для остальных ошибкой считается любой ненулевой код, поэтому || true дописывают там, где ненулевой код штатен.
argument-hint: [период] — подсказка в автодополнении. Сама подстановка аргументов в тело скилла — тема следующего урока; пока это просто анонс того, что скилл ожидает период.
Формат вывода и цикл итерации
Отдельно стоит явно задать структуру отчёта в инструкциях. Без этого каждый запуск даёт немного разный формат, и коллеги перестают воспринимать отчёт с одного взгляда. Ожидаемый результат выглядит так:
Сделано:
- Починил валидацию токена в auth-middleware (3 коммита)
- Обновил схему миграции для таблицы sessions
В работе:
- Ветка feat/session-cleanup, изменены 4 файла, не закоммичены
Блокеры:
- нет
Доводить скилл до этого вида удобно короткими шагами. Claude Code следит за директориями скиллов, и правки SKILL.md подхватываются в текущей сессии без перезапуска. Цикл «поправил файл — вызвал /standup — посмотрел вывод» занимает секунды. Перезапуск нужен лишь в одном случае: если вы создали каталог скиллов верхнего уровня, которого не было на старте сессии.
Осталось решить, где скилл живёт. ~/.claude/skills/standup/ — личная привычка, доступная во всех ваших проектах. .claude/skills/standup/ в репозитории — командное соглашение: файл едет в git, и стендап у всех получается одинаковым. Помните про приоритет: если скилл с таким именем есть на обоих уровнях, персональный перекроет проектный.
Частые ошибки
- Забыть
allowed-tools. Внедрённая команда не спросит разрешение — она просто оборвёт инвокацию сShell command permission check failed. Перечисляйте паттерны для всех команд из тела скилла. - Оставить команду без
|| true. Одна неуспешная команда роняет весь скилл, а не свой блок. Особенно обидно, когда причина — пустой результат, а не реальная поломка. - Поставить
!не в начале строки. После другого символа плейсхолдер остаётся текстом, команда не выполняется, и Claude видит инструкцию вместо данных. - Не задать формат отчёта. Без явной структуры каждый запуск выдаёт свою композицию, и смысл автоматизации теряется.
Наиболее частые вопросы
- Почему не оставить Claude свободу самому выбрать git-команды? — Потому что предсказуемость и есть цель. Вшитые команды дают один и тот же срез данных каждый день.
- Что будет, если за день ничего не закоммичено? —
git logвернёт пустой вывод, скилл отработает штатно. Поэтому в инструкциях полезно прямо сказать, как описывать день без коммитов. - Нужно ли перезапускать Claude Code после правки
SKILL.md? — Нет, изменения подхватываются в текущей сессии. - Можно ли вызвать
/standup, если стоитdisable-model-invocation: true? — Да. Это поле закрывает только автоматическую загрузку моделью, ручной вызов работает. - Куда попадает stderr внедрённой команды? — При bash он по умолчанию сливается в stdout и оказывается во внедрённом тексте.
Итоги
Вы прошли путь, который повторяется почти на каждом полезном скилле: наивная формулировка цели, столкновение с нестабильностью, перенос известной процедуры внутрь скилла и обвязка, которая не даёт ему упасть. Теперь у вас есть рабочий /standup, а вместе с ним — понимание, почему allowed-tools и || true не мелочь, а условие того, что скилл вообще запустится.
Возьмите этот шаблон и приложите к другим своим ритуалам: сводка перед code review, чек-лист перед релизом, обзор чужих изменений за неделю. А на следующем уроке мы научим скиллы принимать аргументы — и тот самый [период] из argument-hint наконец начнёт работать по-настоящему.