Files
spec-kit/extensions/RFC-EXTENSION-SYSTEM.md
Manfred Riem 990a1513c2 fix: address PR review feedback for multi-catalog support
- Rename 'org-approved' catalog to 'default'
- Move 'catalogs' command to 'catalog list' for consistency
- Add 'description' field to CatalogEntry dataclass
- Add --description option to 'catalog add' CLI command
- Align install_allowed default to False in _load_catalog_config
- Add user-level config detection in catalog list footer
- Fix _load_catalog_config docstring (document ValidationError)
- Fix test isolation for test_search_by_tag, test_search_by_query,
  test_search_verified_only, test_get_extension_info
- Update version to 0.1.14 and CHANGELOG
- Update all docs (RFC, User Guide, API Reference)
2026-03-09 14:07:29 -05:00

1911 lines
57 KiB
Markdown

# RFC: Spec Kit Extension System
**Status**: Draft
**Author**: Stats Perform Engineering
**Created**: 2026-01-28
**Updated**: 2026-01-28
---
## Table of Contents
1. [Summary](#summary)
2. [Motivation](#motivation)
3. [Design Principles](#design-principles)
4. [Architecture Overview](#architecture-overview)
5. [Extension Manifest Specification](#extension-manifest-specification)
6. [Extension Lifecycle](#extension-lifecycle)
7. [Command Registration](#command-registration)
8. [Configuration Management](#configuration-management)
9. [Hook System](#hook-system)
10. [Extension Discovery & Catalog](#extension-discovery--catalog)
11. [CLI Commands](#cli-commands)
12. [Compatibility & Versioning](#compatibility--versioning)
13. [Security Considerations](#security-considerations)
14. [Migration Strategy](#migration-strategy)
15. [Implementation Phases](#implementation-phases)
16. [Open Questions](#open-questions)
17. [Appendices](#appendices)
---
## Summary
Introduce an extension system to Spec Kit that allows modular integration with external tools (Jira, Linear, Azure DevOps, etc.) without bloating the core framework. Extensions are self-contained packages installed into `.specify/extensions/` with declarative manifests, versioned independently, and discoverable through a central catalog.
---
## Motivation
### Current Problems
1. **Monolithic Growth**: Adding Jira integration to core spec-kit creates:
- Large configuration files affecting all users
- Dependencies on Jira MCP server for everyone
- Merge conflicts as features accumulate
2. **Limited Flexibility**: Different organizations use different tools:
- GitHub Issues vs Jira vs Linear vs Azure DevOps
- Custom internal tools
- No way to support all without bloat
3. **Maintenance Burden**: Every integration adds:
- Documentation complexity
- Testing matrix expansion
- Breaking change surface area
4. **Community Friction**: External contributors can't easily add integrations without core repo PR approval and release cycles.
### Goals
1. **Modularity**: Core spec-kit remains lean, extensions are opt-in
2. **Extensibility**: Clear API for building new integrations
3. **Independence**: Extensions version/release separately from core
4. **Discoverability**: Central catalog for finding extensions
5. **Safety**: Validation, compatibility checks, sandboxing
---
## Design Principles
### 1. Convention Over Configuration
- Standard directory structure (`.specify/extensions/{name}/`)
- Declarative manifest (`extension.yml`)
- Predictable command naming (`speckit.{extension}.{command}`)
### 2. Fail-Safe Defaults
- Missing extensions gracefully degrade (skip hooks)
- Invalid extensions warn but don't break core functionality
- Extension failures isolated from core operations
### 3. Backward Compatibility
- Core commands remain unchanged
- Extensions additive only (no core modifications)
- Old projects work without extensions
### 4. Developer Experience
- Simple installation: `specify extension add jira`
- Clear error messages for compatibility issues
- Local development mode for testing extensions
### 5. Security First
- Extensions run in same context as AI agent (trust boundary)
- Manifest validation prevents malicious code
- Verify signatures for official extensions (future)
---
## Architecture Overview
### Directory Structure
```text
project/
├── .specify/
│ ├── scripts/ # Core scripts (unchanged)
│ ├── templates/ # Core templates (unchanged)
│ ├── memory/ # Session memory
│ ├── extensions/ # Extensions directory (NEW)
│ │ ├── .registry # Installed extensions metadata (NEW)
│ │ ├── jira/ # Jira extension
│ │ │ ├── extension.yml # Manifest
│ │ │ ├── jira-config.yml # Extension config
│ │ │ ├── commands/ # Command files
│ │ │ ├── scripts/ # Helper scripts
│ │ │ └── docs/ # Documentation
│ │ └── linear/ # Linear extension (example)
│ └── extensions.yml # Project extension configuration (NEW)
└── .gitignore # Ignore local extension configs
```
### Component Diagram
```text
┌─────────────────────────────────────────────────────────┐
│ Spec Kit Core │
│ ┌──────────────────────────────────────────────────┐ │
│ │ CLI (specify) │ │
│ │ - init, check │ │
│ │ - extension add/remove/list/update ← NEW │ │
│ └──────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Extension Manager ← NEW │ │
│ │ - Discovery, Installation, Validation │ │
│ │ - Command Registration, Hook Execution │ │
│ └──────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Core Commands │ │
│ │ - /speckit.specify │ │
│ │ - /speckit.tasks │ │
│ │ - /speckit.implement │ │
│ └─────────┬────────────────────────────────────────┘ │
└────────────┼────────────────────────────────────────────┘
│ Hook Points (after_tasks, after_implement)
┌─────────────────────────────────────────────────────────┐
│ Extensions │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Jira Extension │ │
│ │ - /speckit.jira.specstoissues │ │
│ │ - /speckit.jira.discover-fields │ │
│ └──────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Linear Extension │ │
│ │ - /speckit.linear.sync │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│ Calls external tools
┌─────────────────────────────────────────────────────────┐
│ External Tools │
│ - Jira MCP Server │
│ - Linear API │
│ - GitHub API │
└─────────────────────────────────────────────────────────┘
```
---
## Extension Manifest Specification
### Schema: `extension.yml`
```yaml
# Extension Manifest Schema v1.0
# All extensions MUST include this file at root
# Schema version for compatibility
schema_version: "1.0"
# Extension metadata (REQUIRED)
extension:
id: "jira" # Unique identifier (lowercase, alphanumeric, hyphens)
name: "Jira Integration" # Human-readable name
version: "1.0.0" # Semantic version
description: "Create Jira Epics, Stories, and Issues from spec-kit artifacts"
author: "Stats Perform" # Author/organization
repository: "https://github.com/statsperform/spec-kit-jira"
license: "MIT" # SPDX license identifier
homepage: "https://github.com/statsperform/spec-kit-jira/blob/main/README.md"
# Compatibility requirements (REQUIRED)
requires:
# Spec-kit version (semantic version range)
speckit_version: ">=0.1.0,<2.0.0"
# External tools required by extension
tools:
- name: "jira-mcp-server"
required: true
version: ">=1.0.0" # Optional: version constraint
description: "Jira MCP server for API access"
install_url: "https://github.com/your-org/jira-mcp-server"
check_command: "jira --version" # Optional: CLI command to verify
# Core spec-kit commands this extension depends on
commands:
- "speckit.tasks" # Extension needs tasks command
# Core scripts required
scripts:
- "check-prerequisites.sh"
# What this extension provides (REQUIRED)
provides:
# Commands added to AI agent
commands:
- name: "speckit.jira.specstoissues"
file: "commands/specstoissues.md"
description: "Create Jira hierarchy from spec and tasks"
aliases: ["speckit.specstoissues"] # Alternate names
- name: "speckit.jira.discover-fields"
file: "commands/discover-fields.md"
description: "Discover Jira custom fields for configuration"
- name: "speckit.jira.sync-status"
file: "commands/sync-status.md"
description: "Sync task completion status to Jira"
# Configuration files
config:
- name: "jira-config.yml"
template: "jira-config.template.yml"
description: "Jira integration configuration"
required: true # User must configure before use
# Helper scripts
scripts:
- name: "parse-jira-config.sh"
file: "scripts/parse-jira-config.sh"
description: "Parse jira-config.yml to JSON"
executable: true # Make executable on install
# Extension configuration defaults (OPTIONAL)
defaults:
project:
key: null # No default, user must configure
hierarchy:
issue_type: "subtask"
update_behavior:
mode: "update"
sync_completion: true
# Configuration schema for validation (OPTIONAL)
config_schema:
type: "object"
required: ["project"]
properties:
project:
type: "object"
required: ["key"]
properties:
key:
type: "string"
pattern: "^[A-Z]{2,10}$"
description: "Jira project key (e.g., MSATS)"
# Integration hooks (OPTIONAL)
hooks:
# Hook fired after /speckit.tasks completes
after_tasks:
command: "speckit.jira.specstoissues"
optional: true
prompt: "Create Jira issues from tasks?"
description: "Automatically create Jira hierarchy after task generation"
# Hook fired after /speckit.implement completes
after_implement:
command: "speckit.jira.sync-status"
optional: true
prompt: "Sync completion status to Jira?"
# Tags for discovery (OPTIONAL)
tags:
- "issue-tracking"
- "jira"
- "atlassian"
- "project-management"
# Changelog URL (OPTIONAL)
changelog: "https://github.com/statsperform/spec-kit-jira/blob/main/CHANGELOG.md"
# Support information (OPTIONAL)
support:
documentation: "https://github.com/statsperform/spec-kit-jira/blob/main/docs/"
issues: "https://github.com/statsperform/spec-kit-jira/issues"
discussions: "https://github.com/statsperform/spec-kit-jira/discussions"
email: "support@statsperform.com"
```
### Validation Rules
1. **MUST have** `schema_version`, `extension`, `requires`, `provides`
2. **MUST follow** semantic versioning for `version`
3. **MUST have** unique `id` (no conflicts with other extensions)
4. **MUST declare** all external tool dependencies
5. **SHOULD include** `config_schema` if extension uses config
6. **SHOULD include** `support` information
7. Command `file` paths **MUST be** relative to extension root
8. Hook `command` names **MUST match** a command in `provides.commands`
---
## Extension Lifecycle
### 1. Discovery
```bash
specify extension search jira
# Searches catalog for extensions matching "jira"
```
**Process:**
1. Fetch extension catalog from GitHub
2. Filter by search term (name, tags, description)
3. Display results with metadata
### 2. Installation
```bash
specify extension add jira
```
**Process:**
1. **Resolve**: Look up extension in catalog
2. **Download**: Fetch extension package (ZIP from GitHub release)
3. **Validate**: Check manifest schema, compatibility
4. **Extract**: Unpack to `.specify/extensions/jira/`
5. **Configure**: Copy config templates
6. **Register**: Add commands to AI agent config
7. **Record**: Update `.specify/extensions/.registry`
**Registry Format** (`.specify/extensions/.registry`):
```json
{
"schema_version": "1.0",
"extensions": {
"jira": {
"version": "1.0.0",
"installed_at": "2026-01-28T14:30:00Z",
"source": "catalog",
"manifest_hash": "sha256:abc123...",
"enabled": true
}
}
}
```
### 3. Configuration
```bash
# User edits extension config
vim .specify/extensions/jira/jira-config.yml
```
**Config discovery order:**
1. Extension defaults (`extension.yml``defaults`)
2. Project config (`jira-config.yml`)
3. Local overrides (`jira-config.local.yml` - gitignored)
4. Environment variables (`SPECKIT_JIRA_*`)
### 4. Usage
```bash
claude
> /speckit.jira.specstoissues
```
**Command resolution:**
1. AI agent finds command in `.claude/commands/speckit.jira.specstoissues.md`
2. Command file references extension scripts/config
3. Extension executes with full context
### 5. Update
```bash
specify extension update jira
```
**Process:**
1. Check catalog for newer version
2. Download new version
3. Validate compatibility
4. Back up current config
5. Extract new version (preserve config)
6. Re-register commands
7. Update registry
### 6. Removal
```bash
specify extension remove jira
```
**Process:**
1. Confirm with user (show what will be removed)
2. Unregister commands from AI agent
3. Remove from `.specify/extensions/jira/`
4. Update registry
5. Optionally preserve config for reinstall
---
## Command Registration
### Per-Agent Registration
Extensions provide **universal command format** (Markdown-based), and CLI converts to agent-specific format during registration.
#### Universal Command Format
**Location**: Extension's `commands/specstoissues.md`
```markdown
---
# Universal metadata (parsed by all agents)
description: "Create Jira hierarchy from spec and tasks"
tools:
- 'jira-mcp-server/epic_create'
- 'jira-mcp-server/story_create'
scripts:
sh: ../../scripts/bash/check-prerequisites.sh --json
ps: ../../scripts/powershell/check-prerequisites.ps1 -Json
---
# Command implementation
## User Input
$ARGUMENTS
## Steps
1. Load jira-config.yml
2. Parse spec.md and tasks.md
3. Create Jira items
```
#### Claude Code Registration
**Output**: `.claude/commands/speckit.jira.specstoissues.md`
```markdown
---
description: "Create Jira hierarchy from spec and tasks"
tools:
- 'jira-mcp-server/epic_create'
- 'jira-mcp-server/story_create'
scripts:
sh: .specify/scripts/bash/check-prerequisites.sh --json
ps: .specify/scripts/powershell/check-prerequisites.ps1 -Json
---
# Command implementation (copied from extension)
## User Input
$ARGUMENTS
## Steps
1. Load jira-config.yml from .specify/extensions/jira/
2. Parse spec.md and tasks.md
3. Create Jira items
```
**Transformation:**
- Copy frontmatter with adjustments
- Rewrite script paths (relative to repo root)
- Add extension context (config location)
#### Gemini CLI Registration
**Output**: `.gemini/commands/speckit.jira.specstoissues.toml`
```toml
[command]
name = "speckit.jira.specstoissues"
description = "Create Jira hierarchy from spec and tasks"
[command.tools]
tools = [
"jira-mcp-server/epic_create",
"jira-mcp-server/story_create"
]
[command.script]
sh = ".specify/scripts/bash/check-prerequisites.sh --json"
ps = ".specify/scripts/powershell/check-prerequisites.ps1 -Json"
[command.template]
content = """
# Command implementation
## User Input
{{args}}
## Steps
1. Load jira-config.yml from .specify/extensions/jira/
2. Parse spec.md and tasks.md
3. Create Jira items
"""
```
**Transformation:**
- Convert Markdown frontmatter to TOML
- Convert `$ARGUMENTS` to `{{args}}`
- Rewrite script paths
### Registration Code
**Location**: `src/specify_cli/extensions.py`
```python
def register_extension_commands(
project_path: Path,
ai_assistant: str,
manifest: dict
) -> None:
"""Register extension commands with AI agent."""
agent_config = AGENT_CONFIG.get(ai_assistant)
if not agent_config:
console.print(f"[yellow]Unknown agent: {ai_assistant}[/yellow]")
return
ext_id = manifest['extension']['id']
ext_dir = project_path / ".specify" / "extensions" / ext_id
agent_commands_dir = project_path / agent_config['folder'].rstrip('/') / "commands"
agent_commands_dir.mkdir(parents=True, exist_ok=True)
for cmd_info in manifest['provides']['commands']:
cmd_name = cmd_info['name']
source_file = ext_dir / cmd_info['file']
if not source_file.exists():
console.print(f"[red]Command file not found:[/red] {cmd_info['file']}")
continue
# Convert to agent-specific format
if ai_assistant == "claude":
dest_file = agent_commands_dir / f"{cmd_name}.md"
convert_to_claude(source_file, dest_file, ext_dir)
elif ai_assistant == "gemini":
dest_file = agent_commands_dir / f"{cmd_name}.toml"
convert_to_gemini(source_file, dest_file, ext_dir)
elif ai_assistant == "copilot":
dest_file = agent_commands_dir / f"{cmd_name}.md"
convert_to_copilot(source_file, dest_file, ext_dir)
# ... other agents
console.print(f" ✓ Registered: {cmd_name}")
def convert_to_claude(
source: Path,
dest: Path,
ext_dir: Path
) -> None:
"""Convert universal command to Claude format."""
# Parse universal command
content = source.read_text()
frontmatter, body = parse_frontmatter(content)
# Adjust script paths (relative to repo root)
if 'scripts' in frontmatter:
for key in frontmatter['scripts']:
frontmatter['scripts'][key] = adjust_path_for_repo_root(
frontmatter['scripts'][key]
)
# Inject extension context
body = inject_extension_context(body, ext_dir)
# Write Claude command
dest.write_text(render_frontmatter(frontmatter) + "\n" + body)
```
---
## Configuration Management
### Configuration File Hierarchy
```yaml
# .specify/extensions/jira/jira-config.yml (Project config)
project:
key: "MSATS"
hierarchy:
issue_type: "subtask"
defaults:
epic:
labels: ["spec-driven", "typescript"]
```
```yaml
# .specify/extensions/jira/jira-config.local.yml (Local overrides - gitignored)
project:
key: "MYTEST" # Override for local testing
```
```bash
# Environment variables (highest precedence)
export SPECKIT_JIRA_PROJECT_KEY="DEVTEST"
```
### Config Loading Function
**Location**: Extension command (e.g., `commands/specstoissues.md`)
````markdown
## Load Configuration
1. Run helper script to load and merge config:
```bash
config_json=$(bash .specify/extensions/jira/scripts/parse-jira-config.sh)
echo "$config_json"
```
1. Parse JSON and use in subsequent steps
````
**Script**: `.specify/extensions/jira/scripts/parse-jira-config.sh`
```bash
#!/usr/bin/env bash
set -euo pipefail
EXT_DIR=".specify/extensions/jira"
CONFIG_FILE="$EXT_DIR/jira-config.yml"
LOCAL_CONFIG="$EXT_DIR/jira-config.local.yml"
# Start with defaults from extension.yml
defaults=$(yq eval '.defaults' "$EXT_DIR/extension.yml" -o=json)
# Merge project config
if [ -f "$CONFIG_FILE" ]; then
project_config=$(yq eval '.' "$CONFIG_FILE" -o=json)
defaults=$(echo "$defaults $project_config" | jq -s '.[0] * .[1]')
fi
# Merge local config
if [ -f "$LOCAL_CONFIG" ]; then
local_config=$(yq eval '.' "$LOCAL_CONFIG" -o=json)
defaults=$(echo "$defaults $local_config" | jq -s '.[0] * .[1]')
fi
# Apply environment variable overrides
if [ -n "${SPECKIT_JIRA_PROJECT_KEY:-}" ]; then
defaults=$(echo "$defaults" | jq ".project.key = \"$SPECKIT_JIRA_PROJECT_KEY\"")
fi
# Output merged config as JSON
echo "$defaults"
```
### Config Validation
**In command file**:
````markdown
## Validate Configuration
1. Load config (from previous step)
2. Validate against schema from extension.yml:
```python
import jsonschema
schema = load_yaml(".specify/extensions/jira/extension.yml")['config_schema']
config = json.loads(config_json)
try:
jsonschema.validate(config, schema)
except jsonschema.ValidationError as e:
print(f"❌ Invalid jira-config.yml: {e.message}")
print(f" Path: {'.'.join(str(p) for p in e.path)}")
exit(1)
```
1. Proceed with validated config
````
---
## Hook System
### Hook Definition
**In extension.yml:**
```yaml
hooks:
after_tasks:
command: "speckit.jira.specstoissues"
optional: true
prompt: "Create Jira issues from tasks?"
description: "Automatically create Jira hierarchy"
condition: "config.project.key is set"
```
### Hook Registration
**During extension installation**, record hooks in project config:
**File**: `.specify/extensions.yml` (project-level extension config)
```yaml
# Extensions installed in this project
installed:
- jira
- linear
# Global extension settings
settings:
auto_execute_hooks: true # Prompt for optional hooks after commands
# Hook configuration
hooks:
after_tasks:
- extension: jira
command: speckit.jira.specstoissues
enabled: true
optional: true
prompt: "Create Jira issues from tasks?"
after_implement:
- extension: jira
command: speckit.jira.sync-status
enabled: true
optional: true
prompt: "Sync completion status to Jira?"
```
### Hook Execution
**In core command** (e.g., `templates/commands/tasks.md`):
Add at end of command:
````markdown
## Extension Hooks
After task generation completes, check for registered hooks:
```bash
# Check if extensions.yml exists and has after_tasks hooks
if [ -f ".specify/extensions.yml" ]; then
# Parse hooks for after_tasks
hooks=$(yq eval '.hooks.after_tasks[] | select(.enabled == true)' .specify/extensions.yml -o=json)
if [ -n "$hooks" ]; then
echo ""
echo "📦 Extension hooks available:"
# Iterate hooks
echo "$hooks" | jq -c '.' | while read -r hook; do
extension=$(echo "$hook" | jq -r '.extension')
command=$(echo "$hook" | jq -r '.command')
optional=$(echo "$hook" | jq -r '.optional')
prompt_text=$(echo "$hook" | jq -r '.prompt')
if [ "$optional" = "true" ]; then
# Prompt user
echo ""
read -p "$prompt_text (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "▶ Executing: $command"
# Let AI agent execute the command
# (AI agent will see this and execute)
echo "EXECUTE_COMMAND: $command"
fi
else
# Auto-execute mandatory hooks
echo "▶ Executing: $command (required)"
echo "EXECUTE_COMMAND: $command"
fi
done
fi
fi
```
````
**AI Agent Handling:**
The AI agent sees `EXECUTE_COMMAND: speckit.jira.specstoissues` in output and automatically invokes that command.
**Alternative**: Direct call in agent context (if agent supports it):
```python
# In AI agent's command execution engine
def execute_command_with_hooks(command_name: str, args: str):
# Execute main command
result = execute_command(command_name, args)
# Check for hooks
hooks = load_hooks_for_phase(f"after_{command_name}")
for hook in hooks:
if hook.optional:
if confirm(hook.prompt):
execute_command(hook.command, args)
else:
execute_command(hook.command, args)
return result
```
### Hook Conditions
Extensions can specify **conditions** for hooks:
```yaml
hooks:
after_tasks:
command: "speckit.jira.specstoissues"
optional: true
condition: "config.project.key is set and config.enabled == true"
```
**Condition evaluation** (in hook executor):
```python
def should_execute_hook(hook: dict, config: dict) -> bool:
"""Evaluate hook condition."""
condition = hook.get('condition')
if not condition:
return True # No condition = always eligible
# Simple expression evaluator
# "config.project.key is set" → check if config['project']['key'] exists
# "config.enabled == true" → check if config['enabled'] is True
return eval_condition(condition, config)
```
---
## Extension Discovery & Catalog
### Dual Catalog System
Spec Kit uses two catalog files with different purposes:
#### User Catalog (`catalog.json`)
**URL**: `https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.json`
- **Purpose**: Organization's curated catalog of approved extensions
- **Default State**: Empty by design - users populate with extensions they trust
- **Usage**: Primary catalog (priority 1, `install_allowed: true`) in the default stack
- **Control**: Organizations maintain their own fork/version for their teams
#### Community Reference Catalog (`catalog.community.json`)
**URL**: `https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json`
- **Purpose**: Reference catalog of available community-contributed extensions
- **Verification**: Community extensions may have `verified: false` initially
- **Status**: Active - open for community contributions
- **Submission**: Via Pull Request following the Extension Publishing Guide
- **Usage**: Secondary catalog (priority 2, `install_allowed: false`) in the default stack — discovery only
**How It Works (default stack):**
1. **Discover**: `specify extension search` searches both catalogs — community extensions appear automatically
2. **Review**: Evaluate community extensions for security, quality, and organizational fit
3. **Curate**: Copy approved entries from community catalog to your `catalog.json`, or add to `.specify/extension-catalogs.yml` with `install_allowed: true`
4. **Install**: Use `specify extension add <name>` — only allowed from `install_allowed: true` catalogs
This approach gives organizations full control over which extensions can be installed while still providing community discoverability out of the box.
### Catalog Format
**Format** (same for both catalogs):
```json
{
"schema_version": "1.0",
"updated_at": "2026-01-28T14:30:00Z",
"extensions": {
"jira": {
"name": "Jira Integration",
"id": "jira",
"description": "Create Jira Epics, Stories, and Issues from spec-kit artifacts",
"author": "Stats Perform",
"version": "1.0.0",
"download_url": "https://github.com/statsperform/spec-kit-jira/releases/download/v1.0.0/spec-kit-jira-1.0.0.zip",
"repository": "https://github.com/statsperform/spec-kit-jira",
"homepage": "https://github.com/statsperform/spec-kit-jira/blob/main/README.md",
"documentation": "https://github.com/statsperform/spec-kit-jira/blob/main/docs/",
"changelog": "https://github.com/statsperform/spec-kit-jira/blob/main/CHANGELOG.md",
"license": "MIT",
"requires": {
"speckit_version": ">=0.1.0,<2.0.0",
"tools": [
{
"name": "jira-mcp-server",
"version": ">=1.0.0"
}
]
},
"tags": ["issue-tracking", "jira", "atlassian", "project-management"],
"verified": true,
"downloads": 1250,
"stars": 45
},
"linear": {
"name": "Linear Integration",
"id": "linear",
"description": "Sync spec-kit tasks with Linear issues",
"author": "Community",
"version": "0.9.0",
"download_url": "https://github.com/example/spec-kit-linear/releases/download/v0.9.0/spec-kit-linear-0.9.0.zip",
"repository": "https://github.com/example/spec-kit-linear",
"requires": {
"speckit_version": ">=0.1.0"
},
"tags": ["issue-tracking", "linear"],
"verified": false
}
}
}
```
### Catalog Discovery Commands
```bash
# List all available extensions
specify extension search
# Search by keyword
specify extension search jira
# Search by tag
specify extension search --tag issue-tracking
# Show extension details
specify extension info jira
```
### Custom Catalogs
Spec Kit supports a **catalog stack** — an ordered list of catalogs that the CLI merges and searches across. This allows organizations to maintain their own org-approved extensions alongside an internal catalog and community discovery, all at once.
#### Catalog Stack Resolution
The active catalog stack is resolved in this order (first match wins):
1. **`SPECKIT_CATALOG_URL` environment variable** — single catalog replacing all defaults (backward compat)
2. **Project-level `.specify/extension-catalogs.yml`** — full control for the project
3. **User-level `~/.specify/extension-catalogs.yml`** — personal defaults
4. **Built-in default stack** — `catalog.json` (install_allowed: true) + `catalog.community.json` (install_allowed: false)
#### Default Built-in Stack
When no config file exists, the CLI uses:
| Priority | Catalog | install_allowed | Purpose |
|----------|---------|-----------------|---------|
| 1 | `catalog.json` (default) | `true` | Curated extensions available for installation |
| 2 | `catalog.community.json` (community) | `false` | Discovery only — browse but not install |
This means `specify extension search` surfaces community extensions out of the box, while `specify extension add` is still restricted to entries from catalogs with `install_allowed: true`.
#### `.specify/extension-catalogs.yml` Config File
```yaml
catalogs:
- name: "default"
url: "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.json"
priority: 1 # Highest — only approved entries can be installed
install_allowed: true
description: "Built-in catalog of installable extensions"
- name: "internal"
url: "https://internal.company.com/spec-kit/catalog.json"
priority: 2
install_allowed: true
description: "Internal company extensions"
- name: "community"
url: "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json"
priority: 3 # Lowest — discovery only, not installable
install_allowed: false
description: "Community-contributed extensions (discovery only)"
```
A user-level equivalent lives at `~/.specify/extension-catalogs.yml`. When a project-level config is present with one or more catalog entries, it takes full control and the built-in defaults are not applied. An empty `catalogs: []` list is treated the same as no config file, falling back to defaults.
#### Catalog CLI Commands
```bash
# List active catalogs with name, URL, priority, and install_allowed
specify extension catalog list
# Add a catalog (project-scoped)
specify extension catalog add --name "internal" --install-allowed \
https://internal.company.com/spec-kit/catalog.json
# Add a discovery-only catalog
specify extension catalog add --name "community" \
https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json
# Remove a catalog
specify extension catalog remove internal
# Show which catalog an extension came from
specify extension info jira
# → Source catalog: default
```
#### Merge Conflict Resolution
When the same extension `id` appears in multiple catalogs, the higher-priority (lower priority number) catalog wins. Extensions from lower-priority catalogs with the same `id` are ignored.
#### `install_allowed: false` Behavior
Extensions from discovery-only catalogs are shown in `specify extension search` results but cannot be installed directly:
```
⚠ 'linear' is available in the 'community' catalog but installation is not allowed from that catalog.
To enable installation, add 'linear' to an approved catalog (install_allowed: true) in .specify/extension-catalogs.yml.
```
#### `SPECKIT_CATALOG_URL` (Backward Compatibility)
The `SPECKIT_CATALOG_URL` environment variable still works — it is treated as a single `install_allowed: true` catalog, **replacing both defaults** for full backward compatibility:
```bash
# Point to your organization's catalog
export SPECKIT_CATALOG_URL="https://internal.company.com/spec-kit/catalog.json"
# All extension commands now use your custom catalog
specify extension search # Uses custom catalog
specify extension add jira # Installs from custom catalog
```
**Requirements:**
- URL must use HTTPS (HTTP only allowed for localhost testing)
- Catalog must follow the standard catalog.json schema
- Must be publicly accessible or accessible within your network
**Example for testing:**
```bash
# Test with localhost during development
export SPECKIT_CATALOG_URL="http://localhost:8000/catalog.json"
specify extension search
```
---
## CLI Commands
### `specify extension` Subcommands
#### `specify extension list`
List installed extensions in current project.
```bash
$ specify extension list
Installed Extensions:
✓ jira (v1.0.0) - Jira Integration
Commands: 3 | Hooks: 2 | Status: Enabled
✓ linear (v0.9.0) - Linear Integration
Commands: 1 | Hooks: 1 | Status: Enabled
```
**Options:**
- `--available`: Show available (not installed) extensions from catalog
- `--all`: Show both installed and available
#### `specify extension search [QUERY]`
Search extension catalog.
```bash
$ specify extension search jira
Found 1 extension:
┌─────────────────────────────────────────────────────────┐
│ jira (v1.0.0) ✓ Verified │
│ Jira Integration │
│ │
│ Create Jira Epics, Stories, and Issues from spec-kit │
│ artifacts │
│ │
│ Author: Stats Perform │
│ Tags: issue-tracking, jira, atlassian │
│ Downloads: 1,250 │
│ │
│ Repository: github.com/statsperform/spec-kit-jira │
│ Documentation: github.com/.../docs │
└─────────────────────────────────────────────────────────┘
Install: specify extension add jira
```
**Options:**
- `--tag TAG`: Filter by tag
- `--author AUTHOR`: Filter by author
- `--verified`: Show only verified extensions
#### `specify extension info NAME`
Show detailed information about an extension.
```bash
$ specify extension info jira
Jira Integration (jira) v1.0.0
Description:
Create Jira Epics, Stories, and Issues from spec-kit artifacts
Author: Stats Perform
License: MIT
Repository: https://github.com/statsperform/spec-kit-jira
Documentation: https://github.com/statsperform/spec-kit-jira/blob/main/docs/
Requirements:
• Spec Kit: >=0.1.0,<2.0.0
• Tools: jira-mcp-server (>=1.0.0)
Provides:
Commands:
• speckit.jira.specstoissues - Create Jira hierarchy from spec and tasks
• speckit.jira.discover-fields - Discover Jira custom fields
• speckit.jira.sync-status - Sync task completion status
Hooks:
• after_tasks - Prompt to create Jira issues
• after_implement - Prompt to sync status
Tags: issue-tracking, jira, atlassian, project-management
Downloads: 1,250 | Stars: 45 | Verified: ✓
Install: specify extension add jira
```
#### `specify extension add NAME`
Install an extension.
```bash
$ specify extension add jira
Installing extension: Jira Integration
✓ Downloaded spec-kit-jira-1.0.0.zip (245 KB)
✓ Validated manifest
✓ Checked compatibility (spec-kit 0.1.0 ≥ 0.1.0)
✓ Extracted to .specify/extensions/jira/
✓ Registered 3 commands with claude
✓ Installed config template (jira-config.yml)
⚠ Configuration required:
Edit .specify/extensions/jira/jira-config.yml to set your Jira project key
Extension installed successfully!
Next steps:
1. Configure: vim .specify/extensions/jira/jira-config.yml
2. Discover fields: /speckit.jira.discover-fields
3. Use commands: /speckit.jira.specstoissues
```
**Options:**
- `--from URL`: Install from custom URL or Git repo
- `--version VERSION`: Install specific version
- `--dev PATH`: Install from local path (development mode)
- `--no-register`: Skip command registration (manual setup)
#### `specify extension remove NAME`
Uninstall an extension.
```bash
$ specify extension remove jira
⚠ This will remove:
• 3 commands from AI agent
• Extension directory: .specify/extensions/jira/
• Config file: jira-config.yml (will be backed up)
Continue? (yes/no): yes
✓ Unregistered commands
✓ Backed up config to .specify/extensions/.backup/jira-config.yml
✓ Removed extension directory
✓ Updated registry
Extension removed successfully.
To reinstall: specify extension add jira
```
**Options:**
- `--keep-config`: Don't remove config file
- `--force`: Skip confirmation
#### `specify extension update [NAME]`
Update extension(s) to latest version.
```bash
$ specify extension update jira
Checking for updates...
jira: 1.0.0 → 1.1.0 available
Changes in v1.1.0:
• Added support for custom workflows
• Fixed issue with parallel tasks
• Improved error messages
Update? (yes/no): yes
✓ Downloaded spec-kit-jira-1.1.0.zip
✓ Validated manifest
✓ Backed up current version
✓ Extracted new version
✓ Preserved config file
✓ Re-registered commands
Extension updated successfully!
Changelog: https://github.com/statsperform/spec-kit-jira/blob/main/CHANGELOG.md#v110
```
**Options:**
- `--all`: Update all extensions
- `--check`: Check for updates without installing
- `--force`: Force update even if already latest
#### `specify extension enable/disable NAME`
Enable or disable an extension without removing it.
```bash
$ specify extension disable jira
✓ Disabled extension: jira
• Commands unregistered (but files preserved)
• Hooks will not execute
To re-enable: specify extension enable jira
```
---
## Compatibility & Versioning
### Semantic Versioning
Extensions follow [SemVer 2.0.0](https://semver.org/):
- **MAJOR**: Breaking changes (command API changes, config schema changes)
- **MINOR**: New features (new commands, new config options)
- **PATCH**: Bug fixes (no API changes)
### Compatibility Checks
**At installation:**
```python
def check_compatibility(extension_manifest: dict) -> bool:
"""Check if extension is compatible with current environment."""
requires = extension_manifest['requires']
# 1. Check spec-kit version
current_speckit = get_speckit_version() # e.g., "0.1.5"
required_speckit = requires['speckit_version'] # e.g., ">=0.1.0,<2.0.0"
if not version_satisfies(current_speckit, required_speckit):
raise IncompatibleVersionError(
f"Extension requires spec-kit {required_speckit}, "
f"but {current_speckit} is installed. "
f"Upgrade spec-kit with: uv tool install specify-cli --force"
)
# 2. Check required tools
for tool in requires.get('tools', []):
tool_name = tool['name']
tool_version = tool.get('version')
if tool.get('required', True):
if not check_tool(tool_name):
raise MissingToolError(
f"Extension requires tool: {tool_name}\n"
f"Install from: {tool.get('install_url', 'N/A')}"
)
if tool_version:
installed = get_tool_version(tool_name, tool.get('check_command'))
if not version_satisfies(installed, tool_version):
raise IncompatibleToolVersionError(
f"Extension requires {tool_name} {tool_version}, "
f"but {installed} is installed"
)
# 3. Check required commands
for cmd in requires.get('commands', []):
if not command_exists(cmd):
raise MissingCommandError(
f"Extension requires core command: {cmd}\n"
f"Update spec-kit to latest version"
)
return True
```
### Deprecation Policy
**Extension manifest can mark features as deprecated:**
```yaml
provides:
commands:
- name: "speckit.jira.old-command"
file: "commands/old-command.md"
deprecated: true
deprecated_message: "Use speckit.jira.new-command instead"
removal_version: "2.0.0"
```
**At runtime, show warning:**
```text
⚠️ Warning: /speckit.jira.old-command is deprecated
Use /speckit.jira.new-command instead
This command will be removed in v2.0.0
```
---
## Security Considerations
### Trust Model
Extensions run with **same privileges as AI agent**:
- Can execute shell commands
- Can read/write files in project
- Can make network requests
**Trust boundary**: User must trust extension author.
### Verification
**Verified Extensions** (in catalog):
- Published by known organizations (GitHub, Stats Perform, etc.)
- Code reviewed by spec-kit maintainers
- Marked with ✓ badge in catalog
**Community Extensions**:
- Not verified, use at own risk
- Show warning during installation:
```text
⚠️ This extension is not verified.
Review code before installing: https://github.com/...
Continue? (yes/no):
```
### Sandboxing (Future)
**Phase 2** (not in initial release):
- Extensions declare required permissions in manifest
- CLI enforces permission boundaries
- Example permissions: `filesystem:read`, `network:external`, `env:read`
```yaml
# Future extension.yml
permissions:
- "filesystem:read:.specify/extensions/jira/" # Can only read own config
- "filesystem:write:.specify/memory/" # Can write to memory
- "network:external:*.atlassian.net" # Can call Jira API
- "env:read:SPECKIT_JIRA_*" # Can read own env vars
```
### Package Integrity
**Future**: Sign extension packages with GPG/Sigstore
```yaml
# catalog.json
"jira": {
"download_url": "...",
"checksum": "sha256:abc123...",
"signature": "https://github.com/.../spec-kit-jira-1.0.0.sig",
"signing_key": "https://github.com/statsperform.gpg"
}
```
CLI verifies signature before extraction.
---
## Migration Strategy
### Backward Compatibility
**Goal**: Existing spec-kit projects work without changes.
**Strategy**:
1. **Core commands unchanged**: `/speckit.tasks`, `/speckit.implement`, etc. remain in core
2. **Optional extensions**: Users opt-in to extensions
3. **Gradual migration**: Existing `taskstoissues` stays in core, Jira extension is alternative
4. **Deprecation timeline**:
- **v0.2.0**: Introduce extension system, keep core `taskstoissues`
- **v0.3.0**: Mark core `taskstoissues` as "legacy" (still works)
- **v1.0.0**: Consider removing core `taskstoissues` in favor of extension
### Migration Path for Users
**Scenario 1**: User has no `taskstoissues` usage
- No migration needed, extensions are opt-in
**Scenario 2**: User uses core `taskstoissues` (GitHub Issues)
- Works as before
- Optional: Migrate to `github-projects` extension for more features
**Scenario 3**: User wants Jira (new requirement)
- `specify extension add jira`
- Configure and use
**Scenario 4**: User has custom scripts calling `taskstoissues`
- Scripts still work (core command preserved)
- Migration guide shows how to call extension commands instead
### Extension Migration Guide
**For extension authors** (if core command becomes extension):
```bash
# Old (core command)
/speckit.taskstoissues
# New (extension command)
specify extension add github-projects
/speckit.github.taskstoissues
```
**Compatibility shim** (if needed):
```yaml
# extension.yml
provides:
commands:
- name: "speckit.github.taskstoissues"
file: "commands/taskstoissues.md"
aliases: ["speckit.taskstoissues"] # Backward compatibility
```
AI agent registers both names, so old scripts work.
---
## Implementation Phases
### Phase 1: Core Extension System (Week 1-2)
**Goal**: Basic extension infrastructure
**Deliverables**:
- [ ] Extension manifest schema (`extension.yml`)
- [ ] Extension directory structure
- [ ] CLI commands:
- [ ] `specify extension list`
- [ ] `specify extension add` (from URL)
- [ ] `specify extension remove`
- [ ] Extension registry (`.specify/extensions/.registry`)
- [ ] Command registration (Claude only initially)
- [ ] Basic validation (manifest schema, compatibility)
- [ ] Documentation (extension development guide)
**Testing**:
- [ ] Unit tests for manifest parsing
- [ ] Integration test: Install dummy extension
- [ ] Integration test: Register commands with Claude
### Phase 2: Jira Extension (Week 3)
**Goal**: First production extension
**Deliverables**:
- [ ] Create `spec-kit-jira` repository
- [ ] Port Jira functionality to extension
- [ ] Create `jira-config.yml` template
- [ ] Commands:
- [ ] `specstoissues.md`
- [ ] `discover-fields.md`
- [ ] `sync-status.md`
- [ ] Helper scripts
- [ ] Documentation (README, configuration guide, examples)
- [ ] Release v1.0.0
**Testing**:
- [ ] Test on `eng-msa-ts` project
- [ ] Verify spec→Epic, phase→Story, task→Issue mapping
- [ ] Test configuration loading and validation
- [ ] Test custom field application
### Phase 3: Extension Catalog (Week 4)
**Goal**: Discovery and distribution
**Deliverables**:
- [ ] Central catalog (`extensions/catalog.json` in spec-kit repo)
- [ ] Catalog fetch and parsing
- [ ] CLI commands:
- [ ] `specify extension search`
- [ ] `specify extension info`
- [ ] Catalog publishing process (GitHub Action)
- [ ] Documentation (how to publish extensions)
**Testing**:
- [ ] Test catalog fetch
- [ ] Test extension search/filtering
- [ ] Test catalog caching
### Phase 4: Advanced Features (Week 5-6)
**Goal**: Hooks, updates, multi-agent support
**Deliverables**:
- [ ] Hook system (`hooks` in extension.yml)
- [ ] Hook registration and execution
- [ ] Project extensions config (`.specify/extensions.yml`)
- [ ] CLI commands:
- [ ] `specify extension update`
- [ ] `specify extension enable/disable`
- [ ] Command registration for multiple agents (Gemini, Copilot)
- [ ] Extension update notifications
- [ ] Configuration layer resolution (project, local, env)
**Testing**:
- [ ] Test hooks in core commands
- [ ] Test extension updates (preserve config)
- [ ] Test multi-agent registration
### Phase 5: Polish & Documentation (Week 7)
**Goal**: Production ready
**Deliverables**:
- [ ] Comprehensive documentation:
- [ ] User guide (installing/using extensions)
- [ ] Extension development guide
- [ ] Extension API reference
- [ ] Migration guide (core → extension)
- [ ] Error messages and validation improvements
- [ ] CLI help text updates
- [ ] Example extension template (cookiecutter)
- [ ] Blog post / announcement
- [ ] Video tutorial
**Testing**:
- [ ] End-to-end testing on multiple projects
- [ ] Community beta testing
- [ ] Performance testing (large projects)
---
## Open Questions
### 1. Extension Namespace
**Question**: Should extension commands use namespace prefix?
**Options**:
- A) Prefixed: `/speckit.jira.specstoissues` (explicit, avoids conflicts)
- B) Short alias: `/jira.specstoissues` (shorter, less verbose)
- C) Both: Register both names, prefer prefixed in docs
**Recommendation**: C (both), prefixed is canonical
---
### 2. Config File Location
**Question**: Where should extension configs live?
**Options**:
- A) Extension directory: `.specify/extensions/jira/jira-config.yml` (encapsulated)
- B) Root level: `.specify/jira-config.yml` (more visible)
- C) Unified: `.specify/extensions.yml` (all extension configs in one file)
**Recommendation**: A (extension directory), cleaner separation
---
### 3. Command File Format
**Question**: Should extensions use universal format or agent-specific?
**Options**:
- A) Universal Markdown: Extensions write once, CLI converts per-agent
- B) Agent-specific: Extensions provide separate files for each agent
- C) Hybrid: Universal default, agent-specific overrides
**Recommendation**: A (universal), reduces duplication
---
### 4. Hook Execution Model
**Question**: How should hooks execute?
**Options**:
- A) AI agent interprets: Core commands output `EXECUTE_COMMAND: name`
- B) CLI executes: Core commands call `specify extension hook after_tasks`
- C) Agent built-in: Extension system built into AI agent (Claude SDK)
**Recommendation**: A initially (simpler), move to C long-term
---
### 5. Extension Distribution
**Question**: How should extensions be packaged?
**Options**:
- A) ZIP archives: Downloaded from GitHub releases
- B) Git repos: Cloned directly (`git clone`)
- C) Python packages: Installable via `uv tool install`
**Recommendation**: A (ZIP), simpler for non-Python extensions in future
---
### 6. Multi-Version Support
**Question**: Can multiple versions of same extension coexist?
**Options**:
- A) Single version: Only one version installed at a time
- B) Multi-version: Side-by-side versions (`.specify/extensions/jira@1.0/`, `.specify/extensions/jira@2.0/`)
- C) Per-branch: Different branches use different versions
**Recommendation**: A initially (simpler), consider B in future if needed
---
## Appendices
### Appendix A: Example Extension Structure
**Complete structure of `spec-kit-jira` extension:**
```text
spec-kit-jira/
├── README.md # Overview, features, installation
├── LICENSE # MIT license
├── CHANGELOG.md # Version history
├── .gitignore # Ignore local configs
├── extension.yml # Extension manifest (required)
├── jira-config.template.yml # Config template
├── commands/ # Command files
│ ├── specstoissues.md # Main command
│ ├── discover-fields.md # Helper: Discover custom fields
│ └── sync-status.md # Helper: Sync completion status
├── scripts/ # Helper scripts
│ ├── parse-jira-config.sh # Config loader (bash)
│ ├── parse-jira-config.ps1 # Config loader (PowerShell)
│ └── validate-jira-connection.sh # Connection test
├── docs/ # Documentation
│ ├── installation.md # Installation guide
│ ├── configuration.md # Configuration reference
│ ├── usage.md # Usage examples
│ ├── troubleshooting.md # Common issues
│ └── examples/
│ ├── eng-msa-ts-config.yml # Real-world config example
│ └── simple-project.yml # Minimal config example
├── tests/ # Tests (optional)
│ ├── test-extension.sh # Extension validation
│ └── test-commands.sh # Command execution tests
└── .github/ # GitHub integration
└── workflows/
└── release.yml # Automated releases
```
### Appendix B: Extension Development Guide (Outline)
**Documentation for creating new extensions:**
1. **Getting Started**
- Prerequisites (tools needed)
- Extension template (cookiecutter)
- Directory structure
2. **Extension Manifest**
- Schema reference
- Required vs optional fields
- Versioning guidelines
3. **Command Development**
- Universal command format
- Frontmatter specification
- Template variables
- Script references
4. **Configuration**
- Config file structure
- Schema validation
- Layered config resolution
- Environment variable overrides
5. **Hooks**
- Available hook points
- Hook registration
- Conditional execution
- Best practices
6. **Testing**
- Local development setup
- Testing with `--dev` flag
- Validation checklist
- Integration testing
7. **Publishing**
- Packaging (ZIP format)
- GitHub releases
- Catalog submission
- Versioning strategy
8. **Examples**
- Minimal extension
- Extension with hooks
- Extension with configuration
- Extension with multiple commands
### Appendix C: Compatibility Matrix
**Planned support matrix:**
| Extension Feature | Spec Kit Version | AI Agent Support |
|-------------------|------------------|------------------|
| Basic commands | 0.2.0+ | Claude, Gemini, Copilot |
| Hooks (after_tasks) | 0.3.0+ | Claude, Gemini |
| Config validation | 0.2.0+ | All |
| Multiple catalogs | 0.4.0+ | All |
| Permissions (sandboxing) | 1.0.0+ | TBD |
### Appendix D: Extension Catalog Schema
**Full schema for `catalog.json`:**
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["schema_version", "updated_at", "extensions"],
"properties": {
"schema_version": {
"type": "string",
"pattern": "^\\d+\\.\\d+$"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"extensions": {
"type": "object",
"patternProperties": {
"^[a-z0-9-]+$": {
"type": "object",
"required": ["name", "id", "version", "download_url", "repository"],
"properties": {
"name": { "type": "string" },
"id": { "type": "string", "pattern": "^[a-z0-9-]+$" },
"description": { "type": "string" },
"author": { "type": "string" },
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
"download_url": { "type": "string", "format": "uri" },
"repository": { "type": "string", "format": "uri" },
"homepage": { "type": "string", "format": "uri" },
"documentation": { "type": "string", "format": "uri" },
"changelog": { "type": "string", "format": "uri" },
"license": { "type": "string" },
"requires": {
"type": "object",
"properties": {
"speckit_version": { "type": "string" },
"tools": {
"type": "array",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"version": { "type": "string" }
}
}
}
}
},
"tags": {
"type": "array",
"items": { "type": "string" }
},
"verified": { "type": "boolean" },
"downloads": { "type": "integer" },
"stars": { "type": "integer" },
"checksum": { "type": "string" }
}
}
}
}
}
}
```
---
## Summary & Next Steps
This RFC proposes a comprehensive extension system for Spec Kit that:
1. **Keeps core lean** while enabling unlimited integrations
2. **Supports multiple agents** (Claude, Gemini, Copilot, etc.)
3. **Provides clear extension API** for community contributions
4. **Enables independent versioning** of extensions and core
5. **Includes safety mechanisms** (validation, compatibility checks)
### Immediate Next Steps
1. **Review this RFC** with stakeholders
2. **Gather feedback** on open questions
3. **Refine design** based on feedback
4. **Proceed to Phase A**: Implement core extension system
5. **Then Phase B**: Build Jira extension as proof-of-concept
---
## Questions for Discussion
1. Does the extension architecture meet your needs for Jira integration?
2. Are there additional hook points we should consider?
3. Should we support extension dependencies (extension A requires extension B)?
4. How should we handle extension deprecation/removal from catalog?
5. What level of sandboxing/permissions do we need in v1.0?