Compare commits

...

12 Commits

Author SHA1 Message Date
Den Delimarsky
10e56aa67c Merge pull request #182 from ahmet-cetinkaya/feature/add-qwen-support
feat: add Qwen Code support to Spec Kit
2025-09-17 11:52:23 -07:00
Ahmet Çetinkaya
8b49d5d0fb chore(release): bump version to 0.0.5 and update changelog
Add entry for Qwen Code support as new AI assistant option
2025-09-17 11:39:03 +03:00
Ahmet Çetinkaya
66688dffa3 Merge branch 'main' into feature/add-qwen-support 2025-09-16 10:31:50 +03:00
Den Delimarsky 🌺
b18ef208cb Update template. 2025-09-15 19:08:26 -07:00
Den Delimarsky 🌺
5828e58f84 Update scripts 2025-09-15 17:44:18 -07:00
Den Delimarsky 🌺
dd57e9d444 Update template paths 2025-09-15 17:29:50 -07:00
Den Delimarsky 🌺
558e682865 Update for Cursor rules & script path 2025-09-15 17:16:18 -07:00
Ahmet Çetinkaya
c5e0c1840b chore: address review feedback - remove comment and fix numbering 2025-09-15 11:45:24 +03:00
Ahmet Çetinkaya
856680e3bc Merge main into feature/add-qwen-support
Combines Qwen Code support with new script variant structure from main.
Key additions:
- Qwen Code AI assistant support
- PowerShell script variants alongside Bash
- Updated release packaging for per-script variants
- Maintains all existing Cursor support from main

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-14 13:02:09 +03:00
Ahmet Çetinkaya
0c419e5198 Merge main into feature/add-qwen-support
Resolved conflicts in release workflow and CLI:
- Integrated external script approach for release package creation
- Added Qwen Code support to release script and CLI tool checking
- Maintained all existing functionality for other AI assistants
2025-09-12 14:09:43 +03:00
Ahmet Çetinkaya
fe4de3ca45 Merge branch 'main' into feature/add-qwen-support 2025-09-11 23:46:30 +03:00
Ahmet Çetinkaya
73a9af70a4 feat: add Qwen Code support to Spec Kit
Add comprehensive Qwen Code integration following existing patterns:

- Add Qwen as fourth AI assistant option in CLI
- Update all documentation to include Qwen CLI references
- Extend GitHub Actions workflow for Qwen template generation
- Add Qwen support to shell scripts and templates
- Maintain backward compatibility with existing assistants
2025-09-11 15:35:46 +03:00
10 changed files with 87 additions and 65 deletions

View File

@@ -114,12 +114,19 @@ build_variant() {
local plan_tpl="$base_dir/.specify/templates/plan-template.md" local plan_tpl="$base_dir/.specify/templates/plan-template.md"
if [[ -f "$plan_tpl" ]]; then if [[ -f "$plan_tpl" ]]; then
plan_norm=$(tr -d '\r' < "$plan_tpl") plan_norm=$(tr -d '\r' < "$plan_tpl")
variant_line=$(printf '%s\n' "$plan_norm" | grep -E "<!--[[:space:]]*VARIANT:$script" | head -1 | sed -E "s/.*VARIANT:$script[[:space:]]+//; s/-->.*//; s/^[[:space:]]+//; s/[[:space:]]+$//") # Extract script command from YAML frontmatter
if [[ -n $variant_line ]]; then script_command=$(printf '%s\n' "$plan_norm" | awk -v sv="$script" '/^[[:space:]]*'"$script"':[[:space:]]*/ {sub(/^[[:space:]]*'"$script"':[[:space:]]*/, ""); print; exit}')
if [[ -n $script_command ]]; then
# Always prefix with .specify/ for plan usage
script_command=".specify/$script_command"
tmp_file=$(mktemp) tmp_file=$(mktemp)
sed "s|VARIANT-INJECT|${variant_line}|" "$plan_tpl" | tr -d '\r' | sed "s|__AGENT__|${agent}|g" | sed '/<!--[[:space:]]*VARIANT:sh/d' | sed '/<!--[[:space:]]*VARIANT:ps/d' > "$tmp_file" && mv "$tmp_file" "$plan_tpl" # Replace {SCRIPT} placeholder with the script command and __AGENT__ with agent name
substituted=$(sed "s|{SCRIPT}|${script_command}|g" "$plan_tpl" | tr -d '\r' | sed "s|__AGENT__|${agent}|g")
# Strip YAML frontmatter from plan template output (keep body only)
stripped=$(printf '%s\n' "$substituted" | awk 'BEGIN{fm=0;dash=0} /^---$/ {dash++; if(dash==1){fm=1; next} else if(dash==2){fm=0; next}} {if(!fm) print}')
printf '%s\n' "$stripped" > "$plan_tpl"
else else
echo "Warning: no plan-template variant for $script (pattern not matched)" >&2 echo "Warning: no plan-template script command found for $script in YAML frontmatter" >&2
fi fi
fi fi
case $agent in case $agent in
@@ -136,13 +143,17 @@ build_variant() {
cursor) cursor)
mkdir -p "$base_dir/.cursor/commands" mkdir -p "$base_dir/.cursor/commands"
generate_commands cursor md "\$ARGUMENTS" "$base_dir/.cursor/commands" "$script" ;; generate_commands cursor 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" ;;
esac esac
( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . ) ( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . )
echo "Created spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" echo "Created spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip"
} }
# Determine agent list # Determine agent list
ALL_AGENTS=(claude gemini copilot cursor) ALL_AGENTS=(claude gemini copilot cursor qwen)
ALL_SCRIPTS=(sh ps) ALL_SCRIPTS=(sh ps)
norm_list() { norm_list() {

View File

@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [0.0.5] - 2025-09-17
### Added
- Qwen Code support as additional AI assistant option
## [0.0.4] - 2025-09-14 ## [0.0.4] - 2025-09-14
### Added ### Added

View File

@@ -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: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), or [Gemini CLI](https://github.com/google-gemini/gemini-cli) are recommended, but we're working on adding support for other agents as well. 1. Have an AI coding agent available: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Gemini CLI](https://github.com/google-gemini/gemini-cli), or [Qwen Code](https://github.com/QwenLM/qwen-code). We're working on adding support for other agents as well.
## Submitting a pull request ## Submitting a pull request

View File

@@ -170,7 +170,7 @@ Our research and experimentation focus on:
## 🔧 Prerequisites ## 🔧 Prerequisites
- **Linux/macOS** (or WSL2 on Windows) - **Linux/macOS** (or WSL2 on Windows)
- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Gemini CLI](https://github.com/google-gemini/gemini-cli), or [Cursor](https://cursor.sh/) - AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Cursor](https://cursor.sh/), or [Qwen CLI](https://github.com/QwenLM/qwen-code)
- [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)
@@ -207,11 +207,12 @@ You will be prompted to select the AI agent you are using. You can also proactiv
specify init <project_name> --ai claude specify init <project_name> --ai claude
specify init <project_name> --ai gemini specify init <project_name> --ai gemini
specify init <project_name> --ai copilot specify init <project_name> --ai copilot
specify init <project_name> --ai qwen
# Or in current directory: # Or in current directory:
specify init --here --ai claude specify init --here --ai claude
``` ```
The CLI will check if you have Claude Code or Gemini CLI 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, or Qwen CLI 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 claude --ignore-agent-tools

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "specify-cli" name = "specify-cli"
version = "0.0.4" version = "0.0.5"
description = "Setup tool for Specify spec-driven development projects" description = "Setup tool for Specify spec-driven development projects"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = [ dependencies = [

View File

@@ -4,7 +4,7 @@ REPO_ROOT=$(git rev-parse --show-toplevel)
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
FEATURE_DIR="$REPO_ROOT/specs/$CURRENT_BRANCH" FEATURE_DIR="$REPO_ROOT/specs/$CURRENT_BRANCH"
NEW_PLAN="$FEATURE_DIR/plan.md" NEW_PLAN="$FEATURE_DIR/plan.md"
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"; GEMINI_FILE="$REPO_ROOT/GEMINI.md"; COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md" 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"
AGENT_TYPE="$1" AGENT_TYPE="$1"
[ -f "$NEW_PLAN" ] || { echo "ERROR: No plan.md found at $NEW_PLAN"; exit 1; } [ -f "$NEW_PLAN" ] || { echo "ERROR: No plan.md found at $NEW_PLAN"; exit 1; }
echo "=== Updating agent context files for feature $CURRENT_BRANCH ===" echo "=== Updating agent context files for feature $CURRENT_BRANCH ==="
@@ -13,7 +13,7 @@ NEW_FRAMEWORK=$(grep "^**Primary Dependencies**: " "$NEW_PLAN" 2>/dev/null | hea
NEW_DB=$(grep "^**Storage**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Storage**: //' | grep -v "N/A" | grep -v "NEEDS CLARIFICATION" || echo "") NEW_DB=$(grep "^**Storage**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Storage**: //' | grep -v "N/A" | grep -v "NEEDS CLARIFICATION" || echo "")
NEW_PROJECT_TYPE=$(grep "^**Project Type**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Project Type**: //' || echo "") NEW_PROJECT_TYPE=$(grep "^**Project Type**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Project Type**: //' || echo "")
update_agent_file() { local target_file="$1" agent_name="$2"; echo "Updating $agent_name context file: $target_file"; local temp_file=$(mktemp); if [ ! -f "$target_file" ]; then update_agent_file() { local target_file="$1" agent_name="$2"; echo "Updating $agent_name context file: $target_file"; local temp_file=$(mktemp); if [ ! -f "$target_file" ]; then
echo "Creating new $agent_name context file..."; if [ -f "$REPO_ROOT/templates/agent-file-template.md" ]; then cp "$REPO_ROOT/templates/agent-file-template.md" "$temp_file"; else echo "ERROR: Template not found"; return 1; fi; echo "Creating new $agent_name context file..."; if [ -f "$REPO_ROOT/.specify/templates/agent-file-template.md" ]; then cp "$REPO_ROOT/templates/agent-file-template.md" "$temp_file"; else echo "ERROR: Template not found"; return 1; fi;
sed -i.bak "s/\[PROJECT NAME\]/$(basename $REPO_ROOT)/" "$temp_file"; sed -i.bak "s/\[DATE\]/$(date +%Y-%m-%d)/" "$temp_file"; sed -i.bak "s/\[EXTRACTED FROM ALL PLAN.MD FILES\]/- $NEW_LANG + $NEW_FRAMEWORK ($CURRENT_BRANCH)/" "$temp_file"; sed -i.bak "s/\[PROJECT NAME\]/$(basename $REPO_ROOT)/" "$temp_file"; sed -i.bak "s/\[DATE\]/$(date +%Y-%m-%d)/" "$temp_file"; sed -i.bak "s/\[EXTRACTED FROM ALL PLAN.MD FILES\]/- $NEW_LANG + $NEW_FRAMEWORK ($CURRENT_BRANCH)/" "$temp_file";
if [[ "$NEW_PROJECT_TYPE" == *"web"* ]]; then sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|backend/\nfrontend/\ntests/|" "$temp_file"; else sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|src/\ntests/|" "$temp_file"; fi; if [[ "$NEW_PROJECT_TYPE" == *"web"* ]]; then sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|backend/\nfrontend/\ntests/|" "$temp_file"; else sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|src/\ntests/|" "$temp_file"; fi;
if [[ "$NEW_LANG" == *"Python"* ]]; then COMMANDS="cd src && pytest && ruff check ."; elif [[ "$NEW_LANG" == *"Rust"* ]]; then COMMANDS="cargo test && cargo clippy"; elif [[ "$NEW_LANG" == *"JavaScript"* ]] || [[ "$NEW_LANG" == *"TypeScript"* ]]; then COMMANDS="npm test && npm run lint"; else COMMANDS="# Add commands for $NEW_LANG"; fi; sed -i.bak "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$COMMANDS|" "$temp_file"; if [[ "$NEW_LANG" == *"Python"* ]]; then COMMANDS="cd src && pytest && ruff check ."; elif [[ "$NEW_LANG" == *"Rust"* ]]; then COMMANDS="cargo test && cargo clippy"; elif [[ "$NEW_LANG" == *"JavaScript"* ]] || [[ "$NEW_LANG" == *"TypeScript"* ]]; then COMMANDS="npm test && npm run lint"; else COMMANDS="# Add commands for $NEW_LANG"; fi; sed -i.bak "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$COMMANDS|" "$temp_file";
@@ -51,7 +51,12 @@ case "$AGENT_TYPE" in
claude) update_agent_file "$CLAUDE_FILE" "Claude Code" ;; claude) update_agent_file "$CLAUDE_FILE" "Claude Code" ;;
gemini) update_agent_file "$GEMINI_FILE" "Gemini CLI" ;; gemini) update_agent_file "$GEMINI_FILE" "Gemini CLI" ;;
copilot) update_agent_file "$COPILOT_FILE" "GitHub Copilot" ;; copilot) update_agent_file "$COPILOT_FILE" "GitHub Copilot" ;;
"") [ -f "$CLAUDE_FILE" ] && update_agent_file "$CLAUDE_FILE" "Claude Code"; [ -f "$GEMINI_FILE" ] && update_agent_file "$GEMINI_FILE" "Gemini CLI"; [ -f "$COPILOT_FILE" ] && update_agent_file "$COPILOT_FILE" "GitHub Copilot"; if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ]; then update_agent_file "$CLAUDE_FILE" "Claude Code"; fi ;; cursor) update_agent_file "$CURSOR_FILE" "Cursor IDE" ;;
*) echo "ERROR: Unknown agent type '$AGENT_TYPE'"; exit 1 ;; "") [ -f "$CLAUDE_FILE" ] && update_agent_file "$CLAUDE_FILE" "Claude Code"; \
[ -f "$GEMINI_FILE" ] && update_agent_file "$GEMINI_FILE" "Gemini CLI"; \
[ -f "$COPILOT_FILE" ] && update_agent_file "$COPILOT_FILE" "GitHub Copilot"; \
[ -f "$CURSOR_FILE" ] && update_agent_file "$CURSOR_FILE" "Cursor IDE"; \
if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ] && [ ! -f "$CURSOR_FILE" ]; then update_agent_file "$CLAUDE_FILE" "Claude Code"; fi ;;
*) echo "ERROR: Unknown agent type '$AGENT_TYPE' (expected claude|gemini|copilot|cursor)"; exit 1 ;;
esac esac
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]" 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]"

View File

@@ -12,6 +12,7 @@ if (-not (Test-Path $newPlan)) { Write-Error "ERROR: No plan.md found at $newPla
$claudeFile = Join-Path $repoRoot 'CLAUDE.md' $claudeFile = Join-Path $repoRoot 'CLAUDE.md'
$geminiFile = Join-Path $repoRoot 'GEMINI.md' $geminiFile = Join-Path $repoRoot 'GEMINI.md'
$copilotFile = Join-Path $repoRoot '.github/copilot-instructions.md' $copilotFile = Join-Path $repoRoot '.github/copilot-instructions.md'
$cursorFile = Join-Path $repoRoot '.cursor/rules/specify-rules.mdc'
Write-Output "=== Updating agent context files for feature $currentBranch ===" Write-Output "=== Updating agent context files for feature $currentBranch ==="
@@ -30,7 +31,7 @@ $newProjectType = Get-PlanValue 'Project Type'
function Initialize-AgentFile($targetFile, $agentName) { function Initialize-AgentFile($targetFile, $agentName) {
if (Test-Path $targetFile) { return } if (Test-Path $targetFile) { return }
$template = Join-Path $repoRoot 'templates/agent-file-template.md' $template = Join-Path $repoRoot '.specify/templates/agent-file-template.md'
if (-not (Test-Path $template)) { Write-Error "Template not found: $template"; return } if (-not (Test-Path $template)) { Write-Error "Template not found: $template"; return }
$content = Get-Content $template -Raw $content = Get-Content $template -Raw
$content = $content.Replace('[PROJECT NAME]', (Split-Path $repoRoot -Leaf)) $content = $content.Replace('[PROJECT NAME]', (Split-Path $repoRoot -Leaf))
@@ -55,7 +56,7 @@ function Update-AgentFile($targetFile, $agentName) {
if ($newDb -and $newDb -ne 'N/A' -and ($content -notmatch [regex]::Escape($newDb))) { $content = $content -replace '(## Active Technologies\n)', "`$1- $newDb ($currentBranch)`n" } if ($newDb -and $newDb -ne 'N/A' -and ($content -notmatch [regex]::Escape($newDb))) { $content = $content -replace '(## Active Technologies\n)', "`$1- $newDb ($currentBranch)`n" }
if ($content -match '## Recent Changes\n([\s\S]*?)(\n\n|$)') { if ($content -match '## Recent Changes\n([\s\S]*?)(\n\n|$)') {
$changesBlock = $matches[1].Trim().Split("`n") $changesBlock = $matches[1].Trim().Split("`n")
$changesBlock = ,"- $currentBranch: Added $newLang + $newFramework" + $changesBlock $changesBlock = ,"- ${currentBranch}: Added ${newLang} + ${newFramework}" + $changesBlock
$changesBlock = $changesBlock | Where-Object { $_ } | Select-Object -First 3 $changesBlock = $changesBlock | Where-Object { $_ } | Select-Object -First 3
$joined = ($changesBlock -join "`n") $joined = ($changesBlock -join "`n")
$content = [regex]::Replace($content, '## Recent Changes\n([\s\S]*?)(\n\n|$)', "## Recent Changes`n$joined`n`n") $content = [regex]::Replace($content, '## Recent Changes\n([\s\S]*?)(\n\n|$)', "## Recent Changes`n$joined`n`n")
@@ -69,16 +70,22 @@ switch ($AgentType) {
'claude' { Update-AgentFile $claudeFile 'Claude Code' } 'claude' { Update-AgentFile $claudeFile 'Claude Code' }
'gemini' { Update-AgentFile $geminiFile 'Gemini CLI' } 'gemini' { Update-AgentFile $geminiFile 'Gemini CLI' }
'copilot' { Update-AgentFile $copilotFile 'GitHub Copilot' } 'copilot' { Update-AgentFile $copilotFile 'GitHub Copilot' }
'cursor' { Update-AgentFile $cursorFile 'Cursor IDE' }
'' { '' {
foreach ($pair in @(@{file=$claudeFile; name='Claude Code'}, @{file=$geminiFile; name='Gemini CLI'}, @{file=$copilotFile; name='GitHub Copilot'})) { foreach ($pair in @(
@{file=$claudeFile; name='Claude Code'},
@{file=$geminiFile; name='Gemini CLI'},
@{file=$copilotFile; name='GitHub Copilot'},
@{file=$cursorFile; name='Cursor IDE'}
)) {
if (Test-Path $pair.file) { Update-AgentFile $pair.file $pair.name } if (Test-Path $pair.file) { Update-AgentFile $pair.file $pair.name }
} }
if (-not (Test-Path $claudeFile) -and -not (Test-Path $geminiFile) -and -not (Test-Path $copilotFile)) { if (-not (Test-Path $claudeFile) -and -not (Test-Path $geminiFile) -and -not (Test-Path $copilotFile) -and -not (Test-Path $cursorFile)) {
Write-Output 'No agent context files found. Creating Claude Code context file by default.' Write-Output 'No agent context files found. Creating Claude Code context file by default.'
Update-AgentFile $claudeFile 'Claude Code' Update-AgentFile $claudeFile 'Claude Code'
} }
} }
Default { Write-Error "ERROR: Unknown agent type '$AgentType'. Use: claude, gemini, copilot, or leave empty for all."; exit 1 } Default { Write-Error "ERROR: Unknown agent type '$AgentType'. Use: claude, gemini, copilot, cursor or leave empty for all."; exit 1 }
} }
Write-Output '' Write-Output ''
@@ -88,4 +95,4 @@ if ($newFramework) { Write-Output "- Added framework: $newFramework" }
if ($newDb -and $newDb -ne 'N/A') { Write-Output "- Added database: $newDb" } if ($newDb -and $newDb -ne 'N/A') { Write-Output "- Added database: $newDb" }
Write-Output '' Write-Output ''
Write-Output 'Usage: ./update-agent-context.ps1 [claude|gemini|copilot]' Write-Output 'Usage: ./update-agent-context.ps1 [claude|gemini|copilot|cursor]'

View File

@@ -57,7 +57,8 @@ AI_CHOICES = {
"copilot": "GitHub Copilot", "copilot": "GitHub Copilot",
"claude": "Claude Code", "claude": "Claude Code",
"gemini": "Gemini CLI", "gemini": "Gemini CLI",
"cursor": "Cursor" "cursor": "Cursor",
"qwen": "Qwen Code"
} }
# Add script type choices # Add script type choices
SCRIPT_TYPE_CHOICES = {"sh": "POSIX Shell (bash/zsh)", "ps": "PowerShell"} SCRIPT_TYPE_CHOICES = {"sh": "POSIX Shell (bash/zsh)", "ps": "PowerShell"}
@@ -722,7 +723,7 @@ def ensure_executable_scripts(project_path: Path, tracker: StepTracker | None =
@app.command() @app.command()
def init( def init(
project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here)"), project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here)"),
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, or cursor"), ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor, or qwen"),
script_type: str = typer.Option(None, "--script", help="Script type to use: sh or ps"), script_type: str = typer.Option(None, "--script", help="Script type to use: sh or ps"),
ignore_agent_tools: bool = typer.Option(False, "--ignore-agent-tools", help="Skip checks for AI agent tools like Claude Code"), ignore_agent_tools: bool = typer.Option(False, "--ignore-agent-tools", help="Skip checks for AI agent tools like Claude Code"),
no_git: bool = typer.Option(False, "--no-git", help="Skip git repository initialization"), no_git: bool = typer.Option(False, "--no-git", help="Skip git repository initialization"),
@@ -735,7 +736,7 @@ def init(
This command will: This command will:
1. Check that required tools are installed (git is optional) 1. Check that required tools are installed (git is optional)
2. Let you choose your AI assistant (Claude Code, Gemini CLI, GitHub Copilot, or Cursor) 2. Let you choose your AI assistant (Claude Code, Gemini CLI, GitHub Copilot, Cursor, or Qwen Code)
3. Download the appropriate template from GitHub 3. Download the appropriate template from GitHub
4. Extract the template to a new project directory or current directory 4. Extract the template to a new project directory or current directory
5. Initialize a fresh git repository (if not --no-git and no existing repo) 5. Initialize a fresh git repository (if not --no-git and no existing repo)
@@ -747,6 +748,7 @@ def init(
specify init my-project --ai gemini specify init my-project --ai gemini
specify init my-project --ai copilot --no-git specify init my-project --ai copilot --no-git
specify init my-project --ai cursor specify init my-project --ai cursor
specify init my-project --ai qwen
specify init --ignore-agent-tools my-project specify init --ignore-agent-tools my-project
specify init --here --ai claude specify init --here --ai claude
specify init --here specify init --here
@@ -825,6 +827,11 @@ def init(
if not check_tool("gemini", "Install from: https://github.com/google-gemini/gemini-cli"): if not check_tool("gemini", "Install from: https://github.com/google-gemini/gemini-cli"):
console.print("[red]Error:[/red] Gemini CLI is required for Gemini projects") console.print("[red]Error:[/red] Gemini CLI is required for Gemini projects")
agent_tool_missing = True agent_tool_missing = True
elif selected_ai == "qwen":
if not check_tool("qwen", "Install from: https://github.com/QwenLM/qwen-code"):
console.print("[red]Error:[/red] Qwen CLI is required for Qwen Code projects")
agent_tool_missing = True
# GitHub Copilot and Cursor checks are not needed as they're typically available in supported IDEs
if agent_tool_missing: if agent_tool_missing:
console.print("\n[red]Required AI tool is missing![/red]") console.print("\n[red]Required AI tool is missing![/red]")
@@ -950,6 +957,12 @@ def init(
steps_lines.append(" - See GEMINI.md for all available commands") steps_lines.append(" - See GEMINI.md for all available commands")
elif selected_ai == "copilot": elif selected_ai == "copilot":
steps_lines.append(f"{step_num}. Open in Visual Studio Code and use [bold cyan]/specify[/], [bold cyan]/plan[/], [bold cyan]/tasks[/] commands with GitHub Copilot") steps_lines.append(f"{step_num}. Open in Visual Studio Code and use [bold cyan]/specify[/], [bold cyan]/plan[/], [bold cyan]/tasks[/] commands with GitHub Copilot")
elif selected_ai == "qwen":
steps_lines.append(f"{step_num}. Use / commands with Qwen CLI")
steps_lines.append(" - Run qwen /specify to create specifications")
steps_lines.append(" - Run qwen /plan to create implementation plans")
steps_lines.append(" - Run qwen /tasks to generate tasks")
steps_lines.append(" - See QWEN.md for all available commands")
# Removed script variant step (scripts are transparent to users) # Removed script variant step (scripts are transparent to users)
step_num += 1 step_num += 1
@@ -975,6 +988,7 @@ def check():
tracker.add("git", "Git version control") tracker.add("git", "Git version control")
tracker.add("claude", "Claude Code CLI") tracker.add("claude", "Claude Code CLI")
tracker.add("gemini", "Gemini CLI") tracker.add("gemini", "Gemini CLI")
tracker.add("qwen", "Qwen Code CLI")
tracker.add("code", "VS Code (for GitHub Copilot)") tracker.add("code", "VS Code (for GitHub Copilot)")
tracker.add("cursor-agent", "Cursor IDE agent (optional)") tracker.add("cursor-agent", "Cursor IDE agent (optional)")
@@ -982,6 +996,7 @@ def check():
git_ok = check_tool_for_tracker("git", "https://git-scm.com/downloads", tracker) git_ok = check_tool_for_tracker("git", "https://git-scm.com/downloads", tracker)
claude_ok = check_tool_for_tracker("claude", "https://docs.anthropic.com/en/docs/claude-code/setup", tracker) claude_ok = check_tool_for_tracker("claude", "https://docs.anthropic.com/en/docs/claude-code/setup", tracker)
gemini_ok = check_tool_for_tracker("gemini", "https://github.com/google-gemini/gemini-cli", tracker) gemini_ok = check_tool_for_tracker("gemini", "https://github.com/google-gemini/gemini-cli", tracker)
qwen_ok = check_tool_for_tracker("qwen", "https://github.com/QwenLM/qwen-code", tracker)
# Check for VS Code (code or code-insiders) # Check for VS Code (code or code-insiders)
code_ok = check_tool_for_tracker("code", "https://code.visualstudio.com/", tracker) code_ok = check_tool_for_tracker("code", "https://code.visualstudio.com/", tracker)
if not code_ok: if not code_ok:
@@ -997,7 +1012,7 @@ def check():
# Recommendations # Recommendations
if not git_ok: if not git_ok:
console.print("[dim]Tip: Install git for repository management[/dim]") console.print("[dim]Tip: Install git for repository management[/dim]")
if not (claude_ok or gemini_ok): if not (claude_ok or gemini_ok or qwen_ok):
console.print("[dim]Tip: Install an AI assistant for the best experience[/dim]") console.print("[dim]Tip: Install an AI assistant for the best experience[/dim]")

View File

@@ -19,7 +19,7 @@ Given the implementation details provided as an argument, do this:
4. Execute the implementation plan template: 4. Execute the implementation plan template:
- Load `/templates/plan-template.md` (already copied to IMPL_PLAN path) - Load `/templates/plan-template.md` (already copied to IMPL_PLAN path)
- Set Input path to FEATURE_SPEC - Set Input path to FEATURE_SPEC
- Run the Execution Flow (main) function steps 1-10 - Run the Execution Flow (main) function steps 1-9
- The template is self-contained and executable - The template is self-contained and executable
- Follow error handling and gate checks as specified - Follow error handling and gate checks as specified
- Let the template guide artifact generation in $SPECS_DIR: - Let the template guide artifact generation in $SPECS_DIR:

View File

@@ -1,7 +1,11 @@
# Implementation Plan: [FEATURE] ---
description: "Implementation plan template for feature development"
scripts:
sh: scripts/bash/update-agent-context.sh __AGENT__
ps: scripts/powershell/update-agent-context.ps1 -AgentType __AGENT__
---
<!-- VARIANT:sh - Run `/scripts/bash/update-agent-context.sh __AGENT__` for your AI assistant --> # Implementation Plan: [FEATURE]
<!-- VARIANT:ps - Run `/scripts/powershell/update-agent-context.ps1 -AgentType __AGENT__` for your AI assistant -->
**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link] **Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md` **Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
@@ -13,18 +17,19 @@
2. Fill Technical Context (scan for NEEDS CLARIFICATION) 2. Fill Technical Context (scan for NEEDS CLARIFICATION)
→ Detect Project Type from context (web=frontend+backend, mobile=app+api) → Detect Project Type from context (web=frontend+backend, mobile=app+api)
→ Set Structure Decision based on project type → Set Structure Decision based on project type
3. Evaluate Constitution Check section below 3. Fill the Constitution Check section based on the content of the constitution document.
4. Evaluate Constitution Check section below
→ If violations exist: Document in Complexity Tracking → If violations exist: Document in Complexity Tracking
→ If no justification possible: ERROR "Simplify approach first" → If no justification possible: ERROR "Simplify approach first"
→ Update Progress Tracking: Initial Constitution Check → Update Progress Tracking: Initial Constitution Check
4. Execute Phase 0 → research.md 5. Execute Phase 0 → research.md
→ If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns" → If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns"
5. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, or `GEMINI.md` for Gemini CLI). 6. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, `GEMINI.md` for Gemini CLI, or `QWEN.md` for Qwen Code).
6. Re-evaluate Constitution Check section 7. Re-evaluate Constitution Check section
→ If new violations: Refactor design, return to Phase 1 → If new violations: Refactor design, return to Phase 1
→ Update Progress Tracking: Post-Design Constitution Check → Update Progress Tracking: Post-Design Constitution Check
7. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md) 8. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md)
8. STOP - Ready for /tasks command 9. STOP - Ready for /tasks command
``` ```
**IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands: **IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands:
@@ -48,35 +53,7 @@
## Constitution Check ## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
**Simplicity**: [Gates determined based on constitution file]
- Projects: [#] (max 3 - e.g., api, cli, tests)
- Using framework directly? (no wrapper classes)
- Single data model? (no DTOs unless serialization differs)
- Avoiding patterns? (no Repository/UoW without proven need)
**Architecture**:
- EVERY feature as library? (no direct app code)
- Libraries listed: [name + purpose for each]
- CLI per library: [commands with --help/--version/--format]
- Library docs: llms.txt format planned?
**Testing (NON-NEGOTIABLE)**:
- RED-GREEN-Refactor cycle enforced? (test MUST fail first)
- Git commits show tests before implementation?
- Order: ContractIntegrationE2EUnit strictly followed?
- Real dependencies used? (actual DBs, not mocks)
- Integration tests for: new libraries, contract changes, shared schemas?
- FORBIDDEN: Implementation before test, skipping RED phase
**Observability**:
- Structured logging included?
- Frontend logs backend? (unified stream)
- Error context sufficient?
**Versioning**:
- Version number assigned? (MAJOR.MINOR.BUILD)
- BUILD increments on every change?
- Breaking changes handled? (parallel tests, migration plan)
## Project Structure ## Project Structure
@@ -174,7 +151,7 @@ ios/ or android/
- Quickstart test = story validation steps - Quickstart test = story validation steps
5. **Update agent file incrementally** (O(1) operation): 5. **Update agent file incrementally** (O(1) operation):
VARIANT-INJECT - Run `{SCRIPT}` for your AI assistant
- If exists: Add only NEW tech from current plan - If exists: Add only NEW tech from current plan
- Preserve manual additions between markers - Preserve manual additions between markers
- Update recent changes (keep last 3) - Update recent changes (keep last 3)
@@ -187,7 +164,7 @@ ios/ or android/
*This section describes what the /tasks command will do - DO NOT execute during /plan* *This section describes what the /tasks command will do - DO NOT execute during /plan*
**Task Generation Strategy**: **Task Generation Strategy**:
- Load `/templates/tasks-template.md` as base - Load `.specify/templates/tasks-template.md` as base
- Generate tasks from Phase 1 design docs (contracts, data model, quickstart) - Generate tasks from Phase 1 design docs (contracts, data model, quickstart)
- Each contract → contract test task [P] - Each contract → contract test task [P]
- Each entity → model creation task [P] - Each entity → model creation task [P]