mirror of
https://github.com/github/spec-kit.git
synced 2026-07-07 06:35:06 +08:00
Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b397b02f1 | ||
|
|
697daec733 | ||
|
|
02a1d610df | ||
|
|
8d2797dc03 | ||
|
|
076bb40f2e | ||
|
|
530d1ce514 | ||
|
|
c717cbb42d | ||
|
|
282dd3da56 | ||
|
|
e0fd355dad | ||
|
|
db8131441e | ||
|
|
752683d347 | ||
|
|
9988a46d96 | ||
|
|
27b4fd2e32 | ||
|
|
8fc2bd3489 | ||
|
|
b78a3cdd88 | ||
|
|
2f5417f0ad | ||
|
|
33a28ec8f7 | ||
|
|
f0886bd089 | ||
|
|
39c7b04e5e | ||
|
|
3467d26b1c | ||
|
|
a00e679918 | ||
|
|
c0152e4f3d | ||
|
|
03a9163633 | ||
|
|
4687c33b0f | ||
|
|
de93528fad | ||
|
|
bb7da09b65 | ||
|
|
fe75a45627 | ||
|
|
aa85b2f166 | ||
|
|
e27896e681 | ||
|
|
b67b2856b1 | ||
|
|
52ed84d723 | ||
|
|
cdbea09e1a | ||
|
|
1cb794e516 | ||
|
|
43cb0fa7ab | ||
|
|
74e3f45aa9 | ||
|
|
97ea7cf6a0 | ||
|
|
f43b85096c | ||
|
|
d1b95c2f59 | ||
|
|
8bb08ae1a0 | ||
|
|
5732de60d0 | ||
|
|
b6e19b49ec | ||
|
|
7f1e38491f | ||
|
|
bc0288832e | ||
|
|
e70495c2b8 | ||
|
|
674a66449a | ||
|
|
efeb5489c3 | ||
|
|
8013d0b57e | ||
|
|
0a121b073c | ||
|
|
6af2e64e88 | ||
|
|
66125a80a9 | ||
|
|
55515093a2 | ||
|
|
aa2282ea04 | ||
|
|
1c41aacbac | ||
|
|
cb0d9612ef | ||
|
|
71143598be | ||
|
|
9c73e68528 | ||
|
|
8472e44215 | ||
|
|
2972dec85c | ||
|
|
838bd0fedc | ||
|
|
3028a00b6e | ||
|
|
ac6714de31 | ||
|
|
4deb90f4f5 | ||
|
|
4d58ee945c | ||
|
|
feb839103d | ||
|
|
1c25b5af3b | ||
|
|
375b2fdb1d | ||
|
|
40fb276023 | ||
|
|
6536bc4102 | ||
|
|
1a9e4d1d8d | ||
|
|
aad6f68ae5 | ||
|
|
473a441720 | ||
|
|
55ff148475 | ||
|
|
7f08f31286 | ||
|
|
8b099585c7 | ||
|
|
9c0be46006 | ||
|
|
f92e7e8096 | ||
|
|
4178b61828 | ||
|
|
d9e63a51f1 | ||
|
|
7dc493e613 | ||
|
|
5678ca7757 | ||
|
|
94ba857b78 | ||
|
|
e1ab4f0486 | ||
|
|
535ddbe0d2 | ||
|
|
8353830f97 | ||
|
|
10be484868 | ||
|
|
48b84cc941 | ||
|
|
fac8e59c02 | ||
|
|
87c9e1ce75 | ||
|
|
d40c9a6428 | ||
|
|
cb508d7a36 | ||
|
|
b8e7851234 | ||
|
|
08f69e3d3e | ||
|
|
c8ccb0609d | ||
|
|
663d679f3b | ||
|
|
b1832c9477 | ||
|
|
a858c1d6da | ||
|
|
d9ce7c1fc0 | ||
|
|
4f9d966beb | ||
|
|
b44ffc0101 | ||
|
|
8e14ab1935 | ||
|
|
0945df9ec8 | ||
|
|
ea60efe2fa | ||
|
|
97b9f0f00d | ||
|
|
4df6d963dc | ||
|
|
682ffbfc0d | ||
|
|
b606b38512 | ||
|
|
255371d367 | ||
|
|
3113b72d6f |
4
.github/workflows/docs.yml
vendored
4
.github/workflows/docs.yml
vendored
@@ -26,6 +26,7 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
# Build job
|
# Build job
|
||||||
build:
|
build:
|
||||||
|
if: github.repository == 'github/spec-kit'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -47,7 +48,7 @@ jobs:
|
|||||||
docfx docfx.json
|
docfx docfx.json
|
||||||
|
|
||||||
- name: Setup Pages
|
- name: Setup Pages
|
||||||
uses: actions/configure-pages@v5
|
uses: actions/configure-pages@v6
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-pages-artifact@v3
|
uses: actions/upload-pages-artifact@v3
|
||||||
@@ -56,6 +57,7 @@ jobs:
|
|||||||
|
|
||||||
# Deploy job
|
# Deploy job
|
||||||
deploy:
|
deploy:
|
||||||
|
if: github.repository == 'github/spec-kit'
|
||||||
environment:
|
environment:
|
||||||
name: github-pages
|
name: github-pages
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
|||||||
62
.github/workflows/release.yml
vendored
62
.github/workflows/release.yml
vendored
@@ -27,35 +27,63 @@ jobs:
|
|||||||
- name: Check if release already exists
|
- name: Check if release already exists
|
||||||
id: check_release
|
id: check_release
|
||||||
run: |
|
run: |
|
||||||
chmod +x .github/workflows/scripts/check-release-exists.sh
|
VERSION="${{ steps.version.outputs.tag }}"
|
||||||
.github/workflows/scripts/check-release-exists.sh ${{ steps.version.outputs.tag }}
|
if gh release view "$VERSION" >/dev/null 2>&1; then
|
||||||
|
echo "exists=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "Release $VERSION already exists, skipping..."
|
||||||
|
else
|
||||||
|
echo "exists=false" >> $GITHUB_OUTPUT
|
||||||
|
echo "Release $VERSION does not exist, proceeding..."
|
||||||
|
fi
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Create release package variants
|
|
||||||
if: steps.check_release.outputs.exists == 'false'
|
|
||||||
run: |
|
|
||||||
chmod +x .github/workflows/scripts/create-release-packages.sh
|
|
||||||
.github/workflows/scripts/create-release-packages.sh ${{ steps.version.outputs.tag }}
|
|
||||||
|
|
||||||
- name: Generate release notes
|
- name: Generate release notes
|
||||||
if: steps.check_release.outputs.exists == 'false'
|
if: steps.check_release.outputs.exists == 'false'
|
||||||
id: release_notes
|
|
||||||
run: |
|
run: |
|
||||||
chmod +x .github/workflows/scripts/generate-release-notes.sh
|
VERSION="${{ steps.version.outputs.tag }}"
|
||||||
# Get the previous tag for changelog generation
|
VERSION_NO_V=${VERSION#v}
|
||||||
PREVIOUS_TAG=$(git describe --tags --abbrev=0 ${{ steps.version.outputs.tag }}^ 2>/dev/null || echo "")
|
|
||||||
# Default to v0.0.0 if no previous tag is found (e.g., first release)
|
# Find previous tag
|
||||||
|
PREVIOUS_TAG=$(git tag -l 'v*' --sort=-version:refname | grep -v "^${VERSION}$" | head -n 1)
|
||||||
if [ -z "$PREVIOUS_TAG" ]; then
|
if [ -z "$PREVIOUS_TAG" ]; then
|
||||||
PREVIOUS_TAG="v0.0.0"
|
PREVIOUS_TAG=""
|
||||||
fi
|
fi
|
||||||
.github/workflows/scripts/generate-release-notes.sh ${{ steps.version.outputs.tag }} "$PREVIOUS_TAG"
|
|
||||||
|
# Get commits since previous tag
|
||||||
|
if [ -z "$PREVIOUS_TAG" ]; then
|
||||||
|
COMMIT_COUNT=$(git rev-list --count HEAD)
|
||||||
|
if [ "$COMMIT_COUNT" -gt 20 ]; then
|
||||||
|
COMMITS=$(git log --oneline --pretty=format:"- %s" --no-merges HEAD~20..HEAD)
|
||||||
|
else
|
||||||
|
COMMITS=$(git log --oneline --pretty=format:"- %s" --no-merges)
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
COMMITS=$(git log --oneline --pretty=format:"- %s" --no-merges "$PREVIOUS_TAG"..HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > release_notes.md << NOTES_EOF
|
||||||
|
## Install
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@${VERSION}
|
||||||
|
specify init my-project
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
NOTES_EOF
|
||||||
|
|
||||||
|
echo "## What's Changed" >> release_notes.md
|
||||||
|
echo "" >> release_notes.md
|
||||||
|
echo "$COMMITS" >> release_notes.md
|
||||||
|
|
||||||
- name: Create GitHub Release
|
- name: Create GitHub Release
|
||||||
if: steps.check_release.outputs.exists == 'false'
|
if: steps.check_release.outputs.exists == 'false'
|
||||||
run: |
|
run: |
|
||||||
chmod +x .github/workflows/scripts/create-github-release.sh
|
VERSION="${{ steps.version.outputs.tag }}"
|
||||||
.github/workflows/scripts/create-github-release.sh ${{ steps.version.outputs.tag }}
|
VERSION_NO_V=${VERSION#v}
|
||||||
|
gh release create "$VERSION" \
|
||||||
|
--title "Spec Kit - $VERSION_NO_V" \
|
||||||
|
--notes-file release_notes.md
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# check-release-exists.sh
|
|
||||||
# Check if a GitHub release already exists for the given version
|
|
||||||
# Usage: check-release-exists.sh <version>
|
|
||||||
|
|
||||||
if [[ $# -ne 1 ]]; then
|
|
||||||
echo "Usage: $0 <version>" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERSION="$1"
|
|
||||||
|
|
||||||
if gh release view "$VERSION" >/dev/null 2>&1; then
|
|
||||||
echo "exists=true" >> $GITHUB_OUTPUT
|
|
||||||
echo "Release $VERSION already exists, skipping..."
|
|
||||||
else
|
|
||||||
echo "exists=false" >> $GITHUB_OUTPUT
|
|
||||||
echo "Release $VERSION does not exist, proceeding..."
|
|
||||||
fi
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# create-github-release.sh
|
|
||||||
# Create a GitHub release with all template zip files
|
|
||||||
# Usage: create-github-release.sh <version>
|
|
||||||
|
|
||||||
if [[ $# -ne 1 ]]; then
|
|
||||||
echo "Usage: $0 <version>" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERSION="$1"
|
|
||||||
|
|
||||||
# Remove 'v' prefix from version for release title
|
|
||||||
VERSION_NO_V=${VERSION#v}
|
|
||||||
|
|
||||||
gh release create "$VERSION" \
|
|
||||||
.genreleases/spec-kit-template-copilot-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-copilot-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-claude-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-claude-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-gemini-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-gemini-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-cursor-agent-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-cursor-agent-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-opencode-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-opencode-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-qwen-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-qwen-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-windsurf-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-windsurf-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-junie-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-junie-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-codex-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-codex-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-kilocode-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-kilocode-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-auggie-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-auggie-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-roo-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-roo-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-codebuddy-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-codebuddy-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-qodercli-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-qodercli-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-amp-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-amp-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-shai-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-shai-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-tabnine-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-tabnine-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-kiro-cli-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-kiro-cli-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-agy-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-agy-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-bob-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-bob-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-vibe-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-vibe-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-kimi-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-kimi-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-trae-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-trae-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-pi-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-pi-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-iflow-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-iflow-ps-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-generic-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-generic-ps-"$VERSION".zip \
|
|
||||||
--title "Spec Kit Templates - $VERSION_NO_V" \
|
|
||||||
--notes-file release_notes.md
|
|
||||||
@@ -1,560 +0,0 @@
|
|||||||
#!/usr/bin/env pwsh
|
|
||||||
#requires -Version 7.0
|
|
||||||
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Build Spec Kit template release archives for each supported AI assistant and script type.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
create-release-packages.ps1 (workflow-local)
|
|
||||||
Build Spec Kit template release archives for each supported AI assistant and script type.
|
|
||||||
|
|
||||||
.PARAMETER Version
|
|
||||||
Version string with leading 'v' (e.g., v0.2.0)
|
|
||||||
|
|
||||||
.PARAMETER Agents
|
|
||||||
Comma or space separated subset of agents to build (default: all)
|
|
||||||
Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, junie, codex, kilocode, auggie, roo, codebuddy, amp, kiro-cli, bob, qodercli, shai, tabnine, agy, vibe, kimi, trae, pi, iflow, generic
|
|
||||||
|
|
||||||
.PARAMETER Scripts
|
|
||||||
Comma or space separated subset of script types to build (default: both)
|
|
||||||
Valid scripts: sh, ps
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
.\create-release-packages.ps1 -Version v0.2.0
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
.\create-release-packages.ps1 -Version v0.2.0 -Agents claude,copilot -Scripts sh
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
.\create-release-packages.ps1 -Version v0.2.0 -Agents claude -Scripts ps
|
|
||||||
#>
|
|
||||||
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory=$true, Position=0)]
|
|
||||||
[string]$Version,
|
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
|
||||||
[string]$Agents = "",
|
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
|
||||||
[string]$Scripts = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
|
||||||
|
|
||||||
# Validate version format
|
|
||||||
if ($Version -notmatch '^v\d+\.\d+\.\d+$') {
|
|
||||||
Write-Error "Version must look like v0.0.0"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Building release packages for $Version"
|
|
||||||
|
|
||||||
# Create and use .genreleases directory for all build artifacts
|
|
||||||
$GenReleasesDir = ".genreleases"
|
|
||||||
if (Test-Path $GenReleasesDir) {
|
|
||||||
Remove-Item -Path $GenReleasesDir -Recurse -Force -ErrorAction SilentlyContinue
|
|
||||||
}
|
|
||||||
New-Item -ItemType Directory -Path $GenReleasesDir -Force | Out-Null
|
|
||||||
|
|
||||||
function Rewrite-Paths {
|
|
||||||
param([string]$Content)
|
|
||||||
|
|
||||||
$Content = $Content -replace '(/?)\bmemory/', '.specify/memory/'
|
|
||||||
$Content = $Content -replace '(/?)\bscripts/', '.specify/scripts/'
|
|
||||||
$Content = $Content -replace '(/?)\btemplates/', '.specify/templates/'
|
|
||||||
return $Content
|
|
||||||
}
|
|
||||||
|
|
||||||
function Generate-Commands {
|
|
||||||
param(
|
|
||||||
[string]$Agent,
|
|
||||||
[string]$Extension,
|
|
||||||
[string]$ArgFormat,
|
|
||||||
[string]$OutputDir,
|
|
||||||
[string]$ScriptVariant
|
|
||||||
)
|
|
||||||
|
|
||||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
|
||||||
|
|
||||||
$templates = Get-ChildItem -Path "templates/commands/*.md" -File -ErrorAction SilentlyContinue
|
|
||||||
|
|
||||||
foreach ($template in $templates) {
|
|
||||||
$name = [System.IO.Path]::GetFileNameWithoutExtension($template.Name)
|
|
||||||
|
|
||||||
# Read file content and normalize line endings
|
|
||||||
$fileContent = (Get-Content -Path $template.FullName -Raw) -replace "`r`n", "`n"
|
|
||||||
|
|
||||||
# Extract description from YAML frontmatter
|
|
||||||
$description = ""
|
|
||||||
if ($fileContent -match '(?m)^description:\s*(.+)$') {
|
|
||||||
$description = $matches[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Extract script command from YAML frontmatter
|
|
||||||
$scriptCommand = ""
|
|
||||||
if ($fileContent -match "(?m)^\s*${ScriptVariant}:\s*(.+)$") {
|
|
||||||
$scriptCommand = $matches[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($scriptCommand)) {
|
|
||||||
Write-Warning "No script command found for $ScriptVariant in $($template.Name)"
|
|
||||||
$scriptCommand = "(Missing script command for $ScriptVariant)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Extract agent_script command from YAML frontmatter if present
|
|
||||||
$agentScriptCommand = ""
|
|
||||||
if ($fileContent -match "(?ms)agent_scripts:.*?^\s*${ScriptVariant}:\s*(.+?)$") {
|
|
||||||
$agentScriptCommand = $matches[1].Trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
# Replace {SCRIPT} placeholder with the script command
|
|
||||||
$body = $fileContent -replace '\{SCRIPT\}', $scriptCommand
|
|
||||||
|
|
||||||
# Replace {AGENT_SCRIPT} placeholder with the agent script command if found
|
|
||||||
if (-not [string]::IsNullOrEmpty($agentScriptCommand)) {
|
|
||||||
$body = $body -replace '\{AGENT_SCRIPT\}', $agentScriptCommand
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove the scripts: and agent_scripts: sections from frontmatter
|
|
||||||
$lines = $body -split "`n"
|
|
||||||
$outputLines = @()
|
|
||||||
$inFrontmatter = $false
|
|
||||||
$skipScripts = $false
|
|
||||||
$dashCount = 0
|
|
||||||
|
|
||||||
foreach ($line in $lines) {
|
|
||||||
if ($line -match '^---$') {
|
|
||||||
$outputLines += $line
|
|
||||||
$dashCount++
|
|
||||||
if ($dashCount -eq 1) {
|
|
||||||
$inFrontmatter = $true
|
|
||||||
} else {
|
|
||||||
$inFrontmatter = $false
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($inFrontmatter) {
|
|
||||||
if ($line -match '^(scripts|agent_scripts):$') {
|
|
||||||
$skipScripts = $true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if ($line -match '^[a-zA-Z].*:' -and $skipScripts) {
|
|
||||||
$skipScripts = $false
|
|
||||||
}
|
|
||||||
if ($skipScripts -and $line -match '^\s+') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$outputLines += $line
|
|
||||||
}
|
|
||||||
|
|
||||||
$body = $outputLines -join "`n"
|
|
||||||
|
|
||||||
# Apply other substitutions
|
|
||||||
$body = $body -replace '\{ARGS\}', $ArgFormat
|
|
||||||
$body = $body -replace '__AGENT__', $Agent
|
|
||||||
$body = Rewrite-Paths -Content $body
|
|
||||||
|
|
||||||
# Generate output file based on extension
|
|
||||||
$outputFile = Join-Path $OutputDir "speckit.$name.$Extension"
|
|
||||||
|
|
||||||
switch ($Extension) {
|
|
||||||
'toml' {
|
|
||||||
$body = $body -replace '\\', '\\'
|
|
||||||
$output = "description = `"$description`"`n`nprompt = `"`"`"`n$body`n`"`"`""
|
|
||||||
Set-Content -Path $outputFile -Value $output -NoNewline
|
|
||||||
}
|
|
||||||
'md' {
|
|
||||||
Set-Content -Path $outputFile -Value $body -NoNewline
|
|
||||||
}
|
|
||||||
'agent.md' {
|
|
||||||
Set-Content -Path $outputFile -Value $body -NoNewline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Generate-CopilotPrompts {
|
|
||||||
param(
|
|
||||||
[string]$AgentsDir,
|
|
||||||
[string]$PromptsDir
|
|
||||||
)
|
|
||||||
|
|
||||||
New-Item -ItemType Directory -Path $PromptsDir -Force | Out-Null
|
|
||||||
|
|
||||||
$agentFiles = Get-ChildItem -Path "$AgentsDir/speckit.*.agent.md" -File -ErrorAction SilentlyContinue
|
|
||||||
|
|
||||||
foreach ($agentFile in $agentFiles) {
|
|
||||||
$basename = $agentFile.Name -replace '\.agent\.md$', ''
|
|
||||||
$promptFile = Join-Path $PromptsDir "$basename.prompt.md"
|
|
||||||
|
|
||||||
$content = @"
|
|
||||||
---
|
|
||||||
agent: $basename
|
|
||||||
---
|
|
||||||
"@
|
|
||||||
Set-Content -Path $promptFile -Value $content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create skills in <skills_dir>\<name>\SKILL.md format.
|
|
||||||
# Skills use hyphenated names (e.g. speckit-plan).
|
|
||||||
#
|
|
||||||
# Technical debt note:
|
|
||||||
# Keep SKILL.md frontmatter aligned with `install_ai_skills()` and extension
|
|
||||||
# overrides (at minimum: name/description/compatibility/metadata.{author,source}).
|
|
||||||
function New-Skills {
|
|
||||||
param(
|
|
||||||
[string]$SkillsDir,
|
|
||||||
[string]$ScriptVariant,
|
|
||||||
[string]$AgentName,
|
|
||||||
[string]$Separator = '-'
|
|
||||||
)
|
|
||||||
|
|
||||||
$templates = Get-ChildItem -Path "templates/commands/*.md" -File -ErrorAction SilentlyContinue
|
|
||||||
|
|
||||||
foreach ($template in $templates) {
|
|
||||||
$name = [System.IO.Path]::GetFileNameWithoutExtension($template.Name)
|
|
||||||
$skillName = "speckit${Separator}$name"
|
|
||||||
$skillDir = Join-Path $SkillsDir $skillName
|
|
||||||
New-Item -ItemType Directory -Force -Path $skillDir | Out-Null
|
|
||||||
|
|
||||||
$fileContent = (Get-Content -Path $template.FullName -Raw) -replace "`r`n", "`n"
|
|
||||||
|
|
||||||
# Extract description
|
|
||||||
$description = "Spec Kit: $name workflow"
|
|
||||||
if ($fileContent -match '(?m)^description:\s*(.+)$') {
|
|
||||||
$description = $matches[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Extract script command
|
|
||||||
$scriptCommand = "(Missing script command for $ScriptVariant)"
|
|
||||||
if ($fileContent -match "(?m)^\s*${ScriptVariant}:\s*(.+)$") {
|
|
||||||
$scriptCommand = $matches[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Extract agent_script command from frontmatter if present
|
|
||||||
$agentScriptCommand = ""
|
|
||||||
if ($fileContent -match "(?ms)agent_scripts:.*?^\s*${ScriptVariant}:\s*(.+?)$") {
|
|
||||||
$agentScriptCommand = $matches[1].Trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
# Replace {SCRIPT}, strip scripts sections, rewrite paths
|
|
||||||
$body = $fileContent -replace '\{SCRIPT\}', $scriptCommand
|
|
||||||
if (-not [string]::IsNullOrEmpty($agentScriptCommand)) {
|
|
||||||
$body = $body -replace '\{AGENT_SCRIPT\}', $agentScriptCommand
|
|
||||||
}
|
|
||||||
|
|
||||||
$lines = $body -split "`n"
|
|
||||||
$outputLines = @()
|
|
||||||
$inFrontmatter = $false
|
|
||||||
$skipScripts = $false
|
|
||||||
$dashCount = 0
|
|
||||||
|
|
||||||
foreach ($line in $lines) {
|
|
||||||
if ($line -match '^---$') {
|
|
||||||
$outputLines += $line
|
|
||||||
$dashCount++
|
|
||||||
$inFrontmatter = ($dashCount -eq 1)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if ($inFrontmatter) {
|
|
||||||
if ($line -match '^(scripts|agent_scripts):$') { $skipScripts = $true; continue }
|
|
||||||
if ($line -match '^[a-zA-Z].*:' -and $skipScripts) { $skipScripts = $false }
|
|
||||||
if ($skipScripts -and $line -match '^\s+') { continue }
|
|
||||||
}
|
|
||||||
$outputLines += $line
|
|
||||||
}
|
|
||||||
|
|
||||||
$body = $outputLines -join "`n"
|
|
||||||
$body = $body -replace '\{ARGS\}', '$ARGUMENTS'
|
|
||||||
$body = $body -replace '__AGENT__', $AgentName
|
|
||||||
$body = Rewrite-Paths -Content $body
|
|
||||||
|
|
||||||
# Strip existing frontmatter, keep only body
|
|
||||||
$templateBody = ""
|
|
||||||
$fmCount = 0
|
|
||||||
$inBody = $false
|
|
||||||
foreach ($line in ($body -split "`n")) {
|
|
||||||
if ($line -match '^---$') {
|
|
||||||
$fmCount++
|
|
||||||
if ($fmCount -eq 2) { $inBody = $true }
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if ($inBody) { $templateBody += "$line`n" }
|
|
||||||
}
|
|
||||||
|
|
||||||
$skillContent = "---`nname: `"$skillName`"`ndescription: `"$description`"`ncompatibility: `"Requires spec-kit project structure with .specify/ directory`"`nmetadata:`n author: `"github-spec-kit`"`n source: `"templates/commands/$name.md`"`n---`n`n$templateBody"
|
|
||||||
Set-Content -Path (Join-Path $skillDir "SKILL.md") -Value $skillContent -NoNewline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Build-Variant {
|
|
||||||
param(
|
|
||||||
[string]$Agent,
|
|
||||||
[string]$Script
|
|
||||||
)
|
|
||||||
|
|
||||||
$baseDir = Join-Path $GenReleasesDir "sdd-${Agent}-package-${Script}"
|
|
||||||
Write-Host "Building $Agent ($Script) package..."
|
|
||||||
New-Item -ItemType Directory -Path $baseDir -Force | Out-Null
|
|
||||||
|
|
||||||
# Copy base structure but filter scripts by variant
|
|
||||||
$specDir = Join-Path $baseDir ".specify"
|
|
||||||
New-Item -ItemType Directory -Path $specDir -Force | Out-Null
|
|
||||||
|
|
||||||
# Copy memory directory
|
|
||||||
if (Test-Path "memory") {
|
|
||||||
Copy-Item -Path "memory" -Destination $specDir -Recurse -Force
|
|
||||||
Write-Host "Copied memory -> .specify"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Only copy the relevant script variant directory
|
|
||||||
if (Test-Path "scripts") {
|
|
||||||
$scriptsDestDir = Join-Path $specDir "scripts"
|
|
||||||
New-Item -ItemType Directory -Path $scriptsDestDir -Force | Out-Null
|
|
||||||
|
|
||||||
switch ($Script) {
|
|
||||||
'sh' {
|
|
||||||
if (Test-Path "scripts/bash") {
|
|
||||||
Copy-Item -Path "scripts/bash" -Destination $scriptsDestDir -Recurse -Force
|
|
||||||
Write-Host "Copied scripts/bash -> .specify/scripts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'ps' {
|
|
||||||
if (Test-Path "scripts/powershell") {
|
|
||||||
Copy-Item -Path "scripts/powershell" -Destination $scriptsDestDir -Recurse -Force
|
|
||||||
Write-Host "Copied scripts/powershell -> .specify/scripts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Get-ChildItem -Path "scripts" -File -ErrorAction SilentlyContinue | ForEach-Object {
|
|
||||||
Copy-Item -Path $_.FullName -Destination $scriptsDestDir -Force
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Copy templates (excluding commands directory and vscode-settings.json)
|
|
||||||
if (Test-Path "templates") {
|
|
||||||
$templatesDestDir = Join-Path $specDir "templates"
|
|
||||||
New-Item -ItemType Directory -Path $templatesDestDir -Force | Out-Null
|
|
||||||
|
|
||||||
Get-ChildItem -Path "templates" -Recurse -File | Where-Object {
|
|
||||||
$_.FullName -notmatch 'templates[/\\]commands[/\\]' -and $_.Name -ne 'vscode-settings.json'
|
|
||||||
} | ForEach-Object {
|
|
||||||
$relativePath = $_.FullName.Substring((Resolve-Path "templates").Path.Length + 1)
|
|
||||||
$destFile = Join-Path $templatesDestDir $relativePath
|
|
||||||
$destFileDir = Split-Path $destFile -Parent
|
|
||||||
New-Item -ItemType Directory -Path $destFileDir -Force | Out-Null
|
|
||||||
Copy-Item -Path $_.FullName -Destination $destFile -Force
|
|
||||||
}
|
|
||||||
Write-Host "Copied templates -> .specify/templates"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generate agent-specific command files
|
|
||||||
switch ($Agent) {
|
|
||||||
'claude' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".claude/commands"
|
|
||||||
Generate-Commands -Agent 'claude' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'gemini' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".gemini/commands"
|
|
||||||
Generate-Commands -Agent 'gemini' -Extension 'toml' -ArgFormat '{{args}}' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
if (Test-Path "agent_templates/gemini/GEMINI.md") {
|
|
||||||
Copy-Item -Path "agent_templates/gemini/GEMINI.md" -Destination (Join-Path $baseDir "GEMINI.md")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'copilot' {
|
|
||||||
$agentsDir = Join-Path $baseDir ".github/agents"
|
|
||||||
Generate-Commands -Agent 'copilot' -Extension 'agent.md' -ArgFormat '$ARGUMENTS' -OutputDir $agentsDir -ScriptVariant $Script
|
|
||||||
|
|
||||||
$promptsDir = Join-Path $baseDir ".github/prompts"
|
|
||||||
Generate-CopilotPrompts -AgentsDir $agentsDir -PromptsDir $promptsDir
|
|
||||||
|
|
||||||
$vscodeDir = Join-Path $baseDir ".vscode"
|
|
||||||
New-Item -ItemType Directory -Path $vscodeDir -Force | Out-Null
|
|
||||||
if (Test-Path "templates/vscode-settings.json") {
|
|
||||||
Copy-Item -Path "templates/vscode-settings.json" -Destination (Join-Path $vscodeDir "settings.json")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'cursor-agent' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".cursor/commands"
|
|
||||||
Generate-Commands -Agent 'cursor-agent' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'qwen' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".qwen/commands"
|
|
||||||
Generate-Commands -Agent 'qwen' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
if (Test-Path "agent_templates/qwen/QWEN.md") {
|
|
||||||
Copy-Item -Path "agent_templates/qwen/QWEN.md" -Destination (Join-Path $baseDir "QWEN.md")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'opencode' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".opencode/command"
|
|
||||||
Generate-Commands -Agent 'opencode' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'windsurf' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".windsurf/workflows"
|
|
||||||
Generate-Commands -Agent 'windsurf' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'junie' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".junie/commands"
|
|
||||||
Generate-Commands -Agent 'junie' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'codex' {
|
|
||||||
$skillsDir = Join-Path $baseDir ".agents/skills"
|
|
||||||
New-Item -ItemType Directory -Force -Path $skillsDir | Out-Null
|
|
||||||
New-Skills -SkillsDir $skillsDir -ScriptVariant $Script -AgentName 'codex' -Separator '-'
|
|
||||||
}
|
|
||||||
'kilocode' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".kilocode/workflows"
|
|
||||||
Generate-Commands -Agent 'kilocode' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'auggie' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".augment/commands"
|
|
||||||
Generate-Commands -Agent 'auggie' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'roo' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".roo/commands"
|
|
||||||
Generate-Commands -Agent 'roo' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'codebuddy' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".codebuddy/commands"
|
|
||||||
Generate-Commands -Agent 'codebuddy' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'amp' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".agents/commands"
|
|
||||||
Generate-Commands -Agent 'amp' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'kiro-cli' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".kiro/prompts"
|
|
||||||
Generate-Commands -Agent 'kiro-cli' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'bob' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".bob/commands"
|
|
||||||
Generate-Commands -Agent 'bob' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'qodercli' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".qoder/commands"
|
|
||||||
Generate-Commands -Agent 'qodercli' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'shai' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".shai/commands"
|
|
||||||
Generate-Commands -Agent 'shai' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'tabnine' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".tabnine/agent/commands"
|
|
||||||
Generate-Commands -Agent 'tabnine' -Extension 'toml' -ArgFormat '{{args}}' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
$tabnineTemplate = Join-Path 'agent_templates' 'tabnine/TABNINE.md'
|
|
||||||
if (Test-Path $tabnineTemplate) { Copy-Item $tabnineTemplate (Join-Path $baseDir 'TABNINE.md') }
|
|
||||||
}
|
|
||||||
'agy' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".agent/commands"
|
|
||||||
Generate-Commands -Agent 'agy' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'vibe' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".vibe/prompts"
|
|
||||||
Generate-Commands -Agent 'vibe' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'kimi' {
|
|
||||||
$skillsDir = Join-Path $baseDir ".kimi/skills"
|
|
||||||
New-Item -ItemType Directory -Force -Path $skillsDir | Out-Null
|
|
||||||
New-Skills -SkillsDir $skillsDir -ScriptVariant $Script -AgentName 'kimi'
|
|
||||||
}
|
|
||||||
'trae' {
|
|
||||||
$rulesDir = Join-Path $baseDir ".trae/rules"
|
|
||||||
New-Item -ItemType Directory -Force -Path $rulesDir | Out-Null
|
|
||||||
Generate-Commands -Agent 'trae' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $rulesDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'pi' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".pi/prompts"
|
|
||||||
Generate-Commands -Agent 'pi' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'iflow' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".iflow/commands"
|
|
||||||
Generate-Commands -Agent 'iflow' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
'generic' {
|
|
||||||
$cmdDir = Join-Path $baseDir ".speckit/commands"
|
|
||||||
Generate-Commands -Agent 'generic' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
|
||||||
}
|
|
||||||
default {
|
|
||||||
throw "Unsupported agent '$Agent'."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create zip archive
|
|
||||||
$zipFile = Join-Path $GenReleasesDir "spec-kit-template-${Agent}-${Script}-${Version}.zip"
|
|
||||||
Compress-Archive -Path "$baseDir/*" -DestinationPath $zipFile -Force
|
|
||||||
Write-Host "Created $zipFile"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Define all agents and scripts
|
|
||||||
$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'junie', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'kiro-cli', 'bob', 'qodercli', 'shai', 'tabnine', 'agy', 'vibe', 'kimi', 'trae', 'pi', 'iflow', 'generic')
|
|
||||||
$AllScripts = @('sh', 'ps')
|
|
||||||
|
|
||||||
function Normalize-List {
|
|
||||||
param([string]$Value)
|
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($Value)) {
|
|
||||||
return @()
|
|
||||||
}
|
|
||||||
|
|
||||||
$items = $Value -split '[,\s]+' | Where-Object { $_ } | Select-Object -Unique
|
|
||||||
return $items
|
|
||||||
}
|
|
||||||
|
|
||||||
function Validate-Subset {
|
|
||||||
param(
|
|
||||||
[string]$Type,
|
|
||||||
[string[]]$Allowed,
|
|
||||||
[string[]]$Items
|
|
||||||
)
|
|
||||||
|
|
||||||
$ok = $true
|
|
||||||
foreach ($item in $Items) {
|
|
||||||
if ($item -notin $Allowed) {
|
|
||||||
Write-Error "Unknown $Type '$item' (allowed: $($Allowed -join ', '))"
|
|
||||||
$ok = $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $ok
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determine agent list
|
|
||||||
if (-not [string]::IsNullOrEmpty($Agents)) {
|
|
||||||
$AgentList = Normalize-List -Value $Agents
|
|
||||||
if (-not (Validate-Subset -Type 'agent' -Allowed $AllAgents -Items $AgentList)) {
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$AgentList = $AllAgents
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determine script list
|
|
||||||
if (-not [string]::IsNullOrEmpty($Scripts)) {
|
|
||||||
$ScriptList = Normalize-List -Value $Scripts
|
|
||||||
if (-not (Validate-Subset -Type 'script' -Allowed $AllScripts -Items $ScriptList)) {
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$ScriptList = $AllScripts
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Agents: $($AgentList -join ', ')"
|
|
||||||
Write-Host "Scripts: $($ScriptList -join ', ')"
|
|
||||||
|
|
||||||
# Build all variants
|
|
||||||
foreach ($agent in $AgentList) {
|
|
||||||
foreach ($script in $ScriptList) {
|
|
||||||
Build-Variant -Agent $agent -Script $script
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "`nArchives in ${GenReleasesDir}:"
|
|
||||||
Get-ChildItem -Path $GenReleasesDir -Filter "spec-kit-template-*-${Version}.zip" | ForEach-Object {
|
|
||||||
Write-Host " $($_.Name)"
|
|
||||||
}
|
|
||||||
388
.github/workflows/scripts/create-release-packages.sh
vendored
388
.github/workflows/scripts/create-release-packages.sh
vendored
@@ -1,388 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# create-release-packages.sh (workflow-local)
|
|
||||||
# Build Spec Kit template release archives for each supported AI assistant and script type.
|
|
||||||
# Usage: .github/workflows/scripts/create-release-packages.sh <version>
|
|
||||||
# Version argument should include leading 'v'.
|
|
||||||
# Optionally set AGENTS and/or SCRIPTS env vars to limit what gets built.
|
|
||||||
# AGENTS : space or comma separated subset of: claude gemini copilot cursor-agent qwen opencode windsurf junie codex kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli kimi trae pi iflow generic (default: all)
|
|
||||||
# SCRIPTS : space or comma separated subset of: sh ps (default: both)
|
|
||||||
# Examples:
|
|
||||||
# AGENTS=claude SCRIPTS=sh $0 v0.2.0
|
|
||||||
# AGENTS="copilot,gemini" $0 v0.2.0
|
|
||||||
# SCRIPTS=ps $0 v0.2.0
|
|
||||||
|
|
||||||
if [[ $# -ne 1 ]]; then
|
|
||||||
echo "Usage: $0 <version-with-v-prefix>" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
NEW_VERSION="$1"
|
|
||||||
if [[ ! $NEW_VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
||||||
echo "Version must look like v0.0.0" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Building release packages for $NEW_VERSION"
|
|
||||||
|
|
||||||
# Create and use .genreleases directory for all build artifacts
|
|
||||||
# Override via GENRELEASES_DIR env var (e.g. for tests writing to a temp dir)
|
|
||||||
GENRELEASES_DIR="${GENRELEASES_DIR:-.genreleases}"
|
|
||||||
|
|
||||||
# Guard against unsafe GENRELEASES_DIR values before cleaning
|
|
||||||
if [[ -z "$GENRELEASES_DIR" ]]; then
|
|
||||||
echo "GENRELEASES_DIR must not be empty" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
case "$GENRELEASES_DIR" in
|
|
||||||
'/'|'.'|'..')
|
|
||||||
echo "Refusing to use unsafe GENRELEASES_DIR value: $GENRELEASES_DIR" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
if [[ "$GENRELEASES_DIR" == *".."* ]]; then
|
|
||||||
echo "Refusing to use GENRELEASES_DIR containing '..' path segments: $GENRELEASES_DIR" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "$GENRELEASES_DIR"
|
|
||||||
rm -rf "${GENRELEASES_DIR%/}/"* || true
|
|
||||||
|
|
||||||
rewrite_paths() {
|
|
||||||
sed -E \
|
|
||||||
-e 's@(/?)memory/@.specify/memory/@g' \
|
|
||||||
-e 's@(/?)scripts/@.specify/scripts/@g' \
|
|
||||||
-e 's@(/?)templates/@.specify/templates/@g' \
|
|
||||||
-e 's@\.specify\.specify/@.specify/@g'
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_commands() {
|
|
||||||
local agent=$1 ext=$2 arg_format=$3 output_dir=$4 script_variant=$5
|
|
||||||
mkdir -p "$output_dir"
|
|
||||||
for template in templates/commands/*.md; do
|
|
||||||
[[ -f "$template" ]] || continue
|
|
||||||
local name description script_command agent_script_command body
|
|
||||||
name=$(basename "$template" .md)
|
|
||||||
|
|
||||||
# Normalize line endings
|
|
||||||
file_content=$(tr -d '\r' < "$template")
|
|
||||||
|
|
||||||
# Extract description and script command from YAML frontmatter
|
|
||||||
description=$(printf '%s\n' "$file_content" | awk '/^description:/ {sub(/^description:[[:space:]]*/, ""); print; exit}')
|
|
||||||
script_command=$(printf '%s\n' "$file_content" | awk -v sv="$script_variant" '/^[[:space:]]*'"$script_variant"':[[:space:]]*/ {sub(/^[[:space:]]*'"$script_variant"':[[:space:]]*/, ""); print; exit}')
|
|
||||||
|
|
||||||
if [[ -z $script_command ]]; then
|
|
||||||
echo "Warning: no script command found for $script_variant in $template" >&2
|
|
||||||
script_command="(Missing script command for $script_variant)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Extract agent_script command from YAML frontmatter if present
|
|
||||||
agent_script_command=$(printf '%s\n' "$file_content" | awk '
|
|
||||||
/^agent_scripts:$/ { in_agent_scripts=1; next }
|
|
||||||
in_agent_scripts && /^[[:space:]]*'"$script_variant"':[[:space:]]*/ {
|
|
||||||
sub(/^[[:space:]]*'"$script_variant"':[[:space:]]*/, "")
|
|
||||||
print
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
in_agent_scripts && /^[a-zA-Z]/ { in_agent_scripts=0 }
|
|
||||||
')
|
|
||||||
|
|
||||||
# Replace {SCRIPT} placeholder with the script command
|
|
||||||
body=$(printf '%s\n' "$file_content" | sed "s|{SCRIPT}|${script_command}|g")
|
|
||||||
|
|
||||||
# Replace {AGENT_SCRIPT} placeholder with the agent script command if found
|
|
||||||
if [[ -n $agent_script_command ]]; then
|
|
||||||
body=$(printf '%s\n' "$body" | sed "s|{AGENT_SCRIPT}|${agent_script_command}|g")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Remove the scripts: and agent_scripts: sections from frontmatter while preserving YAML structure
|
|
||||||
body=$(printf '%s\n' "$body" | awk '
|
|
||||||
/^---$/ { print; if (++dash_count == 1) in_frontmatter=1; else in_frontmatter=0; next }
|
|
||||||
in_frontmatter && /^scripts:$/ { skip_scripts=1; next }
|
|
||||||
in_frontmatter && /^agent_scripts:$/ { skip_scripts=1; next }
|
|
||||||
in_frontmatter && /^[a-zA-Z].*:/ && skip_scripts { skip_scripts=0 }
|
|
||||||
in_frontmatter && skip_scripts && /^[[:space:]]/ { next }
|
|
||||||
{ print }
|
|
||||||
')
|
|
||||||
|
|
||||||
# Apply other substitutions
|
|
||||||
body=$(printf '%s\n' "$body" | sed "s/{ARGS}/$arg_format/g" | sed "s/__AGENT__/$agent/g" | rewrite_paths)
|
|
||||||
|
|
||||||
case $ext in
|
|
||||||
toml)
|
|
||||||
body=$(printf '%s\n' "$body" | sed 's/\\/\\\\/g')
|
|
||||||
{ echo "description = \"$description\""; echo; echo "prompt = \"\"\""; echo "$body"; echo "\"\"\""; } > "$output_dir/speckit.$name.$ext" ;;
|
|
||||||
md)
|
|
||||||
echo "$body" > "$output_dir/speckit.$name.$ext" ;;
|
|
||||||
agent.md)
|
|
||||||
echo "$body" > "$output_dir/speckit.$name.$ext" ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_copilot_prompts() {
|
|
||||||
local agents_dir=$1 prompts_dir=$2
|
|
||||||
mkdir -p "$prompts_dir"
|
|
||||||
|
|
||||||
# Generate a .prompt.md file for each .agent.md file
|
|
||||||
for agent_file in "$agents_dir"/speckit.*.agent.md; do
|
|
||||||
[[ -f "$agent_file" ]] || continue
|
|
||||||
|
|
||||||
local basename=$(basename "$agent_file" .agent.md)
|
|
||||||
local prompt_file="$prompts_dir/${basename}.prompt.md"
|
|
||||||
|
|
||||||
cat > "$prompt_file" <<EOF
|
|
||||||
---
|
|
||||||
agent: ${basename}
|
|
||||||
---
|
|
||||||
EOF
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create skills in <skills_dir>/<name>/SKILL.md format.
|
|
||||||
# Skills use hyphenated names (e.g. speckit-plan).
|
|
||||||
#
|
|
||||||
# Technical debt note:
|
|
||||||
# Keep SKILL.md frontmatter aligned with `install_ai_skills()` and extension
|
|
||||||
# overrides (at minimum: name/description/compatibility/metadata.{author,source}).
|
|
||||||
create_skills() {
|
|
||||||
local skills_dir="$1"
|
|
||||||
local script_variant="$2"
|
|
||||||
local agent_name="$3"
|
|
||||||
local separator="${4:-"-"}"
|
|
||||||
|
|
||||||
for template in templates/commands/*.md; do
|
|
||||||
[[ -f "$template" ]] || continue
|
|
||||||
local name
|
|
||||||
name=$(basename "$template" .md)
|
|
||||||
local skill_name="speckit${separator}${name}"
|
|
||||||
local skill_dir="${skills_dir}/${skill_name}"
|
|
||||||
mkdir -p "$skill_dir"
|
|
||||||
|
|
||||||
local file_content
|
|
||||||
file_content=$(tr -d '\r' < "$template")
|
|
||||||
|
|
||||||
# Extract description from frontmatter
|
|
||||||
local description
|
|
||||||
description=$(printf '%s\n' "$file_content" | awk '/^description:/ {sub(/^description:[[:space:]]*/, ""); print; exit}')
|
|
||||||
[[ -z "$description" ]] && description="Spec Kit: ${name} workflow"
|
|
||||||
|
|
||||||
# Extract script command
|
|
||||||
local script_command
|
|
||||||
script_command=$(printf '%s\n' "$file_content" | awk -v sv="$script_variant" '/^[[:space:]]*'"$script_variant"':[[:space:]]*/ {sub(/^[[:space:]]*'"$script_variant"':[[:space:]]*/, ""); print; exit}')
|
|
||||||
[[ -z "$script_command" ]] && script_command="(Missing script command for $script_variant)"
|
|
||||||
|
|
||||||
# Extract agent_script command from frontmatter if present
|
|
||||||
local agent_script_command
|
|
||||||
agent_script_command=$(printf '%s\n' "$file_content" | awk '
|
|
||||||
/^agent_scripts:$/ { in_agent_scripts=1; next }
|
|
||||||
in_agent_scripts && /^[[:space:]]*'"$script_variant"':[[:space:]]*/ {
|
|
||||||
sub(/^[[:space:]]*'"$script_variant"':[[:space:]]*/, "")
|
|
||||||
print
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
in_agent_scripts && /^[a-zA-Z]/ { in_agent_scripts=0 }
|
|
||||||
')
|
|
||||||
|
|
||||||
# Build body: replace placeholders, strip scripts sections, rewrite paths
|
|
||||||
local body
|
|
||||||
body=$(printf '%s\n' "$file_content" | sed "s|{SCRIPT}|${script_command}|g")
|
|
||||||
if [[ -n $agent_script_command ]]; then
|
|
||||||
body=$(printf '%s\n' "$body" | sed "s|{AGENT_SCRIPT}|${agent_script_command}|g")
|
|
||||||
fi
|
|
||||||
body=$(printf '%s\n' "$body" | awk '
|
|
||||||
/^---$/ { print; if (++dash_count == 1) in_frontmatter=1; else in_frontmatter=0; next }
|
|
||||||
in_frontmatter && /^scripts:$/ { skip_scripts=1; next }
|
|
||||||
in_frontmatter && /^agent_scripts:$/ { skip_scripts=1; next }
|
|
||||||
in_frontmatter && /^[a-zA-Z].*:/ && skip_scripts { skip_scripts=0 }
|
|
||||||
in_frontmatter && skip_scripts && /^[[:space:]]/ { next }
|
|
||||||
{ print }
|
|
||||||
')
|
|
||||||
body=$(printf '%s\n' "$body" | sed 's/{ARGS}/\$ARGUMENTS/g' | sed "s/__AGENT__/$agent_name/g" | rewrite_paths)
|
|
||||||
|
|
||||||
# Strip existing frontmatter and prepend skills frontmatter.
|
|
||||||
local template_body
|
|
||||||
template_body=$(printf '%s\n' "$body" | awk '/^---/{p++; if(p==2){found=1; next}} found')
|
|
||||||
|
|
||||||
{
|
|
||||||
printf -- '---\n'
|
|
||||||
printf 'name: "%s"\n' "$skill_name"
|
|
||||||
printf 'description: "%s"\n' "$description"
|
|
||||||
printf 'compatibility: "%s"\n' "Requires spec-kit project structure with .specify/ directory"
|
|
||||||
printf -- 'metadata:\n'
|
|
||||||
printf ' author: "%s"\n' "github-spec-kit"
|
|
||||||
printf ' source: "%s"\n' "templates/commands/${name}.md"
|
|
||||||
printf -- '---\n\n'
|
|
||||||
printf '%s\n' "$template_body"
|
|
||||||
} > "$skill_dir/SKILL.md"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
build_variant() {
|
|
||||||
local agent=$1 script=$2
|
|
||||||
local base_dir="$GENRELEASES_DIR/sdd-${agent}-package-${script}"
|
|
||||||
echo "Building $agent ($script) package..."
|
|
||||||
mkdir -p "$base_dir"
|
|
||||||
|
|
||||||
# Copy base structure but filter scripts by variant
|
|
||||||
SPEC_DIR="$base_dir/.specify"
|
|
||||||
mkdir -p "$SPEC_DIR"
|
|
||||||
|
|
||||||
[[ -d memory ]] && { cp -r memory "$SPEC_DIR/"; echo "Copied memory -> .specify"; }
|
|
||||||
|
|
||||||
# Only copy the relevant script variant directory
|
|
||||||
if [[ -d scripts ]]; then
|
|
||||||
mkdir -p "$SPEC_DIR/scripts"
|
|
||||||
case $script in
|
|
||||||
sh)
|
|
||||||
[[ -d scripts/bash ]] && { cp -r scripts/bash "$SPEC_DIR/scripts/"; echo "Copied scripts/bash -> .specify/scripts"; }
|
|
||||||
find scripts -maxdepth 1 -type f -exec cp {} "$SPEC_DIR/scripts/" \; 2>/dev/null || true
|
|
||||||
;;
|
|
||||||
ps)
|
|
||||||
[[ -d scripts/powershell ]] && { cp -r scripts/powershell "$SPEC_DIR/scripts/"; echo "Copied scripts/powershell -> .specify/scripts"; }
|
|
||||||
find scripts -maxdepth 1 -type f -exec cp {} "$SPEC_DIR/scripts/" \; 2>/dev/null || true
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
[[ -d templates ]] && { mkdir -p "$SPEC_DIR/templates"; find templates -type f -not -path "templates/commands/*" -not -name "vscode-settings.json" | while IFS= read -r f; do d="$SPEC_DIR/$(dirname "$f")"; mkdir -p "$d"; cp "$f" "$d/"; done; echo "Copied templates -> .specify/templates"; }
|
|
||||||
|
|
||||||
case $agent in
|
|
||||||
claude)
|
|
||||||
mkdir -p "$base_dir/.claude/commands"
|
|
||||||
generate_commands claude md "\$ARGUMENTS" "$base_dir/.claude/commands" "$script" ;;
|
|
||||||
gemini)
|
|
||||||
mkdir -p "$base_dir/.gemini/commands"
|
|
||||||
generate_commands gemini toml "{{args}}" "$base_dir/.gemini/commands" "$script"
|
|
||||||
[[ -f agent_templates/gemini/GEMINI.md ]] && cp agent_templates/gemini/GEMINI.md "$base_dir/GEMINI.md" ;;
|
|
||||||
copilot)
|
|
||||||
mkdir -p "$base_dir/.github/agents"
|
|
||||||
generate_commands copilot agent.md "\$ARGUMENTS" "$base_dir/.github/agents" "$script"
|
|
||||||
generate_copilot_prompts "$base_dir/.github/agents" "$base_dir/.github/prompts"
|
|
||||||
mkdir -p "$base_dir/.vscode"
|
|
||||||
[[ -f templates/vscode-settings.json ]] && cp templates/vscode-settings.json "$base_dir/.vscode/settings.json"
|
|
||||||
;;
|
|
||||||
cursor-agent)
|
|
||||||
mkdir -p "$base_dir/.cursor/commands"
|
|
||||||
generate_commands cursor-agent md "\$ARGUMENTS" "$base_dir/.cursor/commands" "$script" ;;
|
|
||||||
qwen)
|
|
||||||
mkdir -p "$base_dir/.qwen/commands"
|
|
||||||
generate_commands qwen md "\$ARGUMENTS" "$base_dir/.qwen/commands" "$script"
|
|
||||||
[[ -f agent_templates/qwen/QWEN.md ]] && cp agent_templates/qwen/QWEN.md "$base_dir/QWEN.md" ;;
|
|
||||||
opencode)
|
|
||||||
mkdir -p "$base_dir/.opencode/command"
|
|
||||||
generate_commands opencode md "\$ARGUMENTS" "$base_dir/.opencode/command" "$script" ;;
|
|
||||||
windsurf)
|
|
||||||
mkdir -p "$base_dir/.windsurf/workflows"
|
|
||||||
generate_commands windsurf md "\$ARGUMENTS" "$base_dir/.windsurf/workflows" "$script" ;;
|
|
||||||
junie)
|
|
||||||
mkdir -p "$base_dir/.junie/commands"
|
|
||||||
generate_commands junie md "\$ARGUMENTS" "$base_dir/.junie/commands" "$script" ;;
|
|
||||||
codex)
|
|
||||||
mkdir -p "$base_dir/.agents/skills"
|
|
||||||
create_skills "$base_dir/.agents/skills" "$script" "codex" "-" ;;
|
|
||||||
kilocode)
|
|
||||||
mkdir -p "$base_dir/.kilocode/workflows"
|
|
||||||
generate_commands kilocode md "\$ARGUMENTS" "$base_dir/.kilocode/workflows" "$script" ;;
|
|
||||||
auggie)
|
|
||||||
mkdir -p "$base_dir/.augment/commands"
|
|
||||||
generate_commands auggie md "\$ARGUMENTS" "$base_dir/.augment/commands" "$script" ;;
|
|
||||||
roo)
|
|
||||||
mkdir -p "$base_dir/.roo/commands"
|
|
||||||
generate_commands roo md "\$ARGUMENTS" "$base_dir/.roo/commands" "$script" ;;
|
|
||||||
codebuddy)
|
|
||||||
mkdir -p "$base_dir/.codebuddy/commands"
|
|
||||||
generate_commands codebuddy md "\$ARGUMENTS" "$base_dir/.codebuddy/commands" "$script" ;;
|
|
||||||
qodercli)
|
|
||||||
mkdir -p "$base_dir/.qoder/commands"
|
|
||||||
generate_commands qodercli md "\$ARGUMENTS" "$base_dir/.qoder/commands" "$script" ;;
|
|
||||||
amp)
|
|
||||||
mkdir -p "$base_dir/.agents/commands"
|
|
||||||
generate_commands amp md "\$ARGUMENTS" "$base_dir/.agents/commands" "$script" ;;
|
|
||||||
shai)
|
|
||||||
mkdir -p "$base_dir/.shai/commands"
|
|
||||||
generate_commands shai md "\$ARGUMENTS" "$base_dir/.shai/commands" "$script" ;;
|
|
||||||
tabnine)
|
|
||||||
mkdir -p "$base_dir/.tabnine/agent/commands"
|
|
||||||
generate_commands tabnine toml "{{args}}" "$base_dir/.tabnine/agent/commands" "$script"
|
|
||||||
[[ -f agent_templates/tabnine/TABNINE.md ]] && cp agent_templates/tabnine/TABNINE.md "$base_dir/TABNINE.md" ;;
|
|
||||||
kiro-cli)
|
|
||||||
mkdir -p "$base_dir/.kiro/prompts"
|
|
||||||
generate_commands kiro-cli md "\$ARGUMENTS" "$base_dir/.kiro/prompts" "$script" ;;
|
|
||||||
agy)
|
|
||||||
mkdir -p "$base_dir/.agent/commands"
|
|
||||||
generate_commands agy md "\$ARGUMENTS" "$base_dir/.agent/commands" "$script" ;;
|
|
||||||
bob)
|
|
||||||
mkdir -p "$base_dir/.bob/commands"
|
|
||||||
generate_commands bob md "\$ARGUMENTS" "$base_dir/.bob/commands" "$script" ;;
|
|
||||||
vibe)
|
|
||||||
mkdir -p "$base_dir/.vibe/prompts"
|
|
||||||
generate_commands vibe md "\$ARGUMENTS" "$base_dir/.vibe/prompts" "$script" ;;
|
|
||||||
kimi)
|
|
||||||
mkdir -p "$base_dir/.kimi/skills"
|
|
||||||
create_skills "$base_dir/.kimi/skills" "$script" "kimi" ;;
|
|
||||||
trae)
|
|
||||||
mkdir -p "$base_dir/.trae/rules"
|
|
||||||
generate_commands trae md "\$ARGUMENTS" "$base_dir/.trae/rules" "$script" ;;
|
|
||||||
pi)
|
|
||||||
mkdir -p "$base_dir/.pi/prompts"
|
|
||||||
generate_commands pi md "\$ARGUMENTS" "$base_dir/.pi/prompts" "$script" ;;
|
|
||||||
iflow)
|
|
||||||
mkdir -p "$base_dir/.iflow/commands"
|
|
||||||
generate_commands iflow md "\$ARGUMENTS" "$base_dir/.iflow/commands" "$script" ;;
|
|
||||||
generic)
|
|
||||||
mkdir -p "$base_dir/.speckit/commands"
|
|
||||||
generate_commands generic md "\$ARGUMENTS" "$base_dir/.speckit/commands" "$script" ;;
|
|
||||||
esac
|
|
||||||
( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . )
|
|
||||||
echo "Created $GENRELEASES_DIR/spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determine agent list
|
|
||||||
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf junie codex kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli kimi trae pi iflow generic)
|
|
||||||
ALL_SCRIPTS=(sh ps)
|
|
||||||
|
|
||||||
validate_subset() {
|
|
||||||
local type=$1; shift
|
|
||||||
local allowed_str="$1"; shift
|
|
||||||
local invalid=0
|
|
||||||
for it in "$@"; do
|
|
||||||
local found=0
|
|
||||||
for a in $allowed_str; do
|
|
||||||
if [[ "$it" == "$a" ]]; then found=1; break; fi
|
|
||||||
done
|
|
||||||
if [[ $found -eq 0 ]]; then
|
|
||||||
echo "Error: unknown $type '$it' (allowed: $allowed_str)" >&2
|
|
||||||
invalid=1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return $invalid
|
|
||||||
}
|
|
||||||
|
|
||||||
read_list() { tr ',\n' ' ' | awk '{for(i=1;i<=NF;i++){if(!seen[$i]++){printf((out?" ":"") $i);out=1}}}END{printf("\n")}'; }
|
|
||||||
|
|
||||||
if [[ -n ${AGENTS:-} ]]; then
|
|
||||||
read -ra AGENT_LIST <<< "$(printf '%s' "$AGENTS" | read_list)"
|
|
||||||
validate_subset agent "${ALL_AGENTS[*]}" "${AGENT_LIST[@]}" || exit 1
|
|
||||||
else
|
|
||||||
AGENT_LIST=("${ALL_AGENTS[@]}")
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n ${SCRIPTS:-} ]]; then
|
|
||||||
read -ra SCRIPT_LIST <<< "$(printf '%s' "$SCRIPTS" | read_list)"
|
|
||||||
validate_subset script "${ALL_SCRIPTS[*]}" "${SCRIPT_LIST[@]}" || exit 1
|
|
||||||
else
|
|
||||||
SCRIPT_LIST=("${ALL_SCRIPTS[@]}")
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Agents: ${AGENT_LIST[*]}"
|
|
||||||
echo "Scripts: ${SCRIPT_LIST[*]}"
|
|
||||||
|
|
||||||
for agent in "${AGENT_LIST[@]}"; do
|
|
||||||
for script in "${SCRIPT_LIST[@]}"; do
|
|
||||||
build_variant "$agent" "$script"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Archives in $GENRELEASES_DIR:"
|
|
||||||
ls -1 "$GENRELEASES_DIR"/spec-kit-template-*-"${NEW_VERSION}".zip
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# generate-release-notes.sh
|
|
||||||
# Generate release notes from git history
|
|
||||||
# Usage: generate-release-notes.sh <new_version> <last_tag>
|
|
||||||
|
|
||||||
if [[ $# -ne 2 ]]; then
|
|
||||||
echo "Usage: $0 <new_version> <last_tag>" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
NEW_VERSION="$1"
|
|
||||||
LAST_TAG="$2"
|
|
||||||
|
|
||||||
# Get commits since last tag
|
|
||||||
if [ "$LAST_TAG" = "v0.0.0" ]; then
|
|
||||||
# Check how many commits we have and use that as the limit
|
|
||||||
COMMIT_COUNT=$(git rev-list --count HEAD)
|
|
||||||
if [ "$COMMIT_COUNT" -gt 10 ]; then
|
|
||||||
COMMITS=$(git log --oneline --pretty=format:"- %s" HEAD~10..HEAD)
|
|
||||||
else
|
|
||||||
COMMITS=$(git log --oneline --pretty=format:"- %s" HEAD~$COMMIT_COUNT..HEAD 2>/dev/null || git log --oneline --pretty=format:"- %s")
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
COMMITS=$(git log --oneline --pretty=format:"- %s" $LAST_TAG..HEAD)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create release notes
|
|
||||||
cat > release_notes.md << EOF
|
|
||||||
This is the latest set of releases that you can use with your agent of choice. We recommend using the Specify CLI to scaffold your projects, however you can download these independently and manage them yourself.
|
|
||||||
|
|
||||||
## Changelog
|
|
||||||
|
|
||||||
$COMMITS
|
|
||||||
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "Generated release notes:"
|
|
||||||
cat release_notes.md
|
|
||||||
24
.github/workflows/scripts/get-next-version.sh
vendored
24
.github/workflows/scripts/get-next-version.sh
vendored
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# get-next-version.sh
|
|
||||||
# Calculate the next version based on the latest git tag and output GitHub Actions variables
|
|
||||||
# Usage: get-next-version.sh
|
|
||||||
|
|
||||||
# Get the latest tag, or use v0.0.0 if no tags exist
|
|
||||||
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
|
|
||||||
echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# Extract version number and increment
|
|
||||||
VERSION=$(echo $LATEST_TAG | sed 's/v//')
|
|
||||||
IFS='.' read -ra VERSION_PARTS <<< "$VERSION"
|
|
||||||
MAJOR=${VERSION_PARTS[0]:-0}
|
|
||||||
MINOR=${VERSION_PARTS[1]:-0}
|
|
||||||
PATCH=${VERSION_PARTS[2]:-0}
|
|
||||||
|
|
||||||
# Increment patch version
|
|
||||||
PATCH=$((PATCH + 1))
|
|
||||||
NEW_VERSION="v$MAJOR.$MINOR.$PATCH"
|
|
||||||
|
|
||||||
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
|
||||||
echo "New version will be: $NEW_VERSION"
|
|
||||||
161
.github/workflows/scripts/simulate-release.sh
vendored
161
.github/workflows/scripts/simulate-release.sh
vendored
@@ -1,161 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# simulate-release.sh
|
|
||||||
# Simulate the release process locally without pushing to GitHub
|
|
||||||
# Usage: simulate-release.sh [version]
|
|
||||||
# If version is omitted, auto-increments patch version
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
echo -e "${BLUE}🧪 Simulating Release Process Locally${NC}"
|
|
||||||
echo "======================================"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 1: Determine version
|
|
||||||
if [[ -n "${1:-}" ]]; then
|
|
||||||
VERSION="${1#v}"
|
|
||||||
TAG="v$VERSION"
|
|
||||||
echo -e "${GREEN}📝 Using manual version: $VERSION${NC}"
|
|
||||||
else
|
|
||||||
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
|
|
||||||
echo -e "${BLUE}Latest tag: $LATEST_TAG${NC}"
|
|
||||||
|
|
||||||
VERSION=$(echo $LATEST_TAG | sed 's/v//')
|
|
||||||
IFS='.' read -ra VERSION_PARTS <<< "$VERSION"
|
|
||||||
MAJOR=${VERSION_PARTS[0]:-0}
|
|
||||||
MINOR=${VERSION_PARTS[1]:-0}
|
|
||||||
PATCH=${VERSION_PARTS[2]:-0}
|
|
||||||
|
|
||||||
PATCH=$((PATCH + 1))
|
|
||||||
VERSION="$MAJOR.$MINOR.$PATCH"
|
|
||||||
TAG="v$VERSION"
|
|
||||||
echo -e "${GREEN}📝 Auto-incremented to: $VERSION${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 2: Check if tag exists
|
|
||||||
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
|
||||||
echo -e "${RED}❌ Error: Tag $TAG already exists!${NC}"
|
|
||||||
echo " Please use a different version or delete the tag first."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo -e "${GREEN}✓ Tag $TAG is available${NC}"
|
|
||||||
|
|
||||||
# Step 3: Backup current state
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}💾 Creating backup of current state...${NC}"
|
|
||||||
BACKUP_DIR=$(mktemp -d)
|
|
||||||
cp pyproject.toml "$BACKUP_DIR/pyproject.toml.bak"
|
|
||||||
cp CHANGELOG.md "$BACKUP_DIR/CHANGELOG.md.bak"
|
|
||||||
echo -e "${GREEN}✓ Backup created at: $BACKUP_DIR${NC}"
|
|
||||||
|
|
||||||
# Step 4: Update pyproject.toml
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}📝 Updating pyproject.toml...${NC}"
|
|
||||||
sed -i.tmp "s/version = \".*\"/version = \"$VERSION\"/" pyproject.toml
|
|
||||||
rm -f pyproject.toml.tmp
|
|
||||||
echo -e "${GREEN}✓ Updated pyproject.toml to version $VERSION${NC}"
|
|
||||||
|
|
||||||
# Step 5: Update CHANGELOG.md
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}📝 Updating CHANGELOG.md...${NC}"
|
|
||||||
DATE=$(date +%Y-%m-%d)
|
|
||||||
|
|
||||||
# Get the previous tag to compare commits
|
|
||||||
PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
|
||||||
|
|
||||||
if [[ -n "$PREVIOUS_TAG" ]]; then
|
|
||||||
echo " Generating changelog from commits since $PREVIOUS_TAG"
|
|
||||||
# Get commits since last tag, format as bullet points
|
|
||||||
COMMITS=$(git log --oneline "$PREVIOUS_TAG"..HEAD --no-merges --pretty=format:"- %s" 2>/dev/null || echo "- Initial release")
|
|
||||||
else
|
|
||||||
echo " No previous tag found - this is the first release"
|
|
||||||
COMMITS="- Initial release"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create temp file with new entry
|
|
||||||
{
|
|
||||||
head -n 8 CHANGELOG.md
|
|
||||||
echo ""
|
|
||||||
echo "## [$VERSION] - $DATE"
|
|
||||||
echo ""
|
|
||||||
echo "### Changed"
|
|
||||||
echo ""
|
|
||||||
echo "$COMMITS"
|
|
||||||
echo ""
|
|
||||||
tail -n +9 CHANGELOG.md
|
|
||||||
} > CHANGELOG.md.tmp
|
|
||||||
mv CHANGELOG.md.tmp CHANGELOG.md
|
|
||||||
echo -e "${GREEN}✓ Updated CHANGELOG.md with commits since $PREVIOUS_TAG${NC}"
|
|
||||||
|
|
||||||
# Step 6: Show what would be committed
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}📋 Changes that would be committed:${NC}"
|
|
||||||
git diff pyproject.toml CHANGELOG.md
|
|
||||||
|
|
||||||
# Step 7: Create temporary tag (no push)
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}🏷️ Creating temporary local tag...${NC}"
|
|
||||||
git tag -a "$TAG" -m "Simulated release $TAG" 2>/dev/null || true
|
|
||||||
echo -e "${GREEN}✓ Tag $TAG created locally${NC}"
|
|
||||||
|
|
||||||
# Step 8: Simulate release artifact creation
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}📦 Simulating release package creation...${NC}"
|
|
||||||
echo " (High-level simulation only; packaging script is not executed)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if script exists and is executable
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
if [[ -x "$SCRIPT_DIR/create-release-packages.sh" ]]; then
|
|
||||||
echo -e "${BLUE}In a real release, the following command would be run to create packages:${NC}"
|
|
||||||
echo " $SCRIPT_DIR/create-release-packages.sh \"$TAG\""
|
|
||||||
echo ""
|
|
||||||
echo "This simulation does not enumerate individual package files to avoid"
|
|
||||||
echo "drifting from the actual behavior of create-release-packages.sh."
|
|
||||||
else
|
|
||||||
echo -e "${RED}⚠️ create-release-packages.sh not found or not executable${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 9: Simulate release notes generation
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}📄 Simulating release notes generation...${NC}"
|
|
||||||
echo ""
|
|
||||||
PREVIOUS_TAG=$(git describe --tags --abbrev=0 $TAG^ 2>/dev/null || echo "")
|
|
||||||
if [[ -n "$PREVIOUS_TAG" ]]; then
|
|
||||||
echo -e "${BLUE}Changes since $PREVIOUS_TAG:${NC}"
|
|
||||||
git log --oneline "$PREVIOUS_TAG".."$TAG" | head -n 10
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
echo -e "${BLUE}No previous tag found - this would be the first release${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 10: Summary
|
|
||||||
echo ""
|
|
||||||
echo -e "${GREEN}🎉 Simulation Complete!${NC}"
|
|
||||||
echo "======================================"
|
|
||||||
echo ""
|
|
||||||
echo -e "${BLUE}Summary:${NC}"
|
|
||||||
echo " Version: $VERSION"
|
|
||||||
echo " Tag: $TAG"
|
|
||||||
echo " Backup: $BACKUP_DIR"
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}⚠️ SIMULATION ONLY - NO CHANGES PUSHED${NC}"
|
|
||||||
echo ""
|
|
||||||
echo -e "${BLUE}Next steps:${NC}"
|
|
||||||
echo " 1. Review the changes above"
|
|
||||||
echo " 2. To keep changes: git add pyproject.toml CHANGELOG.md && git commit"
|
|
||||||
echo " 3. To discard changes: git checkout pyproject.toml CHANGELOG.md && git tag -d $TAG"
|
|
||||||
echo " 4. To restore from backup: cp $BACKUP_DIR/* ."
|
|
||||||
echo ""
|
|
||||||
echo -e "${BLUE}To run the actual release:${NC}"
|
|
||||||
echo " Go to: https://github.com/github/spec-kit/actions/workflows/release-trigger.yml"
|
|
||||||
echo " Click 'Run workflow' and enter version: $VERSION"
|
|
||||||
echo ""
|
|
||||||
23
.github/workflows/scripts/update-version.sh
vendored
23
.github/workflows/scripts/update-version.sh
vendored
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# update-version.sh
|
|
||||||
# Update version in pyproject.toml (for release artifacts only)
|
|
||||||
# Usage: update-version.sh <version>
|
|
||||||
|
|
||||||
if [[ $# -ne 1 ]]; then
|
|
||||||
echo "Usage: $0 <version>" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERSION="$1"
|
|
||||||
|
|
||||||
# Remove 'v' prefix for Python versioning
|
|
||||||
PYTHON_VERSION=${VERSION#v}
|
|
||||||
|
|
||||||
if [ -f "pyproject.toml" ]; then
|
|
||||||
sed -i "s/version = \".*\"/version = \"$PYTHON_VERSION\"/" pyproject.toml
|
|
||||||
echo "Updated pyproject.toml version to $PYTHON_VERSION (for release artifacts only)"
|
|
||||||
else
|
|
||||||
echo "Warning: pyproject.toml not found, skipping version update"
|
|
||||||
fi
|
|
||||||
1
.github/workflows/stale.yml
vendored
1
.github/workflows/stale.yml
vendored
@@ -6,6 +6,7 @@ on:
|
|||||||
workflow_dispatch: # Allow manual triggering
|
workflow_dispatch: # Allow manual triggering
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
|
actions: write
|
||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|
||||||
|
|||||||
11
.github/workflows/test.yml
vendored
11
.github/workflows/test.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
@@ -27,16 +27,17 @@ jobs:
|
|||||||
run: uvx ruff check src/
|
run: uvx ruff check src/
|
||||||
|
|
||||||
pytest:
|
pytest:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
python-version: ["3.11", "3.12", "3.13"]
|
python-version: ["3.11", "3.12", "3.13"]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
@@ -46,5 +47,9 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: uv sync --extra test
|
run: uv sync --extra test
|
||||||
|
|
||||||
|
# On windows-latest, bash tests auto-skip unless Git-for-Windows
|
||||||
|
# bash (MSYS2/MINGW) is detected. The WSL launcher is rejected
|
||||||
|
# because it cannot handle native Windows paths in test fixtures.
|
||||||
|
# See tests/conftest.py::_has_working_bash() for details.
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: uv run pytest
|
run: uv run pytest
|
||||||
|
|||||||
615
AGENTS.md
615
AGENTS.md
@@ -10,276 +10,282 @@ The toolkit supports multiple AI coding assistants, allowing teams to use their
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Adding New Agent Support
|
## Integration Architecture
|
||||||
|
|
||||||
This section explains how to add support for new AI agents/assistants to the Specify CLI. Use this guide as a reference when integrating new AI tools into the Spec-Driven Development workflow.
|
Each AI agent is a self-contained **integration subpackage** under `src/specify_cli/integrations/<key>/`. The subpackage exposes a single class that declares all metadata and inherits setup/teardown logic from a base class. Built-in integrations are then instantiated and added to the global `INTEGRATION_REGISTRY` by `src/specify_cli/integrations/__init__.py` via `_register_builtins()`.
|
||||||
|
|
||||||
### Overview
|
```
|
||||||
|
src/specify_cli/integrations/
|
||||||
|
├── __init__.py # INTEGRATION_REGISTRY + _register_builtins()
|
||||||
|
├── base.py # IntegrationBase, MarkdownIntegration, TomlIntegration, YamlIntegration, SkillsIntegration
|
||||||
|
├── manifest.py # IntegrationManifest (file tracking)
|
||||||
|
├── claude/ # Example: SkillsIntegration subclass
|
||||||
|
│ ├── __init__.py # ClaudeIntegration class
|
||||||
|
│ └── scripts/ # Thin wrapper scripts
|
||||||
|
│ ├── update-context.sh
|
||||||
|
│ └── update-context.ps1
|
||||||
|
├── gemini/ # Example: TomlIntegration subclass
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── scripts/
|
||||||
|
├── windsurf/ # Example: MarkdownIntegration subclass
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── scripts/
|
||||||
|
├── copilot/ # Example: IntegrationBase subclass (custom setup)
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── scripts/
|
||||||
|
└── ... # One subpackage per supported agent
|
||||||
|
```
|
||||||
|
|
||||||
Specify supports multiple AI agents by generating agent-specific command files and directory structures when initializing projects. Each agent has its own conventions for:
|
The registry is the **single source of truth for Python integration metadata**. Supported agents, their directories, formats, and capabilities are derived from the integration classes for the Python integration layer. However, context-update behavior still requires explicit cases in the shared dispatcher scripts (`scripts/bash/update-agent-context.sh` and `scripts/powershell/update-agent-context.ps1`), which currently maintain their own supported-agent lists and agent-key→context-file mappings until they are migrated to registry-based dispatch.
|
||||||
|
|
||||||
- **Command file formats** (Markdown, TOML, etc.)
|
---
|
||||||
- **Directory structures** (`.claude/commands/`, `.windsurf/workflows/`, etc.)
|
|
||||||
- **Command invocation patterns** (slash commands, CLI tools, etc.)
|
|
||||||
- **Argument passing conventions** (`$ARGUMENTS`, `{{args}}`, etc.)
|
|
||||||
|
|
||||||
### Current Supported Agents
|
## Adding a New Integration
|
||||||
|
|
||||||
| Agent | Directory | Format | CLI Tool | Description |
|
### 1. Choose a base class
|
||||||
| -------------------------- | ---------------------- | -------- | --------------- | --------------------------- |
|
|
||||||
| **Claude Code** | `.claude/commands/` | Markdown | `claude` | Anthropic's Claude Code CLI |
|
|
||||||
| **Gemini CLI** | `.gemini/commands/` | TOML | `gemini` | Google's Gemini CLI |
|
|
||||||
| **GitHub Copilot** | `.github/agents/` | Markdown | N/A (IDE-based) | GitHub Copilot in VS Code |
|
|
||||||
| **Cursor** | `.cursor/commands/` | Markdown | N/A (IDE-based) | Cursor IDE (`--ai cursor-agent`) |
|
|
||||||
| **Qwen Code** | `.qwen/commands/` | Markdown | `qwen` | Alibaba's Qwen Code CLI |
|
|
||||||
| **opencode** | `.opencode/command/` | Markdown | `opencode` | opencode CLI |
|
|
||||||
| **Codex CLI** | `.agents/skills/` | Markdown | `codex` | Codex CLI (`--ai codex --ai-skills`) |
|
|
||||||
| **Windsurf** | `.windsurf/workflows/` | Markdown | N/A (IDE-based) | Windsurf IDE workflows |
|
|
||||||
| **Junie** | `.junie/commands/` | Markdown | `junie` | Junie by JetBrains |
|
|
||||||
| **Kilo Code** | `.kilocode/workflows/` | Markdown | N/A (IDE-based) | Kilo Code IDE |
|
|
||||||
| **Auggie CLI** | `.augment/commands/` | Markdown | `auggie` | Auggie CLI |
|
|
||||||
| **Roo Code** | `.roo/commands/` | Markdown | N/A (IDE-based) | Roo Code IDE |
|
|
||||||
| **CodeBuddy CLI** | `.codebuddy/commands/` | Markdown | `codebuddy` | CodeBuddy CLI |
|
|
||||||
| **Qoder CLI** | `.qoder/commands/` | Markdown | `qodercli` | Qoder CLI |
|
|
||||||
| **Kiro CLI** | `.kiro/prompts/` | Markdown | `kiro-cli` | Kiro CLI |
|
|
||||||
| **Amp** | `.agents/commands/` | Markdown | `amp` | Amp CLI |
|
|
||||||
| **SHAI** | `.shai/commands/` | Markdown | `shai` | SHAI CLI |
|
|
||||||
| **Tabnine CLI** | `.tabnine/agent/commands/` | TOML | `tabnine` | Tabnine CLI |
|
|
||||||
| **Kimi Code** | `.kimi/skills/` | Markdown | `kimi` | Kimi Code CLI (Moonshot AI) |
|
|
||||||
| **Pi Coding Agent** | `.pi/prompts/` | Markdown | `pi` | Pi terminal coding agent |
|
|
||||||
| **iFlow CLI** | `.iflow/commands/` | Markdown | `iflow` | iFlow CLI (iflow-ai) |
|
|
||||||
| **IBM Bob** | `.bob/commands/` | Markdown | N/A (IDE-based) | IBM Bob IDE |
|
|
||||||
| **Trae** | `.trae/rules/` | Markdown | N/A (IDE-based) | Trae IDE |
|
|
||||||
| **Antigravity** | `.agent/commands/` | Markdown | N/A (IDE-based) | Antigravity IDE (`--ai agy --ai-skills`) |
|
|
||||||
| **Mistral Vibe** | `.vibe/prompts/` | Markdown | `vibe` | Mistral Vibe CLI |
|
|
||||||
| **Generic** | User-specified via `--ai-commands-dir` | Markdown | N/A | Bring your own agent |
|
|
||||||
|
|
||||||
### Step-by-Step Integration Guide
|
| Your agent needs… | Subclass |
|
||||||
|
|---|---|
|
||||||
|
| Standard markdown commands (`.md`) | `MarkdownIntegration` |
|
||||||
|
| TOML-format commands (`.toml`) | `TomlIntegration` |
|
||||||
|
| YAML recipe files (`.yaml`) | `YamlIntegration` |
|
||||||
|
| Skill directories (`speckit-<name>/SKILL.md`) | `SkillsIntegration` |
|
||||||
|
| Fully custom output (companion files, settings merge, etc.) | `IntegrationBase` directly |
|
||||||
|
|
||||||
Follow these steps to add a new agent (using a hypothetical new agent as an example):
|
Most agents only need `MarkdownIntegration` — a minimal subclass with zero method overrides.
|
||||||
|
|
||||||
#### 1. Add to AGENT_CONFIG
|
### 2. Create the subpackage
|
||||||
|
|
||||||
**IMPORTANT**: Use the actual CLI tool name as the key, not a shortened version.
|
Create `src/specify_cli/integrations/<package_dir>/__init__.py`, where `<package_dir>` is the Python-safe directory name derived from `<key>`: use the key as-is when it contains no hyphens (e.g., key `"gemini"` → `gemini/`), or replace hyphens with underscores when it does (e.g., key `"kiro-cli"` → `kiro_cli/`). The `IntegrationBase.key` class attribute always retains the original hyphenated value, since that is what the CLI and registry use. For CLI-based integrations (`requires_cli: True`), the `key` should match the actual CLI tool name (the executable users install and run) so CLI checks can resolve it correctly. For IDE-based integrations (`requires_cli: False`), use the canonical integration identifier instead.
|
||||||
|
|
||||||
Add the new agent to the `AGENT_CONFIG` dictionary in `src/specify_cli/__init__.py`. This is the **single source of truth** for all agent metadata:
|
**Minimal example — Markdown agent (Windsurf):**
|
||||||
|
|
||||||
```python
|
```python
|
||||||
AGENT_CONFIG = {
|
"""Windsurf IDE integration."""
|
||||||
# ... existing agents ...
|
|
||||||
"new-agent-cli": { # Use the ACTUAL CLI tool name (what users type in terminal)
|
from ..base import MarkdownIntegration
|
||||||
"name": "New Agent Display Name",
|
|
||||||
"folder": ".newagent/", # Directory for agent files
|
|
||||||
"commands_subdir": "commands", # Subdirectory name for command files (default: "commands")
|
class WindsurfIntegration(MarkdownIntegration):
|
||||||
"install_url": "https://example.com/install", # URL for installation docs (or None if IDE-based)
|
key = "windsurf"
|
||||||
"requires_cli": True, # True if CLI tool required, False for IDE-based agents
|
config = {
|
||||||
},
|
"name": "Windsurf",
|
||||||
}
|
"folder": ".windsurf/",
|
||||||
|
"commands_subdir": "workflows",
|
||||||
|
"install_url": None,
|
||||||
|
"requires_cli": False,
|
||||||
|
}
|
||||||
|
registrar_config = {
|
||||||
|
"dir": ".windsurf/workflows",
|
||||||
|
"format": "markdown",
|
||||||
|
"args": "$ARGUMENTS",
|
||||||
|
"extension": ".md",
|
||||||
|
}
|
||||||
|
context_file = ".windsurf/rules/specify-rules.md"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Key Design Principle**: The dictionary key should match the actual executable name that users install. For example:
|
**TOML agent (Gemini):**
|
||||||
|
|
||||||
- ✅ Use `"cursor-agent"` because the CLI tool is literally called `cursor-agent`
|
|
||||||
- ❌ Don't use `"cursor"` as a shortcut if the tool is `cursor-agent`
|
|
||||||
|
|
||||||
This eliminates the need for special-case mappings throughout the codebase.
|
|
||||||
|
|
||||||
**Field Explanations**:
|
|
||||||
|
|
||||||
- `name`: Human-readable display name shown to users
|
|
||||||
- `folder`: Directory where agent-specific files are stored (relative to project root)
|
|
||||||
- `commands_subdir`: Subdirectory name within the agent folder where command/prompt files are stored (default: `"commands"`)
|
|
||||||
- Most agents use `"commands"` (e.g., `.claude/commands/`)
|
|
||||||
- Some agents use alternative names: `"agents"` (copilot), `"workflows"` (windsurf, kilocode), `"prompts"` (codex, kiro-cli, pi), `"command"` (opencode - singular)
|
|
||||||
- This field enables `--ai-skills` to locate command templates correctly for skill generation
|
|
||||||
- `install_url`: Installation documentation URL (set to `None` for IDE-based agents)
|
|
||||||
- `requires_cli`: Whether the agent requires a CLI tool check during initialization
|
|
||||||
|
|
||||||
#### 2. Update CLI Help Text
|
|
||||||
|
|
||||||
Update the `--ai` parameter help text in the `init()` command to include the new agent:
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, codebuddy, new-agent-cli, or kiro-cli"),
|
"""Gemini CLI integration."""
|
||||||
|
|
||||||
|
from ..base import TomlIntegration
|
||||||
|
|
||||||
|
|
||||||
|
class GeminiIntegration(TomlIntegration):
|
||||||
|
key = "gemini"
|
||||||
|
config = {
|
||||||
|
"name": "Gemini CLI",
|
||||||
|
"folder": ".gemini/",
|
||||||
|
"commands_subdir": "commands",
|
||||||
|
"install_url": "https://github.com/google-gemini/gemini-cli",
|
||||||
|
"requires_cli": True,
|
||||||
|
}
|
||||||
|
registrar_config = {
|
||||||
|
"dir": ".gemini/commands",
|
||||||
|
"format": "toml",
|
||||||
|
"args": "{{args}}",
|
||||||
|
"extension": ".toml",
|
||||||
|
}
|
||||||
|
context_file = "GEMINI.md"
|
||||||
```
|
```
|
||||||
|
|
||||||
Also update any function docstrings, examples, and error messages that list available agents.
|
**Skills agent (Codex):**
|
||||||
|
|
||||||
#### 3. Update README Documentation
|
```python
|
||||||
|
"""Codex CLI integration — skills-based agent."""
|
||||||
|
|
||||||
Update the **Supported AI Agents** section in `README.md` to include the new agent:
|
from __future__ import annotations
|
||||||
|
|
||||||
- Add the new agent to the table with appropriate support level (Full/Partial)
|
from ..base import IntegrationOption, SkillsIntegration
|
||||||
- Include the agent's official website link
|
|
||||||
- Add any relevant notes about the agent's implementation
|
|
||||||
- Ensure the table formatting remains aligned and consistent
|
|
||||||
|
|
||||||
#### 4. Update Release Package Script
|
|
||||||
|
|
||||||
Modify `.github/workflows/scripts/create-release-packages.sh`:
|
class CodexIntegration(SkillsIntegration):
|
||||||
|
key = "codex"
|
||||||
|
config = {
|
||||||
|
"name": "Codex CLI",
|
||||||
|
"folder": ".agents/",
|
||||||
|
"commands_subdir": "skills",
|
||||||
|
"install_url": "https://github.com/openai/codex",
|
||||||
|
"requires_cli": True,
|
||||||
|
}
|
||||||
|
registrar_config = {
|
||||||
|
"dir": ".agents/skills",
|
||||||
|
"format": "markdown",
|
||||||
|
"args": "$ARGUMENTS",
|
||||||
|
"extension": "/SKILL.md",
|
||||||
|
}
|
||||||
|
context_file = "AGENTS.md"
|
||||||
|
|
||||||
##### Add to ALL_AGENTS array
|
@classmethod
|
||||||
|
def options(cls) -> list[IntegrationOption]:
|
||||||
|
return [
|
||||||
|
IntegrationOption(
|
||||||
|
"--skills",
|
||||||
|
is_flag=True,
|
||||||
|
default=True,
|
||||||
|
help="Install as agent skills (default for Codex)",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Required fields
|
||||||
|
|
||||||
|
| Field | Location | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| `key` | Class attribute | Unique identifier; for CLI-based integrations (`requires_cli: True`), must match the CLI executable name |
|
||||||
|
| `config` | Class attribute (dict) | Agent metadata: `name`, `folder`, `commands_subdir`, `install_url`, `requires_cli` |
|
||||||
|
| `registrar_config` | Class attribute (dict) | Command output config: `dir`, `format`, `args` placeholder, file `extension` |
|
||||||
|
| `context_file` | Class attribute (str or None) | Path to agent context/instructions file (e.g., `"CLAUDE.md"`, `".github/copilot-instructions.md"`) |
|
||||||
|
|
||||||
|
**Key design rule:** For CLI-based integrations (`requires_cli: True`), `key` must be the actual executable name (e.g., `"cursor-agent"` not `"cursor"`). This ensures `shutil.which(key)` works for CLI-tool checks without special-case mappings. IDE-based integrations (`requires_cli: False`) should use their canonical identifier (e.g., `"windsurf"`, `"copilot"`).
|
||||||
|
|
||||||
|
### 3. Register it
|
||||||
|
|
||||||
|
In `src/specify_cli/integrations/__init__.py`, add one import and one `_register()` call inside `_register_builtins()`. Both lists are alphabetical:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def _register_builtins() -> None:
|
||||||
|
# -- Imports (alphabetical) -------------------------------------------
|
||||||
|
from .claude import ClaudeIntegration
|
||||||
|
# ...
|
||||||
|
from .newagent import NewAgentIntegration # ← add import
|
||||||
|
# ...
|
||||||
|
|
||||||
|
# -- Registration (alphabetical) --------------------------------------
|
||||||
|
_register(ClaudeIntegration())
|
||||||
|
# ...
|
||||||
|
_register(NewAgentIntegration()) # ← add registration
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Add scripts
|
||||||
|
|
||||||
|
Create two thin wrapper scripts in `src/specify_cli/integrations/<package_dir>/scripts/` that delegate to the shared context-update scripts. Each is ~25 lines of boilerplate.
|
||||||
|
|
||||||
|
> **Note on `<package_dir>` vs `<key>`:** `<package_dir>` is the Python-safe directory name for your integration — it matches `<key>` exactly when the key contains no hyphens (e.g., key `"gemini"` → `gemini/`), but uses underscores when it does (e.g., key `"kiro-cli"` → `kiro_cli/`). The `IntegrationBase.key` class attribute always retains the original hyphenated value (e.g., `key = "kiro-cli"`), since that is what the CLI and registry use.
|
||||||
|
|
||||||
|
**`update-context.sh`:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf kiro-cli)
|
#!/usr/bin/env bash
|
||||||
|
# update-context.sh — <Agent Name> integration: create/update <context_file>
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
_script_dir="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
_root="$_script_dir"
|
||||||
|
while [ "$_root" != "/" ] && [ ! -d "$_root/.specify" ]; do _root="$(dirname "$_root")"; done
|
||||||
|
if [ -z "${REPO_ROOT:-}" ]; then
|
||||||
|
if [ -d "$_root/.specify" ]; then
|
||||||
|
REPO_ROOT="$_root"
|
||||||
|
else
|
||||||
|
git_root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
||||||
|
if [ -n "$git_root" ] && [ -d "$git_root/.specify" ]; then
|
||||||
|
REPO_ROOT="$git_root"
|
||||||
|
else
|
||||||
|
REPO_ROOT="$_root"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$REPO_ROOT/.specify/scripts/bash/update-agent-context.sh" <key>
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Add case statement for directory structure
|
**`update-context.ps1`:**
|
||||||
|
|
||||||
```bash
|
|
||||||
case $agent in
|
|
||||||
# ... existing cases ...
|
|
||||||
windsurf)
|
|
||||||
mkdir -p "$base_dir/.windsurf/workflows"
|
|
||||||
generate_commands windsurf md "\$ARGUMENTS" "$base_dir/.windsurf/workflows" "$script" ;;
|
|
||||||
esac
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. Update GitHub Release Script
|
|
||||||
|
|
||||||
Modify `.github/workflows/scripts/create-github-release.sh` to include the new agent's packages:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gh release create "$VERSION" \
|
|
||||||
# ... existing packages ...
|
|
||||||
.genreleases/spec-kit-template-windsurf-sh-"$VERSION".zip \
|
|
||||||
.genreleases/spec-kit-template-windsurf-ps-"$VERSION".zip \
|
|
||||||
# Add new agent packages here
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 5. Update Agent Context Scripts
|
|
||||||
|
|
||||||
##### Bash script (`scripts/bash/update-agent-context.sh`)
|
|
||||||
|
|
||||||
Add file variable:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md"
|
|
||||||
```
|
|
||||||
|
|
||||||
Add to case statement:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
case "$AGENT_TYPE" in
|
|
||||||
# ... existing cases ...
|
|
||||||
windsurf) update_agent_file "$WINDSURF_FILE" "Windsurf" ;;
|
|
||||||
"")
|
|
||||||
# ... existing checks ...
|
|
||||||
[ -f "$WINDSURF_FILE" ] && update_agent_file "$WINDSURF_FILE" "Windsurf";
|
|
||||||
# Update default creation condition
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
```
|
|
||||||
|
|
||||||
##### PowerShell script (`scripts/powershell/update-agent-context.ps1`)
|
|
||||||
|
|
||||||
Add file variable:
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
$windsurfFile = Join-Path $repoRoot '.windsurf/rules/specify-rules.md'
|
# update-context.ps1 — <Agent Name> integration: create/update <context_file>
|
||||||
```
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
Add to switch statement:
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
$repoRoot = try { git rev-parse --show-toplevel 2>$null } catch { $null }
|
||||||
```powershell
|
if (-not $repoRoot -or -not (Test-Path (Join-Path $repoRoot '.specify'))) {
|
||||||
switch ($AgentType) {
|
$repoRoot = $scriptDir
|
||||||
# ... existing cases ...
|
$fsRoot = [System.IO.Path]::GetPathRoot($repoRoot)
|
||||||
'windsurf' { Update-AgentFile $windsurfFile 'Windsurf' }
|
while ($repoRoot -and $repoRoot -ne $fsRoot -and -not (Test-Path (Join-Path $repoRoot '.specify'))) {
|
||||||
'' {
|
$repoRoot = Split-Path -Parent $repoRoot
|
||||||
foreach ($pair in @(
|
|
||||||
# ... existing pairs ...
|
|
||||||
@{file=$windsurfFile; name='Windsurf'}
|
|
||||||
)) {
|
|
||||||
if (Test-Path $pair.file) { Update-AgentFile $pair.file $pair.name }
|
|
||||||
}
|
|
||||||
# Update default creation condition
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 6. Update CLI Tool Checks (Optional)
|
|
||||||
|
|
||||||
For agents that require CLI tools, add checks in the `check()` command and agent validation:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# In check() command
|
|
||||||
tracker.add("windsurf", "Windsurf IDE (optional)")
|
|
||||||
windsurf_ok = check_tool_for_tracker("windsurf", "https://windsurf.com/", tracker)
|
|
||||||
|
|
||||||
# In init validation (only if CLI tool required)
|
|
||||||
elif selected_ai == "windsurf":
|
|
||||||
if not check_tool("windsurf", "Install from: https://windsurf.com/"):
|
|
||||||
console.print("[red]Error:[/red] Windsurf CLI is required for Windsurf projects")
|
|
||||||
agent_tool_missing = True
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: CLI tool checks are now handled automatically based on the `requires_cli` field in AGENT_CONFIG. No additional code changes needed in the `check()` or `init()` commands - they automatically loop through AGENT_CONFIG and check tools as needed.
|
|
||||||
|
|
||||||
## Important Design Decisions
|
|
||||||
|
|
||||||
### Using Actual CLI Tool Names as Keys
|
|
||||||
|
|
||||||
**CRITICAL**: When adding a new agent to AGENT_CONFIG, always use the **actual executable name** as the dictionary key, not a shortened or convenient version.
|
|
||||||
|
|
||||||
**Why this matters:**
|
|
||||||
|
|
||||||
- The `check_tool()` function uses `shutil.which(tool)` to find executables in the system PATH
|
|
||||||
- If the key doesn't match the actual CLI tool name, you'll need special-case mappings throughout the codebase
|
|
||||||
- This creates unnecessary complexity and maintenance burden
|
|
||||||
|
|
||||||
**Example - The Cursor Lesson:**
|
|
||||||
|
|
||||||
❌ **Wrong approach** (requires special-case mapping):
|
|
||||||
|
|
||||||
```python
|
|
||||||
AGENT_CONFIG = {
|
|
||||||
"cursor": { # Shorthand that doesn't match the actual tool
|
|
||||||
"name": "Cursor",
|
|
||||||
# ...
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Then you need special cases everywhere:
|
& "$repoRoot/.specify/scripts/powershell/update-agent-context.ps1" -AgentType <key>
|
||||||
cli_tool = agent_key
|
|
||||||
if agent_key == "cursor":
|
|
||||||
cli_tool = "cursor-agent" # Map to the real tool name
|
|
||||||
```
|
```
|
||||||
|
|
||||||
✅ **Correct approach** (no mapping needed):
|
Replace `<key>` with your integration key and `<Agent Name>` / `<context_file>` with the appropriate values.
|
||||||
|
|
||||||
```python
|
You must also add the agent to the shared context-update scripts so the shared dispatcher recognises the new key:
|
||||||
AGENT_CONFIG = {
|
|
||||||
"cursor-agent": { # Matches the actual executable name
|
|
||||||
"name": "Cursor",
|
|
||||||
# ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# No special cases needed - just use agent_key directly!
|
- **`scripts/bash/update-agent-context.sh`** — add a file-path variable and a case in `update_specific_agent()`.
|
||||||
|
- **`scripts/powershell/update-agent-context.ps1`** — add a file-path variable, add the new key to the `AgentType` parameter's `[ValidateSet(...)]`, add a switch case in `Update-SpecificAgent`, and add an entry in `Update-AllExistingAgents`.
|
||||||
|
|
||||||
|
### 5. Test it
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install into a test project
|
||||||
|
specify init my-project --integration <key>
|
||||||
|
|
||||||
|
# Verify files were created in the commands directory configured by
|
||||||
|
# config["folder"] + config["commands_subdir"] (for example, .windsurf/workflows/)
|
||||||
|
ls -R my-project/.windsurf/workflows/
|
||||||
|
|
||||||
|
# Uninstall cleanly
|
||||||
|
cd my-project && specify integration uninstall <key>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Benefits of this approach:**
|
Each integration also has a dedicated test file at `tests/integrations/test_integration_<key>.py`. Note that hyphens in the key are replaced with underscores in the filename (e.g., key `cursor-agent` → `test_integration_cursor_agent.py`, key `kiro-cli` → `test_integration_kiro_cli.py`). Run it with:
|
||||||
|
|
||||||
- Eliminates special-case logic scattered throughout the codebase
|
```bash
|
||||||
- Makes the code more maintainable and easier to understand
|
pytest tests/integrations/test_integration_<key_with_underscores>.py -v
|
||||||
- Reduces the chance of bugs when adding new agents
|
```
|
||||||
- Tool checking "just works" without additional mappings
|
|
||||||
|
|
||||||
#### 7. Update Devcontainer files (Optional)
|
### 6. Optional overrides
|
||||||
|
|
||||||
|
The base classes handle most work automatically. Override only when the agent deviates from standard patterns:
|
||||||
|
|
||||||
|
| Override | When to use | Example |
|
||||||
|
|---|---|---|
|
||||||
|
| `command_filename(template_name)` | Custom file naming or extension | Copilot → `speckit.{name}.agent.md` |
|
||||||
|
| `options()` | Integration-specific CLI flags via `--integration-options` | Codex → `--skills` flag |
|
||||||
|
| `setup()` | Custom install logic (companion files, settings merge) | Copilot → `.agent.md` + `.prompt.md` + `.vscode/settings.json` |
|
||||||
|
| `teardown()` | Custom uninstall logic | Rarely needed; base handles manifest-tracked files |
|
||||||
|
|
||||||
|
**Example — Copilot (fully custom `setup`):**
|
||||||
|
|
||||||
|
Copilot extends `IntegrationBase` directly because it creates `.agent.md` commands, companion `.prompt.md` files, and merges `.vscode/settings.json`. See `src/specify_cli/integrations/copilot/__init__.py` for the full implementation.
|
||||||
|
|
||||||
|
### 7. Update Devcontainer files (Optional)
|
||||||
|
|
||||||
For agents that have VS Code extensions or require CLI installation, update the devcontainer configuration files:
|
For agents that have VS Code extensions or require CLI installation, update the devcontainer configuration files:
|
||||||
|
|
||||||
##### VS Code Extension-based Agents
|
#### VS Code Extension-based Agents
|
||||||
|
|
||||||
For agents available as VS Code extensions, add them to `.devcontainer/devcontainer.json`:
|
For agents available as VS Code extensions, add them to `.devcontainer/devcontainer.json`:
|
||||||
|
|
||||||
```json
|
```jsonc
|
||||||
{
|
{
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"extensions": [
|
"extensions": [
|
||||||
// ... existing extensions ...
|
// ... existing extensions ...
|
||||||
// [New Agent Name]
|
|
||||||
"[New Agent Extension ID]"
|
"[New Agent Extension ID]"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -287,7 +293,7 @@ For agents available as VS Code extensions, add them to `.devcontainer/devcontai
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
##### CLI-based Agents
|
#### CLI-based Agents
|
||||||
|
|
||||||
For agents that require CLI tools, add installation commands to `.devcontainer/post-create.sh`:
|
For agents that require CLI tools, add installation commands to `.devcontainer/post-create.sh`:
|
||||||
|
|
||||||
@@ -297,62 +303,16 @@ For agents that require CLI tools, add installation commands to `.devcontainer/p
|
|||||||
# Existing installations...
|
# Existing installations...
|
||||||
|
|
||||||
echo -e "\n🤖 Installing [New Agent Name] CLI..."
|
echo -e "\n🤖 Installing [New Agent Name] CLI..."
|
||||||
# run_command "npm install -g [agent-cli-package]@latest" # Example for node-based CLI
|
# run_command "npm install -g [agent-cli-package]@latest"
|
||||||
# or other installation instructions (must be non-interactive and compatible with Linux Debian "Trixie" or later)...
|
|
||||||
echo "✅ Done"
|
echo "✅ Done"
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Quick Tips:**
|
---
|
||||||
|
|
||||||
- **Extension-based agents**: Add to the `extensions` array in `devcontainer.json`
|
|
||||||
- **CLI-based agents**: Add installation scripts to `post-create.sh`
|
|
||||||
- **Hybrid agents**: May require both extension and CLI installation
|
|
||||||
- **Test thoroughly**: Ensure installations work in the devcontainer environment
|
|
||||||
|
|
||||||
## Agent Categories
|
|
||||||
|
|
||||||
### CLI-Based Agents
|
|
||||||
|
|
||||||
Require a command-line tool to be installed:
|
|
||||||
|
|
||||||
- **Claude Code**: `claude` CLI
|
|
||||||
- **Gemini CLI**: `gemini` CLI
|
|
||||||
- **Qwen Code**: `qwen` CLI
|
|
||||||
- **opencode**: `opencode` CLI
|
|
||||||
- **Codex CLI**: `codex` CLI (requires `--ai-skills`)
|
|
||||||
- **Junie**: `junie` CLI
|
|
||||||
- **Auggie CLI**: `auggie` CLI
|
|
||||||
- **CodeBuddy CLI**: `codebuddy` CLI
|
|
||||||
- **Qoder CLI**: `qodercli` CLI
|
|
||||||
- **Kiro CLI**: `kiro-cli` CLI
|
|
||||||
- **Amp**: `amp` CLI
|
|
||||||
- **SHAI**: `shai` CLI
|
|
||||||
- **Tabnine CLI**: `tabnine` CLI
|
|
||||||
- **Kimi Code**: `kimi` CLI
|
|
||||||
- **Mistral Vibe**: `vibe` CLI
|
|
||||||
- **Pi Coding Agent**: `pi` CLI
|
|
||||||
- **iFlow CLI**: `iflow` CLI
|
|
||||||
|
|
||||||
### IDE-Based Agents
|
|
||||||
|
|
||||||
Work within integrated development environments:
|
|
||||||
|
|
||||||
- **GitHub Copilot**: Built into VS Code/compatible editors
|
|
||||||
- **Cursor**: Built into Cursor IDE (`--ai cursor-agent`)
|
|
||||||
- **Windsurf**: Built into Windsurf IDE
|
|
||||||
- **Kilo Code**: Built into Kilo Code IDE
|
|
||||||
- **Roo Code**: Built into Roo Code IDE
|
|
||||||
- **IBM Bob**: Built into IBM Bob IDE
|
|
||||||
- **Trae**: Built into Trae IDE
|
|
||||||
- **Antigravity**: Built into Antigravity IDE (`--ai agy --ai-skills`)
|
|
||||||
|
|
||||||
## Command File Formats
|
## Command File Formats
|
||||||
|
|
||||||
### Markdown Format
|
### Markdown Format
|
||||||
|
|
||||||
Used by: Claude, Cursor, GitHub Copilot, opencode, Windsurf, Junie, Kiro CLI, Amp, SHAI, IBM Bob, Kimi Code, Qwen, Pi, Codex, Auggie, CodeBuddy, Qoder, Roo Code, Kilo Code, Trae, Antigravity, Mistral Vibe, iFlow
|
|
||||||
|
|
||||||
**Standard format:**
|
**Standard format:**
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
@@ -376,8 +336,6 @@ Command content with {SCRIPT} and $ARGUMENTS placeholders.
|
|||||||
|
|
||||||
### TOML Format
|
### TOML Format
|
||||||
|
|
||||||
Used by: Gemini, Tabnine
|
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
description = "Command description"
|
description = "Command description"
|
||||||
|
|
||||||
@@ -386,69 +344,90 @@ Command content with {SCRIPT} and {{args}} placeholders.
|
|||||||
"""
|
"""
|
||||||
```
|
```
|
||||||
|
|
||||||
## Directory Conventions
|
### YAML Format
|
||||||
|
|
||||||
- **CLI agents**: Usually `.<agent-name>/commands/`
|
Used by: Goose
|
||||||
- **Singular command exception**:
|
|
||||||
- opencode: `.opencode/command/` (singular `command`, not `commands`)
|
```yaml
|
||||||
- **Nested path exception**:
|
version: 1.0.0
|
||||||
- Tabnine: `.tabnine/agent/commands/` (extra `agent/` segment)
|
title: "Command Title"
|
||||||
- **Shared `.agents/` folder**:
|
description: "Command description"
|
||||||
- Amp: `.agents/commands/` (shared folder, not `.amp/`)
|
author:
|
||||||
- Codex: `.agents/skills/` (shared folder; requires `--ai-skills`; invoked as `$speckit-<command>`)
|
contact: spec-kit
|
||||||
- **Skills-based exceptions**:
|
extensions:
|
||||||
- Kimi Code: `.kimi/skills/` (skills, invoked as `/skill:speckit-<command>`)
|
- type: builtin
|
||||||
- **Prompt-based exceptions**:
|
name: developer
|
||||||
- Kiro CLI: `.kiro/prompts/`
|
activities:
|
||||||
- Pi: `.pi/prompts/`
|
- Spec-Driven Development
|
||||||
- Mistral Vibe: `.vibe/prompts/`
|
prompt: |
|
||||||
- **Rules-based exceptions**:
|
Command content with {SCRIPT} and {{args}} placeholders.
|
||||||
- Trae: `.trae/rules/`
|
```
|
||||||
- **IDE agents**: Follow IDE-specific patterns:
|
|
||||||
- Copilot: `.github/agents/`
|
|
||||||
- Cursor: `.cursor/commands/`
|
|
||||||
- Windsurf: `.windsurf/workflows/`
|
|
||||||
- Kilo Code: `.kilocode/workflows/`
|
|
||||||
- Roo Code: `.roo/commands/`
|
|
||||||
- IBM Bob: `.bob/commands/`
|
|
||||||
- Antigravity: `.agent/skills/` (`--ai-skills` required; `.agent/commands/` is deprecated)
|
|
||||||
|
|
||||||
## Argument Patterns
|
## Argument Patterns
|
||||||
|
|
||||||
Different agents use different argument placeholders:
|
Different agents use different argument placeholders. The placeholder used in command files is always taken from `registrar_config["args"]` for each integration — check there first when in doubt:
|
||||||
|
|
||||||
- **Markdown/prompt-based**: `$ARGUMENTS`
|
- **Markdown/prompt-based**: `$ARGUMENTS` (default for most markdown agents)
|
||||||
- **TOML-based**: `{{args}}`
|
- **TOML-based**: `{{args}}` (e.g., Gemini)
|
||||||
|
- **YAML-based**: `{{args}}` (e.g., Goose)
|
||||||
|
- **Custom**: some agents override the default (e.g., Forge uses `{{parameters}}`)
|
||||||
- **Script placeholders**: `{SCRIPT}` (replaced with actual script path)
|
- **Script placeholders**: `{SCRIPT}` (replaced with actual script path)
|
||||||
- **Agent placeholders**: `__AGENT__` (replaced with agent name)
|
- **Agent placeholders**: `__AGENT__` (replaced with agent name)
|
||||||
|
|
||||||
## Testing New Agent Integration
|
## Special Processing Requirements
|
||||||
|
|
||||||
1. **Build test**: Run package creation script locally
|
Some agents require custom processing beyond the standard template transformations:
|
||||||
2. **CLI test**: Test `specify init --ai <agent>` command
|
|
||||||
3. **File generation**: Verify correct directory structure and files
|
### Copilot Integration
|
||||||
4. **Command validation**: Ensure generated commands work with the agent
|
|
||||||
5. **Context update**: Test agent context update scripts
|
GitHub Copilot has unique requirements:
|
||||||
|
- Commands use `.agent.md` extension (not `.md`)
|
||||||
|
- Each command gets a companion `.prompt.md` file in `.github/prompts/`
|
||||||
|
- Installs `.vscode/settings.json` with prompt file recommendations
|
||||||
|
- Context file lives at `.github/copilot-instructions.md`
|
||||||
|
|
||||||
|
Implementation: Extends `IntegrationBase` with custom `setup()` method that:
|
||||||
|
1. Processes templates with `process_template()`
|
||||||
|
2. Generates companion `.prompt.md` files
|
||||||
|
3. Merges VS Code settings
|
||||||
|
|
||||||
|
### Forge Integration
|
||||||
|
|
||||||
|
Forge has special frontmatter and argument requirements:
|
||||||
|
- Uses `{{parameters}}` instead of `$ARGUMENTS`
|
||||||
|
- Strips `handoffs` frontmatter key (Forge-specific collaboration feature)
|
||||||
|
- Injects `name` field into frontmatter when missing
|
||||||
|
|
||||||
|
Implementation: Extends `MarkdownIntegration` with custom `setup()` method that:
|
||||||
|
1. Inherits standard template processing from `MarkdownIntegration`
|
||||||
|
2. Adds extra `$ARGUMENTS` → `{{parameters}}` replacement after template processing
|
||||||
|
3. Applies Forge-specific transformations via `_apply_forge_transformations()`
|
||||||
|
4. Strips `handoffs` frontmatter key
|
||||||
|
5. Injects missing `name` fields
|
||||||
|
6. Ensures the shared `update-agent-context.*` scripts include a `forge` case that maps context updates to `AGENTS.md` and lists `forge` in their usage/help text
|
||||||
|
|
||||||
|
### Goose Integration
|
||||||
|
|
||||||
|
Goose is a YAML-format agent using Block's recipe system:
|
||||||
|
- Uses `.goose/recipes/` directory for YAML recipe files
|
||||||
|
- Uses `{{args}}` argument placeholder
|
||||||
|
- Produces YAML with `prompt: |` block scalar for command content
|
||||||
|
|
||||||
|
Implementation: Extends `YamlIntegration` (parallel to `TomlIntegration`):
|
||||||
|
1. Processes templates through the standard placeholder pipeline
|
||||||
|
2. Extracts title and description from frontmatter
|
||||||
|
3. Renders output as Goose recipe YAML (version, title, description, author, extensions, activities, prompt)
|
||||||
|
4. Uses `yaml.safe_dump()` for header fields to ensure proper escaping
|
||||||
|
5. Context updates map to `AGENTS.md` (shared with opencode/codex/pi/forge)
|
||||||
|
|
||||||
## Common Pitfalls
|
## Common Pitfalls
|
||||||
|
|
||||||
1. **Using shorthand keys instead of actual CLI tool names**: Always use the actual executable name as the AGENT_CONFIG key (e.g., `"cursor-agent"` not `"cursor"`). This prevents the need for special-case mappings throughout the codebase.
|
1. **Using shorthand keys for CLI-based integrations**: For CLI-based integrations (`requires_cli: True`), the `key` must match the executable name (e.g., `"cursor-agent"` not `"cursor"`). `shutil.which(key)` is used for CLI tool checks — mismatches require special-case mappings. IDE-based integrations (`requires_cli: False`) are not subject to this constraint.
|
||||||
2. **Forgetting update scripts**: Both bash and PowerShell scripts must be updated when adding new agents.
|
2. **Forgetting update scripts**: Both bash and PowerShell thin wrappers and the shared context-update scripts must be updated.
|
||||||
3. **Incorrect `requires_cli` value**: Set to `True` only for agents that actually have CLI tools to check; set to `False` for IDE-based agents.
|
3. **Incorrect `requires_cli` value**: Set to `True` only for agents that have a CLI tool; set to `False` for IDE-based agents.
|
||||||
4. **Wrong argument format**: Use correct placeholder format for each agent type (`$ARGUMENTS` for Markdown, `{{args}}` for TOML).
|
4. **Wrong argument format**: Use `$ARGUMENTS` for Markdown agents, `{{args}}` for TOML agents.
|
||||||
5. **Directory naming**: Follow agent-specific conventions exactly (check existing agents for patterns).
|
5. **Skipping registration**: The import and `_register()` call in `_register_builtins()` must both be added.
|
||||||
6. **Help text inconsistency**: Update all user-facing text consistently (help strings, docstrings, README, error messages).
|
|
||||||
|
|
||||||
## Future Considerations
|
|
||||||
|
|
||||||
When adding new agents:
|
|
||||||
|
|
||||||
- Consider the agent's native command/workflow patterns
|
|
||||||
- Ensure compatibility with the Spec-Driven Development process
|
|
||||||
- Document any special requirements or limitations
|
|
||||||
- Update this guide with lessons learned
|
|
||||||
- Verify the actual CLI tool name before adding to AGENT_CONFIG
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*This documentation should be updated whenever new agents are added to maintain accuracy and completeness.*
|
*This documentation should be updated whenever new integrations are added to maintain accuracy and completeness.*
|
||||||
|
|||||||
152
CHANGELOG.md
152
CHANGELOG.md
@@ -2,6 +2,158 @@
|
|||||||
|
|
||||||
<!-- insert new changelog below this comment -->
|
<!-- insert new changelog below this comment -->
|
||||||
|
|
||||||
|
## [0.7.2] - 2026-04-16
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- docs: add core commands reference and simplify README CLI section (#2245)
|
||||||
|
- docs: add workflows reference, reorganize into docs/reference/, and add --version flag (#2244)
|
||||||
|
- docs: add presets reference page and rename pack_id to preset_id (#2243)
|
||||||
|
- docs: add extensions reference page and integrations FAQ (#2242)
|
||||||
|
- docs: consolidate integration documentation into docs/integrations.md (#2241)
|
||||||
|
- feat: update memorylint and superpowers-bridge versions to 1.3.0 with new download URLs (#2240)
|
||||||
|
- feat: Integration catalog — discovery, versioning, and community distribution (#2130)
|
||||||
|
- Add Catalog CI extension to community catalog (#2239)
|
||||||
|
- Added issues extension (#2194)
|
||||||
|
- chore: release 0.7.1, begin 0.7.2.dev0 development (#2235)
|
||||||
|
|
||||||
|
## [0.7.1] - 2026-04-15
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- ci: add windows-latest to test matrix (#2233)
|
||||||
|
- docs: remove deprecated --skip-tls references from local-development guide (#2231)
|
||||||
|
- fix: allow Claude to chain skills for hook execution (#2227)
|
||||||
|
- docs: merge TESTING.md into CONTRIBUTING.md, remove TESTING.md (#2228)
|
||||||
|
- Add agent-assign extension to community catalog (#2030)
|
||||||
|
- fix: unofficial PyPI warning (#1982) and legacy extension command name auto-correction (#2017) (#2027)
|
||||||
|
- feat: register architect-preview in community catalog (#2214)
|
||||||
|
- chore: deprecate --ai flag in favor of --integration on specify init (#2218)
|
||||||
|
- chore: release 0.7.0, begin 0.7.1.dev0 development (#2217)
|
||||||
|
|
||||||
|
## [0.7.0] - 2026-04-14
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Add workflow engine with catalog system (#2158)
|
||||||
|
- docs(catalog): add claude-ask-questions to community preset catalog (#2191)
|
||||||
|
- Add SFSpeckit — Salesforce SDD Extension (#2208)
|
||||||
|
- feat(scripts): optional single-segment branch prefix for gitflow (#2202)
|
||||||
|
- chore: release 0.6.2, begin 0.6.3.dev0 development (#2205)
|
||||||
|
- Add Worktrees extension to community catalog (#2207)
|
||||||
|
- feat: Update catalog.community.json for preset-fiction-book-writing (#2199)
|
||||||
|
|
||||||
|
## [0.6.2] - 2026-04-13
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- feat: Register "What-if Analysis" community extension (#2182)
|
||||||
|
- feat: add GitHub Issues Integration to community catalog (#2188)
|
||||||
|
- feat(agents): add Goose AI agent support (#2015)
|
||||||
|
- Update ralph extension to v1.0.1 in community catalog (#2192)
|
||||||
|
- fix: skip docs deployment workflow on forks (#2171)
|
||||||
|
- chore: release 0.6.1, begin 0.6.2.dev0 development (#2162)
|
||||||
|
|
||||||
|
## [0.6.1] - 2026-04-10
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- feat: add bundled lean preset with minimal workflow commands (#2161)
|
||||||
|
- Add Brownfield Bootstrap extension to community catalog (#2145)
|
||||||
|
- Add CI Guard extension to community catalog (#2157)
|
||||||
|
- Add SpecTest extension to community catalog (#2159)
|
||||||
|
- fix: bundled extensions should not have download URLs (#2155)
|
||||||
|
- Add PR Bridge extension to community catalog (#2148)
|
||||||
|
- feat(cursor-agent): migrate from .cursor/commands to .cursor/skills (#2156)
|
||||||
|
- Add TinySpec extension to community catalog (#2147)
|
||||||
|
- chore: bump spec-kit-verify to 1.0.3 and spec-kit-review to 1.0.1 (#2146)
|
||||||
|
- Add Status Report extension to community catalog (#2123)
|
||||||
|
- chore: release 0.6.0, begin 0.6.1.dev0 development (#2144)
|
||||||
|
|
||||||
|
## [0.6.0] - 2026-04-09
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Add Bugfix Workflow community extension to catalog and README (#2135)
|
||||||
|
- Add Worktree Isolation extension to community catalog (#2143)
|
||||||
|
- Add multi-repo-branching preset to community catalog (#2139)
|
||||||
|
- Readme clarity (#2013)
|
||||||
|
- Rewrite AGENTS.md for integration architecture (#2119)
|
||||||
|
- docs: add SpecKit Companion to Community Friends section (#2140)
|
||||||
|
- feat: add memorylint extension to community catalog (#2138)
|
||||||
|
- chore: release 0.5.1, begin 0.5.2.dev0 development (#2137)
|
||||||
|
|
||||||
|
## [0.5.1] - 2026-04-08
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- fix: pin typer>=0.24.0 and click>=8.2.1 to fix import crash (#2136)
|
||||||
|
- feat: update fleet extension to v1.1.0 (#2029)
|
||||||
|
- fix(forge): use hyphen notation in frontmatter name field (#2075)
|
||||||
|
- fix(bash): sed replacement escaping, BSD portability, dead cleanup in update-agent-context.sh (#2090)
|
||||||
|
- Add Spec Diagram community extension to catalog and README (#2129)
|
||||||
|
- feat: Git extension stage 2 — GIT_BRANCH_NAME override, --force for existing dirs, auto-install tests (#1940) (#2117)
|
||||||
|
- fix(git): surface checkout errors for existing branches (#2122)
|
||||||
|
- Add Branch Convention community extension to catalog and README (#2128)
|
||||||
|
- docs: lighten March 2026 newsletter for readability (#2127)
|
||||||
|
- fix: restore alias compatibility for community extensions (#2110) (#2125)
|
||||||
|
- Added March 2026 newsletter (#2124)
|
||||||
|
- Add Spec Refine community extension to catalog and README (#2118)
|
||||||
|
- Add explicit-task-dependencies community preset to catalog and README (#2091)
|
||||||
|
- Add toc-navigation community preset to catalog and README (#2080)
|
||||||
|
- fix: prevent ambiguous TOML closing quotes when body ends with `"` (#2113) (#2115)
|
||||||
|
- fix speckit issue for trae (#2112)
|
||||||
|
- feat: Git extension stage 1 — bundled `extensions/git` with hooks on all core commands (#1941)
|
||||||
|
- Upgraded confluence extension to v.1.1.1 (#2109)
|
||||||
|
- Update V-Model Extension Pack to v0.5.0 (#2108)
|
||||||
|
- Add canon extension and canon-core preset. (#2022)
|
||||||
|
- [stage2] fix: serialize multiline descriptions in legacy TOML renderer (#2097)
|
||||||
|
- [stage1] fix: strip YAML frontmatter from TOML integration prompts (#2096)
|
||||||
|
- Add Confluence extension (#2028)
|
||||||
|
- fix: accept 4+ digit spec numbers in tests and docs (#2094)
|
||||||
|
- fix(scripts): improve git branch creation error handling (#2089)
|
||||||
|
- Add optimize extension to community catalog (#2088)
|
||||||
|
- feat: add "VS Code Ask Questions" preset (#2086)
|
||||||
|
- Add security-review v1.1.1 to community extensions catalog (#2073)
|
||||||
|
- Add `specify integration` subcommand for post-init integration management (#2083)
|
||||||
|
- Remove template version info from CLI, fix Claude user-invocable, cleanup dead code (#2081)
|
||||||
|
- fix: add user-invocable: true to skill frontmatter (#2077)
|
||||||
|
- fix: add actions:write permission to stale workflow (#2079)
|
||||||
|
- feat: add argument-hint frontmatter to Claude Code commands (#1951) (#2059)
|
||||||
|
- Update conduct extension to v1.0.1 (#2078)
|
||||||
|
- chore(deps): bump astral-sh/setup-uv from 7.6.0 to 8.0.0 (#2072)
|
||||||
|
- chore(deps): bump actions/configure-pages from 5 to 6 (#2071)
|
||||||
|
- feat: add spec-kit-fixit extension to community catalog (#2024)
|
||||||
|
- chore: release 0.5.0, begin 0.5.1.dev0 development (#2070)
|
||||||
|
- feat: add Forgecode agent support (#2034)
|
||||||
|
|
||||||
|
## [0.5.0] - 2026-04-02
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Introduces DEVELOPMENT.md (#2069)
|
||||||
|
- Update cc-sdd reference to cc-spex in Community Friends (#2007)
|
||||||
|
- chore: release 0.4.5, begin 0.4.6.dev0 development (#2064)
|
||||||
|
|
||||||
|
## [0.4.5] - 2026-04-02
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Stage 6: Complete migration — remove legacy scaffold path (#1924) (#2063)
|
||||||
|
- Install Claude Code as native skills and align preset/integration flows (#2051)
|
||||||
|
- Add repoindex 0402 (#2062)
|
||||||
|
- Stage 5: Skills, Generic & Option-Driven Integrations (#1924) (#2052)
|
||||||
|
- feat(scripts): add --dry-run flag to create-new-feature (#1998)
|
||||||
|
- fix: support feature branch numbers with 4+ digits (#2040)
|
||||||
|
- Add community content disclaimers (#2058)
|
||||||
|
- docs: add community extensions website link to README and extensions docs (#2014)
|
||||||
|
- docs: remove dead Cognitive Squad and Understanding extension links and from extensions/catalog.community.json (#2057)
|
||||||
|
- Add fix-findings extension to community catalog (#2039)
|
||||||
|
- Stage 4: TOML integrations — gemini and tabnine migrated to plugin architecture (#2050)
|
||||||
|
- feat: add 5 lifecycle extensions to community catalog (#2049)
|
||||||
|
- Stage 3: Standard markdown integrations — 19 agents migrated to plugin architecture (#2038)
|
||||||
|
- chore: release 0.4.4, begin 0.4.5.dev0 development (#2048)
|
||||||
|
|
||||||
## [0.4.4] - 2026-04-01
|
## [0.4.4] - 2026-04-01
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
106
CONTRIBUTING.md
106
CONTRIBUTING.md
@@ -11,7 +11,7 @@ These are one time installations required to be able to test your changes locall
|
|||||||
1. Install [Python 3.11+](https://www.python.org/downloads/)
|
1. Install [Python 3.11+](https://www.python.org/downloads/)
|
||||||
1. Install [uv](https://docs.astral.sh/uv/) for package management
|
1. Install [uv](https://docs.astral.sh/uv/) for package management
|
||||||
1. Install [Git](https://git-scm.com/downloads)
|
1. Install [Git](https://git-scm.com/downloads)
|
||||||
1. Have an [AI coding agent available](README.md#-supported-ai-agents)
|
1. Have an [AI coding agent available](README.md#-supported-ai-coding-agent-integrations)
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><b>💡 Hint if you are using <code>VSCode</code> or <code>GitHub Codespaces</code> as your IDE</b></summary>
|
<summary><b>💡 Hint if you are using <code>VSCode</code> or <code>GitHub Codespaces</code> as your IDE</b></summary>
|
||||||
@@ -44,8 +44,7 @@ On [GitHub Codespaces](https://github.com/features/codespaces) it's even simpler
|
|||||||
1. Push to your fork and submit a pull request
|
1. Push to your fork and submit a pull request
|
||||||
1. Wait for your pull request to be reviewed and merged.
|
1. Wait for your pull request to be reviewed and merged.
|
||||||
|
|
||||||
For the detailed test workflow, command-selection prompt, and PR reporting template, see [`TESTING.md`](./TESTING.md).
|
Activate the project virtual environment (see [Testing setup](#testing-setup) below), then install the CLI from your working tree (`uv pip install -e .` after `uv sync --extra test`) or otherwise ensure the shell uses the local `specify` binary before running the manual slash-command tests described below.
|
||||||
Activate the project virtual environment (see the Setup block in [`TESTING.md`](./TESTING.md)), then install the CLI from your working tree (`uv pip install -e .` after `uv sync --extra test`) or otherwise ensure the shell uses the local `specify` binary before running the manual slash-command tests described below.
|
|
||||||
|
|
||||||
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
|
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
|
||||||
|
|
||||||
@@ -69,34 +68,99 @@ When working on spec-kit:
|
|||||||
|
|
||||||
For the smoothest review experience, validate changes in this order:
|
For the smoothest review experience, validate changes in this order:
|
||||||
|
|
||||||
1. **Run focused automated checks first** — use the quick verification commands in [`TESTING.md`](./TESTING.md) to catch packaging, scaffolding, and configuration regressions early.
|
1. **Run focused automated checks first** — use the quick verification commands [below](#automated-checks) to catch scaffolding and configuration regressions early.
|
||||||
2. **Run manual workflow tests second** — if your change affects slash commands or the developer workflow, follow [`TESTING.md`](./TESTING.md) to choose the right commands, run them in an agent, and capture results for your PR.
|
2. **Run manual workflow tests second** — if your change affects slash commands or the developer workflow, follow the [manual testing](#manual-testing) section to choose the right commands, run them in an agent, and capture results for your PR.
|
||||||
3. **Use local release packages when debugging packaged output** — if you need to inspect the exact files CI-style packaging produces, generate local release packages as described below.
|
|
||||||
|
|
||||||
### Testing template and command changes locally
|
### Automated checks
|
||||||
|
|
||||||
Running `uv run specify init` pulls released packages, which won’t include your local changes.
|
#### Agent configuration and wiring consistency
|
||||||
To test your templates, commands, and other changes locally, follow these steps:
|
|
||||||
|
|
||||||
1. **Create release packages**
|
```bash
|
||||||
|
uv run python -m pytest tests/test_agent_config_consistency.py -q
|
||||||
|
```
|
||||||
|
|
||||||
Run the following command to generate the local packages:
|
Run this when you change agent metadata, context update scripts, or integration wiring.
|
||||||
|
|
||||||
```bash
|
### Manual testing
|
||||||
./.github/workflows/scripts/create-release-packages.sh v1.0.0
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Copy the relevant package to your test project**
|
#### Testing setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp -r .genreleases/sdd-copilot-package-sh/. <path-to-test-project>/
|
# Install the project and test dependencies from your local branch
|
||||||
```
|
cd <spec-kit-repo>
|
||||||
|
uv sync --extra test
|
||||||
|
source .venv/bin/activate # On Windows (CMD): .venv\Scripts\activate | (PowerShell): .venv\Scripts\Activate.ps1
|
||||||
|
uv pip install -e .
|
||||||
|
# Ensure the `specify` binary in this environment points at your working tree so the agent runs the branch you're testing.
|
||||||
|
|
||||||
3. **Open and test the agent**
|
# Initialize a test project using your local changes
|
||||||
|
uv run specify init <temp-dir>/speckit-test --ai <agent> --offline
|
||||||
|
cd <temp-dir>/speckit-test
|
||||||
|
|
||||||
Navigate to your test project folder and open the agent to verify your implementation.
|
# Open in your agent
|
||||||
|
```
|
||||||
|
|
||||||
If you only need to validate generated file structure and content before doing manual agent testing, start with the focused automated checks in [`TESTING.md`](./TESTING.md). Keep this section for the cases where you need to inspect the exact packaged output locally.
|
#### Manual testing process
|
||||||
|
|
||||||
|
Any change that affects a slash command's behavior requires manually testing that command through an AI agent and submitting results with the PR.
|
||||||
|
|
||||||
|
1. **Identify affected commands** — use the [prompt below](#determining-which-tests-to-run) to have your agent analyze your changed files and determine which commands need testing.
|
||||||
|
2. **Set up a test project** — scaffold from your local branch (see [Testing setup](#testing-setup)).
|
||||||
|
3. **Run each affected command** — invoke it in your agent, verify it completes successfully, and confirm it produces the expected output (files created, scripts executed, artifacts populated).
|
||||||
|
4. **Run prerequisites first** — commands that depend on earlier commands (e.g., `/speckit.tasks` requires `/speckit.plan` which requires `/speckit.specify`) must be run in order.
|
||||||
|
5. **Report results** — paste the [reporting template](#reporting-results) into your PR with pass/fail for each command tested.
|
||||||
|
|
||||||
|
#### Reporting results
|
||||||
|
|
||||||
|
Paste this into your PR:
|
||||||
|
|
||||||
|
~~~markdown
|
||||||
|
## Manual test results
|
||||||
|
|
||||||
|
**Agent**: [e.g., GitHub Copilot in VS Code] | **OS/Shell**: [e.g., macOS/zsh]
|
||||||
|
|
||||||
|
| Command tested | Notes |
|
||||||
|
|----------------|-------|
|
||||||
|
| `/speckit.command` | |
|
||||||
|
~~~
|
||||||
|
|
||||||
|
#### Determining which tests to run
|
||||||
|
|
||||||
|
Copy this prompt into your agent. Include the agent's response (selected tests plus a brief explanation of the mapping) in your PR.
|
||||||
|
|
||||||
|
~~~text
|
||||||
|
Read CONTRIBUTING.md, then run `git diff --name-only main` to get my changed files.
|
||||||
|
For each changed file, determine which slash commands it affects by reading
|
||||||
|
the command templates in templates/commands/ to understand what each command
|
||||||
|
invokes. Use these mapping rules:
|
||||||
|
|
||||||
|
- templates/commands/X.md → the command it defines
|
||||||
|
- scripts/bash/Y.sh or scripts/powershell/Y.ps1 → every command that invokes that script (grep templates/commands/ for the script name). Also check transitive dependencies: if the changed script is sourced by other scripts (e.g., common.sh is sourced by create-new-feature.sh, check-prerequisites.sh, setup-plan.sh, update-agent-context.sh), then every command invoking those downstream scripts is also affected
|
||||||
|
- templates/Z-template.md → every command that consumes that template during execution
|
||||||
|
- src/specify_cli/*.py → CLI commands (`specify init`, `specify check`, `specify extension *`, `specify preset *`); test the affected CLI command and, for init/scaffolding changes, at minimum test /speckit.specify
|
||||||
|
- extensions/X/commands/* → the extension command it defines
|
||||||
|
- extensions/X/scripts/* → every extension command that invokes that script
|
||||||
|
- extensions/X/extension.yml or config-template.yml → every command in that extension. Also check if the manifest defines hooks (look for `hooks:` entries like `before_specify`, `after_implement`, etc.) — if so, the core commands those hooks attach to are also affected
|
||||||
|
- presets/*/* → test preset scaffolding via `specify init` with the preset
|
||||||
|
- pyproject.toml → packaging/bundling; test `specify init` and verify bundled assets
|
||||||
|
|
||||||
|
Include prerequisite tests (e.g., T5 requires T3 requires T1).
|
||||||
|
|
||||||
|
Output in this format:
|
||||||
|
|
||||||
|
### Test selection reasoning
|
||||||
|
|
||||||
|
| Changed file | Affects | Test | Why |
|
||||||
|
|---|---|---|---|
|
||||||
|
| (path) | (command) | T# | (reason) |
|
||||||
|
|
||||||
|
### Required tests
|
||||||
|
|
||||||
|
Number each test sequentially (T1, T2, ...). List prerequisite tests first.
|
||||||
|
|
||||||
|
- T1: /speckit.command — (reason)
|
||||||
|
- T2: /speckit.command — (reason)
|
||||||
|
~~~
|
||||||
|
|
||||||
## AI contributions in Spec Kit
|
## AI contributions in Spec Kit
|
||||||
|
|
||||||
|
|||||||
24
DEVELOPMENT.md
Normal file
24
DEVELOPMENT.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Development Notes
|
||||||
|
|
||||||
|
Spec Kit is a toolkit for spec-driven development. At its core, it is a coordinated set of prompts, templates, scripts, and CLI/integration assets that define and deliver a spec-driven workflow for AI coding agents. This document is a starting point for people modifying Spec Kit itself, with a compact orientation to the key project documents and repository organization.
|
||||||
|
|
||||||
|
**Essential project documents:**
|
||||||
|
|
||||||
|
| Document | Role |
|
||||||
|
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||||
|
| [README.md](README.md) | Primary user-facing overview of Spec Kit and its workflow. |
|
||||||
|
| [DEVELOPMENT.md](DEVELOPMENT.md) | This document. |
|
||||||
|
| [spec-driven.md](spec-driven.md) | End-to-end explanation of the Spec-Driven Development workflow supported by Spec Kit. |
|
||||||
|
| [RELEASE-PROCESS.md](.github/workflows/RELEASE-PROCESS.md) | Release workflow, versioning rules, and changelog generation process. |
|
||||||
|
| [docs/index.md](docs/index.md) | Entry point to the `docs/` documentation set. |
|
||||||
|
| [CONTRIBUTING.md](CONTRIBUTING.md) | Contribution process, review expectations, testing, and required development practices. |
|
||||||
|
|
||||||
|
**Main repository components:**
|
||||||
|
|
||||||
|
| Directory | Role |
|
||||||
|
| ------------------ | ------------------------------------------------------------------------------------------- |
|
||||||
|
| `templates/` | Prompt assets and templates that define the core workflow behavior and generated artifacts. |
|
||||||
|
| `scripts/` | Supporting scripts used by the workflow, setup, and repository tooling. |
|
||||||
|
| `src/specify_cli/` | Python source for the `specify` CLI, including agent-specific assets. |
|
||||||
|
| `extensions/` | Extension-related docs, catalogs, and supporting assets. |
|
||||||
|
| `presets/` | Preset-related docs, catalogs, and supporting assets. |
|
||||||
301
README.md
301
README.md
@@ -26,7 +26,7 @@
|
|||||||
- [🎨 Community Presets](#-community-presets)
|
- [🎨 Community Presets](#-community-presets)
|
||||||
- [🚶 Community Walkthroughs](#-community-walkthroughs)
|
- [🚶 Community Walkthroughs](#-community-walkthroughs)
|
||||||
- [🛠️ Community Friends](#️-community-friends)
|
- [🛠️ Community Friends](#️-community-friends)
|
||||||
- [🤖 Supported AI Agents](#-supported-ai-agents)
|
- [🤖 Supported AI Coding Agent Integrations](#-supported-ai-coding-agent-integrations)
|
||||||
- [🔧 Specify CLI Reference](#-specify-cli-reference)
|
- [🔧 Specify CLI Reference](#-specify-cli-reference)
|
||||||
- [🧩 Making Spec Kit Your Own: Extensions & Presets](#-making-spec-kit-your-own-extensions--presets)
|
- [🧩 Making Spec Kit Your Own: Extensions & Presets](#-making-spec-kit-your-own-extensions--presets)
|
||||||
- [📚 Core Philosophy](#-core-philosophy)
|
- [📚 Core Philosophy](#-core-philosophy)
|
||||||
@@ -50,6 +50,8 @@ Spec-Driven Development **flips the script** on traditional software development
|
|||||||
|
|
||||||
Choose your preferred installation method:
|
Choose your preferred installation method:
|
||||||
|
|
||||||
|
> **Important:** The only official, maintained packages for Spec Kit are published from this GitHub repository. Any packages with the same name on PyPI are **not** affiliated with this project and are not maintained by the Spec Kit maintainers. Always install directly from GitHub as shown below.
|
||||||
|
|
||||||
#### Option 1: Persistent Installation (Recommended)
|
#### Option 1: Persistent Installation (Recommended)
|
||||||
|
|
||||||
Install once and use everywhere. Pin a specific release tag for stability (check [Releases](https://github.com/github/spec-kit/releases) for the latest):
|
Install once and use everywhere. Pin a specific release tag for stability (check [Releases](https://github.com/github/spec-kit/releases) for the latest):
|
||||||
@@ -62,16 +64,22 @@ uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@vX
|
|||||||
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git
|
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git
|
||||||
```
|
```
|
||||||
|
|
||||||
Then use the tool directly:
|
Then verify the correct version is installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify version
|
||||||
|
```
|
||||||
|
|
||||||
|
And use the tool directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Create new project
|
# Create new project
|
||||||
specify init <PROJECT_NAME>
|
specify init <PROJECT_NAME>
|
||||||
|
|
||||||
# Or initialize in existing project
|
# Or initialize in existing project
|
||||||
specify init . --ai claude
|
specify init . --ai copilot
|
||||||
# or
|
# or
|
||||||
specify init --here --ai claude
|
specify init --here --ai copilot
|
||||||
|
|
||||||
# Check installed tools
|
# Check installed tools
|
||||||
specify check
|
specify check
|
||||||
@@ -92,9 +100,9 @@ Run directly without installing:
|
|||||||
uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init <PROJECT_NAME>
|
uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init <PROJECT_NAME>
|
||||||
|
|
||||||
# Or initialize in existing project
|
# Or initialize in existing project
|
||||||
uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init . --ai claude
|
uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init . --ai copilot
|
||||||
# or
|
# or
|
||||||
uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init --here --ai claude
|
uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init --here --ai copilot
|
||||||
```
|
```
|
||||||
|
|
||||||
**Benefits of persistent installation:**
|
**Benefits of persistent installation:**
|
||||||
@@ -160,6 +168,11 @@ Want to see Spec Kit in action? Watch our [video overview](https://www.youtube.c
|
|||||||
|
|
||||||
## 🧩 Community Extensions
|
## 🧩 Community Extensions
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Community extensions are independently created and maintained by their respective authors. GitHub and the Spec Kit maintainers may review pull requests that add entries to the community catalog for formatting, catalog structure, or policy compliance, but they do **not review, audit, endorse, or support the extension code itself**. The Community Extensions website is also a third-party resource. Review extension source code before installation and use at your own discretion.
|
||||||
|
|
||||||
|
🔍 **Browse and search community extensions on the [Community Extensions website](https://speckit-community.github.io/extensions/).**
|
||||||
|
|
||||||
The following community-contributed extensions are available in [`catalog.community.json`](extensions/catalog.community.json):
|
The following community-contributed extensions are available in [`catalog.community.json`](extensions/catalog.community.json):
|
||||||
|
|
||||||
**Categories:**
|
**Categories:**
|
||||||
@@ -177,16 +190,28 @@ The following community-contributed extensions are available in [`catalog.commun
|
|||||||
|
|
||||||
| Extension | Purpose | Category | Effect | URL |
|
| Extension | Purpose | Category | Effect | URL |
|
||||||
|-----------|---------|----------|--------|-----|
|
|-----------|---------|----------|--------|-----|
|
||||||
|
| Agent Assign | Assign specialized Claude Code agents to spec-kit tasks for targeted execution | `process` | Read+Write | [spec-kit-agent-assign](https://github.com/xymelon/spec-kit-agent-assign) |
|
||||||
| AI-Driven Engineering (AIDE) | A structured 7-step workflow for building new projects from scratch with AI assistants — from vision through implementation | `process` | Read+Write | [aide](https://github.com/mnriem/spec-kit-extensions/tree/main/aide) |
|
| AI-Driven Engineering (AIDE) | A structured 7-step workflow for building new projects from scratch with AI assistants — from vision through implementation | `process` | Read+Write | [aide](https://github.com/mnriem/spec-kit-extensions/tree/main/aide) |
|
||||||
|
| Architect Impact Previewer | Predicts architectural impact, complexity, and risks of proposed changes before implementation. | `visibility` | Read-only | [spec-kit-architect-preview](https://github.com/UmmeHabiba1312/spec-kit-architect-preview) |
|
||||||
| Archive Extension | Archive merged features into main project memory. | `docs` | Read+Write | [spec-kit-archive](https://github.com/stn1slv/spec-kit-archive) |
|
| Archive Extension | Archive merged features into main project memory. | `docs` | Read+Write | [spec-kit-archive](https://github.com/stn1slv/spec-kit-archive) |
|
||||||
| Azure DevOps Integration | Sync user stories and tasks to Azure DevOps work items using OAuth authentication | `integration` | Read+Write | [spec-kit-azure-devops](https://github.com/pragya247/spec-kit-azure-devops) |
|
| Azure DevOps Integration | Sync user stories and tasks to Azure DevOps work items using OAuth authentication | `integration` | Read+Write | [spec-kit-azure-devops](https://github.com/pragya247/spec-kit-azure-devops) |
|
||||||
|
| Branch Convention | Configurable branch and folder naming conventions for /specify with presets and custom patterns | `process` | Read+Write | [spec-kit-branch-convention](https://github.com/Quratulain-bilal/spec-kit-branch-convention) |
|
||||||
|
| Brownfield Bootstrap | Bootstrap spec-kit for existing codebases — auto-discover architecture and adopt SDD incrementally | `process` | Read+Write | [spec-kit-brownfield](https://github.com/Quratulain-bilal/spec-kit-brownfield) |
|
||||||
|
| Bugfix Workflow | Structured bugfix workflow — capture bugs, trace to spec artifacts, and patch specs surgically | `process` | Read+Write | [spec-kit-bugfix](https://github.com/Quratulain-bilal/spec-kit-bugfix) |
|
||||||
|
| Canon | Adds canon-driven (baseline-driven) workflows: spec-first, code-first, spec-drift. Requires Canon Core preset installation. | `process` | Read+Write | [spec-kit-canon](https://github.com/maximiliamus/spec-kit-canon/tree/master/extension) |
|
||||||
|
| Catalog CI | Automated validation for spec-kit community catalog entries — structure, URLs, diffs, and linting | `process` | Read-only | [spec-kit-catalog-ci](https://github.com/Quratulain-bilal/spec-kit-catalog-ci) |
|
||||||
|
| CI Guard | Spec compliance gates for CI/CD — verify specs exist, check drift, and block merges on gaps | `process` | Read-only | [spec-kit-ci-guard](https://github.com/Quratulain-bilal/spec-kit-ci-guard) |
|
||||||
| Checkpoint Extension | Commit the changes made during the middle of the implementation, so you don't end up with just one very large commit at the end | `code` | Read+Write | [spec-kit-checkpoint](https://github.com/aaronrsun/spec-kit-checkpoint) |
|
| Checkpoint Extension | Commit the changes made during the middle of the implementation, so you don't end up with just one very large commit at the end | `code` | Read+Write | [spec-kit-checkpoint](https://github.com/aaronrsun/spec-kit-checkpoint) |
|
||||||
| 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 | `code` | Read+Write | [spec-kit-cleanup](https://github.com/dsrednicki/spec-kit-cleanup) |
|
| 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 | `code` | Read+Write | [spec-kit-cleanup](https://github.com/dsrednicki/spec-kit-cleanup) |
|
||||||
| Cognitive Squad | Multi-agent cognitive system with Triadic Model: understanding, internalization, application — with quality gates, backpropagation verification, and self-healing | `docs` | Read+Write | [cognitive-squad](https://github.com/Testimonial/cognitive-squad) |
|
|
||||||
| Conduct Extension | Orchestrates spec-kit phases via sub-agent delegation to reduce context pollution. | `process` | Read+Write | [spec-kit-conduct-ext](https://github.com/twbrandon7/spec-kit-conduct-ext) |
|
| Conduct Extension | Orchestrates spec-kit phases via sub-agent delegation to reduce context pollution. | `process` | Read+Write | [spec-kit-conduct-ext](https://github.com/twbrandon7/spec-kit-conduct-ext) |
|
||||||
|
| Confluence Extension | Create a doc in Confluence summarizing the specifications and planning files | `integration` | Read+Write | [spec-kit-confluence](https://github.com/aaronrsun/spec-kit-confluence) |
|
||||||
| DocGuard — CDD Enforcement | Canonical-Driven Development enforcement. Validates, scores, and traces project documentation with automated checks, AI-driven workflows, and spec-kit hooks. Zero NPM runtime dependencies. | `docs` | Read+Write | [spec-kit-docguard](https://github.com/raccioly/docguard) |
|
| DocGuard — CDD Enforcement | Canonical-Driven Development enforcement. Validates, scores, and traces project documentation with automated checks, AI-driven workflows, and spec-kit hooks. Zero NPM runtime dependencies. | `docs` | Read+Write | [spec-kit-docguard](https://github.com/raccioly/docguard) |
|
||||||
| Extensify | Create and validate extensions and extension catalogs | `process` | Read+Write | [extensify](https://github.com/mnriem/spec-kit-extensions/tree/main/extensify) |
|
| Extensify | Create and validate extensions and extension catalogs | `process` | Read+Write | [extensify](https://github.com/mnriem/spec-kit-extensions/tree/main/extensify) |
|
||||||
|
| Fix Findings | Automated analyze-fix-reanalyze loop that resolves spec findings until clean | `code` | Read+Write | [spec-kit-fix-findings](https://github.com/Quratulain-bilal/spec-kit-fix-findings) |
|
||||||
|
| FixIt Extension | Spec-aware bug fixing — maps bugs to spec artifacts, proposes a plan, applies minimal changes | `code` | Read+Write | [spec-kit-fixit](https://github.com/speckit-community/spec-kit-fixit) |
|
||||||
| Fleet Orchestrator | Orchestrate a full feature lifecycle with human-in-the-loop gates across all SpecKit phases | `process` | Read+Write | [spec-kit-fleet](https://github.com/sharathsatish/spec-kit-fleet) |
|
| Fleet Orchestrator | Orchestrate a full feature lifecycle with human-in-the-loop gates across all SpecKit phases | `process` | Read+Write | [spec-kit-fleet](https://github.com/sharathsatish/spec-kit-fleet) |
|
||||||
|
| GitHub Issues Integration 1 | Generate spec artifacts from GitHub Issues - import issues, sync updates, and maintain bidirectional traceability | `integration` | Read+Write | [spec-kit-github-issues](https://github.com/Fatima367/spec-kit-github-issues) |
|
||||||
|
| GitHub Issues Integration 2 | Creates and syncs local specs from an existing GitHub issue | `integration` | Read+Write | [spec-kit-issue](https://github.com/aaronrsun/spec-kit-issue) |
|
||||||
| Iterate | Iterate on spec documents with a two-phase define-and-apply workflow — refine specs mid-implementation and go straight back to building | `docs` | Read+Write | [spec-kit-iterate](https://github.com/imviancagrace/spec-kit-iterate) |
|
| Iterate | Iterate on spec documents with a two-phase define-and-apply workflow — refine specs mid-implementation and go straight back to building | `docs` | Read+Write | [spec-kit-iterate](https://github.com/imviancagrace/spec-kit-iterate) |
|
||||||
| Jira Integration | Create Jira Epics, Stories, and Issues from spec-kit specifications and task breakdowns with configurable hierarchy and custom field support | `integration` | Read+Write | [spec-kit-jira](https://github.com/mbachorik/spec-kit-jira) |
|
| Jira Integration | Create Jira Epics, Stories, and Issues from spec-kit specifications and task breakdowns with configurable hierarchy and custom field support | `integration` | Read+Write | [spec-kit-jira](https://github.com/mbachorik/spec-kit-jira) |
|
||||||
| Learning Extension | Generate educational guides from implementations and enhance clarifications with mentoring context | `docs` | Read+Write | [spec-kit-learn](https://github.com/imviancagrace/spec-kit-learn) |
|
| Learning Extension | Generate educational guides from implementations and enhance clarifications with mentoring context | `docs` | Read+Write | [spec-kit-learn](https://github.com/imviancagrace/spec-kit-learn) |
|
||||||
@@ -197,39 +222,69 @@ The following community-contributed extensions are available in [`catalog.commun
|
|||||||
| MAQA Jira Integration | Jira integration for MAQA — syncs Stories and Subtasks as features progress through the board | `integration` | Read+Write | [spec-kit-maqa-jira](https://github.com/GenieRobot/spec-kit-maqa-jira) |
|
| MAQA Jira Integration | Jira integration for MAQA — syncs Stories and Subtasks as features progress through the board | `integration` | Read+Write | [spec-kit-maqa-jira](https://github.com/GenieRobot/spec-kit-maqa-jira) |
|
||||||
| MAQA Linear Integration | Linear integration for MAQA — syncs issues and sub-issues across workflow states as features progress | `integration` | Read+Write | [spec-kit-maqa-linear](https://github.com/GenieRobot/spec-kit-maqa-linear) |
|
| MAQA Linear Integration | Linear integration for MAQA — syncs issues and sub-issues across workflow states as features progress | `integration` | Read+Write | [spec-kit-maqa-linear](https://github.com/GenieRobot/spec-kit-maqa-linear) |
|
||||||
| MAQA Trello Integration | Trello board integration for MAQA — populates board from specs, moves cards, real-time checklist ticking | `integration` | Read+Write | [spec-kit-maqa-trello](https://github.com/GenieRobot/spec-kit-maqa-trello) |
|
| MAQA Trello Integration | Trello board integration for MAQA — populates board from specs, moves cards, real-time checklist ticking | `integration` | Read+Write | [spec-kit-maqa-trello](https://github.com/GenieRobot/spec-kit-maqa-trello) |
|
||||||
|
| MemoryLint | Agent memory governance tool: Automatically audits and fixes boundary conflicts between AGENTS.md and the constitution. | `process` | Read+Write | [memorylint](https://github.com/RbBtSn0w/spec-kit-extensions/tree/main/memorylint) |
|
||||||
| Onboard | Contextual onboarding and progressive growth for developers new to spec-kit projects. Explains specs, maps dependencies, validates understanding, and guides the next step | `process` | Read+Write | [spec-kit-onboard](https://github.com/dmux/spec-kit-onboard) |
|
| Onboard | Contextual onboarding and progressive growth for developers new to spec-kit projects. Explains specs, maps dependencies, validates understanding, and guides the next step | `process` | Read+Write | [spec-kit-onboard](https://github.com/dmux/spec-kit-onboard) |
|
||||||
|
| Optimize | Audit and optimize AI governance for context efficiency — token budgets, rule health, interpretability, compression, coherence, and echo detection | `process` | Read+Write | [spec-kit-optimize](https://github.com/sakitA/spec-kit-optimize) |
|
||||||
| Plan Review Gate | Require spec.md and plan.md to be merged via MR/PR before allowing task generation | `process` | Read-only | [spec-kit-plan-review-gate](https://github.com/luno/spec-kit-plan-review-gate) |
|
| Plan Review Gate | Require spec.md and plan.md to be merged via MR/PR before allowing task generation | `process` | Read-only | [spec-kit-plan-review-gate](https://github.com/luno/spec-kit-plan-review-gate) |
|
||||||
|
| PR Bridge | Auto-generate pull request descriptions, checklists, and summaries from spec artifacts | `process` | Read-only | [spec-kit-pr-bridge-](https://github.com/Quratulain-bilal/spec-kit-pr-bridge-) |
|
||||||
| Presetify | Create and validate presets and preset catalogs | `process` | Read+Write | [presetify](https://github.com/mnriem/spec-kit-extensions/tree/main/presetify) |
|
| Presetify | Create and validate presets and preset catalogs | `process` | Read+Write | [presetify](https://github.com/mnriem/spec-kit-extensions/tree/main/presetify) |
|
||||||
| Product Forge | Full product lifecycle: research → product spec → SpecKit → implement → verify → test | `process` | Read+Write | [speckit-product-forge](https://github.com/VaiYav/speckit-product-forge) |
|
| Product Forge | Full product lifecycle: research → product spec → SpecKit → implement → verify → test | `process` | Read+Write | [speckit-product-forge](https://github.com/VaiYav/speckit-product-forge) |
|
||||||
| Project Health Check | Diagnose a Spec Kit project and report health issues across structure, agents, features, scripts, extensions, and git | `visibility` | Read-only | [spec-kit-doctor](https://github.com/KhawarHabibKhan/spec-kit-doctor) |
|
| Project Health Check | Diagnose a Spec Kit project and report health issues across structure, agents, features, scripts, extensions, and git | `visibility` | Read-only | [spec-kit-doctor](https://github.com/KhawarHabibKhan/spec-kit-doctor) |
|
||||||
| Project Status | Show current SDD workflow progress — active feature, artifact status, task completion, workflow phase, and extensions summary | `visibility` | Read-only | [spec-kit-status](https://github.com/KhawarHabibKhan/spec-kit-status) |
|
| Project Status | Show current SDD workflow progress — active feature, artifact status, task completion, workflow phase, and extensions summary | `visibility` | Read-only | [spec-kit-status](https://github.com/KhawarHabibKhan/spec-kit-status) |
|
||||||
|
| QA Testing Extension | Systematic QA testing with browser-driven or CLI-based validation of acceptance criteria from spec | `code` | Read-only | [spec-kit-qa](https://github.com/arunt14/spec-kit-qa) |
|
||||||
| Ralph Loop | Autonomous implementation loop using AI agent CLI | `code` | Read+Write | [spec-kit-ralph](https://github.com/Rubiss/spec-kit-ralph) |
|
| Ralph Loop | Autonomous implementation loop using AI agent CLI | `code` | Read+Write | [spec-kit-ralph](https://github.com/Rubiss/spec-kit-ralph) |
|
||||||
| Reconcile Extension | Reconcile implementation drift by surgically updating feature artifacts. | `docs` | Read+Write | [spec-kit-reconcile](https://github.com/stn1slv/spec-kit-reconcile) |
|
| Reconcile Extension | Reconcile implementation drift by surgically updating feature artifacts. | `docs` | Read+Write | [spec-kit-reconcile](https://github.com/stn1slv/spec-kit-reconcile) |
|
||||||
|
| Repository Index | Generate index for existing repo for overview, architecture and module level. | `docs` | Read-only | [spec-kit-repoindex](https://github.com/liuyiyu/spec-kit-repoindex) |
|
||||||
|
| Retro Extension | Sprint retrospective analysis with metrics, spec accuracy assessment, and improvement suggestions | `process` | Read+Write | [spec-kit-retro](https://github.com/arunt14/spec-kit-retro) |
|
||||||
| Retrospective Extension | Post-implementation retrospective with spec adherence scoring, drift analysis, and human-gated spec updates | `docs` | Read+Write | [spec-kit-retrospective](https://github.com/emi-dm/spec-kit-retrospective) |
|
| Retrospective Extension | Post-implementation retrospective with spec adherence scoring, drift analysis, and human-gated spec updates | `docs` | Read+Write | [spec-kit-retrospective](https://github.com/emi-dm/spec-kit-retrospective) |
|
||||||
| Review Extension | Post-implementation comprehensive code review with specialized agents for code quality, comments, tests, error handling, type design, and simplification | `code` | Read-only | [spec-kit-review](https://github.com/ismaelJimenez/spec-kit-review) |
|
| Review Extension | Post-implementation comprehensive code review with specialized agents for code quality, comments, tests, error handling, type design, and simplification | `code` | Read-only | [spec-kit-review](https://github.com/ismaelJimenez/spec-kit-review) |
|
||||||
| SDD Utilities | Resume interrupted workflows, validate project health, and verify spec-to-task traceability | `process` | Read+Write | [speckit-utils](https://github.com/mvanhorn/speckit-utils) |
|
| SDD Utilities | Resume interrupted workflows, validate project health, and verify spec-to-task traceability | `process` | Read+Write | [speckit-utils](https://github.com/mvanhorn/speckit-utils) |
|
||||||
| Superpowers Bridge | Orchestrates obra/superpowers skills within the spec-kit SDD workflow across the full lifecycle (clarification, TDD, review, verification, critique, debugging, branch completion) | `process` | Read+Write | [superpowers-bridge](https://github.com/RbBtSn0w/spec-kit-extensions/tree/main/superpowers-bridge) |
|
| Security Review | Comprehensive security audit of codebases using AI-powered DevSecOps analysis | `code` | Read-only | [spec-kit-security-review](https://github.com/DyanGalih/spec-kit-security-review) |
|
||||||
|
| SFSpeckit | Enterprise Salesforce SDLC with 18 commands for the full SDD lifecycle. | `process` | Read+Write | [spec-kit-sf](https://github.com/ysumanth06/spec-kit-sf) |
|
||||||
|
| Ship Release Extension | Automates release pipeline: pre-flight checks, branch sync, changelog generation, CI verification, and PR creation | `process` | Read+Write | [spec-kit-ship](https://github.com/arunt14/spec-kit-ship) |
|
||||||
|
| Spec Critique Extension | Dual-lens critical review of spec and plan from product strategy and engineering risk perspectives | `docs` | Read-only | [spec-kit-critique](https://github.com/arunt14/spec-kit-critique) |
|
||||||
|
| Spec Diagram | Auto-generate Mermaid diagrams of SDD workflow state, feature progress, and task dependencies | `visibility` | Read-only | [spec-kit-diagram-](https://github.com/Quratulain-bilal/spec-kit-diagram-) |
|
||||||
|
| Spec Refine | Update specs in-place, propagate changes to plan and tasks, and diff impact across artifacts | `process` | Read+Write | [spec-kit-refine](https://github.com/Quratulain-bilal/spec-kit-refine) |
|
||||||
| Spec Sync | Detect and resolve drift between specs and implementation. AI-assisted resolution with human approval | `docs` | Read+Write | [spec-kit-sync](https://github.com/bgervin/spec-kit-sync) |
|
| Spec Sync | Detect and resolve drift between specs and implementation. AI-assisted resolution with human approval | `docs` | Read+Write | [spec-kit-sync](https://github.com/bgervin/spec-kit-sync) |
|
||||||
| Understanding | Automated requirements quality analysis — 31 deterministic metrics against IEEE/ISO standards with experimental energy-based ambiguity detection | `docs` | Read-only | [understanding](https://github.com/Testimonial/understanding) |
|
| SpecTest | Auto-generate test scaffolds from spec criteria, map coverage, and find untested requirements | `code` | Read+Write | [spec-kit-spectest](https://github.com/Quratulain-bilal/spec-kit-spectest) |
|
||||||
|
| Staff Review Extension | Staff-engineer-level code review that validates implementation against spec, checks security, performance, and test coverage | `code` | Read-only | [spec-kit-staff-review](https://github.com/arunt14/spec-kit-staff-review) |
|
||||||
|
| Status Report | Project status, feature progress, and next-action recommendations for spec-driven workflows | `visibility` | Read-only | [Open-Agent-Tools/spec-kit-status](https://github.com/Open-Agent-Tools/spec-kit-status) |
|
||||||
|
| Superpowers Bridge | Orchestrates obra/superpowers skills within the spec-kit SDD workflow across the full lifecycle (clarification, TDD, review, verification, critique, debugging, branch completion) | `process` | Read+Write | [superpowers-bridge](https://github.com/RbBtSn0w/spec-kit-extensions/tree/main/superpowers-bridge) |
|
||||||
|
| TinySpec | Lightweight single-file workflow for small tasks — skip the heavy multi-step SDD process | `process` | Read+Write | [spec-kit-tinyspec](https://github.com/Quratulain-bilal/spec-kit-tinyspec) |
|
||||||
| V-Model Extension Pack | Enforces V-Model paired generation of development specs and test specs with full traceability | `docs` | Read+Write | [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 | `docs` | Read+Write | [spec-kit-v-model](https://github.com/leocamello/spec-kit-v-model) |
|
||||||
| Verify Extension | Post-implementation quality gate that validates implemented code against specification artifacts | `code` | Read-only | [spec-kit-verify](https://github.com/ismaelJimenez/spec-kit-verify) |
|
| Verify Extension | Post-implementation quality gate that validates implemented code against specification artifacts | `code` | Read-only | [spec-kit-verify](https://github.com/ismaelJimenez/spec-kit-verify) |
|
||||||
| Verify Tasks Extension | Detect phantom completions: tasks marked [X] in tasks.md with no real implementation | `code` | Read-only | [spec-kit-verify-tasks](https://github.com/datastone-inc/spec-kit-verify-tasks) |
|
| Verify Tasks Extension | Detect phantom completions: tasks marked [X] in tasks.md with no real implementation | `code` | Read-only | [spec-kit-verify-tasks](https://github.com/datastone-inc/spec-kit-verify-tasks) |
|
||||||
|
| What-if Analysis | Preview the downstream impact (complexity, effort, tasks, risks) of requirement changes before committing to them | `visibility` | Read-only | [spec-kit-whatif](https://github.com/DevAbdullah90/spec-kit-whatif) |
|
||||||
|
| Worktree Isolation | Spawn isolated git worktrees for parallel feature development without checkout switching | `process` | Read+Write | [spec-kit-worktree](https://github.com/Quratulain-bilal/spec-kit-worktree) |
|
||||||
|
| Worktrees | Default-on worktree isolation for parallel agents — sibling or nested layout | `process` | Read+Write | [spec-kit-worktree-parallel](https://github.com/dango85/spec-kit-worktree-parallel) |
|
||||||
|
|
||||||
To submit your own extension, see the [Extension Publishing Guide](extensions/EXTENSION-PUBLISHING-GUIDE.md).
|
To submit your own extension, see the [Extension Publishing Guide](extensions/EXTENSION-PUBLISHING-GUIDE.md).
|
||||||
|
|
||||||
## 🎨 Community Presets
|
## 🎨 Community Presets
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Community presets are independently created and maintained by their respective authors. GitHub and the Spec Kit maintainers may review pull requests that add entries to the community catalog for formatting, catalog structure, or policy compliance, but they do **not review, audit, endorse, or support the preset code itself**. Review preset source code before installation and use at your own discretion.
|
||||||
|
|
||||||
The following community-contributed presets customize how Spec Kit behaves — overriding templates, commands, and terminology without changing any tooling. Presets are available in [`catalog.community.json`](presets/catalog.community.json):
|
The following community-contributed presets customize how Spec Kit behaves — overriding templates, commands, and terminology without changing any tooling. Presets are available in [`catalog.community.json`](presets/catalog.community.json):
|
||||||
|
|
||||||
| Preset | Purpose | Provides | Requires | URL |
|
| Preset | Purpose | Provides | Requires | URL |
|
||||||
|--------|---------|----------|----------|-----|
|
|--------|---------|----------|----------|-----|
|
||||||
| AIDE In-Place Migration | Adapts the AIDE extension workflow for in-place technology migrations (X → Y pattern) — adds migration objectives, verification gates, knowledge documents, and behavioral equivalence criteria | 2 templates, 8 commands | AIDE extension | [spec-kit-presets](https://github.com/mnriem/spec-kit-presets) |
|
| AIDE In-Place Migration | Adapts the AIDE extension workflow for in-place technology migrations (X → Y pattern) — adds migration objectives, verification gates, knowledge documents, and behavioral equivalence criteria | 2 templates, 8 commands | AIDE extension | [spec-kit-presets](https://github.com/mnriem/spec-kit-presets) |
|
||||||
|
| Canon Core | Adapts original Spec Kit workflow to work together with Canon extension | 2 templates, 8 commands | — | [spec-kit-canon](https://github.com/maximiliamus/spec-kit-canon) |
|
||||||
|
| Explicit Task Dependencies | Adds explicit `(depends on T###)` dependency declarations and an Execution Wave DAG to tasks.md for parallel scheduling | 1 template, 1 command | — | [spec-kit-preset-explicit-task-dependencies](https://github.com/Quratulain-bilal/spec-kit-preset-explicit-task-dependencies) |
|
||||||
|
| Fiction Book Writing | It adapts the Spec-Driven Development workflow for storytelling: features become story elements, specs become story briefs, plans become story structures, and tasks become scene-by-scene writing tasks. Supports single and multi-POV, all major plot structure frameworks, and two style modes, author voice sample or humanized AI prose. | 21 templates, 17 commands | — | [spec-kit-preset-fiction-book-writing](https://github.com/adaumann/speckit-preset-fiction-book-writing) |
|
||||||
|
| Multi-Repo Branching | Coordinates feature branch creation across multiple git repositories (independent repos and submodules) during plan and tasks phases | 2 commands | — | [spec-kit-preset-multi-repo-branching](https://github.com/sakitA/spec-kit-preset-multi-repo-branching) |
|
||||||
| Pirate Speak (Full) | Transforms all Spec Kit output into pirate speak — specs become "Voyage Manifests", plans become "Battle Plans", tasks become "Crew Assignments" | 6 templates, 9 commands | — | [spec-kit-presets](https://github.com/mnriem/spec-kit-presets) |
|
| Pirate Speak (Full) | Transforms all Spec Kit output into pirate speak — specs become "Voyage Manifests", plans become "Battle Plans", tasks become "Crew Assignments" | 6 templates, 9 commands | — | [spec-kit-presets](https://github.com/mnriem/spec-kit-presets) |
|
||||||
|
| Table of Contents Navigation | Adds a navigable Table of Contents to generated spec.md, plan.md, and tasks.md documents | 3 templates, 3 commands | — | [spec-kit-preset-toc-navigation](https://github.com/Quratulain-bilal/spec-kit-preset-toc-navigation) |
|
||||||
|
| VS Code Ask Questions | Enhances the clarify command to use `vscode/askQuestions` for batched interactive questioning. | 1 command | — | [spec-kit-presets](https://github.com/fdcastel/spec-kit-presets) |
|
||||||
|
|
||||||
To build and publish your own preset, see the [Presets Publishing Guide](presets/PUBLISHING.md).
|
To build and publish your own preset, see the [Presets Publishing Guide](presets/PUBLISHING.md).
|
||||||
|
|
||||||
## 🚶 Community Walkthroughs
|
## 🚶 Community Walkthroughs
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Community walkthroughs are independently created and maintained by their respective authors. They are **not reviewed, nor endorsed, nor supported by GitHub**. Review their content before following along and use at your own discretion.
|
||||||
|
|
||||||
See Spec-Driven Development in action across different scenarios with these community-contributed walkthroughs:
|
See Spec-Driven Development in action across different scenarios with these community-contributed walkthroughs:
|
||||||
|
|
||||||
- **[Greenfield .NET CLI tool](https://github.com/mnriem/spec-kit-dotnet-cli-demo)** — Builds a Timezone Utility as a .NET single-binary CLI tool from a blank directory, covering the full spec-kit workflow: constitution, specify, plan, tasks, and multi-pass implement using GitHub Copilot agents.
|
- **[Greenfield .NET CLI tool](https://github.com/mnriem/spec-kit-dotnet-cli-demo)** — Builds a Timezone Utility as a .NET single-binary CLI tool from a blank directory, covering the full spec-kit workflow: constitution, specify, plan, tasks, and multi-pass implement using GitHub Copilot agents.
|
||||||
@@ -248,206 +303,70 @@ See Spec-Driven Development in action across different scenarios with these comm
|
|||||||
|
|
||||||
## 🛠️ Community Friends
|
## 🛠️ Community Friends
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Community projects listed here are independently created and maintained by their respective authors. They are **not reviewed, nor endorsed, nor supported by GitHub**. Review their source code before installation and use at your own discretion.
|
||||||
|
|
||||||
Community projects that extend, visualize, or build on Spec Kit:
|
Community projects that extend, visualize, or build on Spec Kit:
|
||||||
|
|
||||||
- **[cc-sdd](https://github.com/rhuss/cc-sdd)** - A Claude Code plugin that adds composable traits on top of Spec Kit with [Superpowers](https://github.com/obra/superpowers)-based quality gates, spec/code review, git worktree isolation, and parallel implementation via agent teams.
|
- **[cc-spex](https://github.com/rhuss/cc-spex)** - A Claude Code plugin that adds composable traits on top of Spec Kit with [Superpowers](https://github.com/obra/superpowers)-based quality gates, spec/code review, git worktree isolation, and parallel implementation via agent teams.
|
||||||
|
|
||||||
- **[Spec Kit Assistant](https://marketplace.visualstudio.com/items?itemName=rfsales.speckit-assistant)** — A VS Code extension that provides a visual orchestrator for the full SDD workflow (constitution → specification → planning → tasks → implementation) with phase status visualization, an interactive task checklist, DAG visualization, and support for Claude, Gemini, GitHub Copilot, and OpenAI backends. Requires the `specify` CLI in your PATH.
|
- **[Spec Kit Assistant](https://marketplace.visualstudio.com/items?itemName=rfsales.speckit-assistant)** — A VS Code extension that provides a visual orchestrator for the full SDD workflow (constitution → specification → planning → tasks → implementation) with phase status visualization, an interactive task checklist, DAG visualization, and support for Claude, Gemini, GitHub Copilot, and OpenAI backends. Requires the `specify` CLI in your PATH.
|
||||||
|
|
||||||
## 🤖 Supported AI Agents
|
- **[SpecKit Companion](https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion)** — A VS Code extension that brings a visual GUI to Spec Kit. Browse specs in a rich markdown viewer with clickable file references, create specifications with image attachments, comment and refine each step inline (GitHub-style review), track your progress through the SDD workflow with a visual phase stepper, and manage steering documents like constitutions and templates.
|
||||||
|
|
||||||
| Agent | Support | Notes |
|
## 🤖 Supported AI Coding Agent Integrations
|
||||||
| ------------------------------------------------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| [Qoder CLI](https://qoder.com/cli) | ✅ | |
|
|
||||||
| [Kiro CLI](https://kiro.dev/docs/cli/) | ✅ | Use `--ai kiro-cli` (alias: `--ai kiro`) |
|
|
||||||
| [Amp](https://ampcode.com/) | ✅ | |
|
|
||||||
| [Auggie CLI](https://docs.augmentcode.com/cli/overview) | ✅ | |
|
|
||||||
| [Claude Code](https://www.anthropic.com/claude-code) | ✅ | |
|
|
||||||
| [CodeBuddy CLI](https://www.codebuddy.ai/cli) | ✅ | |
|
|
||||||
| [Codex CLI](https://github.com/openai/codex) | ✅ | Requires `--ai-skills`. Codex recommends [skills](https://developers.openai.com/codex/skills) and treats [custom prompts](https://developers.openai.com/codex/custom-prompts) as deprecated. Spec-kit installs Codex skills into `.agents/skills` and invokes them as `$speckit-<command>`. |
|
|
||||||
| [Cursor](https://cursor.sh/) | ✅ | |
|
|
||||||
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | ✅ | |
|
|
||||||
| [GitHub Copilot](https://code.visualstudio.com/) | ✅ | |
|
|
||||||
| [IBM Bob](https://www.ibm.com/products/bob) | ✅ | IDE-based agent with slash command support |
|
|
||||||
| [Jules](https://jules.google.com/) | ✅ | |
|
|
||||||
| [Kilo Code](https://github.com/Kilo-Org/kilocode) | ✅ | |
|
|
||||||
| [opencode](https://opencode.ai/) | ✅ | |
|
|
||||||
| [Pi Coding Agent](https://pi.dev) | ✅ | Pi doesn't have MCP support out of the box, so `taskstoissues` won't work as intended. MCP support can be added via [extensions](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent#extensions) |
|
|
||||||
| [Qwen Code](https://github.com/QwenLM/qwen-code) | ✅ | |
|
|
||||||
| [Roo Code](https://roocode.com/) | ✅ | |
|
|
||||||
| [SHAI (OVHcloud)](https://github.com/ovh/shai) | ✅ | |
|
|
||||||
| [Tabnine CLI](https://docs.tabnine.com/main/getting-started/tabnine-cli) | ✅ | |
|
|
||||||
| [Mistral Vibe](https://github.com/mistralai/mistral-vibe) | ✅ | |
|
|
||||||
| [Kimi Code](https://code.kimi.com/) | ✅ | |
|
|
||||||
| [iFlow CLI](https://docs.iflow.cn/en/cli/quickstart) | ✅ | |
|
|
||||||
| [Windsurf](https://windsurf.com/) | ✅ | |
|
|
||||||
| [Junie](https://junie.jetbrains.com/) | ✅ | |
|
|
||||||
| [Antigravity (agy)](https://antigravity.google/) | ✅ | Requires `--ai-skills` |
|
|
||||||
| [Trae](https://www.trae.ai/) | ✅ | |
|
|
||||||
| Generic | ✅ | Bring your own agent — use `--ai generic --ai-commands-dir <path>` for unsupported agents |
|
|
||||||
|
|
||||||
## 🔧 Specify CLI Reference
|
Spec Kit works with 30+ AI coding agents — both CLI tools and IDE-based assistants. See the full list with notes and usage details in the [Supported AI Coding Agent Integrations](https://github.github.io/spec-kit/reference/integrations.html) guide.
|
||||||
|
|
||||||
The `specify` command supports the following options:
|
Run `specify integration list` to see all available integrations in your installed version.
|
||||||
|
|
||||||
### Commands
|
## Available Slash Commands
|
||||||
|
|
||||||
| Command | Description |
|
After running `specify init`, your AI coding agent will have access to these slash commands for structured development. If you pass `--ai <agent> --ai-skills`, Spec Kit installs agent skills instead of slash-command prompt files; `--ai-skills` requires `--ai`.
|
||||||
| ------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| `init` | Initialize a new Specify project from the latest template |
|
|
||||||
| `check` | Check for installed tools: `git` plus all CLI-based agents configured in `AGENT_CONFIG` (for example: `claude`, `gemini`, `code`/`code-insiders`, `cursor-agent`, `windsurf`, `junie`, `qwen`, `opencode`, `codex`, `kiro-cli`, `shai`, `qodercli`, `vibe`, `kimi`, `iflow`, `pi`, etc.) |
|
|
||||||
|
|
||||||
### `specify init` Arguments & Options
|
|
||||||
|
|
||||||
| Argument/Option | Type | Description |
|
|
||||||
| ---------------------- | -------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| `<project-name>` | Argument | Name for your new project directory (optional if using `--here`, or use `.` for current directory) |
|
|
||||||
| `--ai` | Option | AI assistant to use (see `AGENT_CONFIG` for the full, up-to-date list). Common options include: `claude`, `gemini`, `copilot`, `cursor-agent`, `qwen`, `opencode`, `codex`, `windsurf`, `junie`, `kilocode`, `auggie`, `roo`, `codebuddy`, `amp`, `shai`, `kiro-cli` (`kiro` alias), `agy`, `bob`, `qodercli`, `vibe`, `kimi`, `iflow`, `pi`, or `generic` (requires `--ai-commands-dir`) |
|
|
||||||
| `--ai-commands-dir` | Option | Directory for agent command files (required with `--ai generic`, e.g. `.myagent/commands/`) |
|
|
||||||
| `--script` | Option | Script variant to use: `sh` (bash/zsh) or `ps` (PowerShell) |
|
|
||||||
| `--ignore-agent-tools` | Flag | Skip checks for AI agent tools like Claude Code |
|
|
||||||
| `--no-git` | Flag | Skip git repository initialization |
|
|
||||||
| `--here` | Flag | Initialize project in the current directory instead of creating a new one |
|
|
||||||
| `--force` | Flag | Force merge/overwrite when initializing in current directory (skip confirmation) |
|
|
||||||
| `--skip-tls` | Flag | Skip SSL/TLS verification (not recommended) |
|
|
||||||
| `--debug` | Flag | Enable detailed debug output for troubleshooting |
|
|
||||||
| `--github-token` | Option | GitHub token for API requests (or set GH_TOKEN/GITHUB_TOKEN env variable) |
|
|
||||||
| `--ai-skills` | Flag | Install Prompt.MD templates as agent skills in agent-specific `skills/` directory (requires `--ai`). Extension commands are also auto-registered as skills when extensions are added later. |
|
|
||||||
| `--branch-numbering` | Option | Branch numbering strategy: `sequential` (default — `001`, `002`, `003`) or `timestamp` (`YYYYMMDD-HHMMSS`). Timestamp mode is useful for distributed teams to avoid numbering conflicts |
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Basic project initialization
|
|
||||||
specify init my-project
|
|
||||||
|
|
||||||
# Initialize with specific AI assistant
|
|
||||||
specify init my-project --ai claude
|
|
||||||
|
|
||||||
# Initialize with Cursor support
|
|
||||||
specify init my-project --ai cursor-agent
|
|
||||||
|
|
||||||
# Initialize with Qoder support
|
|
||||||
specify init my-project --ai qodercli
|
|
||||||
|
|
||||||
# Initialize with Windsurf support
|
|
||||||
specify init my-project --ai windsurf
|
|
||||||
|
|
||||||
# Initialize with Kiro CLI support
|
|
||||||
specify init my-project --ai kiro-cli
|
|
||||||
|
|
||||||
# Initialize with Amp support
|
|
||||||
specify init my-project --ai amp
|
|
||||||
|
|
||||||
# Initialize with SHAI support
|
|
||||||
specify init my-project --ai shai
|
|
||||||
|
|
||||||
# Initialize with Mistral Vibe support
|
|
||||||
specify init my-project --ai vibe
|
|
||||||
|
|
||||||
# Initialize with IBM Bob support
|
|
||||||
specify init my-project --ai bob
|
|
||||||
|
|
||||||
# Initialize with Pi Coding Agent support
|
|
||||||
specify init my-project --ai pi
|
|
||||||
|
|
||||||
# Initialize with Codex CLI support
|
|
||||||
specify init my-project --ai codex --ai-skills
|
|
||||||
|
|
||||||
# Initialize with Antigravity support
|
|
||||||
specify init my-project --ai agy --ai-skills
|
|
||||||
|
|
||||||
# Initialize with an unsupported agent (generic / bring your own agent)
|
|
||||||
specify init my-project --ai generic --ai-commands-dir .myagent/commands/
|
|
||||||
|
|
||||||
# Initialize with PowerShell scripts (Windows/cross-platform)
|
|
||||||
specify init my-project --ai copilot --script ps
|
|
||||||
|
|
||||||
# Initialize in current directory
|
|
||||||
specify init . --ai copilot
|
|
||||||
# or use the --here flag
|
|
||||||
specify init --here --ai copilot
|
|
||||||
|
|
||||||
# Force merge into current (non-empty) directory without confirmation
|
|
||||||
specify init . --force --ai copilot
|
|
||||||
# or
|
|
||||||
specify init --here --force --ai copilot
|
|
||||||
|
|
||||||
# Skip git initialization
|
|
||||||
specify init my-project --ai gemini --no-git
|
|
||||||
|
|
||||||
# Enable debug output for troubleshooting
|
|
||||||
specify init my-project --ai claude --debug
|
|
||||||
|
|
||||||
# Use GitHub token for API requests (helpful for corporate environments)
|
|
||||||
specify init my-project --ai claude --github-token ghp_your_token_here
|
|
||||||
|
|
||||||
# Install agent skills with the project
|
|
||||||
specify init my-project --ai claude --ai-skills
|
|
||||||
|
|
||||||
# Initialize in current directory with agent skills
|
|
||||||
specify init --here --ai gemini --ai-skills
|
|
||||||
|
|
||||||
# Use timestamp-based branch numbering (useful for distributed teams)
|
|
||||||
specify init my-project --ai claude --branch-numbering timestamp
|
|
||||||
|
|
||||||
# Check system requirements
|
|
||||||
specify check
|
|
||||||
```
|
|
||||||
|
|
||||||
### Available Slash Commands
|
|
||||||
|
|
||||||
After running `specify init`, your AI coding agent will have access to these slash commands for structured development.
|
|
||||||
|
|
||||||
For Codex CLI, `--ai-skills` installs spec-kit as agent skills instead of slash-command prompt files. In Codex skills mode, invoke spec-kit as `$speckit-constitution`, `$speckit-specify`, `$speckit-plan`, `$speckit-tasks`, and `$speckit-implement`.
|
|
||||||
|
|
||||||
#### Core Commands
|
#### Core Commands
|
||||||
|
|
||||||
Essential commands for the Spec-Driven Development workflow:
|
Essential commands for the Spec-Driven Development workflow:
|
||||||
|
|
||||||
| Command | Description |
|
| Command | Agent Skill | Description |
|
||||||
| ----------------------- | ------------------------------------------------------------------------ |
|
| ------------------------ | ---------------------- | -------------------------------------------------------------------------- |
|
||||||
| `/speckit.constitution` | Create or update project governing principles and development guidelines |
|
| `/speckit.constitution` | `speckit-constitution` | Create or update project governing principles and development guidelines |
|
||||||
| `/speckit.specify` | Define what you want to build (requirements and user stories) |
|
| `/speckit.specify` | `speckit-specify` | Define what you want to build (requirements and user stories) |
|
||||||
| `/speckit.plan` | Create technical implementation plans with your chosen tech stack |
|
| `/speckit.plan` | `speckit-plan` | Create technical implementation plans with your chosen tech stack |
|
||||||
| `/speckit.tasks` | Generate actionable task lists for implementation |
|
| `/speckit.tasks` | `speckit-tasks` | Generate actionable task lists for implementation |
|
||||||
| `/speckit.implement` | Execute all tasks to build the feature according to the plan |
|
| `/speckit.taskstoissues` | `speckit-taskstoissues`| Convert generated task lists into GitHub issues for tracking and execution |
|
||||||
|
| `/speckit.implement` | `speckit-implement` | Execute all tasks to build the feature according to the plan |
|
||||||
|
|
||||||
#### Optional Commands
|
#### Optional Commands
|
||||||
|
|
||||||
Additional commands for enhanced quality and validation:
|
Additional commands for enhanced quality and validation:
|
||||||
|
|
||||||
| Command | Description |
|
| Command | Agent Skill | Description |
|
||||||
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
| -------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `/speckit.clarify` | Clarify underspecified areas (recommended before `/speckit.plan`; formerly `/quizme`) |
|
| `/speckit.clarify` | `speckit-clarify` | Clarify underspecified areas (recommended before `/speckit.plan`; formerly `/quizme`) |
|
||||||
| `/speckit.analyze` | Cross-artifact consistency & coverage analysis (run after `/speckit.tasks`, before `/speckit.implement`) |
|
| `/speckit.analyze` | `speckit-analyze` | Cross-artifact consistency & coverage analysis (run after `/speckit.tasks`, before `/speckit.implement`) |
|
||||||
| `/speckit.checklist` | Generate custom quality checklists that validate requirements completeness, clarity, and consistency (like "unit tests for English") |
|
| `/speckit.checklist` | `speckit-checklist` | Generate custom quality checklists that validate requirements completeness, clarity, and consistency (like "unit tests for English") |
|
||||||
|
|
||||||
### Environment Variables
|
## 🔧 Specify CLI Reference
|
||||||
|
|
||||||
| Variable | Description |
|
For full command details, options, and examples, see the [CLI Reference](https://github.github.io/spec-kit/reference/overview.html).
|
||||||
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
||||||
| `SPECIFY_FEATURE` | Override feature detection for non-Git repositories. Set to the feature directory name (e.g., `001-photo-albums`) to work on a specific feature when not using Git branches.<br/>\*\*Must be set in the context of the agent you're working with prior to using `/speckit.plan` or follow-up commands. |
|
|
||||||
|
|
||||||
## 🧩 Making Spec Kit Your Own: Extensions & Presets
|
## 🧩 Making Spec Kit Your Own: Extensions & Presets
|
||||||
|
|
||||||
Spec Kit can be tailored to your needs through two complementary systems — **extensions** and **presets** — plus project-local overrides for one-off adjustments:
|
Spec Kit can be tailored to your needs through two complementary systems — **extensions** and **presets** — plus project-local overrides for one-off adjustments:
|
||||||
|
|
||||||
```mermaid
|
| Priority | Component Type | Location |
|
||||||
block-beta
|
| -------: | ------------------------------------------------- | -------------------------------- |
|
||||||
columns 1
|
| ⬆ 1 | Project-Local Overrides | `.specify/templates/overrides/` |
|
||||||
overrides["⬆ Highest priority\nProject-Local Overrides\n.specify/templates/overrides/"]
|
| 2 | Presets — Customize core & extensions | `.specify/presets/templates/` |
|
||||||
presets["Presets — Customize core & extensions\n.specify/presets/<preset-id>/templates/"]
|
| 3 | Extensions — Add new capabilities | `.specify/extensions/templates/` |
|
||||||
extensions["Extensions — Add new capabilities\n.specify/extensions/<ext-id>/templates/"]
|
| ⬇ 4 | Spec Kit Core — Built-in SDD commands & templates | `.specify/templates/` |
|
||||||
core["Spec Kit Core — Built-in SDD commands & templates\n.specify/templates/\n⬇ Lowest priority"]
|
|
||||||
|
|
||||||
style overrides fill:transparent,stroke:#999
|
- **Templates** are resolved at **runtime** — Spec Kit walks the stack top-down and uses the first match.
|
||||||
style presets fill:transparent,stroke:#4a9eda
|
- Project-local overrides (`.specify/templates/overrides/`) let you make one-off adjustments for a single project without creating a full preset.
|
||||||
style extensions fill:transparent,stroke:#4a9e4a
|
- **Extension/preset commands** are applied at **install time** — when you run `specify extension add` or `specify preset add`, command files are written into agent directories (e.g., `.claude/commands/`).
|
||||||
style core fill:transparent,stroke:#e6a817
|
- If multiple presets or extensions provide the same command, the highest-priority version wins. On removal, the next-highest-priority version is restored automatically.
|
||||||
```
|
- If no overrides or customizations exist, Spec Kit uses its core defaults.
|
||||||
|
|
||||||
**Templates** are resolved at **runtime** — Spec Kit walks the stack top-down and uses the first match. Project-local overrides (`.specify/templates/overrides/`) let you make one-off adjustments for a single project without creating a full preset. **Commands** are applied at **install time** — when you run `specify extension add` or `specify preset add`, command files are written into agent directories (e.g., `.claude/commands/`). If multiple presets or extensions provide the same command, the highest-priority version wins. On removal, the next-highest-priority version is restored automatically. If no overrides or customizations exist, Spec Kit uses its core defaults.
|
|
||||||
|
|
||||||
### Extensions — Add New Capabilities
|
### Extensions — Add New Capabilities
|
||||||
|
|
||||||
@@ -463,7 +382,7 @@ specify extension add <extension-name>
|
|||||||
|
|
||||||
For example, extensions could add Jira integration, post-implementation code review, V-Model test traceability, or project health diagnostics.
|
For example, extensions could add Jira integration, post-implementation code review, V-Model test traceability, or project health diagnostics.
|
||||||
|
|
||||||
See the [Extensions README](./extensions/README.md) for the full guide and how to build and publish your own. Browse the [community extensions](#-community-extensions) above for what's available.
|
See the [Extensions reference](https://github.github.io/spec-kit/reference/extensions.html) for the full command guide. Browse the [community extensions](#-community-extensions) above for what's available.
|
||||||
|
|
||||||
### Presets — Customize Existing Workflows
|
### Presets — Customize Existing Workflows
|
||||||
|
|
||||||
@@ -479,7 +398,7 @@ specify preset add <preset-name>
|
|||||||
|
|
||||||
For example, presets could restructure spec templates to require regulatory traceability, adapt the workflow to fit the methodology you use (e.g., Agile, Kanban, Waterfall, jobs-to-be-done, or domain-driven design), add mandatory security review gates to plans, enforce test-first task ordering, or localize the entire workflow to a different language. The [pirate-speak demo](https://github.com/mnriem/spec-kit-pirate-speak-preset-demo) shows just how deep the customization can go. Multiple presets can be stacked with priority ordering.
|
For example, presets could restructure spec templates to require regulatory traceability, adapt the workflow to fit the methodology you use (e.g., Agile, Kanban, Waterfall, jobs-to-be-done, or domain-driven design), add mandatory security review gates to plans, enforce test-first task ordering, or localize the entire workflow to a different language. The [pirate-speak demo](https://github.com/mnriem/spec-kit-pirate-speak-preset-demo) shows just how deep the customization can go. Multiple presets can be stacked with priority ordering.
|
||||||
|
|
||||||
See the [Presets README](./presets/README.md) for the full guide, including resolution order, priority, and how to create your own.
|
See the [Presets reference](https://github.github.io/spec-kit/reference/presets.html) for the full command guide, including resolution order and priority stacking.
|
||||||
|
|
||||||
### When to Use Which
|
### When to Use Which
|
||||||
|
|
||||||
@@ -537,7 +456,7 @@ Our research and experimentation focus on:
|
|||||||
## 🔧 Prerequisites
|
## 🔧 Prerequisites
|
||||||
|
|
||||||
- **Linux/macOS/Windows**
|
- **Linux/macOS/Windows**
|
||||||
- [Supported](#-supported-ai-agents) AI coding agent.
|
- [Supported](#-supported-ai-coding-agent-integrations) AI coding agent.
|
||||||
- [uv](https://docs.astral.sh/uv/) for package management
|
- [uv](https://docs.astral.sh/uv/) for package management
|
||||||
- [Python 3.11+](https://www.python.org/downloads/)
|
- [Python 3.11+](https://www.python.org/downloads/)
|
||||||
- [Git](https://git-scm.com/downloads)
|
- [Git](https://git-scm.com/downloads)
|
||||||
@@ -579,29 +498,29 @@ specify init --here --force
|
|||||||
You will be prompted to select the AI agent you are using. You can also proactively specify it directly in the terminal:
|
You will be prompted to select the AI agent you are using. You can also proactively specify it directly in the terminal:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
specify init <project_name> --ai claude
|
specify init <project_name> --ai copilot
|
||||||
specify init <project_name> --ai gemini
|
specify init <project_name> --ai gemini
|
||||||
specify init <project_name> --ai copilot
|
specify init <project_name> --ai copilot
|
||||||
|
|
||||||
# Or in current directory:
|
# Or in current directory:
|
||||||
specify init . --ai claude
|
specify init . --ai copilot
|
||||||
specify init . --ai codex --ai-skills
|
specify init . --ai codex --ai-skills
|
||||||
|
|
||||||
# or use --here flag
|
# or use --here flag
|
||||||
specify init --here --ai claude
|
specify init --here --ai copilot
|
||||||
specify init --here --ai codex --ai-skills
|
specify init --here --ai codex --ai-skills
|
||||||
|
|
||||||
# Force merge into a non-empty current directory
|
# Force merge into a non-empty current directory
|
||||||
specify init . --force --ai claude
|
specify init . --force --ai copilot
|
||||||
|
|
||||||
# or
|
# or
|
||||||
specify init --here --force --ai claude
|
specify init --here --force --ai copilot
|
||||||
```
|
```
|
||||||
|
|
||||||
The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, Tabnine CLI, Kiro CLI, Pi, or Mistral Vibe installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command:
|
The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, Tabnine CLI, Kiro CLI, Pi, Forge, Goose, or Mistral Vibe installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
specify init <project_name> --ai claude --ignore-agent-tools
|
specify init <project_name> --ai copilot --ignore-agent-tools
|
||||||
```
|
```
|
||||||
|
|
||||||
### **STEP 1:** Establish project principles
|
### **STEP 1:** Establish project principles
|
||||||
|
|||||||
133
TESTING.md
133
TESTING.md
@@ -1,133 +0,0 @@
|
|||||||
# Testing Guide
|
|
||||||
|
|
||||||
This document is the detailed testing companion to [`CONTRIBUTING.md`](./CONTRIBUTING.md).
|
|
||||||
|
|
||||||
Use it for three things:
|
|
||||||
|
|
||||||
1. running quick automated checks before manual testing,
|
|
||||||
2. manually testing affected slash commands through an AI agent, and
|
|
||||||
3. capturing the results in a PR-friendly format.
|
|
||||||
|
|
||||||
Any change that affects a slash command's behavior requires manually testing that command through an AI agent and submitting results with the PR.
|
|
||||||
|
|
||||||
## Recommended order
|
|
||||||
|
|
||||||
1. **Sync your environment** — install the project and test dependencies.
|
|
||||||
2. **Run focused automated checks** — especially for packaging, scaffolding, agent config, and generated-file changes.
|
|
||||||
3. **Run manual agent tests** — for any affected slash commands.
|
|
||||||
4. **Paste results into your PR** — include both command-selection reasoning and manual test results.
|
|
||||||
|
|
||||||
## Quick automated checks
|
|
||||||
|
|
||||||
Run these before manual testing when your change affects packaging, scaffolding, templates, release artifacts, or agent wiring.
|
|
||||||
|
|
||||||
### Environment setup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd <spec-kit-repo>
|
|
||||||
uv sync --extra test
|
|
||||||
source .venv/bin/activate # On Windows (CMD): .venv\Scripts\activate | (PowerShell): .venv\Scripts\Activate.ps1
|
|
||||||
```
|
|
||||||
|
|
||||||
### Generated package structure and content
|
|
||||||
|
|
||||||
```bash
|
|
||||||
uv run python -m pytest tests/test_core_pack_scaffold.py -q
|
|
||||||
```
|
|
||||||
|
|
||||||
This validates the generated files that CI-style packaging depends on, including directory layout, file names, frontmatter/TOML validity, placeholder replacement, `.specify/` path rewrites, and parity with `create-release-packages.sh`.
|
|
||||||
|
|
||||||
### Agent configuration and release wiring consistency
|
|
||||||
|
|
||||||
```bash
|
|
||||||
uv run python -m pytest tests/test_agent_config_consistency.py -q
|
|
||||||
```
|
|
||||||
|
|
||||||
Run this when you change agent metadata, release scripts, context update scripts, or artifact naming.
|
|
||||||
|
|
||||||
### Optional single-agent packaging spot check
|
|
||||||
|
|
||||||
```bash
|
|
||||||
AGENTS=copilot SCRIPTS=sh ./.github/workflows/scripts/create-release-packages.sh v1.0.0
|
|
||||||
```
|
|
||||||
|
|
||||||
Inspect `.genreleases/sdd-copilot-package-sh/` and the matching ZIP in `.genreleases/` when you want to review the exact packaged output for one agent/script combination.
|
|
||||||
|
|
||||||
## Manual testing process
|
|
||||||
|
|
||||||
1. **Identify affected commands** — use the [prompt below](#determining-which-tests-to-run) to have your agent analyze your changed files and determine which commands need testing.
|
|
||||||
2. **Set up a test project** — scaffold from your local branch (see [Setup](#setup)).
|
|
||||||
3. **Run each affected command** — invoke it in your agent, verify it completes successfully, and confirm it produces the expected output (files created, scripts executed, artifacts populated).
|
|
||||||
4. **Run prerequisites first** — commands that depend on earlier commands (e.g., `/speckit.tasks` requires `/speckit.plan` which requires `/speckit.specify`) must be run in order.
|
|
||||||
5. **Report results** — paste the [reporting template](#reporting-results) into your PR with pass/fail for each command tested.
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install the project and test dependencies from your local branch
|
|
||||||
cd <spec-kit-repo>
|
|
||||||
uv sync --extra test
|
|
||||||
source .venv/bin/activate # On Windows (CMD): .venv\Scripts\activate | (PowerShell): .venv\Scripts\Activate.ps1
|
|
||||||
uv pip install -e .
|
|
||||||
# Ensure the `specify` binary in this environment points at your working tree so the agent runs the branch you're testing.
|
|
||||||
|
|
||||||
# Initialize a test project using your local changes
|
|
||||||
uv run specify init /tmp/speckit-test --ai <agent> --offline
|
|
||||||
cd /tmp/speckit-test
|
|
||||||
|
|
||||||
# Open in your agent
|
|
||||||
```
|
|
||||||
|
|
||||||
If you are testing the packaged output rather than the live source tree, create a local release package first as described in [`CONTRIBUTING.md`](./CONTRIBUTING.md).
|
|
||||||
|
|
||||||
## Reporting results
|
|
||||||
|
|
||||||
Paste this into your PR:
|
|
||||||
|
|
||||||
~~~markdown
|
|
||||||
## Manual test results
|
|
||||||
|
|
||||||
**Agent**: [e.g., GitHub Copilot in VS Code] | **OS/Shell**: [e.g., macOS/zsh]
|
|
||||||
|
|
||||||
| Command tested | Notes |
|
|
||||||
|----------------|-------|
|
|
||||||
| `/speckit.command` | |
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Determining which tests to run
|
|
||||||
|
|
||||||
Copy this prompt into your agent. Include the agent's response (selected tests plus a brief explanation of the mapping) in your PR.
|
|
||||||
|
|
||||||
~~~text
|
|
||||||
Read TESTING.md, then run `git diff --name-only main` to get my changed files.
|
|
||||||
For each changed file, determine which slash commands it affects by reading
|
|
||||||
the command templates in templates/commands/ to understand what each command
|
|
||||||
invokes. Use these mapping rules:
|
|
||||||
|
|
||||||
- templates/commands/X.md → the command it defines
|
|
||||||
- scripts/bash/Y.sh or scripts/powershell/Y.ps1 → every command that invokes that script (grep templates/commands/ for the script name). Also check transitive dependencies: if the changed script is sourced by other scripts (e.g., common.sh is sourced by create-new-feature.sh, check-prerequisites.sh, setup-plan.sh, update-agent-context.sh), then every command invoking those downstream scripts is also affected
|
|
||||||
- templates/Z-template.md → every command that consumes that template during execution
|
|
||||||
- src/specify_cli/*.py → CLI commands (`specify init`, `specify check`, `specify extension *`, `specify preset *`); test the affected CLI command and, for init/scaffolding changes, at minimum test /speckit.specify
|
|
||||||
- extensions/X/commands/* → the extension command it defines
|
|
||||||
- extensions/X/scripts/* → every extension command that invokes that script
|
|
||||||
- extensions/X/extension.yml or config-template.yml → every command in that extension. Also check if the manifest defines hooks (look for `hooks:` entries like `before_specify`, `after_implement`, etc.) — if so, the core commands those hooks attach to are also affected
|
|
||||||
- presets/*/* → test preset scaffolding via `specify init` with the preset
|
|
||||||
- pyproject.toml → packaging/bundling; test `specify init` and verify bundled assets
|
|
||||||
|
|
||||||
Include prerequisite tests (e.g., T5 requires T3 requires T1).
|
|
||||||
|
|
||||||
Output in this format:
|
|
||||||
|
|
||||||
### Test selection reasoning
|
|
||||||
|
|
||||||
| Changed file | Affects | Test | Why |
|
|
||||||
|---|---|---|---|
|
|
||||||
| (path) | (command) | T# | (reason) |
|
|
||||||
|
|
||||||
### Required tests
|
|
||||||
|
|
||||||
Number each test sequentially (T1, T2, ...). List prerequisite tests first.
|
|
||||||
|
|
||||||
- T1: /speckit.command — (reason)
|
|
||||||
- T2: /speckit.command — (reason)
|
|
||||||
~~~
|
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
> **Important:** The only official, maintained packages for Spec Kit come from the [github/spec-kit](https://github.com/github/spec-kit) GitHub repository. Any packages with the same name available on PyPI (e.g. `specify-cli` on pypi.org) are **not** affiliated with this project and are not maintained by the Spec Kit maintainers. For normal installs, use the GitHub-based commands shown below. For offline or air-gapped environments, locally built wheels created from this repository are also valid.
|
||||||
|
|
||||||
### Initialize a New Project
|
### Initialize a New Project
|
||||||
|
|
||||||
The easiest way to get started is to initialize a new project. Pin a specific release tag for stability (check [Releases](https://github.com/github/spec-kit/releases) for the latest):
|
The easiest way to get started is to initialize a new project. Pin a specific release tag for stability (check [Releases](https://github.com/github/spec-kit/releases) for the latest):
|
||||||
@@ -69,6 +71,14 @@ uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init <proje
|
|||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
|
After installation, run the following command to confirm the correct version is installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify version
|
||||||
|
```
|
||||||
|
|
||||||
|
This helps verify you are running the official Spec Kit build from GitHub, not an unrelated package with the same name.
|
||||||
|
|
||||||
After initialization, you should see the following commands available in your AI agent:
|
After initialization, you should see the following commands available in your AI agent:
|
||||||
|
|
||||||
- `/speckit.specify` - Create specifications
|
- `/speckit.specify` - Create specifications
|
||||||
|
|||||||
@@ -128,16 +128,14 @@ python -m src.specify_cli init --here --ai claude --ignore-agent-tools --script
|
|||||||
|
|
||||||
Or copy only the modified CLI portion if you want a lighter sandbox.
|
Or copy only the modified CLI portion if you want a lighter sandbox.
|
||||||
|
|
||||||
## 9. Debug Network / TLS Skips
|
## 9. Debug Network / TLS Issues
|
||||||
|
|
||||||
If you need to bypass TLS validation while experimenting:
|
> **Deprecated:** The `--skip-tls` flag is a no-op and has no effect.
|
||||||
|
> It was previously used to bypass TLS validation during local testing.
|
||||||
```bash
|
> If you encounter TLS errors (e.g., on a corporate network), configure your
|
||||||
specify check --skip-tls
|
> environment's certificate store or proxy instead.
|
||||||
specify init demo --skip-tls --ai gemini --ignore-agent-tools --script ps
|
>
|
||||||
```
|
> For example, set `SSL_CERT_FILE` or configure `HTTPS_PROXY` / `HTTP_PROXY`.
|
||||||
|
|
||||||
(Use only for local experimentation.)
|
|
||||||
|
|
||||||
## 10. Rapid Edit Loop Summary
|
## 10. Rapid Edit Loop Summary
|
||||||
|
|
||||||
@@ -166,7 +164,7 @@ rm -rf .venv dist build *.egg-info
|
|||||||
| Scripts not executable (Linux) | Re-run init or `chmod +x scripts/*.sh` |
|
| Scripts not executable (Linux) | Re-run init or `chmod +x scripts/*.sh` |
|
||||||
| Git step skipped | You passed `--no-git` or Git not installed |
|
| Git step skipped | You passed `--no-git` or Git not installed |
|
||||||
| Wrong script type downloaded | Pass `--script sh` or `--script ps` explicitly |
|
| Wrong script type downloaded | Pass `--script sh` or `--script ps` explicitly |
|
||||||
| TLS errors on corporate network | Try `--skip-tls` (not for production) |
|
| TLS errors on corporate network | Configure your environment's certificate store or proxy. The `--skip-tls` flag is deprecated and has no effect. |
|
||||||
|
|
||||||
## 13. Next Steps
|
## 13. Next Steps
|
||||||
|
|
||||||
|
|||||||
79
docs/reference/core.md
Normal file
79
docs/reference/core.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Core Commands
|
||||||
|
|
||||||
|
The core `specify` commands handle project initialization, system checks, and version information.
|
||||||
|
|
||||||
|
## Initialize a Project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify init [<project_name>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ------------------------ | ------------------------------------------------------------------------ |
|
||||||
|
| `--integration <key>` | AI coding agent integration to use (e.g. `copilot`, `claude`, `gemini`). See the [Integrations reference](integrations.md) for all available keys |
|
||||||
|
| `--integration-options` | Options for the integration (e.g. `--integration-options="--commands-dir .myagent/cmds"`) |
|
||||||
|
| `--script sh\|ps` | Script type: `sh` (bash/zsh) or `ps` (PowerShell) |
|
||||||
|
| `--here` | Initialize in the current directory instead of creating a new one |
|
||||||
|
| `--force` | Force merge/overwrite when initializing in an existing directory |
|
||||||
|
| `--no-git` | Skip git repository initialization |
|
||||||
|
| `--ignore-agent-tools` | Skip checks for AI coding agent CLI tools |
|
||||||
|
| `--preset <id>` | Install a preset during initialization |
|
||||||
|
| `--branch-numbering` | Branch numbering strategy: `sequential` (default) or `timestamp` |
|
||||||
|
|
||||||
|
Creates a new Spec Kit project with the necessary directory structure, templates, scripts, and AI coding agent integration files.
|
||||||
|
|
||||||
|
Use `<project_name>` to create a new directory, or `--here` (or `.`) to initialize in the current directory. If the directory already has files, use `--force` to merge without confirmation.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a new project with an integration
|
||||||
|
specify init my-project --integration copilot
|
||||||
|
|
||||||
|
# Initialize in the current directory
|
||||||
|
specify init --here --integration copilot
|
||||||
|
|
||||||
|
# Force merge into a non-empty directory
|
||||||
|
specify init --here --force --integration copilot
|
||||||
|
|
||||||
|
# Use PowerShell scripts (Windows/cross-platform)
|
||||||
|
specify init my-project --integration copilot --script ps
|
||||||
|
|
||||||
|
# Skip git initialization
|
||||||
|
specify init my-project --integration copilot --no-git
|
||||||
|
|
||||||
|
# Install a preset during initialization
|
||||||
|
specify init my-project --integration copilot --preset compliance
|
||||||
|
|
||||||
|
# Use timestamp-based branch numbering (useful for distributed teams)
|
||||||
|
specify init my-project --integration copilot --branch-numbering timestamp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| ----------------- | ------------------------------------------------------------------------ |
|
||||||
|
| `SPECIFY_FEATURE` | Override feature detection for non-Git repositories. Set to the feature directory name (e.g., `001-photo-albums`) to work on a specific feature when not using Git branches. Must be set in the context of the agent prior to using `/speckit.plan` or follow-up commands. |
|
||||||
|
|
||||||
|
## Check Installed Tools
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify check
|
||||||
|
```
|
||||||
|
|
||||||
|
Checks that required tools are available on your system: `git` and any CLI-based AI coding agents. IDE-based agents are skipped since they don't require a CLI tool.
|
||||||
|
|
||||||
|
## Version Information
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify version
|
||||||
|
```
|
||||||
|
|
||||||
|
Displays the Spec Kit CLI version, Python version, platform, and architecture.
|
||||||
|
|
||||||
|
A quick version check is also available via:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify --version
|
||||||
|
specify -V
|
||||||
|
```
|
||||||
201
docs/reference/extensions.md
Normal file
201
docs/reference/extensions.md
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
# Extensions
|
||||||
|
|
||||||
|
Extensions add new capabilities to Spec Kit — domain-specific commands, external tool integrations, quality gates, and more. They introduce new commands and templates that go beyond the built-in Spec-Driven Development workflow.
|
||||||
|
|
||||||
|
## Search Available Extensions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension search [query]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ------------ | ------------------------------------ |
|
||||||
|
| `--tag` | Filter by tag |
|
||||||
|
| `--author` | Filter by author |
|
||||||
|
| `--verified` | Show only verified extensions |
|
||||||
|
|
||||||
|
Searches all active catalogs for extensions matching the query. Without a query, lists all available extensions.
|
||||||
|
|
||||||
|
## Install an Extension
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension add <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| --------------- | -------------------------------------------------------- |
|
||||||
|
| `--dev` | Install from a local directory (for development) |
|
||||||
|
| `--from <url>` | Install from a custom URL instead of the catalog |
|
||||||
|
| `--priority <N>`| Resolution priority (default: 10; lower = higher precedence) |
|
||||||
|
|
||||||
|
Installs an extension from the catalog, a URL, or a local directory. Extension commands are automatically registered with the currently installed AI coding agent integration.
|
||||||
|
|
||||||
|
> **Note:** All extension commands require a project already initialized with `specify init`.
|
||||||
|
|
||||||
|
## Remove an Extension
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension remove <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| --------------- | ---------------------------------------------- |
|
||||||
|
| `--keep-config` | Preserve configuration files during removal |
|
||||||
|
| `--force` | Skip confirmation prompt |
|
||||||
|
|
||||||
|
Removes an installed extension. Configuration files are backed up by default; use `--keep-config` to leave them in place or `--force` to skip the confirmation.
|
||||||
|
|
||||||
|
## List Installed Extensions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension list
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ------------- | -------------------------------------------------- |
|
||||||
|
| `--available` | Show available (uninstalled) extensions |
|
||||||
|
| `--all` | Show both installed and available extensions |
|
||||||
|
|
||||||
|
Lists installed extensions with their status, version, and command counts.
|
||||||
|
|
||||||
|
## Extension Info
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension info <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows detailed information about an installed or available extension, including its description, version, commands, and configuration.
|
||||||
|
|
||||||
|
## Update Extensions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension update [<name>]
|
||||||
|
```
|
||||||
|
|
||||||
|
Updates a specific extension, or all installed extensions if no name is given.
|
||||||
|
|
||||||
|
## Enable / Disable an Extension
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension enable <name>
|
||||||
|
specify extension disable <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Disable an extension without removing it. Disabled extensions are not loaded and their commands are not available. Re-enable with `enable`.
|
||||||
|
|
||||||
|
## Set Extension Priority
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension set-priority <name> <priority>
|
||||||
|
```
|
||||||
|
|
||||||
|
Changes the resolution priority of an extension. When multiple extensions provide a command with the same name, the extension with the lowest priority number takes precedence.
|
||||||
|
|
||||||
|
## Catalog Management
|
||||||
|
|
||||||
|
Extension catalogs control where `search` and `add` look for extensions. Catalogs are checked in priority order (lower number = higher precedence).
|
||||||
|
|
||||||
|
### List Catalogs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension catalog list
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows all active catalogs in the stack with their priorities and install permissions.
|
||||||
|
|
||||||
|
### Add a Catalog
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension catalog add <url>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ------------------------------------ | -------------------------------------------------- |
|
||||||
|
| `--name <name>` | Required. Unique name for the catalog |
|
||||||
|
| `--priority <N>` | Priority (default: 10; lower = higher precedence) |
|
||||||
|
| `--install-allowed / --no-install-allowed` | Whether extensions can be installed from this catalog |
|
||||||
|
| `--description <text>` | Optional description |
|
||||||
|
|
||||||
|
Adds a catalog to the project's `.specify/extension-catalogs.yml`.
|
||||||
|
|
||||||
|
### Remove a Catalog
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify extension catalog remove <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes a catalog from the project configuration.
|
||||||
|
|
||||||
|
### Catalog Resolution Order
|
||||||
|
|
||||||
|
Catalogs are resolved in this order (first match wins):
|
||||||
|
|
||||||
|
1. **Environment variable** — `SPECKIT_CATALOG_URL` overrides all catalogs
|
||||||
|
2. **Project config** — `.specify/extension-catalogs.yml`
|
||||||
|
3. **User config** — `~/.specify/extension-catalogs.yml`
|
||||||
|
4. **Built-in defaults** — official catalog + community catalog
|
||||||
|
|
||||||
|
Example `.specify/extension-catalogs.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
catalogs:
|
||||||
|
- name: "my-org-catalog"
|
||||||
|
url: "https://example.com/catalog.json"
|
||||||
|
priority: 5
|
||||||
|
install_allowed: true
|
||||||
|
description: "Our approved extensions"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Extension Configuration
|
||||||
|
|
||||||
|
Most extensions include configuration files in their install directory:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.specify/extensions/<ext>/
|
||||||
|
├── <ext>-config.yml # Project config (version controlled)
|
||||||
|
├── <ext>-config.local.yml # Local overrides (gitignored)
|
||||||
|
└── <ext>-config.template.yml # Template reference
|
||||||
|
```
|
||||||
|
|
||||||
|
Configuration is merged in this order (highest priority last):
|
||||||
|
|
||||||
|
1. **Extension defaults** (from `extension.yml`)
|
||||||
|
2. **Project config** (`<ext>-config.yml`)
|
||||||
|
3. **Local overrides** (`<ext>-config.local.yml`)
|
||||||
|
4. **Environment variables** (`SPECKIT_<EXT>_*`)
|
||||||
|
|
||||||
|
To set up configuration for a newly installed extension, copy the template:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .specify/extensions/<ext>/<ext>-config.template.yml \
|
||||||
|
.specify/extensions/<ext>/<ext>-config.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### Why can't I find an extension with `search`?
|
||||||
|
|
||||||
|
Check the spelling of the extension name. The extension may not be published yet, or it may be in a catalog you haven't added. Use `specify extension catalog list` to see which catalogs are active.
|
||||||
|
|
||||||
|
### Why doesn't the extension command appear in my AI coding agent?
|
||||||
|
|
||||||
|
Verify the extension is installed and enabled with `specify extension list`. If it shows as installed, restart your AI coding agent — it may need to reload for it to take effect.
|
||||||
|
|
||||||
|
### How do I set up extension configuration?
|
||||||
|
|
||||||
|
Copy the config template that ships with the extension:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .specify/extensions/<ext>/<ext>-config.template.yml \
|
||||||
|
.specify/extensions/<ext>/<ext>-config.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
See [Extension Configuration](#extension-configuration) for details on config layers and overrides.
|
||||||
|
|
||||||
|
### How do I resolve an incompatible version error?
|
||||||
|
|
||||||
|
Update Spec Kit to the version required by the extension.
|
||||||
|
|
||||||
|
### Who maintains extensions?
|
||||||
|
|
||||||
|
Most extensions are independently created and maintained by their respective authors. The Spec Kit maintainers do not review, audit, endorse, or support extension code. Review an extension's source code before installing and use at your own discretion. For issues with a specific extension, contact its author or file an issue on the extension's repository.
|
||||||
140
docs/reference/integrations.md
Normal file
140
docs/reference/integrations.md
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# Supported AI Coding Agent Integrations
|
||||||
|
|
||||||
|
The Specify CLI supports a wide range of AI coding agents. When you run `specify init`, the CLI sets up the appropriate command files, context rules, and directory structures for your chosen AI coding agent — so you can start using Spec-Driven Development immediately, regardless of which tool you prefer.
|
||||||
|
|
||||||
|
## Supported AI Coding Agents
|
||||||
|
|
||||||
|
| Agent | Key | Notes |
|
||||||
|
| ------------------------------------------------------------------------------------ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| [Amp](https://ampcode.com/) | `amp` | |
|
||||||
|
| [Antigravity (agy)](https://antigravity.google/) | `agy` | Skills-based integration; skills are installed automatically |
|
||||||
|
| [Auggie CLI](https://docs.augmentcode.com/cli/overview) | `auggie` | |
|
||||||
|
| [Claude Code](https://www.anthropic.com/claude-code) | `claude` | Skills-based integration; installs skills in `.claude/skills` |
|
||||||
|
| [CodeBuddy CLI](https://www.codebuddy.ai/cli) | `codebuddy` | |
|
||||||
|
| [Codex CLI](https://github.com/openai/codex) | `codex` | Skills-based integration; installs skills into `.agents/skills` and invokes them as `$speckit-<command>` |
|
||||||
|
| [Cursor](https://cursor.sh/) | `cursor-agent` | |
|
||||||
|
| [Forge](https://forgecode.dev/) | `forge` | |
|
||||||
|
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `gemini` | |
|
||||||
|
| [GitHub Copilot](https://code.visualstudio.com/) | `copilot` | |
|
||||||
|
| [Goose](https://block.github.io/goose/) | `goose` | Uses YAML recipe format in `.goose/recipes/` |
|
||||||
|
| [IBM Bob](https://www.ibm.com/products/bob) | `bob` | IDE-based agent |
|
||||||
|
| [iFlow CLI](https://docs.iflow.cn/en/cli/quickstart) | `iflow` | |
|
||||||
|
| [Junie](https://junie.jetbrains.com/) | `junie` | |
|
||||||
|
| [Kilo Code](https://github.com/Kilo-Org/kilocode) | `kilocode` | |
|
||||||
|
| [Kimi Code](https://code.kimi.com/) | `kimi` | Skills-based integration; supports `--migrate-legacy` for dotted→hyphenated directory migration |
|
||||||
|
| [Kiro CLI](https://kiro.dev/docs/cli/) | `kiro-cli` | Alias: `--integration kiro` |
|
||||||
|
| [Mistral Vibe](https://github.com/mistralai/mistral-vibe) | `vibe` | |
|
||||||
|
| [opencode](https://opencode.ai/) | `opencode` | |
|
||||||
|
| [Pi Coding Agent](https://pi.dev) | `pi` | Pi doesn't have MCP support out of the box, so `taskstoissues` won't work as intended. MCP support can be added via [extensions](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent#extensions) |
|
||||||
|
| [Qoder CLI](https://qoder.com/cli) | `qodercli` | |
|
||||||
|
| [Qwen Code](https://github.com/QwenLM/qwen-code) | `qwen` | |
|
||||||
|
| [Roo Code](https://roocode.com/) | `roo` | |
|
||||||
|
| [SHAI (OVHcloud)](https://github.com/ovh/shai) | `shai` | |
|
||||||
|
| [Tabnine CLI](https://docs.tabnine.com/main/getting-started/tabnine-cli) | `tabnine` | |
|
||||||
|
| [Trae](https://www.trae.ai/) | `trae` | Skills-based integration; skills are installed automatically |
|
||||||
|
| [Windsurf](https://windsurf.com/) | `windsurf` | |
|
||||||
|
| Generic | `generic` | Bring your own agent — use `--integration generic --integration-options="--commands-dir <path>"` for AI coding agents not listed above |
|
||||||
|
|
||||||
|
## List Available Integrations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify integration list
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows all available integrations, which one is currently installed, and whether each requires a CLI tool or is IDE-based.
|
||||||
|
|
||||||
|
## Install an Integration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify integration install <key>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ------------------------ | ------------------------------------------------------------------------ |
|
||||||
|
| `--script sh\|ps` | Script type: `sh` (bash/zsh) or `ps` (PowerShell) |
|
||||||
|
| `--integration-options` | Integration-specific options (e.g. `--integration-options="--commands-dir .myagent/cmds"`) |
|
||||||
|
|
||||||
|
Installs the specified integration into the current project. Fails if another integration is already installed — use `switch` instead. If the installation fails partway through, it automatically rolls back to a clean state.
|
||||||
|
|
||||||
|
> **Note:** All integration management commands require a project already initialized with `specify init`. To start a new project with a specific agent, use `specify init <project> --integration <key>` instead.
|
||||||
|
|
||||||
|
## Uninstall an Integration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify integration uninstall [<key>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| --------- | --------------------------------------------------- |
|
||||||
|
| `--force` | Remove files even if they have been modified |
|
||||||
|
|
||||||
|
Uninstalls the current integration (or the specified one). Spec Kit tracks every file created during install along with a SHA-256 hash of the original content:
|
||||||
|
|
||||||
|
- **Unmodified files** are removed automatically.
|
||||||
|
- **Modified files** (where you've made manual edits) are preserved so your customizations are not lost.
|
||||||
|
- Use `--force` to remove all integration files regardless of modifications.
|
||||||
|
|
||||||
|
## Switch to a Different Integration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify integration switch <key>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ------------------------ | ------------------------------------------------------------------------ |
|
||||||
|
| `--script sh\|ps` | Script type: `sh` (bash/zsh) or `ps` (PowerShell) |
|
||||||
|
| `--force` | Force removal of modified files during uninstall |
|
||||||
|
| `--integration-options` | Options for the target integration |
|
||||||
|
|
||||||
|
Equivalent to running `uninstall` followed by `install` in a single step.
|
||||||
|
|
||||||
|
## Upgrade an Integration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify integration upgrade [<key>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ------------------------ | ------------------------------------------------------------------------ |
|
||||||
|
| `--force` | Overwrite files even if they have been modified |
|
||||||
|
| `--script sh\|ps` | Script type: `sh` (bash/zsh) or `ps` (PowerShell) |
|
||||||
|
| `--integration-options` | Options for the integration |
|
||||||
|
|
||||||
|
Reinstalls the current integration with updated templates and commands (e.g., after upgrading Spec Kit). Defaults to the currently installed integration; if a key is provided, it must match the installed one — otherwise the command fails and suggests using `switch` instead. Detects locally modified files and blocks the upgrade unless `--force` is used. Stale files from the previous install that are no longer needed are removed automatically.
|
||||||
|
|
||||||
|
## Integration-Specific Options
|
||||||
|
|
||||||
|
Some integrations accept additional options via `--integration-options`:
|
||||||
|
|
||||||
|
| Integration | Option | Description |
|
||||||
|
| ----------- | ------------------- | -------------------------------------------------------------- |
|
||||||
|
| `generic` | `--commands-dir` | Required. Directory for command files |
|
||||||
|
| `kimi` | `--migrate-legacy` | Migrate legacy dotted skill directories to hyphenated format |
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify integration install generic --integration-options="--commands-dir .myagent/cmds"
|
||||||
|
```
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### Can I use multiple integrations at the same time?
|
||||||
|
|
||||||
|
No. Only one AI coding agent integration can be installed per project. Use `specify integration switch <key>` to change to a different AI coding agent.
|
||||||
|
|
||||||
|
### What happens to my changes when I uninstall or switch?
|
||||||
|
|
||||||
|
Files you've modified are preserved automatically. Only unmodified files (matching their original SHA-256 hash) are removed. Use `--force` to override this.
|
||||||
|
|
||||||
|
### How do I know which key to use?
|
||||||
|
|
||||||
|
Run `specify integration list` to see all available integrations with their keys, or check the [Supported AI Coding Agents](#supported-ai-coding-agents) table above.
|
||||||
|
|
||||||
|
### Do I need the AI coding agent installed to use an integration?
|
||||||
|
|
||||||
|
CLI-based integrations (like Claude Code, Gemini CLI) require the tool to be installed. IDE-based integrations (like Windsurf, Cursor) work through the IDE itself. Some agents like GitHub Copilot support both IDE and CLI usage. `specify integration list` shows which type each integration is.
|
||||||
|
|
||||||
|
### When should I use `upgrade` vs `switch`?
|
||||||
|
|
||||||
|
Use `upgrade` when you've upgraded Spec Kit and want to refresh the same integration's templates. Use `switch` when you want to change to a different AI coding agent.
|
||||||
33
docs/reference/overview.md
Normal file
33
docs/reference/overview.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# CLI Reference
|
||||||
|
|
||||||
|
The Specify CLI (`specify`) manages the full lifecycle of Spec-Driven Development — from project initialization to workflow automation.
|
||||||
|
|
||||||
|
## Core Commands
|
||||||
|
|
||||||
|
The foundational commands for creating and managing Spec Kit projects. Initialize a new project with the necessary directory structure, templates, and scripts. Verify that your system has the required tools installed. Check version and system information.
|
||||||
|
|
||||||
|
[Core Commands reference →](core.md)
|
||||||
|
|
||||||
|
## Integrations
|
||||||
|
|
||||||
|
Integrations connect Spec Kit to your AI coding agent. Each integration sets up the appropriate command files, context rules, and directory structures for a specific agent. Only one integration is active per project at a time, and you can switch between them at any point.
|
||||||
|
|
||||||
|
[Integrations reference →](integrations.md)
|
||||||
|
|
||||||
|
## Extensions
|
||||||
|
|
||||||
|
Extensions add new capabilities to Spec Kit — domain-specific commands, external tool integrations, quality gates, and more. They are discovered through catalogs and can be installed, updated, enabled, disabled, or removed independently. Multiple extensions can coexist in a single project.
|
||||||
|
|
||||||
|
[Extensions reference →](extensions.md)
|
||||||
|
|
||||||
|
## Presets
|
||||||
|
|
||||||
|
Presets customize how Spec Kit works — overriding command files, template files, and script files without changing any tooling. They let you enforce organizational standards, adapt the workflow to your methodology, or localize the entire experience. Multiple presets can be stacked with priority ordering to layer customizations.
|
||||||
|
|
||||||
|
[Presets reference →](presets.md)
|
||||||
|
|
||||||
|
## Workflows
|
||||||
|
|
||||||
|
Workflows automate multi-step Spec-Driven Development processes into repeatable sequences. They chain commands, prompts, shell steps, and human checkpoints together, with support for conditional logic, loops, fan-out/fan-in, and the ability to pause and resume from the exact point of interruption.
|
||||||
|
|
||||||
|
[Workflows reference →](workflows.md)
|
||||||
224
docs/reference/presets.md
Normal file
224
docs/reference/presets.md
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
# Presets
|
||||||
|
|
||||||
|
Presets customize how Spec Kit works — overriding templates, commands, and terminology without changing any tooling. They let you enforce organizational standards, adapt the workflow to your methodology, or localize the entire experience. Multiple presets can be stacked with priority ordering.
|
||||||
|
|
||||||
|
## Search Available Presets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset search [query]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ---------- | -------------------- |
|
||||||
|
| `--tag` | Filter by tag |
|
||||||
|
| `--author` | Filter by author |
|
||||||
|
|
||||||
|
Searches all active catalogs for presets matching the query. Without a query, lists all available presets.
|
||||||
|
|
||||||
|
## Install a Preset
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset add [<preset_id>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ---------------- | -------------------------------------------------------- |
|
||||||
|
| `--dev <path>` | Install from a local directory (for development) |
|
||||||
|
| `--from <url>` | Install from a custom URL instead of the catalog |
|
||||||
|
| `--priority <N>` | Resolution priority (default: 10; lower = higher precedence) |
|
||||||
|
|
||||||
|
Installs a preset from the catalog, a URL, or a local directory. Preset commands are automatically registered with the currently installed AI coding agent integration.
|
||||||
|
|
||||||
|
> **Note:** All preset commands require a project already initialized with `specify init`.
|
||||||
|
|
||||||
|
## Remove a Preset
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset remove <preset_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes an installed preset and cleans up its registered commands.
|
||||||
|
|
||||||
|
## List Installed Presets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset list
|
||||||
|
```
|
||||||
|
|
||||||
|
Lists installed presets with their versions, descriptions, template counts, and current status.
|
||||||
|
|
||||||
|
## Preset Info
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset info <preset_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows detailed information about an installed or available preset, including its templates, metadata, and tags.
|
||||||
|
|
||||||
|
## Resolve a File
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset resolve <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows which file will be used for a given name by tracing the full resolution stack. Useful for debugging when multiple presets provide the same file.
|
||||||
|
|
||||||
|
## Enable / Disable a Preset
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset enable <preset_id>
|
||||||
|
specify preset disable <preset_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Disable a preset without removing it. Disabled presets are skipped during file resolution but their commands remain registered. Re-enable with `enable`.
|
||||||
|
|
||||||
|
## Set Preset Priority
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset set-priority <preset_id> <priority>
|
||||||
|
```
|
||||||
|
|
||||||
|
Changes the resolution priority of an installed preset. Lower numbers take precedence. When multiple presets provide the same file, the one with the lowest priority number wins.
|
||||||
|
|
||||||
|
## Catalog Management
|
||||||
|
|
||||||
|
Preset catalogs control where `search` and `add` look for presets. Catalogs are checked in priority order (lower number = higher precedence).
|
||||||
|
|
||||||
|
### List Catalogs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset catalog list
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows all active catalogs with their priorities and install permissions.
|
||||||
|
|
||||||
|
### Add a Catalog
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset catalog add <url>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| -------------------------------------------- | -------------------------------------------------- |
|
||||||
|
| `--name <name>` | Required. Unique name for the catalog |
|
||||||
|
| `--priority <N>` | Priority (default: 10; lower = higher precedence) |
|
||||||
|
| `--install-allowed / --no-install-allowed` | Whether presets can be installed from this catalog (default: discovery only) |
|
||||||
|
| `--description <text>` | Optional description |
|
||||||
|
|
||||||
|
Adds a catalog to the project's `.specify/preset-catalogs.yml`.
|
||||||
|
|
||||||
|
### Remove a Catalog
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset catalog remove <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes a catalog from the project configuration.
|
||||||
|
|
||||||
|
### Catalog Resolution Order
|
||||||
|
|
||||||
|
Catalogs are resolved in this order (first match wins):
|
||||||
|
|
||||||
|
1. **Environment variable** — `SPECKIT_PRESET_CATALOG_URL` overrides all catalogs
|
||||||
|
2. **Project config** — `.specify/preset-catalogs.yml`
|
||||||
|
3. **User config** — `~/.specify/preset-catalogs.yml`
|
||||||
|
4. **Built-in defaults** — official catalog + community catalog
|
||||||
|
|
||||||
|
Example `.specify/preset-catalogs.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
catalogs:
|
||||||
|
- name: "my-org-presets"
|
||||||
|
url: "https://example.com/preset-catalog.json"
|
||||||
|
priority: 5
|
||||||
|
install_allowed: true
|
||||||
|
description: "Our approved presets"
|
||||||
|
```
|
||||||
|
|
||||||
|
## File Resolution
|
||||||
|
|
||||||
|
Presets can provide command files, template files (like `plan-template.md`), and script files. These are resolved at runtime using a **replace** strategy — the first match in the priority stack wins and is used entirely. Each file is looked up independently, so different files can come from different layers.
|
||||||
|
|
||||||
|
> **Note:** Additional composition strategies (`append`, `prepend`, `wrap`) are planned for a future release.
|
||||||
|
|
||||||
|
The resolution stack, from highest to lowest precedence:
|
||||||
|
|
||||||
|
1. **Project-local overrides** — `.specify/templates/overrides/`
|
||||||
|
2. **Installed presets** — sorted by priority (lower = checked first)
|
||||||
|
3. **Installed extensions** — sorted by priority
|
||||||
|
4. **Spec Kit core** — `.specify/templates/`
|
||||||
|
|
||||||
|
Commands are registered at install time (not resolved through the stack at runtime).
|
||||||
|
|
||||||
|
### Resolution Stack
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
subgraph stack [" "]
|
||||||
|
direction TB
|
||||||
|
A["⬆ Highest precedence<br/><br/>1. Project-local overrides<br/>.specify/templates/overrides/"]
|
||||||
|
B["2. Presets — by priority<br/>.specify/presets/‹id›/"]
|
||||||
|
C["3. Extensions — by priority<br/>.specify/extensions/‹id›/"]
|
||||||
|
D["4. Spec Kit core<br/>.specify/templates/<br/><br/>⬇ Lowest precedence"]
|
||||||
|
end
|
||||||
|
|
||||||
|
A --> B --> C --> D
|
||||||
|
|
||||||
|
style A fill:#4a9,color:#fff
|
||||||
|
style B fill:#49a,color:#fff
|
||||||
|
style C fill:#a94,color:#fff
|
||||||
|
style D fill:#999,color:#fff
|
||||||
|
```
|
||||||
|
|
||||||
|
Within each layer, files are organized by type:
|
||||||
|
|
||||||
|
| Type | Subdirectory | Override path |
|
||||||
|
| --------- | -------------- | ------------------------------------------ |
|
||||||
|
| Templates | `templates/` | `.specify/templates/overrides/` |
|
||||||
|
| Commands | `commands/` | `.specify/templates/overrides/` |
|
||||||
|
| Scripts | `scripts/` | `.specify/templates/overrides/scripts/` |
|
||||||
|
|
||||||
|
### Resolution in Action
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
A["File requested:<br/>plan-template.md"] --> B{"Project-local override?"}
|
||||||
|
B -- Found --> Z["✓ Use this file"]
|
||||||
|
B -- Not found --> C{"Preset: compliance<br/>(priority 5)"}
|
||||||
|
C -- Found --> Z
|
||||||
|
C -- Not found --> D{"Preset: team-workflow<br/>(priority 10)"}
|
||||||
|
D -- Found --> Z
|
||||||
|
D -- Not found --> E{"Extension files?"}
|
||||||
|
E -- Found --> Z
|
||||||
|
E -- Not found --> F["Spec Kit core"]
|
||||||
|
F --> Z
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify preset add compliance --priority 5
|
||||||
|
specify preset add team-workflow --priority 10
|
||||||
|
```
|
||||||
|
|
||||||
|
For any file that both provide, `compliance` wins (priority 5 < 10). For files only one provides, that one is used. For files neither provides, the core default is used.
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### Can I use multiple presets at the same time?
|
||||||
|
|
||||||
|
Yes. Presets stack by priority — each file is resolved independently from the highest-priority source that provides it. Use `specify preset set-priority` to control the order.
|
||||||
|
|
||||||
|
### How do I see which file is actually being used?
|
||||||
|
|
||||||
|
Run `specify preset resolve <name>` to trace the resolution stack and see which file wins.
|
||||||
|
|
||||||
|
### What's the difference between disabling and removing a preset?
|
||||||
|
|
||||||
|
**Disabling** (`specify preset disable`) keeps the preset installed but excludes its files from the resolution stack. Commands the preset registered remain available in your AI coding agent. This is useful for temporarily testing behavior without a preset, or comparing output with and without it. Re-enable anytime with `specify preset enable`.
|
||||||
|
|
||||||
|
**Removing** (`specify preset remove`) fully uninstalls the preset — deletes its files, unregisters its commands from your AI coding agent, and removes it from the registry.
|
||||||
|
|
||||||
|
### Who maintains presets?
|
||||||
|
|
||||||
|
Most presets are independently created and maintained by their respective authors. The Spec Kit maintainers do not review, audit, endorse, or support preset code. Review a preset's source code before installing and use at your own discretion. For issues with a specific preset, contact its author or file an issue on the preset's repository.
|
||||||
289
docs/reference/workflows.md
Normal file
289
docs/reference/workflows.md
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
# Workflows
|
||||||
|
|
||||||
|
Workflows automate multi-step Spec-Driven Development processes — chaining commands, prompts, shell steps, and human checkpoints into repeatable sequences. They support conditional logic, loops, fan-out/fan-in, and can be paused and resumed from the exact point of interruption.
|
||||||
|
|
||||||
|
## Run a Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow run <source>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ------------------- | -------------------------------------------------------- |
|
||||||
|
| `-i` / `--input` | Pass input values as `key=value` (repeatable) |
|
||||||
|
|
||||||
|
Runs a workflow from a catalog ID, URL, or local file path. Inputs declared by the workflow can be provided via `--input` or will be prompted interactively.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow run speckit -i spec="Build a kanban board with drag-and-drop task management" -i scope=full
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** All workflow commands require a project already initialized with `specify init`.
|
||||||
|
|
||||||
|
## Resume a Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow resume <run_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Resumes a paused or failed workflow run from the exact step where it stopped. Useful after responding to a gate step or fixing an issue that caused a failure.
|
||||||
|
|
||||||
|
## Workflow Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow status [<run_id>]
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows the status of a specific run, or lists all runs if no ID is given. Run states: `created`, `running`, `completed`, `paused`, `failed`, `aborted`.
|
||||||
|
|
||||||
|
## List Installed Workflows
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow list
|
||||||
|
```
|
||||||
|
|
||||||
|
Lists workflows installed in the current project.
|
||||||
|
|
||||||
|
## Install a Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow add <source>
|
||||||
|
```
|
||||||
|
|
||||||
|
Installs a workflow from the catalog, a URL (HTTPS required), or a local file path.
|
||||||
|
|
||||||
|
## Remove a Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow remove <workflow_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes an installed workflow from the project.
|
||||||
|
|
||||||
|
## Search Available Workflows
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow search [query]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| ------- | --------------- |
|
||||||
|
| `--tag` | Filter by tag |
|
||||||
|
|
||||||
|
Searches all active catalogs for workflows matching the query.
|
||||||
|
|
||||||
|
## Workflow Info
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow info <workflow_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows detailed information about a workflow, including its steps, inputs, and requirements.
|
||||||
|
|
||||||
|
## Catalog Management
|
||||||
|
|
||||||
|
Workflow catalogs control where `search` and `add` look for workflows. Catalogs are checked in priority order.
|
||||||
|
|
||||||
|
### List Catalogs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow catalog list
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows all active catalog sources.
|
||||||
|
|
||||||
|
### Add a Catalog
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow catalog add <url>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
| --------------- | -------------------------------- |
|
||||||
|
| `--name <name>` | Optional name for the catalog |
|
||||||
|
|
||||||
|
Adds a custom catalog URL to the project's `.specify/workflow-catalogs.yml`.
|
||||||
|
|
||||||
|
### Remove a Catalog
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow catalog remove <index>
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes a catalog by its index in the catalog list.
|
||||||
|
|
||||||
|
### Catalog Resolution Order
|
||||||
|
|
||||||
|
Catalogs are resolved in this order (first match wins):
|
||||||
|
|
||||||
|
1. **Environment variable** — `SPECKIT_WORKFLOW_CATALOG_URL` overrides all catalogs
|
||||||
|
2. **Project config** — `.specify/workflow-catalogs.yml`
|
||||||
|
3. **User config** — `~/.specify/workflow-catalogs.yml`
|
||||||
|
4. **Built-in defaults** — official catalog + community catalog
|
||||||
|
|
||||||
|
## Workflow Definition
|
||||||
|
|
||||||
|
Workflows are defined in YAML files. Here is the built-in **Full SDD Cycle** workflow that ships with Spec Kit:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
schema_version: "1.0"
|
||||||
|
workflow:
|
||||||
|
id: "speckit"
|
||||||
|
name: "Full SDD Cycle"
|
||||||
|
version: "1.0.0"
|
||||||
|
author: "GitHub"
|
||||||
|
description: "Runs specify → plan → tasks → implement with review gates"
|
||||||
|
|
||||||
|
requires:
|
||||||
|
speckit_version: ">=0.7.2"
|
||||||
|
integrations:
|
||||||
|
any: ["copilot", "claude", "gemini"]
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
spec:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
prompt: "Describe what you want to build"
|
||||||
|
integration:
|
||||||
|
type: string
|
||||||
|
default: "copilot"
|
||||||
|
prompt: "Integration to use (e.g. claude, copilot, gemini)"
|
||||||
|
scope:
|
||||||
|
type: string
|
||||||
|
default: "full"
|
||||||
|
enum: ["full", "backend-only", "frontend-only"]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- id: specify
|
||||||
|
command: speckit.specify
|
||||||
|
integration: "{{ inputs.integration }}"
|
||||||
|
input:
|
||||||
|
args: "{{ inputs.spec }}"
|
||||||
|
|
||||||
|
- id: review-spec
|
||||||
|
type: gate
|
||||||
|
message: "Review the generated spec before planning."
|
||||||
|
options: [approve, reject]
|
||||||
|
on_reject: abort
|
||||||
|
|
||||||
|
- id: plan
|
||||||
|
command: speckit.plan
|
||||||
|
integration: "{{ inputs.integration }}"
|
||||||
|
input:
|
||||||
|
args: "{{ inputs.spec }}"
|
||||||
|
|
||||||
|
- id: review-plan
|
||||||
|
type: gate
|
||||||
|
message: "Review the plan before generating tasks."
|
||||||
|
options: [approve, reject]
|
||||||
|
on_reject: abort
|
||||||
|
|
||||||
|
- id: tasks
|
||||||
|
command: speckit.tasks
|
||||||
|
integration: "{{ inputs.integration }}"
|
||||||
|
input:
|
||||||
|
args: "{{ inputs.spec }}"
|
||||||
|
|
||||||
|
- id: implement
|
||||||
|
command: speckit.implement
|
||||||
|
integration: "{{ inputs.integration }}"
|
||||||
|
input:
|
||||||
|
args: "{{ inputs.spec }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces the following execution flow:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
A["specify<br/>(command)"] --> B{"review-spec<br/>(gate)"}
|
||||||
|
B -- approve --> C["plan<br/>(command)"]
|
||||||
|
B -- reject --> X1["⏹ Abort"]
|
||||||
|
C --> D{"review-plan<br/>(gate)"}
|
||||||
|
D -- approve --> E["tasks<br/>(command)"]
|
||||||
|
D -- reject --> X2["⏹ Abort"]
|
||||||
|
E --> F["implement<br/>(command)"]
|
||||||
|
|
||||||
|
style A fill:#49a,color:#fff
|
||||||
|
style B fill:#a94,color:#fff
|
||||||
|
style C fill:#49a,color:#fff
|
||||||
|
style D fill:#a94,color:#fff
|
||||||
|
style E fill:#49a,color:#fff
|
||||||
|
style F fill:#49a,color:#fff
|
||||||
|
style X1 fill:#999,color:#fff
|
||||||
|
style X2 fill:#999,color:#fff
|
||||||
|
```
|
||||||
|
|
||||||
|
Run it with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
specify workflow run speckit -i spec="Build a kanban board with drag-and-drop task management"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step Types
|
||||||
|
|
||||||
|
| Type | Purpose |
|
||||||
|
| ------------ | ------------------------------------------------ |
|
||||||
|
| `command` | Invoke a Spec Kit command (e.g., `speckit.plan`) |
|
||||||
|
| `prompt` | Send an arbitrary prompt to the AI coding agent |
|
||||||
|
| `shell` | Execute a shell command and capture output |
|
||||||
|
| `gate` | Pause for human approval before continuing |
|
||||||
|
| `if` | Conditional branching (then/else) |
|
||||||
|
| `switch` | Multi-branch dispatch on an expression |
|
||||||
|
| `while` | Loop while a condition is true |
|
||||||
|
| `do-while` | Execute at least once, then loop on condition |
|
||||||
|
| `fan-out` | Dispatch a step for each item in a list |
|
||||||
|
| `fan-in` | Aggregate results from a fan-out step |
|
||||||
|
|
||||||
|
## Expressions
|
||||||
|
|
||||||
|
Steps can reference inputs and previous step outputs using `{{ expression }}` syntax:
|
||||||
|
|
||||||
|
| Namespace | Description |
|
||||||
|
| ------------------------------ | ------------------------------------ |
|
||||||
|
| `inputs.spec` | Workflow input values |
|
||||||
|
| `steps.specify.output.file` | Output from a previous step |
|
||||||
|
| `item` | Current item in a fan-out iteration |
|
||||||
|
|
||||||
|
Available filters: `default`, `join`, `contains`, `map`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
condition: "{{ steps.test.output.exit_code == 0 }}"
|
||||||
|
args: "{{ inputs.spec }}"
|
||||||
|
message: "{{ status | default('pending') }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Input Types
|
||||||
|
|
||||||
|
| Type | Coercion |
|
||||||
|
| --------- | ------------------------------------------------- |
|
||||||
|
| `string` | Pass-through |
|
||||||
|
| `number` | `"42"` → `42`, `"3.14"` → `3.14` |
|
||||||
|
| `boolean` | `"true"` / `"1"` / `"yes"` → `True` |
|
||||||
|
|
||||||
|
## State and Resume
|
||||||
|
|
||||||
|
Each workflow run persists its state at `.specify/workflows/runs/<run_id>/`:
|
||||||
|
|
||||||
|
- `state.json` — current run state and step progress
|
||||||
|
- `inputs.json` — resolved input values
|
||||||
|
- `log.jsonl` — step-by-step execution log
|
||||||
|
|
||||||
|
This enables `specify workflow resume` to continue from the exact step where a run was paused (e.g., at a gate) or failed.
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### What happens when a workflow hits a gate step?
|
||||||
|
|
||||||
|
The workflow pauses and waits for human input. Run `specify workflow resume <run_id>` after reviewing to continue.
|
||||||
|
|
||||||
|
### Can I run the same workflow multiple times?
|
||||||
|
|
||||||
|
Yes. Each run gets a unique ID and its own state directory. Use `specify workflow status` to see all runs.
|
||||||
|
|
||||||
|
### Who maintains workflows?
|
||||||
|
|
||||||
|
Most workflows are independently created and maintained by their respective authors. The Spec Kit maintainers do not review, audit, endorse, or support workflow code. Review a workflow's source before installing and use at your own discretion.
|
||||||
16
docs/toc.yml
16
docs/toc.yml
@@ -12,6 +12,22 @@
|
|||||||
- name: Upgrade
|
- name: Upgrade
|
||||||
href: upgrade.md
|
href: upgrade.md
|
||||||
|
|
||||||
|
# Reference
|
||||||
|
- name: Reference
|
||||||
|
items:
|
||||||
|
- name: Overview
|
||||||
|
href: reference/overview.md
|
||||||
|
- name: Core Commands
|
||||||
|
href: reference/core.md
|
||||||
|
- name: Integrations
|
||||||
|
href: reference/integrations.md
|
||||||
|
- name: Extensions
|
||||||
|
href: reference/extensions.md
|
||||||
|
- name: Presets
|
||||||
|
href: reference/presets.md
|
||||||
|
- name: Workflows
|
||||||
|
href: reference/workflows.md
|
||||||
|
|
||||||
# Development workflows
|
# Development workflows
|
||||||
- name: Development
|
- name: Development
|
||||||
items:
|
items:
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ Run this inside your project directory:
|
|||||||
specify init --here --force --ai <your-agent>
|
specify init --here --force --ai <your-agent>
|
||||||
```
|
```
|
||||||
|
|
||||||
Replace `<your-agent>` with your AI assistant. Refer to this list of [Supported AI Agents](../README.md#-supported-ai-agents)
|
Replace `<your-agent>` with your AI coding agent. Refer to this list of [Supported AI Coding Agent Integrations](reference/integrations.md)
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
@@ -292,7 +292,7 @@ This tells Spec Kit which feature directory to use when creating specs, plans, a
|
|||||||
```bash
|
```bash
|
||||||
ls -la .claude/commands/ # Claude Code
|
ls -la .claude/commands/ # Claude Code
|
||||||
ls -la .gemini/commands/ # Gemini
|
ls -la .gemini/commands/ # Gemini
|
||||||
ls -la .cursor/commands/ # Cursor
|
ls -la .cursor/skills/ # Cursor
|
||||||
ls -la .pi/prompts/ # Pi Coding Agent
|
ls -la .pi/prompts/ # Pi Coding Agent
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -401,7 +401,7 @@ The `specify` CLI tool is used for:
|
|||||||
- **Upgrades:** `specify init --here --force` to update templates and commands
|
- **Upgrades:** `specify init --here --force` to update templates and commands
|
||||||
- **Diagnostics:** `specify check` to verify tool installation
|
- **Diagnostics:** `specify check` to verify tool installation
|
||||||
|
|
||||||
Once you've run `specify init`, the slash commands (like `/speckit.specify`, `/speckit.plan`, etc.) are **permanently installed** in your project's agent folder (`.claude/`, `.github/prompts/`, `.pi/prompts/`, etc.). Your AI assistant reads these command files directly—no need to run `specify` again.
|
Once you've run `specify init`, the slash commands (like `/speckit.specify`, `/speckit.plan`, etc.) are **permanently installed** in your project's agent folder (`.claude/`, `.github/prompts/`, `.pi/prompts/`, etc.). Your AI coding agent reads these command files directly—no need to run `specify` again.
|
||||||
|
|
||||||
**If your agent isn't recognizing slash commands:**
|
**If your agent isn't recognizing slash commands:**
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ defaults: # Optional, default configuration values
|
|||||||
#### `hooks`
|
#### `hooks`
|
||||||
|
|
||||||
- **Type**: object
|
- **Type**: object
|
||||||
- **Keys**: Event names (e.g., `after_specify`, `after_plan`, `after_tasks`, `after_implement`, `before_commit`)
|
- **Keys**: Event names (e.g., `after_specify`, `after_plan`, `after_tasks`, `after_implement`, `before_analyze`)
|
||||||
- **Description**: Hooks that execute at lifecycle events
|
- **Description**: Hooks that execute at lifecycle events
|
||||||
- **Events**: Defined by core spec-kit commands
|
- **Events**: Defined by core spec-kit commands
|
||||||
|
|
||||||
@@ -559,8 +559,16 @@ Standard events (defined by core):
|
|||||||
- `after_tasks` - After task generation
|
- `after_tasks` - After task generation
|
||||||
- `before_implement` - Before implementation
|
- `before_implement` - Before implementation
|
||||||
- `after_implement` - After implementation
|
- `after_implement` - After implementation
|
||||||
- `before_commit` - Before git commit *(planned - not yet wired into core templates)*
|
- `before_analyze` - Before cross-artifact analysis
|
||||||
- `after_commit` - After git commit *(planned - not yet wired into core templates)*
|
- `after_analyze` - After cross-artifact analysis
|
||||||
|
- `before_checklist` - Before checklist generation
|
||||||
|
- `after_checklist` - After checklist generation
|
||||||
|
- `before_clarify` - Before spec clarification
|
||||||
|
- `after_clarify` - After spec clarification
|
||||||
|
- `before_constitution` - Before constitution update
|
||||||
|
- `after_constitution` - After constitution update
|
||||||
|
- `before_taskstoissues` - Before tasks-to-issues conversion
|
||||||
|
- `after_taskstoissues` - After tasks-to-issues conversion
|
||||||
|
|
||||||
### Hook Configuration
|
### Hook Configuration
|
||||||
|
|
||||||
|
|||||||
@@ -177,9 +177,9 @@ Compatibility requirements.
|
|||||||
|
|
||||||
What the extension provides.
|
What the extension provides.
|
||||||
|
|
||||||
**Required sub-fields**:
|
**Optional sub-fields**:
|
||||||
|
|
||||||
- `commands`: Array of command objects (must have at least one)
|
- `commands`: Array of command objects (at least one command or hook is required)
|
||||||
|
|
||||||
**Command object**:
|
**Command object**:
|
||||||
|
|
||||||
@@ -196,12 +196,19 @@ Integration hooks for automatic execution.
|
|||||||
|
|
||||||
Available hook points:
|
Available hook points:
|
||||||
|
|
||||||
- `after_tasks`: After `/speckit.tasks` completes
|
- `before_specify` / `after_specify`: Before/after specification generation
|
||||||
- `after_implement`: After `/speckit.implement` completes (future)
|
- `before_plan` / `after_plan`: Before/after implementation planning
|
||||||
|
- `before_tasks` / `after_tasks`: Before/after task generation
|
||||||
|
- `before_implement` / `after_implement`: Before/after implementation
|
||||||
|
- `before_analyze` / `after_analyze`: Before/after cross-artifact analysis
|
||||||
|
- `before_checklist` / `after_checklist`: Before/after checklist generation
|
||||||
|
- `before_clarify` / `after_clarify`: Before/after spec clarification
|
||||||
|
- `before_constitution` / `after_constitution`: Before/after constitution update
|
||||||
|
- `before_taskstoissues` / `after_taskstoissues`: Before/after tasks-to-issues conversion
|
||||||
|
|
||||||
Hook object:
|
Hook object:
|
||||||
|
|
||||||
- `command`: Command to execute (must be in `provides.commands`)
|
- `command`: Command to execute (typically from `provides.commands`, but can reference any registered command)
|
||||||
- `optional`: If true, prompt user before executing
|
- `optional`: If true, prompt user before executing
|
||||||
- `prompt`: Prompt text for optional hooks
|
- `prompt`: Prompt text for optional hooks
|
||||||
- `description`: Hook description
|
- `description`: Hook description
|
||||||
|
|||||||
@@ -403,8 +403,10 @@ settings:
|
|||||||
|
|
||||||
# Hook configuration
|
# Hook configuration
|
||||||
# Available events: before_specify, after_specify, before_plan, after_plan,
|
# Available events: before_specify, after_specify, before_plan, after_plan,
|
||||||
# before_tasks, after_tasks, before_implement, after_implement
|
# before_tasks, after_tasks, before_implement, after_implement,
|
||||||
# Planned (not yet wired into core templates): before_commit, after_commit
|
# before_analyze, after_analyze, before_checklist, after_checklist,
|
||||||
|
# before_clarify, after_clarify, before_constitution, after_constitution,
|
||||||
|
# before_taskstoissues, after_taskstoissues
|
||||||
hooks:
|
hooks:
|
||||||
after_tasks:
|
after_tasks:
|
||||||
- extension: jira
|
- extension: jira
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ specify extension search # Now uses your organization's catalog instead of the
|
|||||||
|
|
||||||
### Community Reference Catalog (`catalog.community.json`)
|
### Community Reference Catalog (`catalog.community.json`)
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Community extensions are independently created and maintained by their respective authors. GitHub and the Spec Kit maintainers may review pull requests that add entries to the community catalog for formatting, catalog structure, or policy compliance, but they do **not review, audit, endorse, or support the extension code itself**. Review extension source code before installation and use at your own discretion.
|
||||||
|
|
||||||
- **Purpose**: Browse available community-contributed extensions
|
- **Purpose**: Browse available community-contributed extensions
|
||||||
- **Status**: Active - contains extensions submitted by the community
|
- **Status**: Active - contains extensions submitted by the community
|
||||||
- **Location**: `extensions/catalog.community.json`
|
- **Location**: `extensions/catalog.community.json`
|
||||||
@@ -68,6 +71,11 @@ specify extension add <extension-name> --from https://github.com/org/spec-kit-ex
|
|||||||
|
|
||||||
## Available Community Extensions
|
## Available Community Extensions
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Community extensions are independently created and maintained by their respective authors. GitHub and the Spec Kit maintainers may review pull requests that add entries to the community catalog for formatting, catalog structure, or policy compliance, but they do **not review, audit, endorse, or support the extension code itself**. The Community Extensions website is also a third-party resource. Review extension source code before installation and use at your own discretion.
|
||||||
|
|
||||||
|
🔍 **Browse and search community extensions on the [Community Extensions website](https://speckit-community.github.io/extensions/).**
|
||||||
|
|
||||||
See the [Community Extensions](../README.md#-community-extensions) section in the main README for the full list of available community-contributed extensions.
|
See the [Community Extensions](../README.md#-community-extensions) section in the main README for the full list of available community-contributed extensions.
|
||||||
|
|
||||||
For the raw catalog data, see [`catalog.community.json`](catalog.community.json).
|
For the raw catalog data, see [`catalog.community.json`](catalog.community.json).
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,21 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.0",
|
||||||
"updated_at": "2026-03-10T00:00:00Z",
|
"updated_at": "2026-04-10T00:00:00Z",
|
||||||
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.json",
|
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.json",
|
||||||
"extensions": {
|
"extensions": {
|
||||||
"selftest": {
|
"git": {
|
||||||
"name": "Spec Kit Self-Test Utility",
|
"name": "Git Branching Workflow",
|
||||||
"id": "selftest",
|
"id": "git",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Verifies catalog extensions by programmatically walking through the discovery, installation, and registration lifecycle.",
|
"description": "Feature branch creation, numbering (sequential/timestamp), validation, and Git remote detection",
|
||||||
"author": "spec-kit-core",
|
"author": "spec-kit-core",
|
||||||
"repository": "https://github.com/github/spec-kit",
|
"repository": "https://github.com/github/spec-kit",
|
||||||
"download_url": "https://github.com/github/spec-kit/releases/download/selftest-v1.0.0/selftest.zip",
|
"bundled": true,
|
||||||
"tags": [
|
"tags": [
|
||||||
"testing",
|
"git",
|
||||||
"core",
|
"branching",
|
||||||
"utility"
|
"workflow",
|
||||||
|
"core"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
100
extensions/git/README.md
Normal file
100
extensions/git/README.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Git Branching Workflow Extension
|
||||||
|
|
||||||
|
Git repository initialization, feature branch creation, numbering (sequential/timestamp), validation, remote detection, and auto-commit for Spec Kit.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This extension provides Git operations as an optional, self-contained module. It manages:
|
||||||
|
|
||||||
|
- **Repository initialization** with configurable commit messages
|
||||||
|
- **Feature branch creation** with sequential (`001-feature-name`) or timestamp (`20260319-143022-feature-name`) numbering
|
||||||
|
- **Branch validation** to ensure branches follow naming conventions
|
||||||
|
- **Git remote detection** for GitHub integration (e.g., issue creation)
|
||||||
|
- **Auto-commit** after core commands (configurable per-command with custom messages)
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `speckit.git.initialize` | Initialize a Git repository with a configurable commit message |
|
||||||
|
| `speckit.git.feature` | Create a feature branch with sequential or timestamp numbering |
|
||||||
|
| `speckit.git.validate` | Validate current branch follows feature branch naming conventions |
|
||||||
|
| `speckit.git.remote` | Detect Git remote URL for GitHub integration |
|
||||||
|
| `speckit.git.commit` | Auto-commit changes (configurable per-command enable/disable and messages) |
|
||||||
|
|
||||||
|
## Hooks
|
||||||
|
|
||||||
|
| Event | Command | Optional | Description |
|
||||||
|
|-------|---------|----------|-------------|
|
||||||
|
| `before_constitution` | `speckit.git.initialize` | No | Init git repo before constitution |
|
||||||
|
| `before_specify` | `speckit.git.feature` | No | Create feature branch before specification |
|
||||||
|
| `before_clarify` | `speckit.git.commit` | Yes | Commit outstanding changes before clarification |
|
||||||
|
| `before_plan` | `speckit.git.commit` | Yes | Commit outstanding changes before planning |
|
||||||
|
| `before_tasks` | `speckit.git.commit` | Yes | Commit outstanding changes before task generation |
|
||||||
|
| `before_implement` | `speckit.git.commit` | Yes | Commit outstanding changes before implementation |
|
||||||
|
| `before_checklist` | `speckit.git.commit` | Yes | Commit outstanding changes before checklist |
|
||||||
|
| `before_analyze` | `speckit.git.commit` | Yes | Commit outstanding changes before analysis |
|
||||||
|
| `before_taskstoissues` | `speckit.git.commit` | Yes | Commit outstanding changes before issue sync |
|
||||||
|
| `after_constitution` | `speckit.git.commit` | Yes | Auto-commit after constitution update |
|
||||||
|
| `after_specify` | `speckit.git.commit` | Yes | Auto-commit after specification |
|
||||||
|
| `after_clarify` | `speckit.git.commit` | Yes | Auto-commit after clarification |
|
||||||
|
| `after_plan` | `speckit.git.commit` | Yes | Auto-commit after planning |
|
||||||
|
| `after_tasks` | `speckit.git.commit` | Yes | Auto-commit after task generation |
|
||||||
|
| `after_implement` | `speckit.git.commit` | Yes | Auto-commit after implementation |
|
||||||
|
| `after_checklist` | `speckit.git.commit` | Yes | Auto-commit after checklist |
|
||||||
|
| `after_analyze` | `speckit.git.commit` | Yes | Auto-commit after analysis |
|
||||||
|
| `after_taskstoissues` | `speckit.git.commit` | Yes | Auto-commit after issue sync |
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Configuration is stored in `.specify/extensions/git/git-config.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Branch numbering strategy: "sequential" or "timestamp"
|
||||||
|
branch_numbering: sequential
|
||||||
|
|
||||||
|
# Custom commit message for git init
|
||||||
|
init_commit_message: "[Spec Kit] Initial commit"
|
||||||
|
|
||||||
|
# Auto-commit per command (all disabled by default)
|
||||||
|
# Example: enable auto-commit after specify
|
||||||
|
auto_commit:
|
||||||
|
default: false
|
||||||
|
after_specify:
|
||||||
|
enabled: true
|
||||||
|
message: "[Spec Kit] Add specification"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install the bundled git extension (no network required)
|
||||||
|
specify extension add git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Disabling
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Disable the git extension (spec creation continues without branching)
|
||||||
|
specify extension disable git
|
||||||
|
|
||||||
|
# Re-enable it
|
||||||
|
specify extension enable git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Graceful Degradation
|
||||||
|
|
||||||
|
When Git is not installed or the directory is not a Git repository:
|
||||||
|
- Spec directories are still created under `specs/`
|
||||||
|
- Branch creation is skipped with a warning
|
||||||
|
- Branch validation is skipped with a warning
|
||||||
|
- Remote detection returns empty results
|
||||||
|
|
||||||
|
## Scripts
|
||||||
|
|
||||||
|
The extension bundles cross-platform scripts:
|
||||||
|
|
||||||
|
- `scripts/bash/create-new-feature.sh` — Bash implementation
|
||||||
|
- `scripts/bash/git-common.sh` — Shared Git utilities (Bash)
|
||||||
|
- `scripts/powershell/create-new-feature.ps1` — PowerShell implementation
|
||||||
|
- `scripts/powershell/git-common.ps1` — Shared Git utilities (PowerShell)
|
||||||
48
extensions/git/commands/speckit.git.commit.md
Normal file
48
extensions/git/commands/speckit.git.commit.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
description: "Auto-commit changes after a Spec Kit command completes"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Auto-Commit Changes
|
||||||
|
|
||||||
|
Automatically stage and commit all changes after a Spec Kit command completes.
|
||||||
|
|
||||||
|
## Behavior
|
||||||
|
|
||||||
|
This command is invoked as a hook after (or before) core commands. It:
|
||||||
|
|
||||||
|
1. Determines the event name from the hook context (e.g., if invoked as an `after_specify` hook, the event is `after_specify`; if `before_plan`, the event is `before_plan`)
|
||||||
|
2. Checks `.specify/extensions/git/git-config.yml` for the `auto_commit` section
|
||||||
|
3. Looks up the specific event key to see if auto-commit is enabled
|
||||||
|
4. Falls back to `auto_commit.default` if no event-specific key exists
|
||||||
|
5. Uses the per-command `message` if configured, otherwise a default message
|
||||||
|
6. If enabled and there are uncommitted changes, runs `git add .` + `git commit`
|
||||||
|
|
||||||
|
## Execution
|
||||||
|
|
||||||
|
Determine the event name from the hook that triggered this command, then run the script:
|
||||||
|
|
||||||
|
- **Bash**: `.specify/extensions/git/scripts/bash/auto-commit.sh <event_name>`
|
||||||
|
- **PowerShell**: `.specify/extensions/git/scripts/powershell/auto-commit.ps1 <event_name>`
|
||||||
|
|
||||||
|
Replace `<event_name>` with the actual hook event (e.g., `after_specify`, `before_plan`, `after_implement`).
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
In `.specify/extensions/git/git-config.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
auto_commit:
|
||||||
|
default: false # Global toggle — set true to enable for all commands
|
||||||
|
after_specify:
|
||||||
|
enabled: true # Override per-command
|
||||||
|
message: "[Spec Kit] Add specification"
|
||||||
|
after_plan:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add implementation plan"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Graceful Degradation
|
||||||
|
|
||||||
|
- If Git is not available or the current directory is not a repository: skips with a warning
|
||||||
|
- If no config file exists: skips (disabled by default)
|
||||||
|
- If no changes to commit: skips with a message
|
||||||
67
extensions/git/commands/speckit.git.feature.md
Normal file
67
extensions/git/commands/speckit.git.feature.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
description: "Create a feature branch with sequential or timestamp numbering"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Create Feature Branch
|
||||||
|
|
||||||
|
Create and switch to a new git feature branch for the given specification. This command handles **branch creation only** — the spec directory and files are created by the core `/speckit.specify` workflow.
|
||||||
|
|
||||||
|
## User Input
|
||||||
|
|
||||||
|
```text
|
||||||
|
$ARGUMENTS
|
||||||
|
```
|
||||||
|
|
||||||
|
You **MUST** consider the user input before proceeding (if not empty).
|
||||||
|
|
||||||
|
## Environment Variable Override
|
||||||
|
|
||||||
|
If the user explicitly provided `GIT_BRANCH_NAME` (e.g., via environment variable, argument, or in their request), pass it through to the script by setting the `GIT_BRANCH_NAME` environment variable before invoking the script. When `GIT_BRANCH_NAME` is set:
|
||||||
|
- The script uses the exact value as the branch name, bypassing all prefix/suffix generation
|
||||||
|
- `--short-name`, `--number`, and `--timestamp` flags are ignored
|
||||||
|
- `FEATURE_NUM` is extracted from the name if it starts with a numeric prefix, otherwise set to the full branch name
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Verify Git is available by running `git rev-parse --is-inside-work-tree 2>/dev/null`
|
||||||
|
- If Git is not available, warn the user and skip branch creation
|
||||||
|
|
||||||
|
## Branch Numbering Mode
|
||||||
|
|
||||||
|
Determine the branch numbering strategy by checking configuration in this order:
|
||||||
|
|
||||||
|
1. Check `.specify/extensions/git/git-config.yml` for `branch_numbering` value
|
||||||
|
2. Check `.specify/init-options.json` for `branch_numbering` value (backward compatibility)
|
||||||
|
3. Default to `sequential` if neither exists
|
||||||
|
|
||||||
|
## Execution
|
||||||
|
|
||||||
|
Generate a concise short name (2-4 words) for the branch:
|
||||||
|
- Analyze the feature description and extract the most meaningful keywords
|
||||||
|
- Use action-noun format when possible (e.g., "add-user-auth", "fix-payment-bug")
|
||||||
|
- Preserve technical terms and acronyms (OAuth2, API, JWT, etc.)
|
||||||
|
|
||||||
|
Run the appropriate script based on your platform:
|
||||||
|
|
||||||
|
- **Bash**: `.specify/extensions/git/scripts/bash/create-new-feature.sh --json --short-name "<short-name>" "<feature description>"`
|
||||||
|
- **Bash (timestamp)**: `.specify/extensions/git/scripts/bash/create-new-feature.sh --json --timestamp --short-name "<short-name>" "<feature description>"`
|
||||||
|
- **PowerShell**: `.specify/extensions/git/scripts/powershell/create-new-feature.ps1 -Json -ShortName "<short-name>" "<feature description>"`
|
||||||
|
- **PowerShell (timestamp)**: `.specify/extensions/git/scripts/powershell/create-new-feature.ps1 -Json -Timestamp -ShortName "<short-name>" "<feature description>"`
|
||||||
|
|
||||||
|
**IMPORTANT**:
|
||||||
|
- Do NOT pass `--number` — the script determines the correct next number automatically
|
||||||
|
- Always include the JSON flag (`--json` for Bash, `-Json` for PowerShell) so the output can be parsed reliably
|
||||||
|
- You must only ever run this script once per feature
|
||||||
|
- The JSON output will contain `BRANCH_NAME` and `FEATURE_NUM`
|
||||||
|
|
||||||
|
## Graceful Degradation
|
||||||
|
|
||||||
|
If Git is not installed or the current directory is not a Git repository:
|
||||||
|
- Branch creation is skipped with a warning: `[specify] Warning: Git repository not detected; skipped branch creation`
|
||||||
|
- The script still outputs `BRANCH_NAME` and `FEATURE_NUM` so the caller can reference them
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
The script outputs JSON with:
|
||||||
|
- `BRANCH_NAME`: The branch name (e.g., `003-user-auth` or `20260319-143022-user-auth`)
|
||||||
|
- `FEATURE_NUM`: The numeric or timestamp prefix used
|
||||||
49
extensions/git/commands/speckit.git.initialize.md
Normal file
49
extensions/git/commands/speckit.git.initialize.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
description: "Initialize a Git repository with an initial commit"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Initialize Git Repository
|
||||||
|
|
||||||
|
Initialize a Git repository in the current project directory if one does not already exist.
|
||||||
|
|
||||||
|
## Execution
|
||||||
|
|
||||||
|
Run the appropriate script from the project root:
|
||||||
|
|
||||||
|
- **Bash**: `.specify/extensions/git/scripts/bash/initialize-repo.sh`
|
||||||
|
- **PowerShell**: `.specify/extensions/git/scripts/powershell/initialize-repo.ps1`
|
||||||
|
|
||||||
|
If the extension scripts are not found, fall back to:
|
||||||
|
- **Bash**: `git init && git add . && git commit -m "Initial commit from Specify template"`
|
||||||
|
- **PowerShell**: `git init; git add .; git commit -m "Initial commit from Specify template"`
|
||||||
|
|
||||||
|
The script handles all checks internally:
|
||||||
|
- Skips if Git is not available
|
||||||
|
- Skips if already inside a Git repository
|
||||||
|
- Runs `git init`, `git add .`, and `git commit` with an initial commit message
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
Replace the script to add project-specific Git initialization steps:
|
||||||
|
- Custom `.gitignore` templates
|
||||||
|
- Default branch naming (`git config init.defaultBranch`)
|
||||||
|
- Git LFS setup
|
||||||
|
- Git hooks installation
|
||||||
|
- Commit signing configuration
|
||||||
|
- Git Flow initialization
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
On success:
|
||||||
|
- `✓ Git repository initialized`
|
||||||
|
|
||||||
|
## Graceful Degradation
|
||||||
|
|
||||||
|
If Git is not installed:
|
||||||
|
- Warn the user
|
||||||
|
- Skip repository initialization
|
||||||
|
- The project continues to function without Git (specs can still be created under `specs/`)
|
||||||
|
|
||||||
|
If Git is installed but `git init`, `git add .`, or `git commit` fails:
|
||||||
|
- Surface the error to the user
|
||||||
|
- Stop this command rather than continuing with a partially initialized repository
|
||||||
45
extensions/git/commands/speckit.git.remote.md
Normal file
45
extensions/git/commands/speckit.git.remote.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
description: "Detect Git remote URL for GitHub integration"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Detect Git Remote URL
|
||||||
|
|
||||||
|
Detect the Git remote URL for integration with GitHub services (e.g., issue creation).
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Check if Git is available by running `git rev-parse --is-inside-work-tree 2>/dev/null`
|
||||||
|
- If Git is not available, output a warning and return empty:
|
||||||
|
```
|
||||||
|
[specify] Warning: Git repository not detected; cannot determine remote URL
|
||||||
|
```
|
||||||
|
|
||||||
|
## Execution
|
||||||
|
|
||||||
|
Run the following command to get the remote URL:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git config --get remote.origin.url
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
Parse the remote URL and determine:
|
||||||
|
|
||||||
|
1. **Repository owner**: Extract from the URL (e.g., `github` from `https://github.com/github/spec-kit.git`)
|
||||||
|
2. **Repository name**: Extract from the URL (e.g., `spec-kit` from `https://github.com/github/spec-kit.git`)
|
||||||
|
3. **Is GitHub**: Whether the remote points to a GitHub repository
|
||||||
|
|
||||||
|
Supported URL formats:
|
||||||
|
- HTTPS: `https://github.com/<owner>/<repo>.git`
|
||||||
|
- SSH: `git@github.com:<owner>/<repo>.git`
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> ONLY report a GitHub repository if the remote URL actually points to github.com.
|
||||||
|
> Do NOT assume the remote is GitHub if the URL format doesn't match.
|
||||||
|
|
||||||
|
## Graceful Degradation
|
||||||
|
|
||||||
|
If Git is not installed, the directory is not a Git repository, or no remote is configured:
|
||||||
|
- Return an empty result
|
||||||
|
- Do NOT error — other workflows should continue without Git remote information
|
||||||
49
extensions/git/commands/speckit.git.validate.md
Normal file
49
extensions/git/commands/speckit.git.validate.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
description: "Validate current branch follows feature branch naming conventions"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Validate Feature Branch
|
||||||
|
|
||||||
|
Validate that the current Git branch follows the expected feature branch naming conventions.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Check if Git is available by running `git rev-parse --is-inside-work-tree 2>/dev/null`
|
||||||
|
- If Git is not available, output a warning and skip validation:
|
||||||
|
```
|
||||||
|
[specify] Warning: Git repository not detected; skipped branch validation
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validation Rules
|
||||||
|
|
||||||
|
Get the current branch name:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git rev-parse --abbrev-ref HEAD
|
||||||
|
```
|
||||||
|
|
||||||
|
The branch name must match one of these patterns:
|
||||||
|
|
||||||
|
1. **Sequential**: `^[0-9]{3,}-` (e.g., `001-feature-name`, `042-fix-bug`, `1000-big-feature`)
|
||||||
|
2. **Timestamp**: `^[0-9]{8}-[0-9]{6}-` (e.g., `20260319-143022-feature-name`)
|
||||||
|
|
||||||
|
## Execution
|
||||||
|
|
||||||
|
If on a feature branch (matches either pattern):
|
||||||
|
- Output: `✓ On feature branch: <branch-name>`
|
||||||
|
- Check if the corresponding spec directory exists under `specs/`:
|
||||||
|
- For sequential branches, look for `specs/<prefix>-*` where prefix matches the numeric portion
|
||||||
|
- For timestamp branches, look for `specs/<prefix>-*` where prefix matches the `YYYYMMDD-HHMMSS` portion
|
||||||
|
- If spec directory exists: `✓ Spec directory found: <path>`
|
||||||
|
- If spec directory missing: `⚠ No spec directory found for prefix <prefix>`
|
||||||
|
|
||||||
|
If NOT on a feature branch:
|
||||||
|
- Output: `✗ Not on a feature branch. Current branch: <branch-name>`
|
||||||
|
- Output: `Feature branches should be named like: 001-feature-name or 20260319-143022-feature-name`
|
||||||
|
|
||||||
|
## Graceful Degradation
|
||||||
|
|
||||||
|
If Git is not installed or the directory is not a Git repository:
|
||||||
|
- Check the `SPECIFY_FEATURE` environment variable as a fallback
|
||||||
|
- If set, validate that value against the naming patterns
|
||||||
|
- If not set, skip validation with a warning
|
||||||
62
extensions/git/config-template.yml
Normal file
62
extensions/git/config-template.yml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Git Branching Workflow Extension Configuration
|
||||||
|
# Copied to .specify/extensions/git/git-config.yml on install
|
||||||
|
|
||||||
|
# Branch numbering strategy: "sequential" (001, 002, ...) or "timestamp" (YYYYMMDD-HHMMSS)
|
||||||
|
branch_numbering: sequential
|
||||||
|
|
||||||
|
# Commit message used by `git commit` during repository initialization
|
||||||
|
init_commit_message: "[Spec Kit] Initial commit"
|
||||||
|
|
||||||
|
# Auto-commit before/after core commands.
|
||||||
|
# Set "default" to enable for all commands, then override per-command.
|
||||||
|
# Each key can be true/false. Message is customizable per-command.
|
||||||
|
auto_commit:
|
||||||
|
default: false
|
||||||
|
before_clarify:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before clarification"
|
||||||
|
before_plan:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before planning"
|
||||||
|
before_tasks:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before task generation"
|
||||||
|
before_implement:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before implementation"
|
||||||
|
before_checklist:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before checklist"
|
||||||
|
before_analyze:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before analysis"
|
||||||
|
before_taskstoissues:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before issue sync"
|
||||||
|
after_constitution:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add project constitution"
|
||||||
|
after_specify:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add specification"
|
||||||
|
after_clarify:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Clarify specification"
|
||||||
|
after_plan:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add implementation plan"
|
||||||
|
after_tasks:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add tasks"
|
||||||
|
after_implement:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Implementation progress"
|
||||||
|
after_checklist:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add checklist"
|
||||||
|
after_analyze:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add analysis report"
|
||||||
|
after_taskstoissues:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Sync tasks to issues"
|
||||||
140
extensions/git/extension.yml
Normal file
140
extensions/git/extension.yml
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
schema_version: "1.0"
|
||||||
|
|
||||||
|
extension:
|
||||||
|
id: git
|
||||||
|
name: "Git Branching Workflow"
|
||||||
|
version: "1.0.0"
|
||||||
|
description: "Feature branch creation, numbering (sequential/timestamp), validation, and Git remote detection"
|
||||||
|
author: spec-kit-core
|
||||||
|
repository: https://github.com/github/spec-kit
|
||||||
|
license: MIT
|
||||||
|
|
||||||
|
requires:
|
||||||
|
speckit_version: ">=0.2.0"
|
||||||
|
tools:
|
||||||
|
- name: git
|
||||||
|
required: false
|
||||||
|
|
||||||
|
provides:
|
||||||
|
commands:
|
||||||
|
- name: speckit.git.feature
|
||||||
|
file: commands/speckit.git.feature.md
|
||||||
|
description: "Create a feature branch with sequential or timestamp numbering"
|
||||||
|
- name: speckit.git.validate
|
||||||
|
file: commands/speckit.git.validate.md
|
||||||
|
description: "Validate current branch follows feature branch naming conventions"
|
||||||
|
- name: speckit.git.remote
|
||||||
|
file: commands/speckit.git.remote.md
|
||||||
|
description: "Detect Git remote URL for GitHub integration"
|
||||||
|
- name: speckit.git.initialize
|
||||||
|
file: commands/speckit.git.initialize.md
|
||||||
|
description: "Initialize a Git repository with an initial commit"
|
||||||
|
- name: speckit.git.commit
|
||||||
|
file: commands/speckit.git.commit.md
|
||||||
|
description: "Auto-commit changes after a Spec Kit command completes"
|
||||||
|
|
||||||
|
config:
|
||||||
|
- name: "git-config.yml"
|
||||||
|
template: "config-template.yml"
|
||||||
|
description: "Git branching configuration"
|
||||||
|
required: false
|
||||||
|
|
||||||
|
hooks:
|
||||||
|
before_constitution:
|
||||||
|
command: speckit.git.initialize
|
||||||
|
optional: false
|
||||||
|
description: "Initialize Git repository before constitution setup"
|
||||||
|
before_specify:
|
||||||
|
command: speckit.git.feature
|
||||||
|
optional: false
|
||||||
|
description: "Create feature branch before specification"
|
||||||
|
before_clarify:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit outstanding changes before clarification?"
|
||||||
|
description: "Auto-commit before spec clarification"
|
||||||
|
before_plan:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit outstanding changes before planning?"
|
||||||
|
description: "Auto-commit before implementation planning"
|
||||||
|
before_tasks:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit outstanding changes before task generation?"
|
||||||
|
description: "Auto-commit before task generation"
|
||||||
|
before_implement:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit outstanding changes before implementation?"
|
||||||
|
description: "Auto-commit before implementation"
|
||||||
|
before_checklist:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit outstanding changes before checklist?"
|
||||||
|
description: "Auto-commit before checklist generation"
|
||||||
|
before_analyze:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit outstanding changes before analysis?"
|
||||||
|
description: "Auto-commit before analysis"
|
||||||
|
before_taskstoissues:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit outstanding changes before issue sync?"
|
||||||
|
description: "Auto-commit before tasks-to-issues conversion"
|
||||||
|
after_constitution:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit constitution changes?"
|
||||||
|
description: "Auto-commit after constitution update"
|
||||||
|
after_specify:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit specification changes?"
|
||||||
|
description: "Auto-commit after specification"
|
||||||
|
after_clarify:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit clarification changes?"
|
||||||
|
description: "Auto-commit after spec clarification"
|
||||||
|
after_plan:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit plan changes?"
|
||||||
|
description: "Auto-commit after implementation planning"
|
||||||
|
after_tasks:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit task changes?"
|
||||||
|
description: "Auto-commit after task generation"
|
||||||
|
after_implement:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit implementation changes?"
|
||||||
|
description: "Auto-commit after implementation"
|
||||||
|
after_checklist:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit checklist changes?"
|
||||||
|
description: "Auto-commit after checklist generation"
|
||||||
|
after_analyze:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit analysis results?"
|
||||||
|
description: "Auto-commit after analysis"
|
||||||
|
after_taskstoissues:
|
||||||
|
command: speckit.git.commit
|
||||||
|
optional: true
|
||||||
|
prompt: "Commit after syncing issues?"
|
||||||
|
description: "Auto-commit after tasks-to-issues conversion"
|
||||||
|
|
||||||
|
tags:
|
||||||
|
- "git"
|
||||||
|
- "branching"
|
||||||
|
- "workflow"
|
||||||
|
|
||||||
|
config:
|
||||||
|
defaults:
|
||||||
|
branch_numbering: sequential
|
||||||
|
init_commit_message: "[Spec Kit] Initial commit"
|
||||||
62
extensions/git/git-config.yml
Normal file
62
extensions/git/git-config.yml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Git Branching Workflow Extension Configuration
|
||||||
|
# Copied to .specify/extensions/git/git-config.yml on install
|
||||||
|
|
||||||
|
# Branch numbering strategy: "sequential" (001, 002, ...) or "timestamp" (YYYYMMDD-HHMMSS)
|
||||||
|
branch_numbering: sequential
|
||||||
|
|
||||||
|
# Commit message used by `git commit` during repository initialization
|
||||||
|
init_commit_message: "[Spec Kit] Initial commit"
|
||||||
|
|
||||||
|
# Auto-commit before/after core commands.
|
||||||
|
# Set "default" to enable for all commands, then override per-command.
|
||||||
|
# Each key can be true/false. Message is customizable per-command.
|
||||||
|
auto_commit:
|
||||||
|
default: false
|
||||||
|
before_clarify:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before clarification"
|
||||||
|
before_plan:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before planning"
|
||||||
|
before_tasks:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before task generation"
|
||||||
|
before_implement:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before implementation"
|
||||||
|
before_checklist:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before checklist"
|
||||||
|
before_analyze:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before analysis"
|
||||||
|
before_taskstoissues:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Save progress before issue sync"
|
||||||
|
after_constitution:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add project constitution"
|
||||||
|
after_specify:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add specification"
|
||||||
|
after_clarify:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Clarify specification"
|
||||||
|
after_plan:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add implementation plan"
|
||||||
|
after_tasks:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add tasks"
|
||||||
|
after_implement:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Implementation progress"
|
||||||
|
after_checklist:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add checklist"
|
||||||
|
after_analyze:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Add analysis report"
|
||||||
|
after_taskstoissues:
|
||||||
|
enabled: false
|
||||||
|
message: "[Spec Kit] Sync tasks to issues"
|
||||||
140
extensions/git/scripts/bash/auto-commit.sh
Executable file
140
extensions/git/scripts/bash/auto-commit.sh
Executable file
@@ -0,0 +1,140 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Git extension: auto-commit.sh
|
||||||
|
# Automatically commit changes after a Spec Kit command completes.
|
||||||
|
# Checks per-command config keys in git-config.yml before committing.
|
||||||
|
#
|
||||||
|
# Usage: auto-commit.sh <event_name>
|
||||||
|
# e.g.: auto-commit.sh after_specify
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
EVENT_NAME="${1:-}"
|
||||||
|
if [ -z "$EVENT_NAME" ]; then
|
||||||
|
echo "Usage: $0 <event_name>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
_find_project_root() {
|
||||||
|
local dir="$1"
|
||||||
|
while [ "$dir" != "/" ]; do
|
||||||
|
if [ -d "$dir/.specify" ] || [ -d "$dir/.git" ]; then
|
||||||
|
echo "$dir"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
dir="$(dirname "$dir")"
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
REPO_ROOT=$(_find_project_root "$SCRIPT_DIR") || REPO_ROOT="$(pwd)"
|
||||||
|
cd "$REPO_ROOT"
|
||||||
|
|
||||||
|
# Check if git is available
|
||||||
|
if ! command -v git >/dev/null 2>&1; then
|
||||||
|
echo "[specify] Warning: Git not found; skipped auto-commit" >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||||
|
echo "[specify] Warning: Not a Git repository; skipped auto-commit" >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Read per-command config from git-config.yml
|
||||||
|
_config_file="$REPO_ROOT/.specify/extensions/git/git-config.yml"
|
||||||
|
_enabled=false
|
||||||
|
_commit_msg=""
|
||||||
|
|
||||||
|
if [ -f "$_config_file" ]; then
|
||||||
|
# Parse the auto_commit section for this event.
|
||||||
|
# Look for auto_commit.<event_name>.enabled and .message
|
||||||
|
# Also check auto_commit.default as fallback.
|
||||||
|
_in_auto_commit=false
|
||||||
|
_in_event=false
|
||||||
|
_default_enabled=false
|
||||||
|
|
||||||
|
while IFS= read -r _line; do
|
||||||
|
# Detect auto_commit: section
|
||||||
|
if echo "$_line" | grep -q '^auto_commit:'; then
|
||||||
|
_in_auto_commit=true
|
||||||
|
_in_event=false
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit auto_commit section on next top-level key
|
||||||
|
if $_in_auto_commit && echo "$_line" | grep -Eq '^[a-z]'; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $_in_auto_commit; then
|
||||||
|
# Check default key
|
||||||
|
if echo "$_line" | grep -Eq "^[[:space:]]+default:[[:space:]]"; then
|
||||||
|
_val=$(echo "$_line" | sed 's/^[^:]*:[[:space:]]*//' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')
|
||||||
|
[ "$_val" = "true" ] && _default_enabled=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Detect our event subsection
|
||||||
|
if echo "$_line" | grep -Eq "^[[:space:]]+${EVENT_NAME}:"; then
|
||||||
|
_in_event=true
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||