mirror of
https://github.com/github/spec-kit.git
synced 2026-02-01 13:33:37 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed5dbf197f | ||
|
|
df4d7fa062 | ||
|
|
b4ecd14ffa | ||
|
|
26fde7cfda | ||
|
|
8abc812c57 | ||
|
|
940714df0a | ||
|
|
f393ae9825 | ||
|
|
5846a38c68 |
129
AGENTS.md
129
AGENTS.md
@@ -37,58 +37,57 @@ Specify supports multiple AI agents by generating agent-specific command files a
|
|||||||
| **Cursor** | `.cursor/commands/` | Markdown | `cursor-agent` | Cursor CLI |
|
| **Cursor** | `.cursor/commands/` | Markdown | `cursor-agent` | Cursor CLI |
|
||||||
| **Qwen Code** | `.qwen/commands/` | TOML | `qwen` | Alibaba's Qwen Code CLI |
|
| **Qwen Code** | `.qwen/commands/` | TOML | `qwen` | Alibaba's Qwen Code CLI |
|
||||||
| **opencode** | `.opencode/command/` | Markdown | `opencode` | opencode 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 |
|
| **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 |
|
| **CodeBuddy** | `.codebuddy/commands/` | Markdown | `codebuddy` | CodeBuddy |
|
||||||
| **Amazon Q Developer CLI** | `.amazonq/prompts/` | Markdown | `q` | Amazon Q Developer CLI |
|
| **Amazon Q Developer CLI** | `.amazonq/prompts/` | Markdown | `q` | Amazon Q Developer CLI |
|
||||||
|
|
||||||
### Step-by-Step Integration Guide
|
### 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
|
```python
|
||||||
AI_CHOICES = {
|
AGENT_CONFIG = {
|
||||||
"copilot": "GitHub Copilot",
|
# ... existing agents ...
|
||||||
"claude": "Claude Code",
|
"new-agent-cli": { # Use the ACTUAL CLI tool name (what users type in terminal)
|
||||||
"gemini": "Gemini CLI",
|
"name": "New Agent Display Name",
|
||||||
"cursor": "Cursor",
|
"folder": ".newagent/", # Directory for agent files
|
||||||
"qwen": "Qwen Code",
|
"install_url": "https://example.com/install", # URL for installation docs (or None if IDE-based)
|
||||||
"opencode": "opencode",
|
"requires_cli": True, # True if CLI tool required, False for IDE-based agents
|
||||||
"windsurf": "Windsurf",
|
},
|
||||||
"codebuddy": "CodeBuddy"
|
|
||||||
"q": "Amazon Q Developer CLI"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
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
|
This eliminates the need for special-case mappings throughout the codebase.
|
||||||
agent_folder_map = {
|
|
||||||
"claude": ".claude/",
|
**Field Explanations**:
|
||||||
"gemini": ".gemini/",
|
- `name`: Human-readable display name shown to users
|
||||||
"cursor": ".cursor/",
|
- `folder`: Directory where agent-specific files are stored (relative to project root)
|
||||||
"qwen": ".qwen/",
|
- `install_url`: Installation documentation URL (set to `None` for IDE-based agents)
|
||||||
"opencode": ".opencode/",
|
- `requires_cli`: Whether the agent requires a CLI tool check during initialization
|
||||||
"codex": ".codex/",
|
|
||||||
"windsurf": ".windsurf/",
|
|
||||||
"kilocode": ".kilocode/",
|
|
||||||
"auggie": ".auggie/",
|
|
||||||
"copilot": ".github/",
|
|
||||||
"q": ".amazonq/",
|
|
||||||
"codebuddy": ".codebuddy/"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. Update CLI Help Text
|
#### 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
|
```python
|
||||||
- Function docstrings and examples
|
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"),
|
||||||
- Error messages with agent lists
|
```
|
||||||
|
|
||||||
|
Also update any function docstrings, examples, and error messages that list available agents.
|
||||||
|
|
||||||
#### 3. Update README Documentation
|
#### 3. Update README Documentation
|
||||||
|
|
||||||
@@ -192,11 +191,58 @@ elif selected_ai == "windsurf":
|
|||||||
agent_tool_missing = True
|
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
|
## Agent Categories
|
||||||
|
|
||||||
### CLI-Based Agents
|
### CLI-Based Agents
|
||||||
|
|
||||||
Require a command-line tool to be installed:
|
Require a command-line tool to be installed:
|
||||||
- **Claude Code**: `claude` CLI
|
- **Claude Code**: `claude` CLI
|
||||||
- **Gemini CLI**: `gemini` CLI
|
- **Gemini CLI**: `gemini` CLI
|
||||||
@@ -260,19 +306,22 @@ Different agents use different argument placeholders:
|
|||||||
|
|
||||||
## Common Pitfalls
|
## Common Pitfalls
|
||||||
|
|
||||||
1. **Forgetting update scripts**: Both bash and PowerShell scripts must be updated
|
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. **Missing CLI checks**: Only add for agents that actually have CLI tools
|
2. **Forgetting update scripts**: Both bash and PowerShell scripts must be updated when adding new agents.
|
||||||
3. **Wrong argument format**: Use correct placeholder format for each agent type
|
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. **Directory naming**: Follow agent-specific conventions exactly
|
4. **Wrong argument format**: Use correct placeholder format for each agent type (`$ARGUMENTS` for Markdown, `{{args}}` for TOML).
|
||||||
5. **Help text inconsistency**: Update all user-facing text consistently
|
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
|
## Future Considerations
|
||||||
|
|
||||||
When adding new agents:
|
When adding new agents:
|
||||||
|
|
||||||
- Consider the agent's native command/workflow patterns
|
- Consider the agent's native command/workflow patterns
|
||||||
- Ensure compatibility with the Spec-Driven Development process
|
- Ensure compatibility with the Spec-Driven Development process
|
||||||
- Document any special requirements or limitations
|
- Document any special requirements or limitations
|
||||||
- Update this guide with lessons learned
|
- Update this guide with lessons learned
|
||||||
|
- Verify the actual CLI tool name before adding to AGENT_CONFIG
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,12 @@ specify init <PROJECT_NAME>
|
|||||||
specify check
|
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
|
#### Option 2: One-time Usage
|
||||||
|
|
||||||
Run directly without installing:
|
Run directly without installing:
|
||||||
|
|||||||
@@ -882,7 +882,7 @@ def init(
|
|||||||
|
|
||||||
should_init_git = False
|
should_init_git = False
|
||||||
if not no_git:
|
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:
|
if not should_init_git:
|
||||||
console.print("[yellow]Git not found - will skip repository initialization[/yellow]")
|
console.print("[yellow]Git not found - will skip repository initialization[/yellow]")
|
||||||
|
|
||||||
@@ -904,7 +904,7 @@ def init(
|
|||||||
agent_config = AGENT_CONFIG.get(selected_ai)
|
agent_config = AGENT_CONFIG.get(selected_ai)
|
||||||
if agent_config and agent_config["requires_cli"]:
|
if agent_config and agent_config["requires_cli"]:
|
||||||
install_url = agent_config["install_url"]
|
install_url = agent_config["install_url"]
|
||||||
if not check_tool(selected_ai, install_url):
|
if not check_tool(selected_ai):
|
||||||
error_panel = Panel(
|
error_panel = Panel(
|
||||||
f"[cyan]{selected_ai}[/cyan] not found\n"
|
f"[cyan]{selected_ai}[/cyan] not found\n"
|
||||||
f"Install from: [cyan]{install_url}[/cyan]\n"
|
f"Install from: [cyan]{install_url}[/cyan]\n"
|
||||||
|
|||||||
@@ -97,7 +97,15 @@ Execution steps:
|
|||||||
|
|
||||||
4. Sequential questioning loop (interactive):
|
4. Sequential questioning loop (interactive):
|
||||||
- Present EXACTLY ONE question at a time.
|
- Present EXACTLY ONE question at a time.
|
||||||
- For multiple‑choice questions render options as a Markdown table:
|
- For multiple‑choice 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 |
|
| Option | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
@@ -106,9 +114,14 @@ Execution steps:
|
|||||||
| C | <Option C description> | (add D/E as needed up to 5)
|
| 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)
|
| Short | Provide a different short answer (<=5 words) | (Include only if free-form alternative is appropriate)
|
||||||
|
|
||||||
- For short‑answer 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 short‑answer 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:
|
- 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).
|
* 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.
|
* 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:
|
- Stop asking further questions when:
|
||||||
|
|||||||
@@ -8,6 +8,6 @@
|
|||||||
},
|
},
|
||||||
"chat.tools.terminal.autoApprove": {
|
"chat.tools.terminal.autoApprove": {
|
||||||
".specify/scripts/bash/": true,
|
".specify/scripts/bash/": true,
|
||||||
".specify/scripts/ps/": true
|
".specify/scripts/powershell/": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user