Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions .github/workflows/scripts/create-release-packages.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,94 @@ function New-Skills {
}
}

# Create OpenClaw skills in .openclaw/skills/<name>/SKILL.md format.
# OpenClaw discovers skills as directories containing a SKILL.md file,
# invoked as speckit-<name> (e.g. speckit-specify).
function New-OpenClawSkills {
param(
[string]$SkillsDir,
[string]$ScriptVariant
)

$templates = Get-ChildItem -Path "templates/commands/*.md" -File -ErrorAction SilentlyContinue

foreach ($template in $templates) {
$name = [System.IO.Path]::GetFileNameWithoutExtension($template.Name)
$skillName = "speckit-$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__', 'generic'
$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" }
}

# Build SKILL.md with OpenClaw metadata block
$skillContent = "---`nname: `"$skillName`"`ndescription: `"$description`"`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,
Expand Down Expand Up @@ -478,6 +566,11 @@ function Build-Variant {
$cmdDir = Join-Path $baseDir ".iflow/commands"
Generate-Commands -Agent 'iflow' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
}
'openclaw' {
$skillsDir = Join-Path $baseDir ".openclaw/skills"
New-Item -ItemType Directory -Force -Path $skillsDir | Out-Null
New-OpenClawSkills -SkillsDir $skillsDir -ScriptVariant $Script
}
'generic' {
$cmdDir = Join-Path $baseDir ".speckit/commands"
Generate-Commands -Agent 'generic' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
Expand Down
73 changes: 73 additions & 0 deletions .github/workflows/scripts/create-release-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,79 @@ create_skills() {
done
}

# Create OpenClaw skills in .openclaw/skills/<name>/SKILL.md format.
# OpenClaw discovers skills as directories containing a SKILL.md file,
# invoked as speckit-<name> (e.g. speckit-specify).
create_openclaw_skills() {
local skills_dir="$1"
local script_variant="$2"

for template in templates/commands/*.md; do
[[ -f "$template" ]] || continue
local name
name=$(basename "$template" .md)
local skill_name="speckit-${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__/openclaw/g' | rewrite_paths)

# Strip existing frontmatter and prepend OpenClaw SKILL.md 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 'metadata:\n'
printf ' author: "github-spec-kit"\n'
printf ' source: "templates/commands/%s.md"\n' "$name"
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}"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ Community projects that extend, visualize, or build on Spec Kit:
| [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) | ✅ | |
| [OpenClaw](https://openclaw.ai) | ✅ | Persistent AI agent daemon; use `--ai openclaw --ai-skills` |
| [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) | ✅ | |
Expand Down
45 changes: 45 additions & 0 deletions templates/commands/skill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
name: speckit
description: Full Spec-Driven Development (SDD) workflow powered by github/spec-kit. Use speckit-specify to start a feature, then speckit-plan, speckit-tasks, and speckit-implement in sequence.
metadata:
author: github-spec-kit
source: https://github.com/github/spec-kit
version: 1.0.0
---

# Spec Kit — Spec-Driven Development

This skill provides the complete Spec-Driven Development workflow from [github/spec-kit](https://github.com/github/spec-kit).
Individual commands are available as separate skills in this directory — each one maps to a phase of the SDD process.

## Workflow Order

Always follow this sequence — never skip phases:

1. **speckit-constitution** — Establish project governing principles *(run once per project)*
2. **speckit-specify** — Turn a feature description into a structured spec
3. **speckit-clarify** — Resolve ambiguities before planning *(optional but recommended)*
4. **speckit-plan** — Create a phased technical implementation plan
5. **speckit-analyze** — Cross-artifact consistency check *(optional, run after tasks)*
6. **speckit-tasks** — Break the plan into ordered, executable tasks
7. **speckit-implement** — Execute tasks one by one
8. **speckit-checklist** — Post-implementation quality checklist

## Core Rules

- Read `.specify/memory/constitution.md` before every coding decision
- Show the spec summary to the user and wait for approval before planning
- Show task count to the user and wait for approval before implementing
- Use `.specify/scripts/bash/` (Linux/macOS) or `.specify/scripts/powershell/` (Windows) for all file and branch operations
- Never create, move, or delete files in `specs/` without explicit user instruction

## Key File Locations

| File | Purpose |
|------|---------|
| `.specify/memory/constitution.md` | Project governing principles — read before every decision |
| `specs/<feature>/spec.md` | Feature specification created by `speckit-specify` |
| `specs/<feature>/plan.md` | Implementation plan created by `speckit-plan` |
| `specs/<feature>/tasks.md` | Task breakdown created by `speckit-tasks` |
| `.specify/templates/` | Base templates for spec, plan, tasks, and checklist artifacts |
| `.specify/scripts/` | Automation scripts for branch and file management |
10 changes: 10 additions & 0 deletions templates/skill-file-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!--
NOTE: This file is intentionally not used as a runtime template.

The SKILL.md content is generated inline by `install_ai_skills()`, which is
the single source of truth for the SKILL file format.

This placeholder file exists only to document that there is no standalone
SKILL.md template. If you need to change the generated output, update
`install_ai_skills()` instead.
-->