Compare commits

..

16 Commits

Author SHA1 Message Date
Den Delimarsky
6b8b1a8b93 Merge pull request #220 from github/update-cli-script
Update update-agent-context.ps1
2025-09-12 18:43:19 -07:00
Den Delimarsky 🌺
0e6f513c14 Update update-agent-context.ps1 2025-09-12 18:42:45 -07:00
Den Delimarsky 🌺
6f81f7d6a0 Update create-release-packages.sh 2025-09-12 18:39:11 -07:00
Den Delimarsky
c875bd0f30 Merge pull request #217 from github/update-cli
Update with check changes
2025-09-12 15:22:06 -07:00
Den Delimarsky 🌺
736e282562 Update with check changes 2025-09-12 15:20:20 -07:00
Den Delimarsky
542751fcd1 Merge pull request #216 from github/update-cli
Update release definition
2025-09-12 14:42:49 -07:00
Den Delimarsky 🌺
6c83e9ff66 Update wording 2025-09-12 14:39:45 -07:00
Den Delimarsky 🌺
a55448057b Update release.yml 2025-09-12 14:39:00 -07:00
Den Delimarsky
88cded5c4d Merge pull request #215 from github/update-cli
Support Cursor
2025-09-12 14:34:57 -07:00
Den Delimarsky 🌺
0ad2f169d2 Support Cursor 2025-09-12 14:34:13 -07:00
Den Delimarsky
fa3171ca6e Merge pull request #214 from github/update-cli
Saner approach to scripts
2025-09-12 14:06:34 -07:00
Den Delimarsky 🌺
117ec67e47 Saner approach to scripts 2025-09-12 14:05:55 -07:00
Den Delimarsky
5bd7027526 Merge pull request #213 from github/update-cli
Update packaging
2025-09-12 13:45:55 -07:00
Den Delimarsky 🌺
ec7d87f121 Update packaging 2025-09-12 13:45:28 -07:00
Den Delimarsky
85e5eedef8 Merge pull request #212 from github/update-cli
Fix package logic
2025-09-12 13:31:10 -07:00
Den Delimarsky 🌺
0a5b1ac538 Fix package logic 2025-09-12 13:30:15 -07:00
8 changed files with 168 additions and 53 deletions

View File

@@ -81,7 +81,7 @@ jobs:
cat > release_notes.md << EOF cat > release_notes.md << EOF
Template release ${{ steps.get_tag.outputs.new_version }} Template release ${{ steps.get_tag.outputs.new_version }}
Updated specification-driven development templates for GitHub Copilot, Claude Code, and Gemini CLI. Updated specification-driven development templates for GitHub Copilot, Claude Code, Gemini CLI, and Cursor.
Now includes per-script variants for POSIX shell (sh) and PowerShell (ps). Now includes per-script variants for POSIX shell (sh) and PowerShell (ps).
@@ -92,6 +92,8 @@ jobs:
- spec-kit-template-claude-ps-${{ steps.get_tag.outputs.new_version }}.zip - spec-kit-template-claude-ps-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-gemini-sh-${{ steps.get_tag.outputs.new_version }}.zip - spec-kit-template-gemini-sh-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip - spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-cursor-sh-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-cursor-ps-${{ steps.get_tag.outputs.new_version }}.zip
EOF EOF
echo "Generated release notes:" echo "Generated release notes:"
@@ -110,6 +112,8 @@ jobs:
spec-kit-template-claude-ps-${{ steps.get_tag.outputs.new_version }}.zip \ spec-kit-template-claude-ps-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-gemini-sh-${{ steps.get_tag.outputs.new_version }}.zip \ spec-kit-template-gemini-sh-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip \ spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-cursor-sh-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-cursor-ps-${{ steps.get_tag.outputs.new_version }}.zip \
--title "Spec Kit Templates - $VERSION_NO_V" \ --title "Spec Kit Templates - $VERSION_NO_V" \
--notes-file release_notes.md --notes-file release_notes.md
env: env:

View File

@@ -4,7 +4,14 @@ set -euo pipefail
# create-release-packages.sh (workflow-local) # create-release-packages.sh (workflow-local)
# Build Spec Kit template release archives for each supported AI assistant and script type. # Build Spec Kit template release archives for each supported AI assistant and script type.
# Usage: .github/workflows/scripts/create-release-packages.sh <version> # Usage: .github/workflows/scripts/create-release-packages.sh <version>
# Version argument should include leading 'v'. # 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 (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 if [[ $# -ne 1 ]]; then
echo "Usage: $0 <version-with-v-prefix>" >&2 echo "Usage: $0 <version-with-v-prefix>" >&2
@@ -20,14 +27,6 @@ echo "Building release packages for $NEW_VERSION"
rm -rf sdd-package-base* sdd-*-package-* spec-kit-template-*-${NEW_VERSION}.zip || true rm -rf sdd-package-base* sdd-*-package-* spec-kit-template-*-${NEW_VERSION}.zip || true
mkdir -p sdd-package-base
SPEC_DIR="sdd-package-base/.specify"
mkdir -p "$SPEC_DIR"
[[ -d memory ]] && { cp -r memory "$SPEC_DIR/"; echo "Copied memory -> .specify"; }
[[ -d scripts ]] && { cp -r scripts "$SPEC_DIR/"; echo "Copied scripts -> .specify/scripts"; }
[[ -d templates ]] && { mkdir -p "$SPEC_DIR/templates"; find templates -type f -not -path "templates/commands/*" -exec cp --parents {} "$SPEC_DIR"/ \; ; echo "Copied templates -> .specify/templates"; }
rewrite_paths() { rewrite_paths() {
sed -E \ sed -E \
-e 's@(/?)memory/@.specify/memory/@g' \ -e 's@(/?)memory/@.specify/memory/@g' \
@@ -40,22 +39,36 @@ generate_commands() {
mkdir -p "$output_dir" mkdir -p "$output_dir"
for template in templates/commands/*.md; do for template in templates/commands/*.md; do
[[ -f "$template" ]] || continue [[ -f "$template" ]] || continue
local name description raw_body variant_line injected body local name description script_command body
name=$(basename "$template" .md) name=$(basename "$template" .md)
description=$(awk '/^description:/ {gsub(/^description: *"?/, ""); gsub(/"$/, ""); print; exit}' "$template" | tr -d '\r')
raw_body=$(awk '/^---$/{if(++count==2) start=1; next} start' "$template") # Normalize line endings
# Find single-line variant comment matching the variant: <!-- VARIANT:sh ... --> or <!-- VARIANT:ps ... --> file_content=$(tr -d '\r' < "$template")
variant_line=$(printf '%s\n' "$raw_body" | awk -v sv="$script_variant" '/<!--[[:space:]]+VARIANT:'sv'/ {match($0, /VARIANT:'"sv"'[[:space:]]+(.*)-->/, m); if (m[1]!="") {print m[1]; exit}}')
if [[ -z $variant_line ]]; then # Extract description and script command from YAML frontmatter
echo "Warning: no variant line found for $script_variant in $template" >&2 description=$(printf '%s\n' "$file_content" | awk '/^description:/ {sub(/^description:[[:space:]]*/, ""); print; exit}')
variant_line="(Missing variant command for $script_variant)" 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 fi
# Replace the token VARIANT-INJECT with the selected variant line
injected=$(printf '%s\n' "$raw_body" | sed "s/VARIANT-INJECT/${variant_line//\//\/}/") # Replace {SCRIPT} placeholder with the script command
# Remove all single-line variant comments body=$(printf '%s\n' "$file_content" | sed "s|{SCRIPT}|${script_command}|g")
injected=$(printf '%s\n' "$injected" | sed '/<!--[[:space:]]*VARIANT:sh/d' | sed '/<!--[[:space:]]*VARIANT:ps/d')
# Apply arg substitution and path rewrite # Remove the scripts: section from frontmatter while preserving YAML structure
body=$(printf '%s\n' "$injected" | sed "s/{ARGS}/$arg_format/g" | sed "s/__AGENT__/$agent/g" | rewrite_paths) 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 && /^[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 case $ext in
toml) toml)
{ echo "description = \"$description\""; echo; echo "prompt = \"\"\""; echo "$body"; echo "\"\"\""; } > "$output_dir/$name.$ext" ;; { echo "description = \"$description\""; echo; echo "prompt = \"\"\""; echo "$body"; echo "\"\"\""; } > "$output_dir/$name.$ext" ;;
@@ -72,16 +85,41 @@ build_variant() {
local base_dir="sdd-${agent}-package-${script}" local base_dir="sdd-${agent}-package-${script}"
echo "Building $agent ($script) package..." echo "Building $agent ($script) package..."
mkdir -p "$base_dir" mkdir -p "$base_dir"
cp -r sdd-package-base/. "$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"; }
# Copy any script files that aren't in variant-specific directories
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"; }
# Copy any script files that aren't in variant-specific directories
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/*" -exec cp --parents {} "$SPEC_DIR"/ \; ; echo "Copied templates -> .specify/templates"; }
# Inject variant into plan-template.md within .specify/templates if present # Inject variant into plan-template.md within .specify/templates if present
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
variant_line=$(awk -v sv="$script" '/<!--[[:space:]]*VARIANT:'"$script"'/ {match($0, /VARIANT:'"$script"'[[:space:]]+(.*)-->/, m); if(m[1]!=""){print m[1]; exit}}' "$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:]]+$//")
if [[ -n $variant_line ]]; then if [[ -n $variant_line ]]; then
tmp_file=$(mktemp) tmp_file=$(mktemp)
sed "s/VARIANT-INJECT/${variant_line//\//\/}/" "$plan_tpl" | sed "/__AGENT__/s//${agent}/g" | sed '/<!--[[:space:]]*VARIANT:sh/d' | sed '/<!--[[:space:]]*VARIANT:ps/d' > "$tmp_file" && mv "$tmp_file" "$plan_tpl" 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"
else else
echo "Warning: no plan-template variant for $script" >&2 echo "Warning: no plan-template variant for $script (pattern not matched)" >&2
fi fi
fi fi
case $agent in case $agent in
@@ -95,14 +133,56 @@ build_variant() {
copilot) copilot)
mkdir -p "$base_dir/.github/prompts" mkdir -p "$base_dir/.github/prompts"
generate_commands copilot prompt.md "\$ARGUMENTS" "$base_dir/.github/prompts" "$script" ;; generate_commands copilot prompt.md "\$ARGUMENTS" "$base_dir/.github/prompts" "$script" ;;
cursor)
mkdir -p "$base_dir/.cursor/commands"
generate_commands cursor md "\$ARGUMENTS" "$base_dir/.cursor/commands" "$script" ;;
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"
} }
# Build for each agent+script variant # Determine agent list
for agent in claude gemini copilot; do ALL_AGENTS=(claude gemini copilot cursor)
for script in sh ps; do ALL_SCRIPTS=(sh ps)
norm_list() {
# convert comma+space separated -> space separated unique while preserving order of first occurrence
tr ',\n' ' ' | awk '{for(i=1;i<=NF;i++){if(!seen[$i]++){printf((out?" ":"") $i)}}}END{printf("\n")}'
}
validate_subset() {
local type=$1; shift; local -n allowed=$1; shift; local items=($@)
local ok=1
for it in "${items[@]}"; do
local found=0
for a in "${allowed[@]}"; do [[ $it == $a ]] && { found=1; break; }; done
if [[ $found -eq 0 ]]; then
echo "Error: unknown $type '$it' (allowed: ${allowed[*]})" >&2
ok=0
fi
done
return $ok
}
if [[ -n ${AGENTS:-} ]]; then
AGENT_LIST=($(printf '%s' "$AGENTS" | norm_list))
validate_subset agent ALL_AGENTS "${AGENT_LIST[@]}" || exit 1
else
AGENT_LIST=(${ALL_AGENTS[@]})
fi
if [[ -n ${SCRIPTS:-} ]]; then
SCRIPT_LIST=($(printf '%s' "$SCRIPTS" | norm_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" build_variant "$agent" "$script"
done done
done done

View File

@@ -45,7 +45,7 @@ uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME
### 2. Create the spec ### 2. Create the spec
Use the `/specify` command to describe what you want to build. Focus on the **what** and **why**, not the tech stack. Use the **`/specify`** command to describe what you want to build. Focus on the **what** and **why**, not the tech stack.
```bash ```bash
/specify Build an application that can help me organize my photos in separate photo albums. Albums are grouped by date and can be re-organized by dragging and dropping on the main page. Albums are never in other nested albums. Within each album, photos are previewed in a tile-like interface. /specify Build an application that can help me organize my photos in separate photo albums. Albums are grouped by date and can be re-organized by dragging and dropping on the main page. Albums are never in other nested albums. Within each album, photos are previewed in a tile-like interface.
@@ -53,7 +53,7 @@ Use the `/specify` command to describe what you want to build. Focus on the **wh
### 3. Create a technical implementation plan ### 3. Create a technical implementation plan
Use the `/plan` command to provide your tech stack and architecture choices. Use the **`/plan`** command to provide your tech stack and architecture choices.
```bash ```bash
/plan The application uses Vite with minimal number of libraries. Use vanilla HTML, CSS, and JavaScript as much as possible. Images are not uploaded anywhere and metadata is stored in a local SQLite database. /plan The application uses Vite with minimal number of libraries. Use vanilla HTML, CSS, and JavaScript as much as possible. Images are not uploaded anywhere and metadata is stored in a local SQLite database.
@@ -61,7 +61,7 @@ Use the `/plan` command to provide your tech stack and architecture choices.
### 4. Break down and implement ### 4. Break down and implement
Use `/tasks` to create an actionable task list, then ask your agent to implement the feature. Use **`/tasks`** to create an actionable task list, then ask your agent to implement the feature.
For detailed step-by-step instructions, see our [comprehensive guide](./spec-driven.md). For detailed step-by-step instructions, see our [comprehensive guide](./spec-driven.md).
@@ -74,18 +74,20 @@ The `specify` command supports the following options:
| Command | Description | | Command | Description |
|-------------|----------------------------------------------------------------| |-------------|----------------------------------------------------------------|
| `init` | Initialize a new Specify project from the latest template | | `init` | Initialize a new Specify project from the latest template |
| `check` | Check for installed tools (`git`, `claude`, `gemini`) | | `check` | Check for installed tools (`git`, `claude`, `gemini`, `code`/`code-insiders`, `cursor-agent`) |
### `specify init` Arguments & Options ### `specify init` Arguments & Options
| Argument/Option | Type | Description | | Argument/Option | Type | Description |
|------------------------|----------|------------------------------------------------------------------------------| |------------------------|----------|------------------------------------------------------------------------------|
| `<project-name>` | Argument | Name for your new project directory (optional if using `--here`) | | `<project-name>` | Argument | Name for your new project directory (optional if using `--here`) |
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, or `copilot` | | `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, or `cursor` |
| `--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 | | `--ignore-agent-tools` | Flag | Skip checks for AI agent tools like Claude Code |
| `--no-git` | Flag | Skip git repository initialization | | `--no-git` | Flag | Skip git repository initialization |
| `--here` | Flag | Initialize project in the current directory instead of creating a new one | | `--here` | Flag | Initialize project in the current directory instead of creating a new one |
| `--skip-tls` | Flag | Skip SSL/TLS verification (not recommended) | | `--skip-tls` | Flag | Skip SSL/TLS verification (not recommended) |
| `--debug` | Flag | Enable detailed debug output for troubleshooting |
### Examples ### Examples
@@ -96,12 +98,21 @@ specify init my-project
# Initialize with specific AI assistant # Initialize with specific AI assistant
specify init my-project --ai claude specify init my-project --ai claude
# Initialize with Cursor support
specify init my-project --ai cursor
# Initialize with PowerShell scripts (Windows/cross-platform)
specify init my-project --ai copilot --script ps
# Initialize in current directory # Initialize in current directory
specify init --here --ai copilot specify init --here --ai copilot
# Skip git initialization # Skip git initialization
specify init my-project --ai gemini --no-git specify init my-project --ai gemini --no-git
# Enable debug output for troubleshooting
specify init my-project --ai claude --debug
# Check system requirements # Check system requirements
specify check specify check
``` ```
@@ -152,7 +163,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/), or [Gemini CLI](https://github.com/google-gemini/gemini-cli) - 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/)
- [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)

View File

@@ -43,8 +43,8 @@ function Initialize-AgentFile($targetFile, $agentName) {
elseif ($newLang -match 'JavaScript|TypeScript') { $commands = 'npm test && npm run lint' } elseif ($newLang -match 'JavaScript|TypeScript') { $commands = 'npm test && npm run lint' }
else { $commands = "# Add commands for $newLang" } else { $commands = "# Add commands for $newLang" }
$content = $content.Replace('[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES]', $commands) $content = $content.Replace('[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES]', $commands)
$content = $content.Replace('[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE]', "$newLang: Follow standard conventions") $content = $content.Replace('[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE]', "${newLang}: Follow standard conventions")
$content = $content.Replace('[LAST 3 FEATURES AND WHAT THEY ADDED]', "- $currentBranch: Added $newLang + $newFramework") $content = $content.Replace('[LAST 3 FEATURES AND WHAT THEY ADDED]', "- ${currentBranch}: Added ${newLang} + ${newFramework}")
$content | Set-Content $targetFile -Encoding UTF8 $content | Set-Content $targetFile -Encoding UTF8
} }

View File

@@ -56,7 +56,8 @@ client = httpx.Client(verify=ssl_context)
AI_CHOICES = { AI_CHOICES = {
"copilot": "GitHub Copilot", "copilot": "GitHub Copilot",
"claude": "Claude Code", "claude": "Claude Code",
"gemini": "Gemini CLI" "gemini": "Gemini CLI",
"cursor": "Cursor"
} }
# 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"}
@@ -721,7 +722,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, or copilot"), ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, or cursor"),
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"),
@@ -734,7 +735,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, or GitHub Copilot) 2. Let you choose your AI assistant (Claude Code, Gemini CLI, GitHub Copilot, or Cursor)
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)
@@ -745,6 +746,7 @@ def init(
specify init my-project --ai claude specify init my-project --ai claude
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 --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
@@ -823,8 +825,7 @@ 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
# GitHub Copilot check is not needed as it's 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]")
console.print("[yellow]Tip:[/yellow] Use --ignore-agent-tools to skip this check") console.print("[yellow]Tip:[/yellow] Use --ignore-agent-tools to skip this check")
@@ -974,11 +975,18 @@ 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("code", "VS Code (for GitHub Copilot)")
tracker.add("cursor-agent", "Cursor IDE agent (optional)")
# Check each tool # Check each tool
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)
# Check for VS Code (code or code-insiders)
code_ok = check_tool_for_tracker("code", "https://code.visualstudio.com/", tracker)
if not code_ok:
code_ok = check_tool_for_tracker("code-insiders", "https://code.visualstudio.com/insiders/", tracker)
cursor_ok = check_tool_for_tracker("cursor-agent", "https://cursor.sh/", tracker)
# Render the final tree # Render the final tree
console.print(tracker.render()) console.print(tracker.render())

View File

@@ -1,9 +1,13 @@
<!-- VARIANT:sh 1. Run `scripts/bash/setup-plan.sh --json` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute. --> ---
<!-- VARIANT:ps 1. Run `scripts/powershell/setup-plan.ps1 -Json` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute. --> description: Execute the implementation planning workflow using the plan template to generate design artifacts.
scripts:
sh: scripts/bash/setup-plan.sh --json
ps: scripts/powershell/setup-plan.ps1 -Json
---
Given the implementation details provided as an argument, do this: Given the implementation details provided as an argument, do this:
1. VARIANT-INJECT 1. Run `{SCRIPT}` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute.
2. Read and analyze the feature specification to understand: 2. Read and analyze the feature specification to understand:
- The feature requirements and user stories - The feature requirements and user stories
- Functional and non-functional requirements - Functional and non-functional requirements

View File

@@ -1,9 +1,13 @@
<!-- VARIANT:sh 1. Run the script `scripts/bash/create-new-feature.sh --json "{ARGS}"` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute. --> ---
<!-- VARIANT:ps 1. Run the script `scripts/powershell/create-new-feature.ps1 -Json "{ARGS}"` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute. --> description: Create or update the feature specification from a natural language feature description.
scripts:
sh: scripts/bash/create-new-feature.sh --json "{ARGS}"
ps: scripts/powershell/create-new-feature.ps1 -Json "{ARGS}"
---
Given the feature description provided as an argument, do this: Given the feature description provided as an argument, do this:
1. VARIANT-INJECT 1. Run the script `{SCRIPT}` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute.
2. Load `templates/spec-template.md` to understand required sections. 2. Load `templates/spec-template.md` to understand required sections.
3. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings. 3. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
4. Report completion with branch name, spec file path, and readiness for the next phase. 4. Report completion with branch name, spec file path, and readiness for the next phase.

View File

@@ -1,9 +1,13 @@
<!-- VARIANT:sh 1. Run `scripts/bash/check-task-prerequisites.sh --json` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. --> ---
<!-- VARIANT:ps 1. Run `scripts/powershell/check-task-prerequisites.ps1 -Json` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. --> description: Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts.
scripts:
sh: scripts/bash/check-task-prerequisites.sh --json
ps: scripts/powershell/check-task-prerequisites.ps1 -Json
---
Given the context provided as an argument, do this: Given the context provided as an argument, do this:
1. VARIANT-INJECT 1. Run `{SCRIPT}` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute.
2. Load and analyze available design documents: 2. Load and analyze available design documents:
- Always read plan.md for tech stack and libraries - Always read plan.md for tech stack and libraries
- IF EXISTS: Read data-model.md for entities - IF EXISTS: Read data-model.md for entities