This page provides a comprehensive guide for developers who want to create custom extensions for Spec Kit. It covers the extension directory structure, manifest schema, command definitions, hook registration, configuration management, and multi-agent support.
For information about installing and managing extensions as a user, see Extension Management Commands. For details about the internal architecture and how extensions are processed, see Extension Architecture. For publishing extensions to the catalog, see the Extension Publishing Guide referenced in the CHANGELOG.
Extensions are self-contained packages that add commands and functionality to Spec Kit without bloating the core CLI. Each extension consists of:
extension.yml): Metadata, command definitions, hooks, and default configurationExtensions are installed into .specify/extensions/{extension-id}/ and registered in .specify/extensions/.registry.
Sources: CHANGELOG.md14-28 CHANGELOG.md108-114
The basic structure of an extension follows this pattern:
my-extension/
├── extension.yml # Manifest file (required)
├── commands/ # Command templates directory
│ ├── command1.md # Markdown format command
│ └── command2.toml # TOML format command (optional)
├── config/
│ └── default-config.yml # Default configuration (optional)
├── README.md # Documentation (recommended)
├── LICENSE # License file (recommended)
├── CHANGELOG.md # Change history (recommended)
└── examples/ # Usage examples (optional)
└── example-usage.md
After installation by the ExtensionManager, the extension is copied to:
.specify/extensions/
├── .registry # JSON registry of installed extensions
├── .cache/ # Catalog cache
└── my-extension/ # Installed extension
├── extension.yml
├── commands/
├── config/
│ ├── default-config.yml
│ ├── my-extension-config.yml # Project config (Layer 2)
│ └── local-config.yml # Local config (Layer 3, gitignored)
└── README.md
Commands from commands/ are automatically registered with detected AI agents during installation.
Sources: CHANGELOG.md108-114 CHANGELOG.md18
The extension.yml file defines the extension's metadata, commands, hooks, and configuration. Here is the complete schema:
Sources: CHANGELOG.md16-17
| Field | Type | Description |
|---|---|---|
id | string | Unique extension identifier (lowercase, hyphenated) |
name | string | Human-readable extension name |
version | string | Semantic version (e.g., 1.0.0) |
description | string | Brief description of extension functionality |
author | string | Author name or organization |
license | string | SPDX license identifier (e.g., MIT) |
| Field | Type | Description |
|---|---|---|
repository | string | URL to extension source repository |
min_speckit_version | string | Minimum required Spec Kit version |
tags | array | Categorization tags (e.g., ["integration", "project-management"]) |
Sources: CHANGELOG.md41-50 CHANGELOG.md16-17
Command files are templates that define the prompts AI agents execute. Spec Kit supports two formats based on agent requirements:
Used by most CLI-based agents (Claude, Cursor, Copilot, Qwen Code, etc.):
The $ARGUMENTS placeholder is replaced with user-provided arguments at runtime.
Sources: CHANGELOG.md71-72
Used by TOML-based agents (Gemini CLI, Qwen CLI in TOML mode):
The {{args}} placeholder is the TOML equivalent of $ARGUMENTS.
Sources: CHANGELOG.md71-72
Sources: CHANGELOG.md68-77
Hooks allow extensions to automatically execute commands at specific points in the Spec-Driven Development workflow. The HookExecutor class manages hook registration and execution.
| Event | Trigger Point | Use Case |
|---|---|---|
before_plan | Before /speckit.plan execution | Pre-plan validation or data gathering |
after_plan | After /speckit.plan completion | Plan analysis or artifact generation |
before_tasks | Before /speckit.tasks execution | Task template preparation |
after_tasks | After /speckit.tasks completion | Issue creation, estimation |
before_implement | Before /speckit.implement execution | Environment setup, dependency checks |
after_implement | After /speckit.implement completion | Deployment, documentation generation |
Conditions control when hooks execute. Supported patterns:
Config-based conditions:
Environment-based conditions:
The HookExecutor evaluates conditions before execution. Invalid conditions default to false (hook skipped).
Sources: CHANGELOG.md51-59 CHANGELOG.md88-94
Sources: CHANGELOG.md95-101
After core commands like /speckit.plan or /speckit.tasks, AI agents should query available hooks:
The check_hooks_for_event() method returns condition-filtered hooks with formatted messages.
Sources: CHANGELOG.md96-100
Extensions support a four-layer configuration cascade that balances flexibility with security. The ConfigManager class handles configuration merging and access.
Sources: CHANGELOG.md78-87
| Layer | File Location | Version Control | Use Case |
|---|---|---|---|
| Layer 1 | extension.yml config section | Committed | Sensible defaults provided by extension author |
| Layer 2 | .specify/extensions/{ext-id}/{ext-id}-config.yml | Committed | Team-wide project settings |
| Layer 3 | .specify/extensions/{ext-id}/local-config.yml | Gitignored | Machine-specific overrides (API keys, local paths) |
| Layer 4 | SPECKIT_{EXT_ID}_{KEY} environment variables | Runtime | CI/CD environments, temporary overrides |
In extension.yml:
.specify/extensions/jira/jira-config.yml:
.specify/extensions/jira/local-config.yml (gitignored):
Environment variable naming convention: SPECKIT_{EXT_ID}_{KEY} where keys are uppercased and nested paths use underscores (e.g., SPECKIT_JIRA_ISSUE_TYPE_MAPPING_STORY).
Sources: CHANGELOG.md78-87
Command templates can reference configuration values. At runtime, the AI agent resolves these through the ConfigManager:
Configuration values are injected as environment variables or passed as command context.
Extensions must work across 16+ AI agents with different conventions. The CommandRegistrar handles agent-specific adaptations during installation.
Sources: CHANGELOG.md68-77
| Agent | Directory | Format | Placeholder |
|---|---|---|---|
| Claude Code | .claude/commands/ | Markdown | $ARGUMENTS |
| Gemini CLI | .gemini/commands/ | TOML | {{args}} |
| GitHub Copilot | .github/agents/ | Markdown | $ARGUMENTS |
| Cursor | .cursor/commands/ | Markdown | $ARGUMENTS |
| Qwen Code | .qwen/commands/ | TOML | {{args}} |
| Windsurf | .windsurf/workflows/ | Markdown | $ARGUMENTS |
| ... | ... | ... | ... |
The CommandRegistrar.register_commands_for_all_agents() method automatically detects installed agents and generates appropriate command files.
Sources: CHANGELOG.md68-77
When registering a Markdown command for a TOML-based agent:
Source (Markdown):
Generated (TOML):
The CommandRegistrar performs this conversion automatically by:
$ARGUMENTS → {{args}}Sources: CHANGELOG.md71-72
Before publishing, test extensions locally using the --dev flag:
Development mode installs extensions from a local directory without copying to .specify/extensions/, allowing live editing.
specify extension info my-extension displays correct metadataspecify extension remove my-extension cleans up properlySources: CHANGELOG.md21
Spec Kit provides a starter template in extensions/template/ with fully commented examples:
extensions/template/
├── extension.yml # Annotated manifest with all options
├── commands/
│ └── example-command.md # Detailed command example
├── config/
│ └── default-config.yml # Configuration examples
├── EXAMPLE-README.md # Documentation template
├── LICENSE # MIT license template
├── CHANGELOG.md # Change history template
└── .gitignore # Recommended ignore patterns
Copy this template as a starting point:
Sources: CHANGELOG.md108-114
To make your extension discoverable via specify extension search, add it to the central catalog:
Prepare extension repository:
v1.0.0)Submit catalog entry:
extensions/catalog.jsonCatalog entry schema:
verified: false - Community extensions (default)verified: true - Official extensions reviewed by maintainersOnce merged, users can install your extension:
Sources: CHANGELOG.md30-39
| Entity | Location | Purpose |
|---|---|---|
ExtensionManager | src/specify_cli/extensions.py | Main extension lifecycle manager |
CommandRegistrar | src/specify_cli/extensions.py | Multi-agent command registration |
HookExecutor | src/specify_cli/extensions.py | Hook lifecycle and execution |
ConfigManager | src/specify_cli/extensions.py | Configuration cascade management |
ExtensionCatalog | src/specify_cli/extensions.py | Catalog fetching and caching |
| Extension Registry | .specify/extensions/.registry | JSON database of installed extensions |
| Extension Catalog | extensions/catalog.json | Central directory of published extensions |
| Extension Template | extensions/template/ | Starter template for new extensions |
| Jira Extension | extensions/jira/ | Reference implementation example |
Sources: CHANGELOG.md18 CHANGELOG.md31-33 CHANGELOG.md52-54 CHANGELOG.md84
Creating Spec Kit extensions involves:
extension.yml, commands/, and optional config/extension.yml$ARGUMENTS placeholdersCommandRegistrar handle agent-specific format conversion automatically--dev flag for local testing before publishingThe extension system provides a clean separation between core Spec Kit functionality and domain-specific integrations, enabling a rich ecosystem of tools while keeping the base CLI lightweight.
Sources: CHANGELOG.md14-28 CHANGELOG.md68-77 CHANGELOG.md78-87 CHANGELOG.md88-101 CHANGELOG.md108-114
Refresh this wiki