Skip to content

Commit 0889635

Browse files
committed
Update with Windsurf support
1 parent 2825bb1 commit 0889635

File tree

6 files changed

+260
-15
lines changed

6 files changed

+260
-15
lines changed

.github/workflows/release.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181
cat > release_notes.md << EOF
8282
Template release ${{ steps.get_tag.outputs.new_version }}
8383
84-
Updated specification-driven development templates for GitHub Copilot, Claude Code, Gemini CLI, Cursor, Qwen, and opencode.
84+
Updated specification-driven development templates for GitHub Copilot, Claude Code, Gemini CLI, Cursor, Qwen, opencode, and Windsurf.
8585
8686
Now includes per-script variants for POSIX shell (sh) and PowerShell (ps).
8787
@@ -98,6 +98,8 @@ jobs:
9898
- spec-kit-template-opencode-ps-${{ steps.get_tag.outputs.new_version }}.zip
9999
- spec-kit-template-qwen-sh-${{ steps.get_tag.outputs.new_version }}.zip
100100
- spec-kit-template-qwen-ps-${{ steps.get_tag.outputs.new_version }}.zip
101+
- spec-kit-template-windsurf-sh-${{ steps.get_tag.outputs.new_version }}.zip
102+
- spec-kit-template-windsurf-ps-${{ steps.get_tag.outputs.new_version }}.zip
101103
EOF
102104
103105
echo "Generated release notes:"
@@ -122,6 +124,8 @@ jobs:
122124
spec-kit-template-opencode-ps-${{ steps.get_tag.outputs.new_version }}.zip \
123125
spec-kit-template-qwen-sh-${{ steps.get_tag.outputs.new_version }}.zip \
124126
spec-kit-template-qwen-ps-${{ steps.get_tag.outputs.new_version }}.zip \
127+
spec-kit-template-windsurf-sh-${{ steps.get_tag.outputs.new_version }}.zip \
128+
spec-kit-template-windsurf-ps-${{ steps.get_tag.outputs.new_version }}.zip \
125129
--title "Spec Kit Templates - $VERSION_NO_V" \
126130
--notes-file release_notes.md
127131
env:

.github/workflows/scripts/create-release-packages.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,16 @@ build_variant() {
154154
opencode)
155155
mkdir -p "$base_dir/.opencode/command"
156156
generate_commands opencode md "\$ARGUMENTS" "$base_dir/.opencode/command" "$script" ;;
157+
windsurf)
158+
mkdir -p "$base_dir/.windsurf/workflows"
159+
generate_commands windsurf md "\$ARGUMENTS" "$base_dir/.windsurf/workflows" "$script" ;;
157160
esac
158161
( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . )
159162
echo "Created spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip"
160163
}
161164

162165
# Determine agent list
163-
ALL_AGENTS=(claude gemini copilot cursor qwen opencode)
166+
ALL_AGENTS=(claude gemini copilot cursor qwen opencode windsurf)
164167
ALL_SCRIPTS=(sh ps)
165168

166169

AGENTS.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
# AGENTS.md
2+
3+
## About Spec Kit and Specify
4+
5+
**GitHub Spec Kit** is a comprehensive toolkit for implementing Spec-Driven Development (SDD) - a methodology that emphasizes creating clear specifications before implementation. The toolkit includes templates, scripts, and workflows that guide development teams through a structured approach to building software.
6+
7+
**Specify CLI** is the command-line interface that bootstraps projects with the Spec Kit framework. It sets up the necessary directory structures, templates, and AI agent integrations to support the Spec-Driven Development workflow.
8+
9+
The toolkit supports multiple AI coding assistants, allowing teams to use their preferred tools while maintaining consistent project structure and development practices.
10+
11+
---
12+
13+
## Adding New Agent Support
14+
15+
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.
16+
17+
### Overview
18+
19+
Specify supports multiple AI agents by generating agent-specific command files and directory structures when initializing projects. Each agent has its own conventions for:
20+
21+
- **Command file formats** (Markdown, TOML, etc.)
22+
- **Directory structures** (`.claude/commands/`, `.windsurf/workflows/`, etc.)
23+
- **Command invocation patterns** (slash commands, CLI tools, etc.)
24+
- **Argument passing conventions** (`$ARGUMENTS`, `{{args}}`, etc.)
25+
26+
### Current Supported Agents
27+
28+
| Agent | Directory | Format | CLI Tool | Description |
29+
|-------|-----------|---------|----------|-------------|
30+
| **Claude Code** | `.claude/commands/` | Markdown | `claude` | Anthropic's Claude Code CLI |
31+
| **Gemini CLI** | `.gemini/commands/` | TOML | `gemini` | Google's Gemini CLI |
32+
| **GitHub Copilot** | `.github/prompts/` | Markdown | N/A (IDE-based) | GitHub Copilot in VS Code |
33+
| **Cursor** | `.cursor/commands/` | Markdown | `cursor-agent` | Cursor CLI |
34+
| **Qwen Code** | `.qwen/commands/` | TOML | `qwen` | Alibaba's Qwen Code CLI |
35+
| **opencode** | `.opencode/command/` | Markdown | `opencode` | opencode CLI |
36+
| **Windsurf** | `.windsurf/workflows/` | Markdown | N/A (IDE-based) | Windsurf IDE workflows |
37+
38+
### Step-by-Step Integration Guide
39+
40+
Follow these steps to add a new agent (using Windsurf as an example):
41+
42+
#### 1. Update AI_CHOICES Constant
43+
44+
Add the new agent to the `AI_CHOICES` dictionary in `src/specify_cli/__init__.py`:
45+
46+
```python
47+
AI_CHOICES = {
48+
"copilot": "GitHub Copilot",
49+
"claude": "Claude Code",
50+
"gemini": "Gemini CLI",
51+
"cursor": "Cursor",
52+
"qwen": "Qwen Code",
53+
"opencode": "opencode",
54+
"windsurf": "Windsurf" # Add new agent here
55+
}
56+
```
57+
58+
#### 2. Update CLI Help Text
59+
60+
Update all help text and examples to include the new agent:
61+
62+
- Command option help: `--ai` parameter description
63+
- Function docstrings and examples
64+
- Error messages with agent lists
65+
66+
#### 3. Update Release Package Script
67+
68+
Modify `.github/workflows/scripts/create-release-packages.sh`:
69+
70+
##### Add to ALL_AGENTS array:
71+
```bash
72+
ALL_AGENTS=(claude gemini copilot cursor qwen opencode windsurf)
73+
```
74+
75+
##### Add case statement for directory structure:
76+
```bash
77+
case $agent in
78+
# ... existing cases ...
79+
windsurf)
80+
mkdir -p "$base_dir/.windsurf/workflows"
81+
generate_commands windsurf md "\$ARGUMENTS" "$base_dir/.windsurf/workflows" "$script" ;;
82+
esac
83+
```
84+
85+
#### 4. Update Agent Context Scripts
86+
87+
##### Bash script (`scripts/bash/update-agent-context.sh`):
88+
89+
Add file variable:
90+
```bash
91+
WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md"
92+
```
93+
94+
Add to case statement:
95+
```bash
96+
case "$AGENT_TYPE" in
97+
# ... existing cases ...
98+
windsurf) update_agent_file "$WINDSURF_FILE" "Windsurf" ;;
99+
"")
100+
# ... existing checks ...
101+
[ -f "$WINDSURF_FILE" ] && update_agent_file "$WINDSURF_FILE" "Windsurf";
102+
# Update default creation condition
103+
;;
104+
esac
105+
```
106+
107+
##### PowerShell script (`scripts/powershell/update-agent-context.ps1`):
108+
109+
Add file variable:
110+
```powershell
111+
$windsurfFile = Join-Path $repoRoot '.windsurf/rules/specify-rules.md'
112+
```
113+
114+
Add to switch statement:
115+
```powershell
116+
switch ($AgentType) {
117+
# ... existing cases ...
118+
'windsurf' { Update-AgentFile $windsurfFile 'Windsurf' }
119+
'' {
120+
foreach ($pair in @(
121+
# ... existing pairs ...
122+
@{file=$windsurfFile; name='Windsurf'}
123+
)) {
124+
if (Test-Path $pair.file) { Update-AgentFile $pair.file $pair.name }
125+
}
126+
# Update default creation condition
127+
}
128+
}
129+
```
130+
131+
#### 5. Update CLI Tool Checks (Optional)
132+
133+
For agents that require CLI tools, add checks in the `check()` command and agent validation:
134+
135+
```python
136+
# In check() command
137+
tracker.add("windsurf", "Windsurf IDE (optional)")
138+
windsurf_ok = check_tool_for_tracker("windsurf", "https://windsurf.com/", tracker)
139+
140+
# In init validation (only if CLI tool required)
141+
elif selected_ai == "windsurf":
142+
if not check_tool("windsurf", "Install from: https://windsurf.com/"):
143+
console.print("[red]Error:[/red] Windsurf CLI is required for Windsurf projects")
144+
agent_tool_missing = True
145+
```
146+
147+
**Note**: Skip CLI checks for IDE-based agents (Copilot, Windsurf).
148+
149+
## Agent Categories
150+
151+
### CLI-Based Agents
152+
Require a command-line tool to be installed:
153+
- **Claude Code**: `claude` CLI
154+
- **Gemini CLI**: `gemini` CLI
155+
- **Cursor**: `cursor-agent` CLI
156+
- **Qwen Code**: `qwen` CLI
157+
- **opencode**: `opencode` CLI
158+
159+
### IDE-Based Agents
160+
Work within integrated development environments:
161+
- **GitHub Copilot**: Built into VS Code/compatible editors
162+
- **Windsurf**: Built into Windsurf IDE
163+
164+
## Command File Formats
165+
166+
### Markdown Format
167+
Used by: Claude, Cursor, opencode, Windsurf
168+
169+
```markdown
170+
---
171+
description: "Command description"
172+
---
173+
174+
Command content with {SCRIPT} and $ARGUMENTS placeholders.
175+
```
176+
177+
### TOML Format
178+
Used by: Gemini, Qwen
179+
180+
```toml
181+
description = "Command description"
182+
183+
prompt = """
184+
Command content with {SCRIPT} and {{args}} placeholders.
185+
"""
186+
```
187+
188+
## Directory Conventions
189+
190+
- **CLI agents**: Usually `.<agent-name>/commands/`
191+
- **IDE agents**: Follow IDE-specific patterns:
192+
- Copilot: `.github/prompts/`
193+
- Cursor: `.cursor/commands/`
194+
- Windsurf: `.windsurf/workflows/`
195+
196+
## Argument Patterns
197+
198+
Different agents use different argument placeholders:
199+
- **Markdown/prompt-based**: `$ARGUMENTS`
200+
- **TOML-based**: `{{args}}`
201+
- **Script placeholders**: `{SCRIPT}` (replaced with actual script path)
202+
- **Agent placeholders**: `__AGENT__` (replaced with agent name)
203+
204+
## Testing New Agent Integration
205+
206+
1. **Build test**: Run package creation script locally
207+
2. **CLI test**: Test `specify init --ai <agent>` command
208+
3. **File generation**: Verify correct directory structure and files
209+
4. **Command validation**: Ensure generated commands work with the agent
210+
5. **Context update**: Test agent context update scripts
211+
212+
## Common Pitfalls
213+
214+
1. **Forgetting update scripts**: Both bash and PowerShell scripts must be updated
215+
2. **Missing CLI checks**: Only add for agents that actually have CLI tools
216+
3. **Wrong argument format**: Use correct placeholder format for each agent type
217+
4. **Directory naming**: Follow agent-specific conventions exactly
218+
5. **Help text inconsistency**: Update all user-facing text consistently
219+
220+
## Future Considerations
221+
222+
When adding new agents:
223+
- Consider the agent's native command/workflow patterns
224+
- Ensure compatibility with the Spec-Driven Development process
225+
- Document any special requirements or limitations
226+
- Update this guide with lessons learned
227+
228+
---
229+
230+
*This documentation should be updated whenever new agents are added to maintain accuracy and completeness.*

scripts/bash/update-agent-context.sh

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ REPO_ROOT=$(git rev-parse --show-toplevel)
44
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
55
FEATURE_DIR="$REPO_ROOT/specs/$CURRENT_BRANCH"
66
NEW_PLAN="$FEATURE_DIR/plan.md"
7-
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"; GEMINI_FILE="$REPO_ROOT/GEMINI.md"; COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"; CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc"; QWEN_FILE="$REPO_ROOT/QWEN.md"; AGENTS_FILE="$REPO_ROOT/AGENTS.md"
7+
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"; GEMINI_FILE="$REPO_ROOT/GEMINI.md"; COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"; CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc"; QWEN_FILE="$REPO_ROOT/QWEN.md"; AGENTS_FILE="$REPO_ROOT/AGENTS.md"; WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md"
88
AGENT_TYPE="$1"
99
[ -f "$NEW_PLAN" ] || { echo "ERROR: No plan.md found at $NEW_PLAN"; exit 1; }
1010
echo "=== Updating agent context files for feature $CURRENT_BRANCH ==="
@@ -54,13 +54,15 @@ case "$AGENT_TYPE" in
5454
cursor) update_agent_file "$CURSOR_FILE" "Cursor IDE" ;;
5555
qwen) update_agent_file "$QWEN_FILE" "Qwen Code" ;;
5656
opencode) update_agent_file "$AGENTS_FILE" "opencode" ;;
57+
windsurf) update_agent_file "$WINDSURF_FILE" "Windsurf" ;;
5758
"") [ -f "$CLAUDE_FILE" ] && update_agent_file "$CLAUDE_FILE" "Claude Code"; \
5859
[ -f "$GEMINI_FILE" ] && update_agent_file "$GEMINI_FILE" "Gemini CLI"; \
5960
[ -f "$COPILOT_FILE" ] && update_agent_file "$COPILOT_FILE" "GitHub Copilot"; \
6061
[ -f "$CURSOR_FILE" ] && update_agent_file "$CURSOR_FILE" "Cursor IDE"; \
6162
[ -f "$QWEN_FILE" ] && update_agent_file "$QWEN_FILE" "Qwen Code"; \
6263
[ -f "$AGENTS_FILE" ] && update_agent_file "$AGENTS_FILE" "opencode"; \
63-
if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ] && [ ! -f "$CURSOR_FILE" ] && [ ! -f "$QWEN_FILE" ] && [ ! -f "$AGENTS_FILE" ]; then update_agent_file "$CLAUDE_FILE" "Claude Code"; fi ;;
64-
*) echo "ERROR: Unknown agent type '$AGENT_TYPE' (expected claude|gemini|copilot|cursor|qwen|opencode)"; exit 1 ;;
64+
[ -f "$WINDSURF_FILE" ] && update_agent_file "$WINDSURF_FILE" "Windsurf"; \
65+
if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ] && [ ! -f "$CURSOR_FILE" ] && [ ! -f "$QWEN_FILE" ] && [ ! -f "$AGENTS_FILE" ] && [ ! -f "$WINDSURF_FILE" ]; then update_agent_file "$CLAUDE_FILE" "Claude Code"; fi ;;
66+
*) echo "ERROR: Unknown agent type '$AGENT_TYPE' (expected claude|gemini|copilot|cursor|qwen|opencode|windsurf)"; exit 1 ;;
6567
esac
66-
echo; echo "Summary of changes:"; [ -n "$NEW_LANG" ] && echo "- Added language: $NEW_LANG"; [ -n "$NEW_FRAMEWORK" ] && echo "- Added framework: $NEW_FRAMEWORK"; [ -n "$NEW_DB" ] && [ "$NEW_DB" != "N/A" ] && echo "- Added database: $NEW_DB"; echo; echo "Usage: $0 [claude|gemini|copilot|cursor|qwen|opencode]"
68+
echo; echo "Summary of changes:"; [ -n "$NEW_LANG" ] && echo "- Added language: $NEW_LANG"; [ -n "$NEW_FRAMEWORK" ] && echo "- Added framework: $NEW_FRAMEWORK"; [ -n "$NEW_DB" ] && [ "$NEW_DB" != "N/A" ] && echo "- Added database: $NEW_DB"; echo; echo "Usage: $0 [claude|gemini|copilot|cursor|qwen|opencode|windsurf]"

scripts/powershell/update-agent-context.ps1

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ $copilotFile = Join-Path $repoRoot '.github/copilot-instructions.md'
1515
$cursorFile = Join-Path $repoRoot '.cursor/rules/specify-rules.mdc'
1616
$qwenFile = Join-Path $repoRoot 'QWEN.md'
1717
$agentsFile = Join-Path $repoRoot 'AGENTS.md'
18+
$windsurfFile = Join-Path $repoRoot '.windsurf/rules/specify-rules.md'
1819

1920
Write-Output "=== Updating agent context files for feature $currentBranch ==="
2021

@@ -75,23 +76,25 @@ switch ($AgentType) {
7576
'cursor' { Update-AgentFile $cursorFile 'Cursor IDE' }
7677
'qwen' { Update-AgentFile $qwenFile 'Qwen Code' }
7778
'opencode' { Update-AgentFile $agentsFile 'opencode' }
79+
'windsurf' { Update-AgentFile $windsurfFile 'Windsurf' }
7880
'' {
7981
foreach ($pair in @(
8082
@{file=$claudeFile; name='Claude Code'},
8183
@{file=$geminiFile; name='Gemini CLI'},
8284
@{file=$copilotFile; name='GitHub Copilot'},
8385
@{file=$cursorFile; name='Cursor IDE'},
8486
@{file=$qwenFile; name='Qwen Code'},
85-
@{file=$agentsFile; name='opencode'}
87+
@{file=$agentsFile; name='opencode'},
88+
@{file=$windsurfFile; name='Windsurf'}
8689
)) {
8790
if (Test-Path $pair.file) { Update-AgentFile $pair.file $pair.name }
8891
}
89-
if (-not (Test-Path $claudeFile) -and -not (Test-Path $geminiFile) -and -not (Test-Path $copilotFile) -and -not (Test-Path $cursorFile) -and -not (Test-Path $qwenFile) -and -not (Test-Path $agentsFile)) {
92+
if (-not (Test-Path $claudeFile) -and -not (Test-Path $geminiFile) -and -not (Test-Path $copilotFile) -and -not (Test-Path $cursorFile) -and -not (Test-Path $qwenFile) -and -not (Test-Path $agentsFile) -and -not (Test-Path $windsurfFile)) {
9093
Write-Output 'No agent context files found. Creating Claude Code context file by default.'
9194
Update-AgentFile $claudeFile 'Claude Code'
9295
}
9396
}
94-
Default { Write-Error "ERROR: Unknown agent type '$AgentType'. Use: claude, gemini, copilot, cursor, qwen, opencode or leave empty for all."; exit 1 }
97+
Default { Write-Error "ERROR: Unknown agent type '$AgentType'. Use: claude, gemini, copilot, cursor, qwen, opencode, windsurf or leave empty for all."; exit 1 }
9598
}
9699

97100
Write-Output ''
@@ -101,4 +104,4 @@ if ($newFramework) { Write-Output "- Added framework: $newFramework" }
101104
if ($newDb -and $newDb -ne 'N/A') { Write-Output "- Added database: $newDb" }
102105

103106
Write-Output ''
104-
Write-Output 'Usage: ./update-agent-context.ps1 [claude|gemini|copilot|cursor|qwen|opencode]'
107+
Write-Output 'Usage: ./update-agent-context.ps1 [claude|gemini|copilot|cursor|qwen|opencode|windsurf]'

0 commit comments

Comments
 (0)