mirror of
https://github.com/github/spec-kit.git
synced 2026-03-17 19:03:08 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61b0637a6d | ||
|
|
56deda7be3 | ||
|
|
525cdc17ec | ||
|
|
607760e72f | ||
|
|
c7ecdfb998 | ||
|
|
f444ccba3a | ||
|
|
3040d33c31 | ||
|
|
6cc61025cb | ||
|
|
c1034f1d9d | ||
|
|
cee4f26fac |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -1,3 +1,3 @@
|
|||||||
# Global code owner
|
# Global code owner
|
||||||
* @localden
|
* @mnriem
|
||||||
|
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -51,7 +51,7 @@ body:
|
|||||||
id: version
|
id: version
|
||||||
attributes:
|
attributes:
|
||||||
label: Specify CLI Version
|
label: Specify CLI Version
|
||||||
description: "Run `specify --version` or `pip show spec-kit`"
|
description: "Run `specify version` or `pip show spec-kit`"
|
||||||
placeholder: "e.g., 1.3.0"
|
placeholder: "e.g., 1.3.0"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Fetch all history for git info
|
fetch-depth: 0 # Fetch all history for git info
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Run markdownlint-cli2
|
- name: Run markdownlint-cli2
|
||||||
uses: DavidAnson/markdownlint-cli2-action@v19
|
uses: DavidAnson/markdownlint-cli2-action@v19
|
||||||
|
|||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
23
CHANGELOG.md
23
CHANGELOG.md
@@ -2,12 +2,23 @@
|
|||||||
|
|
||||||
<!-- markdownlint-disable MD024 -->
|
<!-- markdownlint-disable MD024 -->
|
||||||
|
|
||||||
All notable changes to the Specify CLI and templates are documented here.
|
Recent changes to the Specify CLI and templates are documented here.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [0.1.5] - Unreleased
|
## [0.1.6] - 2026-02-23
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Parameter Ordering Issues (#1641)**: Fixed CLI parameter parsing issue where option flags were incorrectly consumed as values for preceding options
|
||||||
|
- Added validation to detect when `--ai` or `--ai-commands-dir` incorrectly consume following flags like `--here` or `--ai-skills`
|
||||||
|
- Now provides clear error messages: "Invalid value for --ai: '--here'"
|
||||||
|
- Includes helpful hints suggesting proper usage and listing available agents
|
||||||
|
- Commands like `specify init --ai-skills --ai --here` now fail with actionable feedback instead of confusing "Must specify project name" errors
|
||||||
|
- Added comprehensive test suite (5 new tests) to prevent regressions
|
||||||
|
|
||||||
|
## [0.1.5] - 2026-02-21
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
@@ -16,13 +27,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Affected agents now work correctly: copilot (`.github/agents/`), opencode (`.opencode/command/`), windsurf (`.windsurf/workflows/`), codex (`.codex/prompts/`), kilocode (`.kilocode/workflows/`), q (`.amazonq/prompts/`), and agy (`.agent/workflows/`)
|
- Affected agents now work correctly: copilot (`.github/agents/`), opencode (`.opencode/command/`), windsurf (`.windsurf/workflows/`), codex (`.codex/prompts/`), kilocode (`.kilocode/workflows/`), q (`.amazonq/prompts/`), and agy (`.agent/workflows/`)
|
||||||
- The `install_ai_skills()` function now uses the correct path for all agents instead of assuming `commands/` for everyone
|
- The `install_ai_skills()` function now uses the correct path for all agents instead of assuming `commands/` for everyone
|
||||||
|
|
||||||
## [0.1.4] - Unreleased
|
## [0.1.4] - 2026-02-20
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- **Qoder CLI detection**: Renamed `AGENT_CONFIG` key from `"qoder"` to `"qodercli"` to match the actual executable name, fixing `specify check` and `specify init --ai` detection failures
|
- **Qoder CLI detection**: Renamed `AGENT_CONFIG` key from `"qoder"` to `"qodercli"` to match the actual executable name, fixing `specify check` and `specify init --ai` detection failures
|
||||||
|
|
||||||
## [0.1.3] - Unreleased
|
## [0.1.3] - 2026-02-20
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
@@ -69,7 +80,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
## [0.0.94] - 2026-02-11
|
## [0.0.94] - 2026-02-11
|
||||||
|
|
||||||
- Add stale workflow for 180-day inactive issues and PRs (#1594)
|
- Add stale workflow for 180-day inactive issues and PRs (#1594)
|
||||||
|
|
||||||
## [0.0.93] - 2026-02-10
|
|
||||||
|
|
||||||
- Add modular extension system (#1551)
|
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ Then, use the `/speckit.implement` slash command to execute the plan.
|
|||||||
/speckit.implement
|
/speckit.implement
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> **Phased Implementation**: For complex projects, implement in phases to avoid overwhelming the agent's context. Start with core functionality, validate it works, then add features incrementally.
|
||||||
|
|
||||||
## Detailed Example: Building Taskify
|
## Detailed Example: Building Taskify
|
||||||
|
|
||||||
Here's a complete example of building a team productivity platform:
|
Here's a complete example of building a team productivity platform:
|
||||||
@@ -135,7 +138,15 @@ Be specific about your tech stack and technical requirements:
|
|||||||
/speckit.plan We are going to generate this using .NET Aspire, using Postgres as the database. The frontend should use Blazor server with drag-and-drop task boards, real-time updates. There should be a REST API created with a projects API, tasks API, and a notifications API.
|
/speckit.plan We are going to generate this using .NET Aspire, using Postgres as the database. The frontend should use Blazor server with drag-and-drop task boards, real-time updates. There should be a REST API created with a projects API, tasks API, and a notifications API.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 6: Validate and Implement
|
### Step 6: Define Tasks
|
||||||
|
|
||||||
|
Generate an actionable task list using the `/speckit.tasks` command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/speckit.tasks
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 7: Validate and Implement
|
||||||
|
|
||||||
Have your AI agent audit the implementation plan using `/speckit.analyze`:
|
Have your AI agent audit the implementation plan using `/speckit.analyze`:
|
||||||
|
|
||||||
@@ -149,6 +160,9 @@ Finally, implement the solution:
|
|||||||
/speckit.implement
|
/speckit.implement
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> **Phased Implementation**: For large projects like Taskify, consider implementing in phases (e.g., Phase 1: Basic project/task structure, Phase 2: Kanban functionality, Phase 3: Comments and assignments). This prevents context saturation and allows for validation at each stage.
|
||||||
|
|
||||||
## Key Principles
|
## Key Principles
|
||||||
|
|
||||||
- **Be explicit** about what you're building and why
|
- **Be explicit** about what you're building and why
|
||||||
|
|||||||
@@ -456,18 +456,20 @@ Users install with:
|
|||||||
specify extension add --from https://github.com/.../spec-kit-my-ext-1.0.0.zip
|
specify extension add --from https://github.com/.../spec-kit-my-ext-1.0.0.zip
|
||||||
```
|
```
|
||||||
|
|
||||||
### Option 3: Extension Catalog (Future)
|
### Option 3: Community Reference Catalog
|
||||||
|
|
||||||
Submit to official catalog:
|
Submit to the community catalog for public discovery:
|
||||||
|
|
||||||
1. **Fork** spec-kit repository
|
1. **Fork** spec-kit repository
|
||||||
2. **Add entry** to `extensions/catalog.json`
|
2. **Add entry** to `extensions/catalog.community.json`
|
||||||
3. **Create PR**
|
3. **Update** `extensions/README.md` with your extension
|
||||||
4. **After merge**, users can install with:
|
4. **Create PR** following the [Extension Publishing Guide](EXTENSION-PUBLISHING-GUIDE.md)
|
||||||
|
5. **After merge**, your extension becomes available:
|
||||||
|
- Users can browse `catalog.community.json` to discover your extension
|
||||||
|
- Users copy the entry to their own `catalog.json`
|
||||||
|
- Users install with: `specify extension add my-ext` (from their catalog)
|
||||||
|
|
||||||
```bash
|
See the [Extension Publishing Guide](EXTENSION-PUBLISHING-GUIDE.md) for detailed submission instructions.
|
||||||
specify extension add my-ext # No URL needed!
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -129,26 +129,32 @@ specify extension add --from https://github.com/your-org/spec-kit-your-extension
|
|||||||
|
|
||||||
## Submit to Catalog
|
## Submit to Catalog
|
||||||
|
|
||||||
|
### Understanding the Catalogs
|
||||||
|
|
||||||
|
Spec Kit uses a dual-catalog system. For details about how catalogs work, see the main [Extensions README](README.md#extension-catalogs).
|
||||||
|
|
||||||
|
**For extension publishing**: All community extensions should be added to `catalog.community.json`. Users browse this catalog and copy extensions they trust into their own `catalog.json`.
|
||||||
|
|
||||||
### 1. Fork the spec-kit Repository
|
### 1. Fork the spec-kit Repository
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Fork on GitHub
|
# Fork on GitHub
|
||||||
# https://github.com/statsperform/spec-kit/fork
|
# https://github.com/github/spec-kit/fork
|
||||||
|
|
||||||
# Clone your fork
|
# Clone your fork
|
||||||
git clone https://github.com/YOUR-USERNAME/spec-kit.git
|
git clone https://github.com/YOUR-USERNAME/spec-kit.git
|
||||||
cd spec-kit
|
cd spec-kit
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Add Extension to Catalog
|
### 2. Add Extension to Community Catalog
|
||||||
|
|
||||||
Edit `extensions/catalog.json` and add your extension:
|
Edit `extensions/catalog.community.json` and add your extension:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.0",
|
||||||
"updated_at": "2026-01-28T15:54:00Z",
|
"updated_at": "2026-01-28T15:54:00Z",
|
||||||
"catalog_url": "https://raw.githubusercontent.com/statsperform/spec-kit/main/extensions/catalog.json",
|
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json",
|
||||||
"extensions": {
|
"extensions": {
|
||||||
"your-extension": {
|
"your-extension": {
|
||||||
"name": "Your Extension Name",
|
"name": "Your Extension Name",
|
||||||
@@ -198,15 +204,25 @@ Edit `extensions/catalog.json` and add your extension:
|
|||||||
- Use current timestamp for `created_at` and `updated_at`
|
- Use current timestamp for `created_at` and `updated_at`
|
||||||
- Update the top-level `updated_at` to current time
|
- Update the top-level `updated_at` to current time
|
||||||
|
|
||||||
### 3. Submit Pull Request
|
### 3. Update Extensions README
|
||||||
|
|
||||||
|
Add your extension to the Available Extensions table in `extensions/README.md`:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
| Your Extension Name | Brief description of what it does | [repo-name](https://github.com/your-org/spec-kit-your-extension) |
|
||||||
|
```
|
||||||
|
|
||||||
|
Insert your extension in alphabetical order in the table.
|
||||||
|
|
||||||
|
### 4. Submit Pull Request
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Create a branch
|
# Create a branch
|
||||||
git checkout -b add-your-extension
|
git checkout -b add-your-extension
|
||||||
|
|
||||||
# Commit your changes
|
# Commit your changes
|
||||||
git add extensions/catalog.json
|
git add extensions/catalog.community.json extensions/README.md
|
||||||
git commit -m "Add your-extension to catalog
|
git commit -m "Add your-extension to community catalog
|
||||||
|
|
||||||
- Extension ID: your-extension
|
- Extension ID: your-extension
|
||||||
- Version: 1.0.0
|
- Version: 1.0.0
|
||||||
@@ -218,7 +234,7 @@ git commit -m "Add your-extension to catalog
|
|||||||
git push origin add-your-extension
|
git push origin add-your-extension
|
||||||
|
|
||||||
# Create Pull Request on GitHub
|
# Create Pull Request on GitHub
|
||||||
# https://github.com/statsperform/spec-kit/compare
|
# https://github.com/github/spec-kit/compare
|
||||||
```
|
```
|
||||||
|
|
||||||
**Pull Request Template**:
|
**Pull Request Template**:
|
||||||
@@ -243,6 +259,8 @@ Brief description of what your extension does.
|
|||||||
- [x] Extension tested on real project
|
- [x] Extension tested on real project
|
||||||
- [x] All commands working
|
- [x] All commands working
|
||||||
- [x] No security vulnerabilities
|
- [x] No security vulnerabilities
|
||||||
|
- [x] Added to extensions/catalog.community.json
|
||||||
|
- [x] Added to extensions/README.md Available Extensions table
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
Tested on:
|
Tested on:
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ Extensions are modular packages that add new commands and functionality to Spec
|
|||||||
### Check Your Version
|
### Check Your Version
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
specify --version
|
specify version
|
||||||
# Should show 0.1.0 or higher
|
# Should show 0.1.0 or higher
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -76,13 +76,15 @@ vim .specify/extensions/jira/jira-config.yml
|
|||||||
|
|
||||||
## Finding Extensions
|
## Finding Extensions
|
||||||
|
|
||||||
|
**Note**: By default, `specify extension search` uses your organization's catalog (`catalog.json`). If the catalog is empty, you won't see any results. See [Extension Catalogs](#extension-catalogs) to learn how to populate your catalog from the community reference catalog.
|
||||||
|
|
||||||
### Browse All Extensions
|
### Browse All Extensions
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
specify extension search
|
specify extension search
|
||||||
```
|
```
|
||||||
|
|
||||||
Shows all available extensions in the catalog.
|
Shows all extensions in your organization's catalog.
|
||||||
|
|
||||||
### Search by Keyword
|
### Search by Keyword
|
||||||
|
|
||||||
@@ -415,11 +417,15 @@ export SPECKIT_CATALOG_URL="https://example.com/staging/catalog.json"
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Extension Catalogs
|
||||||
|
|
||||||
|
For information about how Spec Kit's dual-catalog system works (`catalog.json` vs `catalog.community.json`), see the main [Extensions README](README.md#extension-catalogs).
|
||||||
|
|
||||||
## Organization Catalog Customization
|
## Organization Catalog Customization
|
||||||
|
|
||||||
### Why the Default Catalog is Empty
|
### Why Customize Your Catalog
|
||||||
|
|
||||||
The default spec-kit catalog ships empty by design. This allows organizations to:
|
Organizations customize their `catalog.json` to:
|
||||||
|
|
||||||
- **Control available extensions** - Curate which extensions your team can install
|
- **Control available extensions** - Curate which extensions your team can install
|
||||||
- **Host private extensions** - Internal tools that shouldn't be public
|
- **Host private extensions** - Internal tools that shouldn't be public
|
||||||
|
|||||||
@@ -1,13 +1,119 @@
|
|||||||
# Spec Kit Community Extensions
|
# Spec Kit Extensions
|
||||||
|
|
||||||
Community-contributed extensions for [Spec Kit](https://github.com/github/spec-kit).
|
Extension system for [Spec Kit](https://github.com/github/spec-kit) - add new functionality without bloating the core framework.
|
||||||
|
|
||||||
## Available Extensions
|
## Extension Catalogs
|
||||||
|
|
||||||
|
Spec Kit provides two catalog files with different purposes:
|
||||||
|
|
||||||
|
### Your Catalog (`catalog.json`)
|
||||||
|
|
||||||
|
- **Purpose**: Default upstream catalog of extensions used by the Spec Kit CLI
|
||||||
|
- **Default State**: Empty by design in the upstream project - you or your organization populate a fork/copy with extensions you trust
|
||||||
|
- **Location (upstream)**: `extensions/catalog.json` in the GitHub-hosted spec-kit repo
|
||||||
|
- **CLI Default**: The `specify extension` commands use the upstream catalog URL by default, unless overridden
|
||||||
|
- **Org Catalog**: Point `SPECKIT_CATALOG_URL` at your organization's fork or hosted catalog JSON to use it instead of the upstream default
|
||||||
|
- **Customization**: Copy entries from the community catalog into your org catalog, or add your own extensions directly
|
||||||
|
|
||||||
|
**Example override:**
|
||||||
|
```bash
|
||||||
|
# Override the default upstream catalog with your organization's catalog
|
||||||
|
export SPECKIT_CATALOG_URL="https://your-org.com/spec-kit/catalog.json"
|
||||||
|
specify extension search # Now uses your organization's catalog instead of the upstream default
|
||||||
|
```
|
||||||
|
|
||||||
|
### Community Reference Catalog (`catalog.community.json`)
|
||||||
|
|
||||||
|
- **Purpose**: Browse available community-contributed extensions
|
||||||
|
- **Status**: Active - contains extensions submitted by the community
|
||||||
|
- **Location**: `extensions/catalog.community.json`
|
||||||
|
- **Usage**: Reference catalog for discovering available extensions
|
||||||
|
- **Submission**: Open to community contributions via Pull Request
|
||||||
|
|
||||||
|
**How It Works:**
|
||||||
|
|
||||||
|
## Making Extensions Available
|
||||||
|
|
||||||
|
You control which extensions your team can discover and install:
|
||||||
|
|
||||||
|
### Option 1: Curated Catalog (Recommended for Organizations)
|
||||||
|
|
||||||
|
Populate your `catalog.json` with approved extensions:
|
||||||
|
|
||||||
|
1. **Discover** extensions from various sources:
|
||||||
|
- Browse `catalog.community.json` for community extensions
|
||||||
|
- Find private/internal extensions in your organization's repos
|
||||||
|
- Discover extensions from trusted third parties
|
||||||
|
2. **Review** extensions and choose which ones you want to make available
|
||||||
|
3. **Add** those extension entries to your own `catalog.json`
|
||||||
|
4. **Team members** can now discover and install them:
|
||||||
|
- `specify extension search` shows your curated catalog
|
||||||
|
- `specify extension add <name>` installs from your catalog
|
||||||
|
|
||||||
|
**Benefits**: Full control over available extensions, team consistency, organizational approval workflow
|
||||||
|
|
||||||
|
**Example**: Copy an entry from `catalog.community.json` to your `catalog.json`, then your team can discover and install it by name.
|
||||||
|
|
||||||
|
### Option 2: Direct URLs (For Ad-hoc Use)
|
||||||
|
|
||||||
|
Skip catalog curation - team members install directly using URLs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension add --from https://github.com/org/spec-kit-ext/archive/refs/tags/v1.0.0.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits**: Quick for one-off testing or private extensions
|
||||||
|
|
||||||
|
**Tradeoff**: Extensions installed this way won't appear in `specify extension search` for other team members unless you also add them to your `catalog.json`.
|
||||||
|
|
||||||
|
## Available Community Extensions
|
||||||
|
|
||||||
|
The following community-contributed extensions are available in [`catalog.community.json`](catalog.community.json):
|
||||||
|
|
||||||
| Extension | Purpose | URL |
|
| Extension | Purpose | URL |
|
||||||
|-----------|---------|-----|
|
|-----------|---------|-----|
|
||||||
| V-Model Extension Pack | Enforces V-Model paired generation of development specs and test specs with full traceability | [spec-kit-v-model](https://github.com/leocamello/spec-kit-v-model) |
|
| V-Model Extension Pack | Enforces V-Model paired generation of development specs and test specs with full traceability | [spec-kit-v-model](https://github.com/leocamello/spec-kit-v-model) |
|
||||||
|
| Cleanup Extension | Post-implementation quality gate that reviews changes, fixes small issues (scout rule), creates tasks for medium issues, and generates analysis for large issues | [spec-kit-cleanup](https://github.com/dsrednicki/spec-kit-cleanup) |
|
||||||
|
|
||||||
## Adding Your Extension
|
## Adding Your Extension
|
||||||
|
|
||||||
See the [Extension Publishing Guide](EXTENSION-PUBLISHING-GUIDE.md) for instructions on how to submit your extension to the community catalog.
|
### Submission Process
|
||||||
|
|
||||||
|
To add your extension to the community catalog:
|
||||||
|
|
||||||
|
1. **Prepare your extension** following the [Extension Development Guide](EXTENSION-DEVELOPMENT-GUIDE.md)
|
||||||
|
2. **Create a GitHub release** for your extension
|
||||||
|
3. **Submit a Pull Request** that:
|
||||||
|
- Adds your extension to `extensions/catalog.community.json`
|
||||||
|
- Updates this README with your extension in the Available Extensions table
|
||||||
|
4. **Wait for review** - maintainers will review and merge if criteria are met
|
||||||
|
|
||||||
|
See the [Extension Publishing Guide](EXTENSION-PUBLISHING-GUIDE.md) for detailed step-by-step instructions.
|
||||||
|
|
||||||
|
### Submission Checklist
|
||||||
|
|
||||||
|
Before submitting, ensure:
|
||||||
|
|
||||||
|
- ✅ Valid `extension.yml` manifest
|
||||||
|
- ✅ Complete README with installation and usage instructions
|
||||||
|
- ✅ LICENSE file included
|
||||||
|
- ✅ GitHub release created with semantic version (e.g., v1.0.0)
|
||||||
|
- ✅ Extension tested on a real project
|
||||||
|
- ✅ All commands working as documented
|
||||||
|
|
||||||
|
## Installing Extensions
|
||||||
|
Once extensions are available (either in your catalog or via direct URL), install them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your curated catalog (by name)
|
||||||
|
specify extension search # See what's in your catalog
|
||||||
|
specify extension add <extension-name> # Install by name
|
||||||
|
|
||||||
|
# Direct from URL (bypasses catalog)
|
||||||
|
specify extension add --from https://github.com/<org>/<repo>/archive/refs/tags/<version>.zip
|
||||||
|
|
||||||
|
# List installed extensions
|
||||||
|
specify extension list
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information, see the [Extension User Guide](EXTENSION-USER-GUIDE.md).
|
||||||
|
|||||||
@@ -858,11 +858,41 @@ def should_execute_hook(hook: dict, config: dict) -> bool:
|
|||||||
|
|
||||||
## Extension Discovery & Catalog
|
## Extension Discovery & Catalog
|
||||||
|
|
||||||
### Central 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`
|
**URL**: `https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.json`
|
||||||
|
|
||||||
**Format**:
|
- **Purpose**: Organization's curated catalog of approved extensions
|
||||||
|
- **Default State**: Empty by design - users populate with extensions they trust
|
||||||
|
- **Usage**: Default catalog used by `specify extension` CLI commands
|
||||||
|
- **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**: Browse to discover extensions, then copy to your `catalog.json`
|
||||||
|
|
||||||
|
**How It Works:**
|
||||||
|
|
||||||
|
1. **Discover**: Browse `catalog.community.json` to find available extensions
|
||||||
|
2. **Review**: Evaluate extensions for security, quality, and organizational fit
|
||||||
|
3. **Curate**: Copy approved extension entries from community catalog to your `catalog.json`
|
||||||
|
4. **Install**: Use `specify extension add <name>` (pulls from your curated catalog)
|
||||||
|
|
||||||
|
This approach gives organizations full control over which extensions are available to their teams while maintaining a shared community resource for discovery.
|
||||||
|
|
||||||
|
### Catalog Format
|
||||||
|
|
||||||
|
**Format** (same for both catalogs):
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -931,25 +961,52 @@ specify extension info jira
|
|||||||
|
|
||||||
### Custom Catalogs
|
### Custom Catalogs
|
||||||
|
|
||||||
Organizations can host private catalogs:
|
**⚠️ FUTURE FEATURE - NOT YET IMPLEMENTED**
|
||||||
|
|
||||||
|
The following catalog management commands are proposed design concepts but are not yet available in the current implementation:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Add custom catalog
|
# Add custom catalog (FUTURE - NOT AVAILABLE)
|
||||||
specify extension add-catalog https://internal.company.com/spec-kit/catalog.json
|
specify extension add-catalog https://internal.company.com/spec-kit/catalog.json
|
||||||
|
|
||||||
# Set as default
|
# Set as default (FUTURE - NOT AVAILABLE)
|
||||||
specify extension set-catalog --default https://internal.company.com/spec-kit/catalog.json
|
specify extension set-catalog --default https://internal.company.com/spec-kit/catalog.json
|
||||||
|
|
||||||
# List catalogs
|
# List catalogs (FUTURE - NOT AVAILABLE)
|
||||||
specify extension catalogs
|
specify extension catalogs
|
||||||
```
|
```
|
||||||
|
|
||||||
**Catalog priority**:
|
**Proposed catalog priority** (future design):
|
||||||
|
|
||||||
1. Project-specific catalog (`.specify/extension-catalogs.yml`)
|
1. Project-specific catalog (`.specify/extension-catalogs.yml`) - *not implemented*
|
||||||
2. User-level catalog (`~/.specify/extension-catalogs.yml`)
|
2. User-level catalog (`~/.specify/extension-catalogs.yml`) - *not implemented*
|
||||||
3. Default GitHub catalog
|
3. Default GitHub catalog
|
||||||
|
|
||||||
|
#### Current Implementation: SPECKIT_CATALOG_URL
|
||||||
|
|
||||||
|
**The currently available method** for using custom catalogs is the `SPECKIT_CATALOG_URL` environment variable:
|
||||||
|
|
||||||
|
```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
|
## CLI Commands
|
||||||
|
|||||||
@@ -1,15 +1,67 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.0",
|
||||||
"updated_at": "2026-02-20T00:00:00Z",
|
"updated_at": "2026-02-24T00:00:00Z",
|
||||||
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json",
|
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json",
|
||||||
"extensions": {
|
"extensions": {
|
||||||
|
"cleanup": {
|
||||||
|
"name": "Cleanup Extension",
|
||||||
|
"id": "cleanup",
|
||||||
|
"description": "Post-implementation quality gate that reviews changes, fixes small issues (scout rule), creates tasks for medium issues, and generates analysis for large issues.",
|
||||||
|
"author": "dsrednicki",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"download_url": "https://github.com/dsrednicki/spec-kit-cleanup/archive/refs/tags/v1.0.0.zip",
|
||||||
|
"repository": "https://github.com/dsrednicki/spec-kit-cleanup",
|
||||||
|
"homepage": "https://github.com/dsrednicki/spec-kit-cleanup",
|
||||||
|
"documentation": "https://github.com/dsrednicki/spec-kit-cleanup/blob/main/README.md",
|
||||||
|
"changelog": "https://github.com/dsrednicki/spec-kit-cleanup/blob/main/CHANGELOG.md",
|
||||||
|
"license": "MIT",
|
||||||
|
"requires": {
|
||||||
|
"speckit_version": ">=0.1.0"
|
||||||
|
},
|
||||||
|
"provides": {
|
||||||
|
"commands": 1,
|
||||||
|
"hooks": 1
|
||||||
|
},
|
||||||
|
"tags": ["quality", "tech-debt", "review", "cleanup", "scout-rule"],
|
||||||
|
"verified": false,
|
||||||
|
"downloads": 0,
|
||||||
|
"stars": 0,
|
||||||
|
"created_at": "2026-02-22T00:00:00Z",
|
||||||
|
"updated_at": "2026-02-22T00:00:00Z"
|
||||||
|
},
|
||||||
|
"retrospective": {
|
||||||
|
"name": "Retrospective Extension",
|
||||||
|
"id": "retrospective",
|
||||||
|
"description": "Post-implementation retrospective with spec adherence scoring, drift analysis, and human-gated spec updates.",
|
||||||
|
"author": "emi-dm",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"download_url": "https://github.com/emi-dm/spec-kit-retrospective/archive/refs/tags/v1.0.0.zip",
|
||||||
|
"repository": "https://github.com/emi-dm/spec-kit-retrospective",
|
||||||
|
"homepage": "https://github.com/emi-dm/spec-kit-retrospective",
|
||||||
|
"documentation": "https://github.com/emi-dm/spec-kit-retrospective/blob/main/README.md",
|
||||||
|
"changelog": "https://github.com/emi-dm/spec-kit-retrospective/blob/main/CHANGELOG.md",
|
||||||
|
"license": "MIT",
|
||||||
|
"requires": {
|
||||||
|
"speckit_version": ">=0.1.0"
|
||||||
|
},
|
||||||
|
"provides": {
|
||||||
|
"commands": 1,
|
||||||
|
"hooks": 1
|
||||||
|
},
|
||||||
|
"tags": ["retrospective", "spec-drift", "quality", "analysis", "governance"],
|
||||||
|
"verified": false,
|
||||||
|
"downloads": 0,
|
||||||
|
"stars": 0,
|
||||||
|
"created_at": "2026-02-24T00:00:00Z",
|
||||||
|
"updated_at": "2026-02-24T00:00:00Z"
|
||||||
|
},
|
||||||
"v-model": {
|
"v-model": {
|
||||||
"name": "V-Model Extension Pack",
|
"name": "V-Model Extension Pack",
|
||||||
"id": "v-model",
|
"id": "v-model",
|
||||||
"description": "Enforces V-Model paired generation of development specs and test specs with full traceability.",
|
"description": "Enforces V-Model paired generation of development specs and test specs with full traceability.",
|
||||||
"author": "leocamello",
|
"author": "leocamello",
|
||||||
"version": "0.2.0",
|
"version": "0.4.0",
|
||||||
"download_url": "https://github.com/leocamello/spec-kit-v-model/archive/refs/tags/v0.2.0.zip",
|
"download_url": "https://github.com/leocamello/spec-kit-v-model/archive/refs/tags/v0.4.0.zip",
|
||||||
"repository": "https://github.com/leocamello/spec-kit-v-model",
|
"repository": "https://github.com/leocamello/spec-kit-v-model",
|
||||||
"homepage": "https://github.com/leocamello/spec-kit-v-model",
|
"homepage": "https://github.com/leocamello/spec-kit-v-model",
|
||||||
"documentation": "https://github.com/leocamello/spec-kit-v-model/blob/main/README.md",
|
"documentation": "https://github.com/leocamello/spec-kit-v-model/blob/main/README.md",
|
||||||
@@ -19,7 +71,7 @@
|
|||||||
"speckit_version": ">=0.1.0"
|
"speckit_version": ">=0.1.0"
|
||||||
},
|
},
|
||||||
"provides": {
|
"provides": {
|
||||||
"commands": 5,
|
"commands": 9,
|
||||||
"hooks": 1
|
"hooks": 1
|
||||||
},
|
},
|
||||||
"tags": ["v-model", "traceability", "testing", "compliance", "safety-critical"],
|
"tags": ["v-model", "traceability", "testing", "compliance", "safety-critical"],
|
||||||
@@ -27,7 +79,7 @@
|
|||||||
"downloads": 0,
|
"downloads": 0,
|
||||||
"stars": 0,
|
"stars": 0,
|
||||||
"created_at": "2026-02-20T00:00:00Z",
|
"created_at": "2026-02-20T00:00:00Z",
|
||||||
"updated_at": "2026-02-20T00:00:00Z"
|
"updated_at": "2026-02-22T00:00:00Z"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "specify-cli"
|
name = "specify-cli"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
|
description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -1256,6 +1256,20 @@ def init(
|
|||||||
|
|
||||||
show_banner()
|
show_banner()
|
||||||
|
|
||||||
|
# Detect when option values are likely misinterpreted flags (parameter ordering issue)
|
||||||
|
if ai_assistant and ai_assistant.startswith("--"):
|
||||||
|
console.print(f"[red]Error:[/red] Invalid value for --ai: '{ai_assistant}'")
|
||||||
|
console.print("[yellow]Hint:[/yellow] Did you forget to provide a value for --ai?")
|
||||||
|
console.print("[yellow]Example:[/yellow] specify init --ai claude --here")
|
||||||
|
console.print(f"[yellow]Available agents:[/yellow] {', '.join(AGENT_CONFIG.keys())}")
|
||||||
|
raise typer.Exit(1)
|
||||||
|
|
||||||
|
if ai_commands_dir and ai_commands_dir.startswith("--"):
|
||||||
|
console.print(f"[red]Error:[/red] Invalid value for --ai-commands-dir: '{ai_commands_dir}'")
|
||||||
|
console.print("[yellow]Hint:[/yellow] Did you forget to provide a value for --ai-commands-dir?")
|
||||||
|
console.print("[yellow]Example:[/yellow] specify init --ai generic --ai-commands-dir .myagent/commands/")
|
||||||
|
raise typer.Exit(1)
|
||||||
|
|
||||||
if project_name == ".":
|
if project_name == ".":
|
||||||
here = True
|
here = True
|
||||||
project_name = None # Clear project_name to use existing validation logic
|
project_name = None # Clear project_name to use existing validation logic
|
||||||
|
|||||||
@@ -630,3 +630,65 @@ class TestCliValidation:
|
|||||||
plain = re.sub(r'\x1b\[[0-9;]*m', '', result.output)
|
plain = re.sub(r'\x1b\[[0-9;]*m', '', result.output)
|
||||||
assert "--ai-skills" in plain
|
assert "--ai-skills" in plain
|
||||||
assert "agent skills" in plain.lower()
|
assert "agent skills" in plain.lower()
|
||||||
|
|
||||||
|
|
||||||
|
class TestParameterOrderingIssue:
|
||||||
|
"""Test fix for GitHub issue #1641: parameter ordering issues."""
|
||||||
|
|
||||||
|
def test_ai_flag_consuming_here_flag(self):
|
||||||
|
"""--ai without value should not consume --here flag (issue #1641)."""
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
# This used to fail with "Must specify project name" because --here was consumed by --ai
|
||||||
|
result = runner.invoke(app, ["init", "--ai-skills", "--ai", "--here"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert "Invalid value for --ai" in result.output
|
||||||
|
assert "--here" in result.output # Should mention the invalid value
|
||||||
|
|
||||||
|
def test_ai_flag_consuming_ai_skills_flag(self):
|
||||||
|
"""--ai without value should not consume --ai-skills flag."""
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
# This should fail with helpful error about missing --ai value
|
||||||
|
result = runner.invoke(app, ["init", "--here", "--ai", "--ai-skills"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert "Invalid value for --ai" in result.output
|
||||||
|
assert "--ai-skills" in result.output # Should mention the invalid value
|
||||||
|
|
||||||
|
def test_error_message_provides_hint(self):
|
||||||
|
"""Error message should provide helpful hint about missing value."""
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(app, ["init", "--ai", "--here"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert "Hint:" in result.output or "hint" in result.output.lower()
|
||||||
|
assert "forget to provide a value" in result.output.lower()
|
||||||
|
|
||||||
|
def test_error_message_lists_available_agents(self):
|
||||||
|
"""Error message should list available agents."""
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(app, ["init", "--ai", "--here"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
# Should mention some known agents
|
||||||
|
output_lower = result.output.lower()
|
||||||
|
assert any(agent in output_lower for agent in ["claude", "copilot", "gemini"])
|
||||||
|
|
||||||
|
def test_ai_commands_dir_consuming_flag(self):
|
||||||
|
"""--ai-commands-dir without value should not consume next flag."""
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(app, ["init", "myproject", "--ai", "generic", "--ai-commands-dir", "--here"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert "Invalid value for --ai-commands-dir" in result.output
|
||||||
|
assert "--here" in result.output
|
||||||
|
|||||||
Reference in New Issue
Block a user