mirror of
https://github.com/github/spec-kit.git
synced 2026-03-17 02:43:08 +00:00
Add modular extension system (#1551)
* Add modular extension system for Spec Kit Implement a complete extension system that allows third-party developers to extend Spec Kit functionality through plugins. ## Core Features - Extension discovery and loading from local and global directories - YAML-based extension manifest (extension.yml) with metadata and capabilities - Command extensions: custom slash commands with markdown templates - Hook system: pre/post hooks for generate, task, and sync operations - Extension catalog for discovering and installing community extensions - SPECKIT_CATALOG_URL environment variable for catalog URL override ## Installation Methods - Catalog install: `specify extension add <name>` - URL install: `specify extension add <name> --from <url>` - Dev install: `specify extension add --dev <path>` ## Implementation - ExtensionManager class for lifecycle management (load, enable, disable) - Support for extension dependencies and version constraints - Configuration layering (global → project → extension) - Hook conditions for conditional execution ## Documentation - RFC with design rationale and architecture decisions - API reference for extension developers - Development guide with examples - User guide for installing and managing extensions - Publishing guide for the extension catalog ## Included - Extension template for bootstrapping new extensions - Comprehensive test suite - Example catalog.json structure Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Update Jira extension to v2.1.0 in catalog Adds 2-level mode support (Epic → Stories only). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Address PR review feedback - Fix Zip Slip vulnerability in ZIP extraction with path validation - Fix keep_config option to actually preserve config files on removal - Add URL validation for SPECKIT_CATALOG_URL (HTTPS required, localhost exception) - Add security warning when installing from custom URLs (--from flag) - Empty catalog.json so organizations can ship their own catalogs - Fix markdown linter errors (MD040: add language to code blocks) - Remove redundant import and fix unused variables in tests - Add comment explaining empty except clause for backwards compatibility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add comprehensive organization catalog customization docs - Explain why default catalog is empty (org control) - Document how to create and host custom catalogs - Add catalog JSON schema reference - Include use cases: private extensions, curated catalogs, air-gapped environments - Add examples for combining catalog with direct installation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix test assertions for extension system data structures - Update test_config_backup_on_remove to use new subdirectory structure (.backup/test-ext/file.yml instead of .backup/test-ext-file.yml) - Update test_full_install_and_remove_workflow to handle registered_commands being a dict keyed by agent name instead of a flat list Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Address Copilot review feedback - Fix localhost URL check to use parsed.hostname instead of netloc.startswith() This correctly handles URLs with ports like localhost:8080 - Fix YAML indentation error in config-template.yml (line 57) - Fix double space typo in example.md (line 172) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add catalog.example.json as reference for organizations The main catalog.json is intentionally empty so organizations can ship their own curated catalogs. This example file shows the expected schema and structure for creating organization-specific catalogs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Address remaining Copilot security and logic review feedback - Fix Zip Slip vulnerability by using relative_to() for safe path validation - Add HTTPS validation for extension download URLs - Backup both *-config.yml and *-config.local.yml files on remove - Normalize boolean values to lowercase for hook condition comparisons - Show non-default catalog warning only once per instance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Ignoring linter for extensions directory --------- Co-authored-by: iamaeroplane <michal.bachorik@gmail.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Manfred Riem <manfred.riem@microsoft.com>
This commit is contained in:
530
extensions/EXTENSION-PUBLISHING-GUIDE.md
Normal file
530
extensions/EXTENSION-PUBLISHING-GUIDE.md
Normal file
@@ -0,0 +1,530 @@
|
||||
# Extension Publishing Guide
|
||||
|
||||
This guide explains how to publish your extension to the Spec Kit extension catalog, making it discoverable by `specify extension search`.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Prerequisites](#prerequisites)
|
||||
2. [Prepare Your Extension](#prepare-your-extension)
|
||||
3. [Submit to Catalog](#submit-to-catalog)
|
||||
4. [Verification Process](#verification-process)
|
||||
5. [Release Workflow](#release-workflow)
|
||||
6. [Best Practices](#best-practices)
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before publishing an extension, ensure you have:
|
||||
|
||||
1. **Valid Extension**: A working extension with a valid `extension.yml` manifest
|
||||
2. **Git Repository**: Extension hosted on GitHub (or other public git hosting)
|
||||
3. **Documentation**: README.md with installation and usage instructions
|
||||
4. **License**: Open source license file (MIT, Apache 2.0, etc.)
|
||||
5. **Versioning**: Semantic versioning (e.g., 1.0.0)
|
||||
6. **Testing**: Extension tested on real projects
|
||||
|
||||
---
|
||||
|
||||
## Prepare Your Extension
|
||||
|
||||
### 1. Extension Structure
|
||||
|
||||
Ensure your extension follows the standard structure:
|
||||
|
||||
```text
|
||||
your-extension/
|
||||
├── extension.yml # Required: Extension manifest
|
||||
├── README.md # Required: Documentation
|
||||
├── LICENSE # Required: License file
|
||||
├── CHANGELOG.md # Recommended: Version history
|
||||
├── .gitignore # Recommended: Git ignore rules
|
||||
│
|
||||
├── commands/ # Extension commands
|
||||
│ ├── command1.md
|
||||
│ └── command2.md
|
||||
│
|
||||
├── config-template.yml # Config template (if needed)
|
||||
│
|
||||
└── docs/ # Additional documentation
|
||||
├── usage.md
|
||||
└── examples/
|
||||
```
|
||||
|
||||
### 2. extension.yml Validation
|
||||
|
||||
Verify your manifest is valid:
|
||||
|
||||
```yaml
|
||||
schema_version: "1.0"
|
||||
|
||||
extension:
|
||||
id: "your-extension" # Unique lowercase-hyphenated ID
|
||||
name: "Your Extension Name" # Human-readable name
|
||||
version: "1.0.0" # Semantic version
|
||||
description: "Brief description (one sentence)"
|
||||
author: "Your Name or Organization"
|
||||
repository: "https://github.com/your-org/spec-kit-your-extension"
|
||||
license: "MIT"
|
||||
homepage: "https://github.com/your-org/spec-kit-your-extension"
|
||||
|
||||
requires:
|
||||
speckit_version: ">=0.1.0" # Required spec-kit version
|
||||
|
||||
provides:
|
||||
commands: # List all commands
|
||||
- name: "speckit.your-extension.command"
|
||||
file: "commands/command.md"
|
||||
description: "Command description"
|
||||
|
||||
tags: # 2-5 relevant tags
|
||||
- "category"
|
||||
- "tool-name"
|
||||
```
|
||||
|
||||
**Validation Checklist**:
|
||||
|
||||
- ✅ `id` is lowercase with hyphens only (no underscores, spaces, or special characters)
|
||||
- ✅ `version` follows semantic versioning (X.Y.Z)
|
||||
- ✅ `description` is concise (under 100 characters)
|
||||
- ✅ `repository` URL is valid and public
|
||||
- ✅ All command files exist in the extension directory
|
||||
- ✅ Tags are lowercase and descriptive
|
||||
|
||||
### 3. Create GitHub Release
|
||||
|
||||
Create a GitHub release for your extension version:
|
||||
|
||||
```bash
|
||||
# Tag the release
|
||||
git tag v1.0.0
|
||||
git push origin v1.0.0
|
||||
|
||||
# Create release on GitHub
|
||||
# Go to: https://github.com/your-org/spec-kit-your-extension/releases/new
|
||||
# - Tag: v1.0.0
|
||||
# - Title: v1.0.0 - Release Name
|
||||
# - Description: Changelog/release notes
|
||||
```
|
||||
|
||||
The release archive URL will be:
|
||||
|
||||
```text
|
||||
https://github.com/your-org/spec-kit-your-extension/archive/refs/tags/v1.0.0.zip
|
||||
```
|
||||
|
||||
### 4. Test Installation
|
||||
|
||||
Test that users can install from your release:
|
||||
|
||||
```bash
|
||||
# Test dev installation
|
||||
specify extension add --dev /path/to/your-extension
|
||||
|
||||
# Test from GitHub archive
|
||||
specify extension add --from https://github.com/your-org/spec-kit-your-extension/archive/refs/tags/v1.0.0.zip
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Submit to Catalog
|
||||
|
||||
### 1. Fork the spec-kit Repository
|
||||
|
||||
```bash
|
||||
# Fork on GitHub
|
||||
# https://github.com/statsperform/spec-kit/fork
|
||||
|
||||
# Clone your fork
|
||||
git clone https://github.com/YOUR-USERNAME/spec-kit.git
|
||||
cd spec-kit
|
||||
```
|
||||
|
||||
### 2. Add Extension to Catalog
|
||||
|
||||
Edit `extensions/catalog.json` and add your extension:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"updated_at": "2026-01-28T15:54:00Z",
|
||||
"catalog_url": "https://raw.githubusercontent.com/statsperform/spec-kit/main/extensions/catalog.json",
|
||||
"extensions": {
|
||||
"your-extension": {
|
||||
"name": "Your Extension Name",
|
||||
"id": "your-extension",
|
||||
"description": "Brief description of your extension",
|
||||
"author": "Your Name",
|
||||
"version": "1.0.0",
|
||||
"download_url": "https://github.com/your-org/spec-kit-your-extension/archive/refs/tags/v1.0.0.zip",
|
||||
"repository": "https://github.com/your-org/spec-kit-your-extension",
|
||||
"homepage": "https://github.com/your-org/spec-kit-your-extension",
|
||||
"documentation": "https://github.com/your-org/spec-kit-your-extension/blob/main/docs/",
|
||||
"changelog": "https://github.com/your-org/spec-kit-your-extension/blob/main/CHANGELOG.md",
|
||||
"license": "MIT",
|
||||
"requires": {
|
||||
"speckit_version": ">=0.1.0",
|
||||
"tools": [
|
||||
{
|
||||
"name": "required-mcp-tool",
|
||||
"version": ">=1.0.0",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"provides": {
|
||||
"commands": 3,
|
||||
"hooks": 1
|
||||
},
|
||||
"tags": [
|
||||
"category",
|
||||
"tool-name",
|
||||
"feature"
|
||||
],
|
||||
"verified": false,
|
||||
"downloads": 0,
|
||||
"stars": 0,
|
||||
"created_at": "2026-01-28T00:00:00Z",
|
||||
"updated_at": "2026-01-28T00:00:00Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Important**:
|
||||
|
||||
- Set `verified: false` (maintainers will verify)
|
||||
- Set `downloads: 0` and `stars: 0` (auto-updated later)
|
||||
- Use current timestamp for `created_at` and `updated_at`
|
||||
- Update the top-level `updated_at` to current time
|
||||
|
||||
### 3. Submit Pull Request
|
||||
|
||||
```bash
|
||||
# Create a branch
|
||||
git checkout -b add-your-extension
|
||||
|
||||
# Commit your changes
|
||||
git add extensions/catalog.json
|
||||
git commit -m "Add your-extension to catalog
|
||||
|
||||
- Extension ID: your-extension
|
||||
- Version: 1.0.0
|
||||
- Author: Your Name
|
||||
- Description: Brief description
|
||||
"
|
||||
|
||||
# Push to your fork
|
||||
git push origin add-your-extension
|
||||
|
||||
# Create Pull Request on GitHub
|
||||
# https://github.com/statsperform/spec-kit/compare
|
||||
```
|
||||
|
||||
**Pull Request Template**:
|
||||
|
||||
```markdown
|
||||
## Extension Submission
|
||||
|
||||
**Extension Name**: Your Extension Name
|
||||
**Extension ID**: your-extension
|
||||
**Version**: 1.0.0
|
||||
**Author**: Your Name
|
||||
**Repository**: https://github.com/your-org/spec-kit-your-extension
|
||||
|
||||
### Description
|
||||
Brief description of what your extension does.
|
||||
|
||||
### Checklist
|
||||
- [x] Valid extension.yml manifest
|
||||
- [x] README.md with installation and usage docs
|
||||
- [x] LICENSE file included
|
||||
- [x] GitHub release created (v1.0.0)
|
||||
- [x] Extension tested on real project
|
||||
- [x] All commands working
|
||||
- [x] No security vulnerabilities
|
||||
|
||||
### Testing
|
||||
Tested on:
|
||||
- macOS 13.0+ with spec-kit 0.1.0
|
||||
- Project: [Your test project]
|
||||
|
||||
### Additional Notes
|
||||
Any additional context or notes for reviewers.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verification Process
|
||||
|
||||
### What Happens After Submission
|
||||
|
||||
1. **Automated Checks** (if available):
|
||||
- Manifest validation
|
||||
- Download URL accessibility
|
||||
- Repository existence
|
||||
- License file presence
|
||||
|
||||
2. **Manual Review**:
|
||||
- Code quality review
|
||||
- Security audit
|
||||
- Functionality testing
|
||||
- Documentation review
|
||||
|
||||
3. **Verification**:
|
||||
- If approved, `verified: true` is set
|
||||
- Extension appears in `specify extension search --verified`
|
||||
|
||||
### Verification Criteria
|
||||
|
||||
To be verified, your extension must:
|
||||
|
||||
✅ **Functionality**:
|
||||
|
||||
- Works as described in documentation
|
||||
- All commands execute without errors
|
||||
- No breaking changes to user workflows
|
||||
|
||||
✅ **Security**:
|
||||
|
||||
- No known vulnerabilities
|
||||
- No malicious code
|
||||
- Safe handling of user data
|
||||
- Proper validation of inputs
|
||||
|
||||
✅ **Code Quality**:
|
||||
|
||||
- Clean, readable code
|
||||
- Follows extension best practices
|
||||
- Proper error handling
|
||||
- Helpful error messages
|
||||
|
||||
✅ **Documentation**:
|
||||
|
||||
- Clear installation instructions
|
||||
- Usage examples
|
||||
- Troubleshooting section
|
||||
- Accurate description
|
||||
|
||||
✅ **Maintenance**:
|
||||
|
||||
- Active repository
|
||||
- Responsive to issues
|
||||
- Regular updates
|
||||
- Semantic versioning followed
|
||||
|
||||
### Typical Review Timeline
|
||||
|
||||
- **Automated checks**: Immediate (if implemented)
|
||||
- **Manual review**: 3-7 business days
|
||||
- **Verification**: After successful review
|
||||
|
||||
---
|
||||
|
||||
## Release Workflow
|
||||
|
||||
### Publishing New Versions
|
||||
|
||||
When releasing a new version:
|
||||
|
||||
1. **Update version** in `extension.yml`:
|
||||
|
||||
```yaml
|
||||
extension:
|
||||
version: "1.1.0" # Updated version
|
||||
```
|
||||
|
||||
2. **Update CHANGELOG.md**:
|
||||
|
||||
```markdown
|
||||
## [1.1.0] - 2026-02-15
|
||||
|
||||
### Added
|
||||
- New feature X
|
||||
|
||||
### Fixed
|
||||
- Bug fix Y
|
||||
```
|
||||
|
||||
3. **Create GitHub release**:
|
||||
|
||||
```bash
|
||||
git tag v1.1.0
|
||||
git push origin v1.1.0
|
||||
# Create release on GitHub
|
||||
```
|
||||
|
||||
4. **Update catalog**:
|
||||
|
||||
```bash
|
||||
# Fork spec-kit repo (or update existing fork)
|
||||
cd spec-kit
|
||||
|
||||
# Update extensions/catalog.json
|
||||
jq '.extensions["your-extension"].version = "1.1.0"' extensions/catalog.json > tmp.json && mv tmp.json extensions/catalog.json
|
||||
jq '.extensions["your-extension"].download_url = "https://github.com/your-org/spec-kit-your-extension/archive/refs/tags/v1.1.0.zip"' extensions/catalog.json > tmp.json && mv tmp.json extensions/catalog.json
|
||||
jq '.extensions["your-extension"].updated_at = "2026-02-15T00:00:00Z"' extensions/catalog.json > tmp.json && mv tmp.json extensions/catalog.json
|
||||
jq '.updated_at = "2026-02-15T00:00:00Z"' extensions/catalog.json > tmp.json && mv tmp.json extensions/catalog.json
|
||||
|
||||
# Submit PR
|
||||
git checkout -b update-your-extension-v1.1.0
|
||||
git add extensions/catalog.json
|
||||
git commit -m "Update your-extension to v1.1.0"
|
||||
git push origin update-your-extension-v1.1.0
|
||||
```
|
||||
|
||||
5. **Submit update PR** with changelog in description
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Extension Design
|
||||
|
||||
1. **Single Responsibility**: Each extension should focus on one tool/integration
|
||||
2. **Clear Naming**: Use descriptive, unambiguous names
|
||||
3. **Minimal Dependencies**: Avoid unnecessary dependencies
|
||||
4. **Backward Compatibility**: Follow semantic versioning strictly
|
||||
|
||||
### Documentation
|
||||
|
||||
1. **README.md Structure**:
|
||||
- Overview and features
|
||||
- Installation instructions
|
||||
- Configuration guide
|
||||
- Usage examples
|
||||
- Troubleshooting
|
||||
- Contributing guidelines
|
||||
|
||||
2. **Command Documentation**:
|
||||
- Clear description
|
||||
- Prerequisites listed
|
||||
- Step-by-step instructions
|
||||
- Error handling guidance
|
||||
- Examples
|
||||
|
||||
3. **Configuration**:
|
||||
- Provide template file
|
||||
- Document all options
|
||||
- Include examples
|
||||
- Explain defaults
|
||||
|
||||
### Security
|
||||
|
||||
1. **Input Validation**: Validate all user inputs
|
||||
2. **No Hardcoded Secrets**: Never include credentials
|
||||
3. **Safe Dependencies**: Only use trusted dependencies
|
||||
4. **Audit Regularly**: Check for vulnerabilities
|
||||
|
||||
### Maintenance
|
||||
|
||||
1. **Respond to Issues**: Address issues within 1-2 weeks
|
||||
2. **Regular Updates**: Keep dependencies updated
|
||||
3. **Changelog**: Maintain detailed changelog
|
||||
4. **Deprecation**: Give advance notice for breaking changes
|
||||
|
||||
### Community
|
||||
|
||||
1. **License**: Use permissive open-source license (MIT, Apache 2.0)
|
||||
2. **Contributing**: Welcome contributions
|
||||
3. **Code of Conduct**: Be respectful and inclusive
|
||||
4. **Support**: Provide ways to get help (issues, discussions, email)
|
||||
|
||||
---
|
||||
|
||||
## FAQ
|
||||
|
||||
### Q: Can I publish private/proprietary extensions?
|
||||
|
||||
A: The main catalog is for public extensions only. For private extensions:
|
||||
|
||||
- Host your own catalog.json file
|
||||
- Users add your catalog: `specify extension add-catalog https://your-domain.com/catalog.json`
|
||||
- Not yet implemented - coming in Phase 4
|
||||
|
||||
### Q: How long does verification take?
|
||||
|
||||
A: Typically 3-7 business days for initial review. Updates to verified extensions are usually faster.
|
||||
|
||||
### Q: What if my extension is rejected?
|
||||
|
||||
A: You'll receive feedback on what needs to be fixed. Make the changes and resubmit.
|
||||
|
||||
### Q: Can I update my extension anytime?
|
||||
|
||||
A: Yes, submit a PR to update the catalog with your new version. Verified status may be re-evaluated for major changes.
|
||||
|
||||
### Q: Do I need to be verified to be in the catalog?
|
||||
|
||||
A: No, unverified extensions are still searchable. Verification just adds trust and visibility.
|
||||
|
||||
### Q: Can extensions have paid features?
|
||||
|
||||
A: Extensions should be free and open-source. Commercial support/services are allowed, but core functionality must be free.
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
- **Catalog Issues**: <https://github.com/statsperform/spec-kit/issues>
|
||||
- **Extension Template**: <https://github.com/statsperform/spec-kit-extension-template> (coming soon)
|
||||
- **Development Guide**: See EXTENSION-DEVELOPMENT-GUIDE.md
|
||||
- **Community**: Discussions and Q&A
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Catalog Schema
|
||||
|
||||
### Complete Catalog Entry Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "string (required)",
|
||||
"id": "string (required, unique)",
|
||||
"description": "string (required, <200 chars)",
|
||||
"author": "string (required)",
|
||||
"version": "string (required, semver)",
|
||||
"download_url": "string (required, valid URL)",
|
||||
"repository": "string (required, valid URL)",
|
||||
"homepage": "string (optional, valid URL)",
|
||||
"documentation": "string (optional, valid URL)",
|
||||
"changelog": "string (optional, valid URL)",
|
||||
"license": "string (required)",
|
||||
"requires": {
|
||||
"speckit_version": "string (required, version specifier)",
|
||||
"tools": [
|
||||
{
|
||||
"name": "string (required)",
|
||||
"version": "string (optional, version specifier)",
|
||||
"required": "boolean (default: false)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"provides": {
|
||||
"commands": "integer (optional)",
|
||||
"hooks": "integer (optional)"
|
||||
},
|
||||
"tags": ["array of strings (2-10 tags)"],
|
||||
"verified": "boolean (default: false)",
|
||||
"downloads": "integer (auto-updated)",
|
||||
"stars": "integer (auto-updated)",
|
||||
"created_at": "string (ISO 8601 datetime)",
|
||||
"updated_at": "string (ISO 8601 datetime)"
|
||||
}
|
||||
```
|
||||
|
||||
### Valid Tags
|
||||
|
||||
Recommended tag categories:
|
||||
|
||||
- **Integration**: jira, linear, github, gitlab, azure-devops
|
||||
- **Category**: issue-tracking, vcs, ci-cd, documentation, testing
|
||||
- **Platform**: atlassian, microsoft, google
|
||||
- **Feature**: automation, reporting, deployment, monitoring
|
||||
|
||||
Use 2-5 tags that best describe your extension.
|
||||
|
||||
---
|
||||
|
||||
*Last Updated: 2026-01-28*
|
||||
*Catalog Format Version: 1.0*
|
||||
Reference in New Issue
Block a user