Зачем это нужно
Расширения - главный механизм добавления возможностей в Spec Kit: доменные команды, интеграции внешних инструментов, quality gates, хуки. Уже знакомые bundled-расширения bug (урок 16.6) и assess (урок 16.7) - частные случаи; каталог сообщества насчитывает 157 расширений (срез 2026-10-03, урок 16.19).
Этот урок - справочник жизненного цикла расширения: поиск, установка (из каталога, URL или локальной директории), обновление, enable/disable, приоритеты резолюции, каталоги с моделью доверия discovery-only против install-источников и конфигурация расширений и хуков.
Основная идея
Расширение добавляет новые команды, шаблоны, скрипты и хуки поверх встроенного SDD-workflow. Устанавливается в .specify/extensions/<ext>/, команды регистрируются в активной интеграции агента. Несколько расширений сосуществуют; конфликты имен команд решаются приоритетами (меньше число - выше приоритет). Каталоги делятся на install-источники и discovery-only - это граница безопасности, а не техническое ограничение.
Поиск
specify extension search [query]
| Опция | Описание |
|---|---|
--tag |
фильтр по тегу |
--author |
фильтр по автору |
--verified |
только verified-расширения |
Ищет по всем активным каталогам; без запроса выводит все доступные расширения.
Установка
specify extension add <name>
| Опция | Описание |
|---|---|
--dev |
установка из локального каталога (для разработки) |
--from <url> |
установка из кастомного URL вместо каталога |
--version <v> |
точная версия, анонсированная каталогом |
--force |
перезаписать установленное расширение |
--priority <N> |
приоритет резолюции (дефолт 10; меньше = выше) |
Команды расширения регистрируются в активной интеграции. Для generic вызовы идут в настроенный --commands-dir: плоские файлы команд по умолчанию или speckit-<name>/SKILL.md с --skills. Core-команда speckit.taskstoissues остается доступной рядом с namespaced-заменой GitHub-расширения на время миграции.
Если refresh generic-интеграции не может воспроизвести каждый вызов расширения (команда или скилл изменена пользователем или источник отсутствует), команда предупреждает и восстанавливает прежние зарегистрированные артефакты этого расширения; остальные обновляются.
Нюансы пиновки версий: неквалифицированная установка из каталога берет анонсированную текущую версию; --version использует только выигравший каталог-источник для этого ID и не падает обратно на источник ниже приоритетом, если версии там нет; discovery-only каталоги остаются неустанавливаемыми; --version не комбинируется с --dev или --from. ID и версия скачанного архива проверяются до установки.
Все команды расширений требуют проект, инициализированный specify init.
Удаление и список
specify extension remove <name> # --keep-config: сохранить конфиги; --force: без подтверждения
specify extension list [--available|--all|--json]
Удаление по умолчанию бэкапит конфигурационные файлы. Список показывает статус, версию и количество команд; --available - доступные (неустановленные), --all - и те и другие.
Формат --json: массив в stdout, каждый элемент с ключами id, name, description, version, author (null при отсутствии), priority, enabled, source ({"kind":"local"} или {"kind":"catalog","catalog":"<имя>"}) и provides (счетчики commands, templates, scripts, hooks). Успех - ровно один массив и exit 0; сбой рантайма - ровно один {"error":"..."} в stderr и exit 1; usage-ошибка с --json - JSON-объект ошибки в stderr с сохранением usage-кода (обычно 2).
Информация и версии
specify extension info <name> [--versions]
Подробности об установленном или доступном расширении: описание, версия, команды, конфигурация. --versions перечисляет текущую и исторические версии выигравшего каталога; discovery-only источники помечаются как неустанавливаемые. Эквивалентные написания PEP 440 (v1.0 и 1.0) выбирают один релиз; видимое написание - как в каталоге.
Каталоги могут держать текущий релиз в верхних полях и исторические - в маппинге releases (у каждого релиза свои download_url и SHA-256; релиз-специфичные требования - в записи релиза, не наследуются). Текущая версия не должна повторяться в releases; битые и дублирующиеся записи отклоняются. Пины бандлов пока используют текущий путь резолюции каталога.
Обновление и приоритеты
specify extension update [<name>] # одно или все установленные
Bundled-расширения (agent-context, git) не имеют download URL - их обновления ставятся из копии, поставляемой с текущим релизом spec-kit. Если каталог анонсирует более новую версию, чем шипит ваш релиз, обновление потребует сначала апгрейда spec-kit. Для generic неудачное обновление восстанавливает hash-owned вызовы из ранее настроенных --commands-dir-папок, даже если активна другая интеграция.
specify extension enable <name> # включить
specify extension disable <name> # выключить без удаления
specify extension set-priority <name> <priority>
Выключенное расширение не грузится, его команды недоступны. Hook-only расширения ставятся и переключаются даже при невалидных настройках generic-вывода; расширения с командами требуют валидных настроек. Для generic disable удаляет hash-owned вызовы даже после переезда каталога вывода, сохраняя посторонние одноименные файлы в новом каталоге. При конфликте имен команд выигрывает расширение с наименьшим числом приоритета.
Каталоги и модель доверия
Каталоги определяют, где search и add ищут расширения; проверяются в порядке приоритета (меньше число - выше).
Discovery-only против install-источников
Каталоги двух видов, и различие - граница безопасности, а не ограничение:
- install-источники (
install_allowed: true) - каталоги, которым вы доверяете как месту установки: встроенныйdefault(официальный) и любые каталоги, которые вы авторите и вэтите сами; - discovery-only (
install_allowed: false) - поисковые поверхности для нахождения расширений, без установки: встроенныйcommunityкаталог discovery-only и активен дляsearchиз коробки.
community намеренно discovery-only: это открытый невэтченный список - one-command-install всего подряд означало бы тянуть произвольный сторонний код без ревью.
Не переключайте discovery-only каталог в install_allowed - это разрушает саму идею разделения. Два корректных пути установить найденное через community:
-
Установить одно провэтченное расширение напрямую через
--from(без авторинга каталогов). URL архива дастspecify extension info- для discovery-only записей печатается «Candidate archive». Отревьюйте релизный архив, затем:bashspecify extension info <name> # печатает URL архива-кандидата specify extension add <name> --from <archive-url>
Считайте URL недоверенным, пока не провэттили: он из невэтченного каталога.
-
Кураторство собственного каталога под вашим контролем с
install_allowed: true- для управляемого переиспользуемого источника установки (например, для организации).
Управление
specify extension catalog list
specify extension catalog add <url> # --name (обязательно), --priority, --install-allowed|--no-install-allowed, --description
specify extension catalog remove <name>
Каталог добавляется в .specify/extension-catalogs.yml. Повторное добавление именованного каталога с идентичными настройками - no-op; с другими - отказ. Порядок резолюции (первый матч выигрывает):
- переменная
SPECKIT_CATALOG_URLперекрывает все; - конфиг проекта
.specify/extension-catalogs.yml; - пользовательский
~/.specify/extension-catalogs.yml; - встроенные дефолты: официальный
default(install-allowed) +community(discovery-only).
Пример каталога организации:
catalogs:
- name: "my-org-catalog"
url: "https://example.com/catalog.json"
priority: 5
install_allowed: true
description: "Our approved extensions"
--install-allowed включайте только для каталога, которым владеете и который вэтите; никогда - для непроверенного публичного.
Конфигурация расширений
Большинство расширений несут конфиги в каталоге установки:
.specify/extensions/<ext>/
├── <ext>-config.yml # конфиг проекта (под версионным контролем)
├── <ext>-config.local.yml # локальные оверрайды (gitignored)
└── <ext>-config.template.yml # шаблон-референс
Слияние по возрастанию приоритета (последний - самый важный):
1. Дефолты расширения (extension.yml)
2. Конфиг проекта (<ext>-config.yml)
3. Локальные оверрайды (<ext>-config.local.yml)
4. Переменные окружения (SPECKIT_<EXT>_*)
Для настройки нового расширения скопируйте шаблон:
cp .specify/extensions/<ext>/<ext>-config.template.yml \
.specify/extensions/<ext>/<ext>-config.yml
Конфигурация расширений и хуков проекта
Регистрация расширений и хуков уровня проекта хранится в .specify/extensions.yml: установленные расширения, глобальные настройки и хуки, всплывающие до или после команд Spec Kit.
installed:
- git
- my-extension
settings:
auto_execute_hooks: true
hooks:
before_implement:
- extension: git
command: speckit.git.commit
enabled: true
optional: true
priority: 10
prompt: "Commit outstanding changes before implementation?"
description: "Auto-commit before implementation"
after_implement:
- extension: my-extension
command: speckit.my-extension.verify
enabled: true
optional: false
priority: 5
description: "Run verification after implementation"
Поля записи хука:
| Поле | Описание |
|---|---|
extension |
ID расширения, зарегистрировавшего хук |
command |
команда расширения, связанная с хуком |
enabled |
активность; enabled: false - пропуск |
optional |
true: хук показывается с prompt и может быть пропущен; false: эмитится как автоматический (с маркерами EXECUTE_COMMAND) |
priority |
метаданные приоритета: целые >= 1; записи из манифестов без декларации получают 10. Текущие шаблоны команд выводят хуки в YAML-порядке конфигурации, не сортируя по priority |
prompt |
сообщение при вопросе о запуске опционального хука |
description |
человеческое пояснение |
condition |
опциональное выражение для HookExecutor (config.<path> / env.<VAR>, операции is set, ==, !=). Текущие шаблоны команд условия не вычисляют и пропускают хуки с непустым condition |
Имена событий: before_<command> / after_<command> - например, before_implement, after_implement, before_tasks, after_tasks.
Нормализация приоритетов: манифесты расширений отклоняют невалидные приоритеты при установке; для существующих записей HookExecutor.get_hooks_for_event() нормализует через normalize_priority() - отсутствующие значения, булеаны, отвергнутые int() строки и значения < 1 падают в 10; числовые строки и конечные float приводятся int(). Метод возвращает хуки, отсортированные по priority (меньше - раньше), но текущие шаблоны команд читают списки хуков напрямую и выводят в YAML-порядке.
Частые вопросы
- Поиск не находит расширение: проверьте написание; расширение может быть не опубликовано или лежать в неподключенном каталоге (
specify extension catalog list). - Команда расширения не появилась в агенте: проверьте
specify extension list(installed + enabled), затем перезапустите агента - перезагрузка файлов может требоваться. - Конфликт версий: обновите Spec Kit до версии, требуемой расширением.
- Кто поддерживает расширения: большинство создаются и поддерживаются авторами независимо; мейнтейнеры Spec Kit не ревьюят, не аудируют, не одобряют и не поддерживают код расширений. Ревьюйте исходники до установки; по проблемам конкретного расширения - к его автору или в репозиторий расширения.
Практика
- Установите bundled-расширение
git, изучите.specify/extensions.yml(запись вinstalled), затем disable/enable и проверьте исчезновение/возвращение команд. - Найдите в
specify extension searchрасширение из discovery-only каталога, получите черезinfoURL архива-кандидата и установите через--from- пройдите путь «обнаружение -> вэттинг -> установка». - Скопируйте config-template любого установленного расширения в config.yml, поменяйте значение и проверьте порядок слияния с
<ext>-config.local.yml.
Краткое резюме
Расширения добавляют возможности через команды, шаблоны, скрипты и хуки. Жизненный цикл: search -> add (каталог / --from URL / --dev локально / --version пин) -> update / enable / disable / set-priority / remove. Каталоги образуют стек приоритетов с границей безопасности: install-источники против discovery-only; community - discovery-only, установка найденного - через вэттинг --from или кураторский каталог организации. Конфигурация расширений сливается (дефолты -> проект -> локально -> env); хуки .specify/extensions.yml вешаются на before_/after_<command> с флагами optionality и приоритетами.
Главное из урока:
- приоритет резолюции конфликтов - наименьшее число; дефолт 10;
- bundled-расширения обновляются вместе с релизом spec-kit;
--versionне падает на каталоги ниже приоритетом и не комбинируется с--dev/--from;- никогда не включайте
install_allowedдля невэтченного каталога; - хуки:
optional: true- с промптом,optional: false- автоматический;conditionтекущими шаблонами не вычисляется.
Вопросы для самопроверки
- Перечислите источники установки расширения и их флаги. Какие флаги взаимно исключаемы?
- Почему community-каталог discovery-only? Какие два корректных способа установить найденное в нем?
- Опишите порядок резолюции каталогов расширений. Что перекрывает все?
- Как разрешается конфликт, когда два расширения дают команду с одним именем? Какой командой меняется приоритет установленного?
- Из каких слоев сливается конфигурация расширения? Какие файлы в каталоге расширения за что отвечают?
- Чем опциональный хук отличается от автоматического в
.specify/extensions.yml? Что делаетconditionсегодня?
Что дальше
Пресеты меняют существующие шаблоны и команды без нового тулинга. Урок 16.13 - установка, стратегии композиции (replace/overlay), полный порядок резолюции файлов и управление каталогами пресетов.