Compare commits

...

11 Commits

Author SHA1 Message Date
Den Delimarsky
e65660ffc3 Merge pull request #831 from ben-edgar/bugfix/cursor-package-name-update
fix: align Cursor agent naming to use 'cursor-agent' consistently
2025-10-11 09:05:49 -07:00
Ben Greene
f7ae5781b7 A few more places to update from code review 2025-10-10 21:12:06 -04:00
Ben Greene
d09552fc63 fix: align Cursor agent naming to use 'cursor-agent' consistently
The Python CLI was configured to use "cursor-agent" as the agent key in
AGENT_CONFIG, causing it to search for release packages with the pattern
"spec-kit-template-cursor-agent-sh-*.zip". However, the release build
scripts were generating packages named "spec-kit-template-cursor-sh-*.zip",
resulting in a mismatch that prevented successful template downloads.

This commit updates the release scripts to use "cursor-agent" consistently
throughout, aligning with the AGENT_CONFIG key and the documented best
practice of using actual CLI tool names as dictionary keys.

Changes:
- Update ALL_AGENTS array in create-release-packages.sh
- Update case statement for cursor-agent in build_variant()
- Update release asset paths in create-github-release.sh
- Update documentation in README.md and AGENTS.md to reflect correct usage

This ensures that `specify init --ai cursor-agent` correctly finds and
downloads the matching release package from GitHub.

Fixes the bug where cursor-agent initialization would fail with "No matching
release asset found" error.

**Written with the help of a cursor agent**
2025-10-10 20:43:20 -04:00
Den Delimarsky
ed5dbf197f Merge pull request #828 from github/localden/updates
Update clarify.md
2025-10-10 13:19:10 -07:00
den (work)
df4d7fa062 Update clarify.md 2025-10-10 13:09:11 -07:00
Den Delimarsky
b4ecd14ffa Merge pull request #800 from technoch1ef/patch-1
feat: add documentation for upgrading specify installation
2025-10-10 13:03:59 -07:00
Den Delimarsky
26fde7cfda Merge pull request #827 from github/localden/updates
Update vscode-settings.json
2025-10-10 12:30:16 -07:00
den (work)
8abc812c57 Update vscode-settings.json 2025-10-10 12:29:46 -07:00
Den Delimarsky
940714df0a Merge pull request #826 from github/localden/updates
Hot Fix
2025-10-10 11:58:36 -07:00
den (work)
f393ae9825 Update instructions and bug fix 2025-10-10 11:58:10 -07:00
Oleksandr Ovcharov
5846a38c68 add how to upgrade specify installation 2025-10-09 16:19:36 +02:00
9 changed files with 133 additions and 65 deletions

View File

@@ -22,8 +22,8 @@ gh release create "$VERSION" \
.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-sh-"$VERSION".zip \
.genreleases/spec-kit-template-cursor-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 \

View File

@@ -6,7 +6,7 @@ set -euo pipefail
# 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 qwen opencode windsurf codex (default: all)
# AGENTS : space or comma separated subset of: claude gemini copilot cursor-agent qwen opencode windsurf codex (default: all)
# SCRIPTS : space or comma separated subset of: sh ps (default: both)
# Examples:
# AGENTS=claude SCRIPTS=sh $0 v0.2.0
@@ -133,7 +133,7 @@ build_variant() {
[[ -d templates ]] && { mkdir -p "$SPEC_DIR/templates"; find templates -type f -not -path "templates/commands/*" -not -name "vscode-settings.json" -exec cp --parents {} "$SPEC_DIR"/ \; ; echo "Copied templates -> .specify/templates"; }
# NOTE: We substitute {ARGS} internally. Outward tokens differ intentionally:
# * Markdown/prompt (claude, copilot, cursor, opencode): $ARGUMENTS
# * Markdown/prompt (claude, copilot, cursor-agent, opencode): $ARGUMENTS
# * TOML (gemini, qwen): {{args}}
# This keeps formats readable without extra abstraction.
@@ -152,9 +152,9 @@ build_variant() {
mkdir -p "$base_dir/.vscode"
[[ -f templates/vscode-settings.json ]] && cp templates/vscode-settings.json "$base_dir/.vscode/settings.json"
;;
cursor)
cursor-agent)
mkdir -p "$base_dir/.cursor/commands"
generate_commands cursor md "\$ARGUMENTS" "$base_dir/.cursor/commands" "$script" ;;
generate_commands cursor-agent md "\$ARGUMENTS" "$base_dir/.cursor/commands" "$script" ;;
qwen)
mkdir -p "$base_dir/.qwen/commands"
generate_commands qwen toml "{{args}}" "$base_dir/.qwen/commands" "$script"
@@ -190,7 +190,7 @@ build_variant() {
}
# Determine agent list
ALL_AGENTS=(claude gemini copilot cursor qwen opencode windsurf codex kilocode auggie roo codebuddy q)
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy q)
ALL_SCRIPTS=(sh ps)
norm_list() {

133
AGENTS.md
View File

@@ -37,58 +37,57 @@ Specify supports multiple AI agents by generating agent-specific command files a
| **Cursor** | `.cursor/commands/` | Markdown | `cursor-agent` | Cursor CLI |
| **Qwen Code** | `.qwen/commands/` | TOML | `qwen` | Alibaba's Qwen Code CLI |
| **opencode** | `.opencode/command/` | Markdown | `opencode` | opencode CLI |
| **Codex CLI** | `.codex/commands/` | Markdown | `codex` | Codex CLI |
| **Windsurf** | `.windsurf/workflows/` | Markdown | N/A (IDE-based) | Windsurf IDE workflows |
| **Kilo Code** | `.kilocode/rules/` | Markdown | N/A (IDE-based) | Kilo Code IDE |
| **Auggie CLI** | `.augment/rules/` | Markdown | `auggie` | Auggie CLI |
| **Roo Code** | `.roo/rules/` | Markdown | N/A (IDE-based) | Roo Code IDE |
| **CodeBuddy** | `.codebuddy/commands/` | Markdown | `codebuddy` | CodeBuddy |
| **Amazon Q Developer CLI** | `.amazonq/prompts/` | Markdown | `q` | Amazon Q Developer CLI |
### Step-by-Step Integration Guide
Follow these steps to add a new agent (using Windsurf as an example):
Follow these steps to add a new agent (using a hypothetical new agent as an example):
#### 1. Update AI_CHOICES Constant
#### 1. Add to AGENT_CONFIG
Add the new agent to the `AI_CHOICES` dictionary in `src/specify_cli/__init__.py`:
**IMPORTANT**: Use the actual CLI tool name as the key, not a shortened version.
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:
```python
AI_CHOICES = {
"copilot": "GitHub Copilot",
"claude": "Claude Code",
"gemini": "Gemini CLI",
"cursor": "Cursor",
"qwen": "Qwen Code",
"opencode": "opencode",
"windsurf": "Windsurf",
"codebuddy": "CodeBuddy"
"q": "Amazon Q Developer CLI"
AGENT_CONFIG = {
# ... existing agents ...
"new-agent-cli": { # Use the ACTUAL CLI tool name (what users type in terminal)
"name": "New Agent Display Name",
"folder": ".newagent/", # Directory for agent files
"install_url": "https://example.com/install", # URL for installation docs (or None if IDE-based)
"requires_cli": True, # True if CLI tool required, False for IDE-based agents
},
}
```
Also update the `agent_folder_map` in the same file to include the new agent's folder for the security notice:
**Key Design Principle**: The dictionary key should match the actual executable name that users install. For example:
- ✅ 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`
```python
agent_folder_map = {
"claude": ".claude/",
"gemini": ".gemini/",
"cursor": ".cursor/",
"qwen": ".qwen/",
"opencode": ".opencode/",
"codex": ".codex/",
"windsurf": ".windsurf/",
"kilocode": ".kilocode/",
"auggie": ".auggie/",
"copilot": ".github/",
"q": ".amazonq/",
"codebuddy": ".codebuddy/"
}
```
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)
- `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 all help text and examples to include the new agent:
Update the `--ai` parameter help text in the `init()` command to include the new agent:
- Command option help: `--ai` parameter description
- Function docstrings and examples
- Error messages with agent lists
```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 q"),
```
Also update any function docstrings, examples, and error messages that list available agents.
#### 3. Update README Documentation
@@ -105,7 +104,7 @@ Modify `.github/workflows/scripts/create-release-packages.sh`:
##### Add to ALL_AGENTS array:
```bash
ALL_AGENTS=(claude gemini copilot cursor qwen opencode windsurf q)
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf q)
```
##### Add case statement for directory structure:
@@ -192,11 +191,58 @@ elif selected_ai == "windsurf":
agent_tool_missing = True
```
**Note**: Skip CLI checks for IDE-based agents (Copilot, Windsurf).
**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:
cli_tool = agent_key
if agent_key == "cursor":
cli_tool = "cursor-agent" # Map to the real tool name
```
**Correct approach** (no mapping needed):
```python
AGENT_CONFIG = {
"cursor-agent": { # Matches the actual executable name
"name": "Cursor",
# ...
}
}
# No special cases needed - just use agent_key directly!
```
**Benefits of this approach:**
- Eliminates special-case logic scattered throughout the codebase
- Makes the code more maintainable and easier to understand
- Reduces the chance of bugs when adding new agents
- Tool checking "just works" without additional mappings
## Agent Categories
### CLI-Based Agents
Require a command-line tool to be installed:
- **Claude Code**: `claude` CLI
- **Gemini CLI**: `gemini` CLI
@@ -260,20 +306,23 @@ Different agents use different argument placeholders:
## Common Pitfalls
1. **Forgetting update scripts**: Both bash and PowerShell scripts must be updated
2. **Missing CLI checks**: Only add for agents that actually have CLI tools
3. **Wrong argument format**: Use correct placeholder format for each agent type
4. **Directory naming**: Follow agent-specific conventions exactly
5. **Help text inconsistency**: Update all user-facing text consistently
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.
2. **Forgetting update scripts**: Both bash and PowerShell scripts must be updated when adding new agents.
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.
4. **Wrong argument format**: Use correct placeholder format for each agent type (`$ARGUMENTS` for Markdown, `{{args}}` for TOML).
5. **Directory naming**: Follow agent-specific conventions exactly (check existing agents for patterns).
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 agents are added to maintain accuracy and completeness.*

View File

@@ -61,6 +61,12 @@ specify init <PROJECT_NAME>
specify check
```
To upgrade specify run:
```bash
uv tool install specify-cli --force --from git+https://github.com/github/spec-kit.git
```
#### Option 2: One-time Usage
Run directly without installing:
@@ -158,7 +164,7 @@ The `specify` command supports the following 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: `claude`, `gemini`, `copilot`, `cursor`, `qwen`, `opencode`, `codex`, `windsurf`, `kilocode`, `auggie`, `roo`, `codebuddy`, or `q` |
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, `cursor-agent`, `qwen`, `opencode`, `codex`, `windsurf`, `kilocode`, `auggie`, `roo`, `codebuddy`, or `q` |
| `--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 |

View File

@@ -35,7 +35,7 @@
# - Creates default Claude file if no agent files exist
#
# Usage: ./update-agent-context.sh [agent_type]
# Agent types: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|q
# Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|q
# Leave empty to update all existing agent files
set -e
@@ -558,7 +558,7 @@ update_specific_agent() {
copilot)
update_agent_file "$COPILOT_FILE" "GitHub Copilot"
;;
cursor)
cursor-agent)
update_agent_file "$CURSOR_FILE" "Cursor IDE"
;;
qwen)
@@ -590,7 +590,7 @@ update_specific_agent() {
;;
*)
log_error "Unknown agent type '$agent_type'"
log_error "Expected: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|roo|q"
log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|q"
exit 1
;;
esac
@@ -684,7 +684,7 @@ print_summary() {
echo
log_info "Usage: $0 [claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|codebuddy|q]"
log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|codebuddy|q]"
}
#==============================================================================

View File

@@ -9,7 +9,7 @@ Mirrors the behavior of scripts/bash/update-agent-context.sh:
2. Plan Data Extraction
3. Agent File Management (create from template or update existing)
4. Content Generation (technology stack, recent changes, timestamp)
5. Multi-Agent Support (claude, gemini, copilot, cursor, qwen, opencode, codex, windsurf, kilocode, auggie, roo, q)
5. Multi-Agent Support (claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, roo, q)
.PARAMETER AgentType
Optional agent key to update a single agent. If omitted, updates all existing agent files (creating a default Claude file if none exist).
@@ -25,7 +25,7 @@ Relies on common helper functions in common.ps1
#>
param(
[Parameter(Position=0)]
[ValidateSet('claude','gemini','copilot','cursor','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','q')]
[ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','q')]
[string]$AgentType
)
@@ -370,7 +370,7 @@ function Update-SpecificAgent {
'claude' { Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code' }
'gemini' { Update-AgentFile -TargetFile $GEMINI_FILE -AgentName 'Gemini CLI' }
'copilot' { Update-AgentFile -TargetFile $COPILOT_FILE -AgentName 'GitHub Copilot' }
'cursor' { Update-AgentFile -TargetFile $CURSOR_FILE -AgentName 'Cursor IDE' }
'cursor-agent' { Update-AgentFile -TargetFile $CURSOR_FILE -AgentName 'Cursor IDE' }
'qwen' { Update-AgentFile -TargetFile $QWEN_FILE -AgentName 'Qwen Code' }
'opencode' { Update-AgentFile -TargetFile $AGENTS_FILE -AgentName 'opencode' }
'codex' { Update-AgentFile -TargetFile $AGENTS_FILE -AgentName 'Codex CLI' }
@@ -380,7 +380,7 @@ function Update-SpecificAgent {
'roo' { Update-AgentFile -TargetFile $ROO_FILE -AgentName 'Roo Code' }
'codebuddy' { Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy' }
'q' { Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI' }
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|q'; return $false }
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|q'; return $false }
}
}
@@ -413,7 +413,7 @@ function Print-Summary {
if ($NEW_FRAMEWORK) { Write-Host " - Added framework: $NEW_FRAMEWORK" }
if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Host " - Added database: $NEW_DB" }
Write-Host ''
Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|q]'
Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|q]'
}
function Main {

View File

@@ -882,7 +882,7 @@ def init(
should_init_git = False
if not no_git:
should_init_git = check_tool("git", "https://git-scm.com/downloads")
should_init_git = check_tool("git")
if not should_init_git:
console.print("[yellow]Git not found - will skip repository initialization[/yellow]")
@@ -904,7 +904,7 @@ def init(
agent_config = AGENT_CONFIG.get(selected_ai)
if agent_config and agent_config["requires_cli"]:
install_url = agent_config["install_url"]
if not check_tool(selected_ai, install_url):
if not check_tool(selected_ai):
error_panel = Panel(
f"[cyan]{selected_ai}[/cyan] not found\n"
f"Install from: [cyan]{install_url}[/cyan]\n"

View File

@@ -97,7 +97,15 @@ Execution steps:
4. Sequential questioning loop (interactive):
- Present EXACTLY ONE question at a time.
- For multiplechoice questions render options as a Markdown table:
- For multiplechoice questions:
* **Analyze all options** and determine the **most suitable option** based on:
- Best practices for the project type
- Common patterns in similar implementations
- Risk reduction (security, performance, maintainability)
- Alignment with any explicit project goals or constraints visible in the spec
* Present your **recommended option prominently** at the top with clear reasoning (1-2 sentences explaining why this is the best choice).
* Format as: `**Recommended:** Option [X] - <reasoning>`
* Then render all options as a Markdown table:
| Option | Description |
|--------|-------------|
@@ -106,9 +114,14 @@ Execution steps:
| C | <Option C description> | (add D/E as needed up to 5)
| Short | Provide a different short answer (<=5 words) | (Include only if free-form alternative is appropriate)
- For shortanswer style (no meaningful discrete options), output a single line after the question: `Format: Short answer (<=5 words)`.
* After the table, add: `You can reply with the option letter (e.g., "A"), accept the recommendation by saying "yes" or "recommended", or provide your own short answer.`
- For shortanswer style (no meaningful discrete options):
* Provide your **suggested answer** based on best practices and context.
* Format as: `**Suggested:** <your proposed answer> - <brief reasoning>`
* Then output: `Format: Short answer (<=5 words). You can accept the suggestion by saying "yes" or "suggested", or provide your own answer.`
- After the user answers:
* Validate the answer maps to one option or fits the <=5 word constraint.
* If the user replies with "yes", "recommended", or "suggested", use your previously stated recommendation/suggestion as the answer.
* Otherwise, validate the answer maps to one option or fits the <=5 word constraint.
* If ambiguous, ask for a quick disambiguation (count still belongs to same question; do not advance).
* Once satisfactory, record it in working memory (do not yet write to disk) and move to the next queued question.
- Stop asking further questions when:

View File

@@ -8,6 +8,6 @@
},
"chat.tools.terminal.autoApprove": {
".specify/scripts/bash/": true,
".specify/scripts/ps/": true
".specify/scripts/powershell/": true
}
}