Зачем это нужно
CLI specify управляет всем жизненным циклом проекта Spec Kit - от инициализации до автоматизации workflow (справочник по нему открывает блок D модуля). Этот урок - справочник по трем фундаментальным темам CLI: core-команды (init, check, version), переменные окружения, определяющие поведение в CI и монорепо; экспериментальный MCP-сервер; и opt-in аутентификация для приватных каталогов и расширений.
Справочные уроки блока D (16.10-16.16) предполагают, что эти основы усвоены.
Основная идея
Core-команды немногочисленны: init создает проект, check проверяет инструменты, version сообщает информацию о CLI. Вся мощь - в опциях init и переменных окружения, которые разделяют выбор проекта и выбор фичи как две независимые оси. MCP-сервер - экспериментальный stdio-мост к JSON-командам CLI (пока только version). Аутентификация opt-in: без ~/.specify/auth.json ни один запрос не несет креденшелов.
specify init
specify init [<project_name>]
| Опция | Описание |
|---|---|
--integration <key> |
интеграция coding-агента (copilot, claude, gemini и др.; полный список - урок 16.10) |
--integration-options |
опции интеграции (например, --integration-options="--commands-dir .myagent/cmds") |
--script sh|ps|py |
тип скриптов: sh (bash/zsh), ps (PowerShell), py (Python) |
--here |
инициализировать в текущем каталоге вместо создания нового |
--force |
слить/перезаписать без подтверждения при инициализации в непустом каталоге |
--ignore-agent-tools |
пропустить проверку CLI-инструментов агентов |
--preset <id> |
установить пресет при инициализации |
Создает проект Spec Kit: структура каталогов, шаблоны, скрипты и файлы интеграции агента. Инициализацию Git-репозитория и ветвление ведет git-расширение, по умолчанию не ставящееся: specify extension add git после init включает git-workflows.
Примеры:
# новый проект с интеграцией
specify init my-project --integration copilot
# в текущем каталоге
specify init --here --integration copilot
# принудительное слияние в непустой каталог
specify init --here --force --integration copilot
# PowerShell-скрипты
specify init my-project --integration copilot --script ps
# пресет при инициализации
specify init my-project --integration copilot --preset compliance
Без --integration интерактивный терминал предложит выбор; неинтерактивные сессии (CI, пайпы) берут GitHub Copilot - переопределите флагом или переменной SPECKIT_INTEGRATION_DEFAULT.
Переменные окружения
| Переменная | Назначение |
|---|---|
SPECKIT_INTEGRATION_DEFAULT |
дефолтная интеграция specify init при отсутствии --integration (интерактивный дефолт и неинтерактивный fallback). Нераспознанное значение игнорируется с предупреждением, используется встроенный copilot. Явный --integration всегда важнее |
SPECIFY_INIT_DIR |
целевой проект извне его каталога (например, из корня монорепо) без cd - для неинтерактива/CI. Указывает корень проекта - каталог, содержащий .specify/ (относительные пути резолвятся от текущего). Путь обязан существовать и содержать .specify/, иначе ошибка без fallback на текущий каталог. Значение наследуют core-скрипты фич (/speckit.plan, /speckit.tasks, ...) и создание веток git-расширения; те же правила валидации применяет каждая project-scoped-подкоманда (specify integration/extension/workflow/preset ...) |
SPECIFY_FEATURE_DIRECTORY |
переопределить каталог активной фичи (приоритетнее .specify/feature.json). Относительный путь присоединяется к корню проекта без проверки вложенности - ../shared-feature тоже сработает; абсолютный используется как есть. Корень проекта по-прежнему задает контекст команд, но каталог фичи не обязан жить внутри него. Комбинируется с SPECIFY_INIT_DIR для неинтерактивного выбора проекта и фичи |
SPECIFY_FEATURE |
явно переопределить метку активной фичи (например, 001-photo-albums) - идентификатор, который core-хелперы отдают как текущую фичу/ветку. Хелперы Git не инспектируют: с переменной возвращают ее дословно, без - пустую строку. Каталог фичи она не находит: с одной лишь SPECIFY_FEATURE разрешение путей фичи падает с ошибкой «Feature directory not found» - используйте SPECIFY_FEATURE_DIRECTORY или .specify/feature.json |
SPECIFY_FEATURE_NO_PERSIST |
1/true запрещает core-скриптам писать .specify/feature.json, даже когда они персистили бы SPECIFY_FEATURE_DIRECTORY. Полезно, когда несколько агентов работают параллельно с одним checkout и у каждого своя SPECIFY_FEATURE_DIRECTORY - без флага каждый вызов может перезаписать чужую закрепленную фичу |
Две оси резолюции: SPECIFY_INIT_DIR выбирает проект (какой каталог содержит .specify/); SPECIFY_FEATURE_DIRECTORY / .specify/feature.json выбирают фичу - по умолчанию она под specs/ проекта, но явно выбранный каталог фичи не обязан быть внутри него. Оси независимы: сначала проект, затем фича.
Контроль версий: specify init scaffolds управляемый .specify/.gitignore, исключающий machine-local-состояние - feature.json (указатель текущей фичи, перезаписывается при каждом переключении) и per-machine оверрайды расширений extensions/*/local-config.yml - при сохранении шаримости всего остального (конституция, шаблоны, скрипты, конфигурация расширений). Файл отслеживается в манифесте общей инфраструктуры: правки сохраняются при re-init, specify init --here --force восстанавливает managed-контент. specify integration uninstall его не удаляет.
Симлинки: SPECIFY_INIT_DIR переносит, где находится проект, а не меняет отношение команд к симлинкам; команды с широкими путями записи (bundle, workflow run <file>) отказываются работать с симлинкованным .specify/, сохраняя конфайнмент записи.
Именование фич в helper-скриптах
Хелперы create-new-feature при прямом вызове сохраняют Unicode-буквы и цифры в UTF-8: описание «добавить пользователя» даст 001-добавить-пользователя (пример оригинала - 添加用户 -> 001-添加用户). Описание из одной пунктуации даст пустой суффикс 001-; скрипты предупреждают в stderr, JSON-вывод остается парсибельным. Сменить имя, не меняя описания:
bash .specify/scripts/bash/create-new-feature.sh --json --short-name 用户管理 "添加用户"
Python-хелпер принимает --short-name, PowerShell - -ShortName. Короткое имя чистится теми же правилами и обязано содержать букву или цифру. ASCII-капитал переводится в нижний регистр; регистр не-ASCII букв сохраняется.
specify check
specify check
Проверяет доступность CLI-based AI-агентов в системе. IDE-based агенты пропускаются - CLI-инструмент им не нужен. Команда остается офлайн. Если команда ведет себя как старая версия Spec Kit или ожидаемая фича отсутствует - прогоните specify self check, не отстает ли локальный CLI от последнего релиза.
specify version
specify version
Показывает версию CLI, Python, платформу и архитектуру. Инспекция локальных возможностей без сети:
specify version --features
Полная информация (версия, рантайм, система, фичи) как JSON:
specify version --json
Комбинация --features и --json дает тот же полный JSON - --features в JSON-режиме не фильтрует. Недоступная информация OpenSSL отражается как runtime.openssl: null. Успешный JSON пишется только в stdout; при сбое stdout пуст, а в stderr уходит один санитизированный JSON-объект ошибки. Быстрая проверка: specify --version / specify -V.
Экспериментальный MCP-сервер
specify mcp
Стартует сервер Model Context Protocol поверх только stdio. HTTP, SSE, управление демоном/сервисом и выбор транспорта не предоставляются; MCP-хост настраивается на запуск specify mcp как локального субпроцесса. Поскольку stdout несет кадры протокола MCP, сервер не печатает туда баннер, Rich-вывод, стартовые сообщения, предупреждения и логи.
Сервер экспонирует три generic-инструмента:
| Инструмент | Назначение |
|---|---|
specify_list_commands |
список CLI-команд, поддержанных через MCP |
specify_describe_command |
описание одной поддержанной dotted-команды |
specify_run_command |
запуск одной поддержанной команды через реальный CLI |
Первый экспериментальный релиз поддерживает только dotted-команду version; остальные имена отклоняются ошибкой unavailable_command. Сервер не экспонирует обнаружение проектов, артефакты, мутации, установку/обновление, workflows, подтверждения или уровни доступа.
specify_run_command вызывает каноническую команду specify version --json в изолированном дочернем процессе того же Python-окружения. Успех - прямой JSON-объект команды (cli_version, runtime, system, features) без обертки schema_version/ok/result. Сбой CLI - ошибка инструмента с error.code, error.message, error.details из stderr. Пустой/битый/смешанный вывод дочернего процесса - санитизированная adapter_internal_error; сервер никогда не подставляет success-shaped fallback и не раскрывает traceback.
Статус: experimental - инвентарь команд и контракты инструментов могут меняться до объявления MCP-поверхности стабильной.
Аутентификация
Specify CLI использует opt-in-аутентификацию для HTTP-запросов к источникам каталогов, загрузкам расширений и проверкам релизов. Без явной конфигурации креденшелов не отправляется ничего.
Конфигурация
Файл ~/.specify/auth.json включает аутентификацию:
{
"providers": [
{
"hosts": ["github.com", "api.github.com", "raw.githubusercontent.com", "codeload.github.com"],
"provider": "github",
"auth": "bearer",
"token_env": "GH_TOKEN"
}
]
}
Безопасность: ограничьте файл доступом только владельца:
chmod 600 ~/.specify/auth.json
Поля записи
| Поле | Обязательно | Описание |
|---|---|---|
hosts |
да | массив имен хостов; точные имена или ведущий *. только для поддоменов (*.visualstudio.com матчит foo.visualstudio.com, но не visualstudio.com; прочие glob-паттерны не поддерживаются) |
provider |
да | встроенный провайдер: github, azure-devops, bitbucket |
auth |
да | схема (см. ниже) |
token |
нет | значение токена inline; предпочитайте token_env |
token_env |
нет | имя переменной окружения с токеном |
username |
для basic |
имя пользователя Basic-креденшела (для API-токенов Bitbucket - email аккаунта Atlassian); без : |
Для azure-ad дополнительно: tenant_id, client_id, client_secret_env (переменная с секретом service principal). Для схем bearer, basic-pat, basic обязателен token или token_env.
Провайдеры и схемы
GitHub. Схема bearer (Authorization: Bearer <token>) - PAT, fine-grained PAT, OAuth, токены GitHub App. Для GitHub Enterprise Server добавьте github-запись с вашими GHES-хостами: она аутентифицирует и fetch каталогов, и загрузки приватных release-ассетов через GHES REST API (/api/v3). Перечисляйте голый web-хост (ghes.example.com) - там живут URL загрузок релизов; при изоляции поддоменов добавьте и raw./codeload.-поддомены (wildcard *.ghes.example.com голый хост не матчит). Для GHE.com с data residency перечисляйте оба хоста - web и API (tenant.ghe.com, api.tenant.ghe.com).
Azure DevOps. Схемы: basic-pat (PAT), bearer (предвыданные OAuth/Azure AD-токены), azure-cli (токен из az account get-access-token, требует предварительного az login), azure-ad (OAuth2 client credentials flow - для CI/автоматизации).
{
"hosts": ["dev.azure.com"],
"provider": "azure-devops",
"auth": "azure-ad",
"tenant_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"client_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"client_secret_env": "AZURE_CLIENT_SECRET"
}
Bitbucket. Схемы: bearer (access-токены репозитория/проекта/workspace; Atlassian API-токены без email - только api.bitbucket.org; HTTP-токены Data Center) и basic (Atlassian API-токены с email аккаунта как username против api.bitbucket.org; app-пароли Bitbucket Cloud удалены Atlassian 28.07.2026 - используйте API- или access-токен).
Нюанс хостов: web-хост bitbucket.org (страницы браузера, ссылки .../raw/..., git clone по HTTPS) эти креденшелы не принимает. Направляйте каталоги и download_url на api.bitbucket.org (например, GET /2.0/repositories/<workspace>/<repo>/src/<ref>/catalog.json). Загрузки из секции Downloads идут редиректом на pre-signed S3 URL: Specify срезает заголовок Authorization при уходе с заявленных хостов - это ожидаемо, S3 URL самоавторизован; пин sha256 в записях каталога сохраняет integrity-check последнего неаутентифицированного хопа.
Множественные записи и механика
Записей может быть несколько - под разные хосты или организации (например, GitHub + Azure DevOps в одном файле). Как это работает:
- Для каждого исходящего HTTP-запроса hostname матчаится с паттернами
hostsвauth.json. - При совпадении провайдер резолвит токен и прикрепляет нужный заголовок
Authorization. - При ответе 401/403 пробуется следующая совпадающая запись.
- Когда совпадающие записи исчерпаны - финальная попытка без аутентификации.
- При редиректе заголовок
Authorizationсрезается, если цель покидает заявленные хосты записи - креденшелы не утекают на CDN и сторонние сервисы.
Практика
- Инициализируйте тестовый проект с переменной
SPECKIT_INTEGRATION_DEFAULT=geminiбез флага--integrationв неинтерактивном режиме - проверьте, что fallback сработал; затем задайте неверное значение и убедитесь в предупреждении. - В монорепо-подобной структуре попробуйте пару
SPECIFY_INIT_DIR+SPECIFY_FEATURE_DIRECTORYиз корня: убедитесь, что команды находят проект и фичу безcd, а ошибочныйSPECIFY_INIT_DIR(без.specify/) дает ошибку, а не fallback. - Соберите
auth.jsonсtoken_envдля любого своего хостинга, проверьтеchmod 600, затем запуститеspecify version --json- убедитесь, что команда работает независимо от auth-конфигурации (аутентификация opt-in, только для HTTP-запросов к каталогам/релизам).
Краткое резюме
Core-слой CLI мал и предсказуем: init (опции интеграции, скриптов, пресета, интерактива), офлайн check и многоформатный version. Поведение в CI и монорепо управляется пятью переменными окружения с двумя независимыми осями - проект (SPECIFY_INIT_DIR) и фича (SPECIFY_FEATURE_DIRECTORY), плюс защита параллельных агентов SPECIFY_FEATURE_NO_PERSIST. specify mcp - экспериментальный stdio-сервер с поверхностью из трех generic-инструментов и единственной командой version. Аутентификация - opt-in через ~/.specify/auth.json с провайдерами GitHub/Azure DevOps/Bitbucket, матчитнгом хостов, каскадом 401/403 и срезанием Authorization на внешних редиректах.
Главное из урока:
specify initне инициализирует Git - это делает opt-in git-расширение;SPECIFY_FEATUREзадает только метку фичи, не ее каталог - каталог выбираетсяSPECIFY_FEATURE_DIRECTORYилиfeature.json;- MCP-сервер пока version-only: не рассчитывайте на него для управления проектами;
- без
auth.jsonзапросы анонимны; токены храните в переменных окружения (token_env), а не inline; - для Bitbucket указывайте
api.bitbucket.org, неbitbucket.org/.../raw/....
Вопросы для самопроверки
- Перечислите опции
specify initи их назначение. Какая опция устанавливает пресет при инициализации? - Объясните разницу между
SPECIFY_INIT_DIR,SPECIFY_FEATURE_DIRECTORYиSPECIFY_FEATURE. Почему оси проекта и фичи независимы? - Зачем нужна
SPECIFY_FEATURE_NO_PERSIST? Какую проблему параллельной работы она решает? - Какую единственную команду поддерживает экспериментальный MCP-сервер и как обрабатываются сбои дочернего процесса?
- Опишите алгоритм аутентификации исходящего запроса: от матчинга хостов до финального fallback. Когда срезается
Authorization? - Почему для Bitbucket Cloud каталоги должны указывать на
api.bitbucket.org? Что происходит с заголовком при редиректе на S3?
Что дальше
Интеграции - интерфейс между CLI и вашим coding-агентом. Урок 16.10 разбирает 38 интеграций: куда пишутся файлы команд, как переключаться между агентами, синтаксис вызова и каталог интеграций.