mirror of
https://github.com/github/spec-kit.git
synced 2026-07-03 12:28:06 +08:00
* Initial plan * Extract agent context updates into bundled agent-context extension * Potential fix for pull request finding 'Unused import' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * Potential fix for pull request finding 'Unused import' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * fix: address review comments on agent-context extension - bash: parse init-options.json with a single python3 invocation instead of three separate read_json_field calls, for parity with the PowerShell ConvertFrom-Json approach and to avoid divergent error semantics - bash: use parameter expansion to strip PROJECT_ROOT prefix from plan path instead of sed interpolation, avoiding special-character fragility - powershell: limit Get-ChildItem to -Depth 1 so plan.md discovery matches the bash glob specs/*/plan.md (one level deep) — fixes cross-platform inconsistency with nested plan.md files - powershell: replace Substring+Length relative-path with [System.IO.Path]::GetRelativePath for robustness across case/PSDrive differences - __init__.py: move agent-context extension install to after save_init_options so init-options.json is present when hooks run - __init__.py: seed context_markers in init-options only when context_file is truthy; avoids noise for integrations without a context file - integrations/base.py: narrow blanket except Exception in _resolve_context_markers to ImportError / (OSError, ValueError) so unexpected bugs surface instead of being silently swallowed * fix: gate context_markers in _update_init_options_for_integration on context_file Apply the same gating logic used during `specify init`: only write context_markers to init-options.json when the integration actually has a context_file set. When switching to an integration without a context file the stale markers are removed, keeping the two init paths consistent. * fix: move context_file/context_markers from init-options.json to agent-context extension config * Potential fix for pull request finding 'Unused global variable' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * fix: clarify local import comment in agents.py * Fix remaining agent-context review findings * Fix follow-up agent-context review issues * Address review feedback: narrow except, improve PyYAML messaging, surface config-written note * Fix double-space in PyYAML install hint message * Potential fix for pull request finding 'Empty except' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * Potential fix for pull request finding 'Empty except' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * Address latest agent-context review feedback * Harden bash config parse output handling * Clarify ImportError-only fallback comment * Apply review feedback: drop dead try/except, guard ext-config creation, explicit ConvertFrom-Yaml check * Remove redundant $Options = $null in PS1 catch block * Add constitution directives, deprecation warning, agent-context auto-install, and init flow fix - Add constitution-loading directive to specify, clarify, tasks, checklist, taskstoissues commands - Add deprecation warning (v0.12.0) in upsert_context_section() - Auto-install agent-context extension during specify init - Move context_file from init-options.json to agent-context extension config - Add tests: deprecation warning, corrupt config, constitution directives - Update file inventories across all integration tests * Address review: fix init ordering, test coverage, and hermes inventory - Move agent-context extension install after init-options.json is saved so skill registration can read ai_skills + integration key - Write extension config after install (avoids template overwriting context_file) - Fix test_defaults_when_markers_field_missing to truly test missing markers key - Update hermes tests to allow extension-installed agent-context skill * Address review: chmod ordering, preserve markers, PS1 Python check, YAML key order - Move ensure_executable_scripts after agent-context extension install so extension scripts get execute bits set - Use preserve_markers=True on reinit to keep user-customized markers - Add Python 3 version check in PowerShell fallback (matching bash behavior) - Add sort_keys=False to yaml.safe_dump for stable config output * Address review: path traversal guards and docstring fix - Reject absolute paths and '..' segments in context_file in both bash and PowerShell scripts to prevent writes outside the project root - Fix docstring in _update_init_options_for_integration to accurately describe marker preservation behavior * Address review: strict enabled check, docstring, segment-level path traversal - Use 'is not False' for enabled check so only literal False disables - Update upsert_context_section docstring to mention disabled-extension return - Fix path traversal guards to check actual path segments, not substrings (allows filenames like 'notes..md' while rejecting '../' traversal) * Address review: UnicodeError handling, missing extension warning - Add UnicodeError to exception tuples in _load_agent_context_config and _resolve_context_markers so garbled UTF-8 config files fall back to defaults - Emit error (with reinstall command) instead of silent skip when bundled agent-context extension is not found during init * Address review: bash backslash traversal guard, wheel packaging - Reject backslash separators and Windows drive-letter paths in bash context_file validation (prevents traversal on Git-Bash/Windows) - Add extensions/agent-context to pyproject.toml force-include so the bundled extension is included in wheel builds * Address review: write extension config before init-options.json - Reorder writes in _update_init_options_for_integration so the agent-context extension config is updated first; if it fails, init-options.json remains consistent with the previous state --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Manfred Riem <15701806+mnriem@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
437 lines
18 KiB
Markdown
437 lines
18 KiB
Markdown
# AGENTS.md
|
|
|
|
## About Spec Kit and Specify
|
|
|
|
**GitHub Spec Kit** is a comprehensive toolkit for implementing Spec-Driven Development (SDD) - a methodology that emphasizes creating clear specifications before implementation. The toolkit includes templates, scripts, and workflows that guide development teams through a structured approach to building software.
|
|
|
|
**Specify CLI** is the command-line interface that bootstraps projects with the Spec Kit framework. It sets up the necessary directory structures, templates, and AI agent integrations to support the Spec-Driven Development workflow.
|
|
|
|
The toolkit supports multiple AI coding assistants, allowing teams to use their preferred tools while maintaining consistent project structure and development practices.
|
|
|
|
---
|
|
|
|
## Integration Architecture
|
|
|
|
Each AI agent is a self-contained **integration subpackage** under `src/specify_cli/integrations/<key>/`. The subpackage exposes a single class that declares all metadata and inherits setup/teardown logic from a base class. Built-in integrations are then instantiated and added to the global `INTEGRATION_REGISTRY` by `src/specify_cli/integrations/__init__.py` via `_register_builtins()`.
|
|
|
|
```
|
|
src/specify_cli/integrations/
|
|
├── __init__.py # INTEGRATION_REGISTRY + _register_builtins()
|
|
├── base.py # IntegrationBase, MarkdownIntegration, TomlIntegration, YamlIntegration, SkillsIntegration
|
|
├── manifest.py # IntegrationManifest (file tracking)
|
|
├── claude/ # Example: SkillsIntegration subclass
|
|
│ └── __init__.py # ClaudeIntegration class
|
|
├── gemini/ # Example: TomlIntegration subclass
|
|
│ └── __init__.py
|
|
├── windsurf/ # Example: MarkdownIntegration subclass
|
|
│ └── __init__.py
|
|
├── copilot/ # Example: IntegrationBase subclass (custom setup)
|
|
│ └── __init__.py
|
|
└── ... # One subpackage per supported agent
|
|
```
|
|
|
|
The registry is the **single source of truth for Python integration metadata**. Supported agents, their directories, formats, capabilities, and context files are derived from the integration classes for the Python integration layer.
|
|
|
|
---
|
|
|
|
## Adding a New Integration
|
|
|
|
### 1. Choose a base class
|
|
|
|
| Your agent needs… | Subclass |
|
|
|---|---|
|
|
| Standard markdown commands (`.md`) | `MarkdownIntegration` |
|
|
| TOML-format commands (`.toml`) | `TomlIntegration` |
|
|
| YAML recipe files (`.yaml`) | `YamlIntegration` |
|
|
| Skill directories (`speckit-<name>/SKILL.md`) | `SkillsIntegration` |
|
|
| Fully custom output (companion files, settings merge, etc.) | `IntegrationBase` directly |
|
|
|
|
Most agents only need `MarkdownIntegration` — a minimal subclass with zero method overrides.
|
|
|
|
### 2. Create the subpackage
|
|
|
|
Create `src/specify_cli/integrations/<package_dir>/__init__.py`, where `<package_dir>` is the Python-safe directory name derived from `<key>`: use the key as-is when it contains no hyphens (e.g., key `"gemini"` → `gemini/`), or replace hyphens with underscores when it does (e.g., key `"kiro-cli"` → `kiro_cli/`). The `IntegrationBase.key` class attribute always retains the original hyphenated value, since that is what the CLI and registry use. For CLI-based integrations (`requires_cli: True`), the `key` should match the actual CLI tool name (the executable users install and run) so CLI checks can resolve it correctly. For IDE-based integrations (`requires_cli: False`), use the canonical integration identifier instead.
|
|
|
|
**Minimal example — Markdown agent (Windsurf):**
|
|
|
|
```python
|
|
"""Windsurf IDE integration."""
|
|
|
|
from ..base import MarkdownIntegration
|
|
|
|
|
|
class WindsurfIntegration(MarkdownIntegration):
|
|
key = "windsurf"
|
|
config = {
|
|
"name": "Windsurf",
|
|
"folder": ".windsurf/",
|
|
"commands_subdir": "workflows",
|
|
"install_url": None,
|
|
"requires_cli": False,
|
|
}
|
|
registrar_config = {
|
|
"dir": ".windsurf/workflows",
|
|
"format": "markdown",
|
|
"args": "$ARGUMENTS",
|
|
"extension": ".md",
|
|
}
|
|
context_file = ".windsurf/rules/specify-rules.md"
|
|
```
|
|
|
|
**TOML agent (Gemini):**
|
|
|
|
```python
|
|
"""Gemini CLI integration."""
|
|
|
|
from ..base import TomlIntegration
|
|
|
|
|
|
class GeminiIntegration(TomlIntegration):
|
|
key = "gemini"
|
|
config = {
|
|
"name": "Gemini CLI",
|
|
"folder": ".gemini/",
|
|
"commands_subdir": "commands",
|
|
"install_url": "https://github.com/google-gemini/gemini-cli",
|
|
"requires_cli": True,
|
|
}
|
|
registrar_config = {
|
|
"dir": ".gemini/commands",
|
|
"format": "toml",
|
|
"args": "{{args}}",
|
|
"extension": ".toml",
|
|
}
|
|
context_file = "GEMINI.md"
|
|
```
|
|
|
|
**Skills agent (Codex):**
|
|
|
|
```python
|
|
"""Codex CLI integration — skills-based agent."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from ..base import IntegrationOption, SkillsIntegration
|
|
|
|
|
|
class CodexIntegration(SkillsIntegration):
|
|
key = "codex"
|
|
config = {
|
|
"name": "Codex CLI",
|
|
"folder": ".agents/",
|
|
"commands_subdir": "skills",
|
|
"install_url": "https://github.com/openai/codex",
|
|
"requires_cli": True,
|
|
}
|
|
registrar_config = {
|
|
"dir": ".agents/skills",
|
|
"format": "markdown",
|
|
"args": "$ARGUMENTS",
|
|
"extension": "/SKILL.md",
|
|
}
|
|
context_file = "AGENTS.md"
|
|
|
|
@classmethod
|
|
def options(cls) -> list[IntegrationOption]:
|
|
return [
|
|
IntegrationOption(
|
|
"--skills",
|
|
is_flag=True,
|
|
default=True,
|
|
help="Install as agent skills (default for Codex)",
|
|
),
|
|
]
|
|
```
|
|
|
|
#### Required fields
|
|
|
|
| Field | Location | Purpose |
|
|
|---|---|---|
|
|
| `key` | Class attribute | Unique identifier; for CLI-based integrations (`requires_cli: True`), must match the CLI executable name |
|
|
| `config` | Class attribute (dict) | Agent metadata: `name`, `folder`, `commands_subdir`, `install_url`, `requires_cli` |
|
|
| `registrar_config` | Class attribute (dict) | Command output config: `dir`, `format`, `args` placeholder, file `extension` |
|
|
| `context_file` | Class attribute (str or None) | Path to agent context/instructions file (e.g., `"CLAUDE.md"`, `".github/copilot-instructions.md"`) |
|
|
|
|
**Key design rule:** For CLI-based integrations (`requires_cli: True`), `key` must be the actual executable name (e.g., `"cursor-agent"` not `"cursor"`). This ensures `shutil.which(key)` works for CLI-tool checks without special-case mappings. IDE-based integrations (`requires_cli: False`) should use their canonical identifier (e.g., `"windsurf"`, `"copilot"`).
|
|
|
|
### 3. Register it
|
|
|
|
In `src/specify_cli/integrations/__init__.py`, add one import and one `_register()` call inside `_register_builtins()`. Both lists are alphabetical:
|
|
|
|
```python
|
|
def _register_builtins() -> None:
|
|
# -- Imports (alphabetical) -------------------------------------------
|
|
from .claude import ClaudeIntegration
|
|
# ...
|
|
from .newagent import NewAgentIntegration # ← add import
|
|
# ...
|
|
|
|
# -- Registration (alphabetical) --------------------------------------
|
|
_register(ClaudeIntegration())
|
|
# ...
|
|
_register(NewAgentIntegration()) # ← add registration
|
|
# ...
|
|
```
|
|
|
|
### 4. Context file behavior
|
|
|
|
Set `context_file` on the integration class. The base integration setup creates or updates the managed Spec Kit section in that file, and uninstall removes the managed section when appropriate.
|
|
|
|
The managed section is owned by the bundled `agent-context` extension (`extensions/agent-context/`). All configuration flows through the extension's own config file at `.specify/extensions/agent-context/agent-context-config.yml`:
|
|
|
|
```yaml
|
|
# Path to the coding agent context file managed by this extension
|
|
context_file: CLAUDE.md
|
|
|
|
# Delimiters for the managed Spec Kit section
|
|
context_markers:
|
|
start: "<!-- SPECKIT START -->"
|
|
end: "<!-- SPECKIT END -->"
|
|
```
|
|
|
|
- `context_file` is written automatically from the integration's class attribute when `specify init` or `specify integration use` is run.
|
|
- `context_markers.{start,end}` defaults to `IntegrationBase.CONTEXT_MARKER_START` / `CONTEXT_MARKER_END`. Users who want custom markers edit `agent-context-config.yml` directly — both the Python layer (`upsert_context_section()` / `remove_context_section()`) and the bundled scripts (`extensions/agent-context/scripts/bash/update-agent-context.sh` and `.ps1`) read from this single source of truth.
|
|
|
|
Users can opt out entirely with `specify extension disable agent-context`; while disabled, Spec Kit skips context-file creation, updates, and removal (the gates are inside `upsert_context_section()` and `remove_context_section()`).
|
|
|
|
Only add custom setup logic when the agent needs non-standard behavior. Integrations no longer require per-agent thin wrapper scripts or shared context-update dispatcher scripts — the `agent-context` extension is fully generic.
|
|
|
|
### 5. Test it
|
|
|
|
```bash
|
|
# Install into a test project
|
|
specify init my-project --integration <key>
|
|
|
|
# Verify files were created in the commands directory configured by
|
|
# config["folder"] + config["commands_subdir"] (for example, .windsurf/workflows/)
|
|
ls -R my-project/.windsurf/workflows/
|
|
|
|
# Uninstall cleanly
|
|
cd my-project && specify integration uninstall <key>
|
|
```
|
|
|
|
Each integration also has a dedicated test file at `tests/integrations/test_integration_<key>.py`. Note that hyphens in the key are replaced with underscores in the filename (e.g., key `cursor-agent` → `test_integration_cursor_agent.py`, key `kiro-cli` → `test_integration_kiro_cli.py`). Run it with:
|
|
|
|
```bash
|
|
pytest tests/integrations/test_integration_<key_with_underscores>.py -v
|
|
```
|
|
|
|
### 6. Optional overrides
|
|
|
|
The base classes handle most work automatically. Override only when the agent deviates from standard patterns:
|
|
|
|
| Override | When to use | Example |
|
|
|---|---|---|
|
|
| `command_filename(template_name)` | Custom file naming or extension | Copilot → `speckit.{name}.agent.md` |
|
|
| `options()` | Integration-specific CLI flags via `--integration-options` | Codex → `--skills` flag, Copilot → `--skills` flag |
|
|
| `setup()` | Custom install logic (companion files, settings merge) | Copilot → `.agent.md` + `.prompt.md` + `.vscode/settings.json` (default) or `speckit-<name>/SKILL.md` (skills mode) |
|
|
| `teardown()` | Custom uninstall logic | Rarely needed; base handles manifest-tracked files |
|
|
|
|
**Example — Copilot (fully custom `setup`):**
|
|
|
|
Copilot extends `IntegrationBase` directly because it creates `.agent.md` commands, companion `.prompt.md` files, and merges `.vscode/settings.json`. It also supports a `--skills` mode that scaffolds `speckit-<name>/SKILL.md` under `.github/skills/` using composition with an internal `_CopilotSkillsHelper`. See `src/specify_cli/integrations/copilot/__init__.py` for the full implementation.
|
|
|
|
### 7. Update Devcontainer files (Optional)
|
|
|
|
For agents that have VS Code extensions or require CLI installation, update the devcontainer configuration files:
|
|
|
|
#### VS Code Extension-based Agents
|
|
|
|
For agents available as VS Code extensions, add them to `.devcontainer/devcontainer.json`:
|
|
|
|
```jsonc
|
|
{
|
|
"customizations": {
|
|
"vscode": {
|
|
"extensions": [
|
|
// ... existing extensions ...
|
|
"[New Agent Extension ID]"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### CLI-based Agents
|
|
|
|
For agents that require CLI tools, add installation commands to `.devcontainer/post-create.sh`:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Existing installations...
|
|
|
|
echo -e "\n🤖 Installing [New Agent Name] CLI..."
|
|
# run_command "npm install -g [agent-cli-package]@latest"
|
|
echo "✅ Done"
|
|
```
|
|
|
|
---
|
|
|
|
## Command File Formats
|
|
|
|
### Markdown Format
|
|
|
|
**Standard format:**
|
|
|
|
```markdown
|
|
---
|
|
description: "Command description"
|
|
---
|
|
|
|
Command content with {SCRIPT} and $ARGUMENTS placeholders.
|
|
```
|
|
|
|
**GitHub Copilot Chat Mode format:**
|
|
|
|
```markdown
|
|
---
|
|
description: "Command description"
|
|
mode: speckit.command-name
|
|
---
|
|
|
|
Command content with {SCRIPT} and $ARGUMENTS placeholders.
|
|
```
|
|
|
|
### TOML Format
|
|
|
|
```toml
|
|
description = "Command description"
|
|
|
|
prompt = """
|
|
Command content with {SCRIPT} and {{args}} placeholders.
|
|
"""
|
|
```
|
|
|
|
### YAML Format
|
|
|
|
Used by: Goose
|
|
|
|
```yaml
|
|
version: 1.0.0
|
|
title: "Command Title"
|
|
description: "Command description"
|
|
author:
|
|
contact: spec-kit
|
|
extensions:
|
|
- type: builtin
|
|
name: developer
|
|
activities:
|
|
- Spec-Driven Development
|
|
prompt: |
|
|
Command content with {SCRIPT} and {{args}} placeholders.
|
|
```
|
|
|
|
## Argument Patterns
|
|
|
|
Different agents use different argument placeholders. The placeholder used in command files is always taken from `registrar_config["args"]` for each integration — check there first when in doubt:
|
|
|
|
- **Markdown/prompt-based**: `$ARGUMENTS` (default for most markdown agents)
|
|
- **TOML-based**: `{{args}}` (e.g., Gemini)
|
|
- **YAML-based**: `{{args}}` (e.g., Goose)
|
|
- **Custom**: some agents override the default (e.g., Forge uses `{{parameters}}`)
|
|
- **Script placeholders**: `{SCRIPT}` (replaced with actual script path)
|
|
- **Agent placeholders**: `__AGENT__` (replaced with agent name)
|
|
|
|
## Special Processing Requirements
|
|
|
|
Some agents require custom processing beyond the standard template transformations:
|
|
|
|
### Copilot Integration
|
|
|
|
GitHub Copilot has unique requirements:
|
|
- Commands use `.agent.md` extension (not `.md`)
|
|
- Each command gets a companion `.prompt.md` file in `.github/prompts/`
|
|
- Installs `.vscode/settings.json` with prompt file recommendations
|
|
- Context file lives at `.github/copilot-instructions.md`
|
|
|
|
Implementation: Extends `IntegrationBase` with custom `setup()` method that:
|
|
1. Processes templates with `process_template()`
|
|
2. Generates companion `.prompt.md` files
|
|
3. Merges VS Code settings
|
|
|
|
**Skills mode (`--skills`):** Copilot also supports an alternative skills-based layout
|
|
via `--integration-options="--skills"`. When enabled:
|
|
- Commands are scaffolded as `speckit-<name>/SKILL.md` under `.github/skills/`
|
|
- No companion `.prompt.md` files are generated
|
|
- No `.vscode/settings.json` merge
|
|
- `post_process_skill_content()` injects a `mode: speckit.<stem>` frontmatter field
|
|
- `build_command_invocation()` returns `/speckit-<stem>` instead of bare args
|
|
|
|
The two modes are mutually exclusive — a project uses one or the other:
|
|
|
|
```bash
|
|
# Default mode: .agent.md agents + .prompt.md companions + settings merge
|
|
specify init my-project --integration copilot
|
|
|
|
# Skills mode: speckit-<name>/SKILL.md under .github/skills/
|
|
specify init my-project --integration copilot --integration-options="--skills"
|
|
```
|
|
|
|
### Forge Integration
|
|
|
|
Forge has special frontmatter and argument requirements:
|
|
- Uses `{{parameters}}` instead of `$ARGUMENTS`
|
|
- Strips `handoffs` frontmatter key (Forge-specific collaboration feature)
|
|
- Injects `name` field into frontmatter when missing
|
|
|
|
Implementation: Extends `MarkdownIntegration` with custom `setup()` method that:
|
|
1. Inherits standard template processing from `MarkdownIntegration`
|
|
2. Adds extra `$ARGUMENTS` → `{{parameters}}` replacement after template processing
|
|
3. Applies Forge-specific transformations via `_apply_forge_transformations()`
|
|
4. Strips `handoffs` frontmatter key
|
|
5. Injects missing `name` fields
|
|
|
|
### Goose Integration
|
|
|
|
Goose is a YAML-format agent using Block's recipe system:
|
|
- Uses `.goose/recipes/` directory for YAML recipe files
|
|
- Uses `{{args}}` argument placeholder
|
|
- Produces YAML with `prompt: |` block scalar for command content
|
|
|
|
Implementation: Extends `YamlIntegration` (parallel to `TomlIntegration`):
|
|
1. Processes templates through the standard placeholder pipeline
|
|
2. Extracts title and description from frontmatter
|
|
3. Renders output as Goose recipe YAML (version, title, description, author, extensions, activities, prompt)
|
|
4. Uses `yaml.safe_dump()` for header fields to ensure proper escaping
|
|
5. Sets `context_file = "AGENTS.md"` so the base setup manages the Spec Kit context section there
|
|
|
|
## Branch Naming Convention
|
|
|
|
Branches follow one of two patterns depending on whether an issue exists:
|
|
|
|
```
|
|
<type>/<number>-<short-slug> # when an issue is created first
|
|
<type>/<short-slug> # when no issue exists (PR-only changes)
|
|
```
|
|
|
|
When an issue exists, include its number immediately after the prefix — this is what makes branches traceable. For small or self-contained changes that go straight to a PR without a tracking issue, omit the number.
|
|
|
|
| Prefix | When to use | Example |
|
|
|---|---|---|
|
|
| `feat/` | New features | `feat/2342-workflow-cli-alignment` |
|
|
| `fix/` | Bug fixes | `fix/2653-paths-only-validation` |
|
|
| `docs/` | Documentation changes | `docs/2677-branch-naming-convention`, `docs/update-landing-stats` |
|
|
| `community/` | Community catalog additions | `community/2492-add-mde-extension` |
|
|
| `chore/` | Maintenance, tooling, CI | `chore/2366-editorconfig` |
|
|
|
|
**Rules:**
|
|
|
|
1. Include the issue number when one exists — this is what makes branches traceable
|
|
2. Use kebab-case for the slug
|
|
3. Keep the slug short — enough to identify the work without looking up the issue
|
|
|
|
---
|
|
|
|
## Common Pitfalls
|
|
|
|
1. **Using shorthand keys for CLI-based integrations**: For CLI-based integrations (`requires_cli: True`), the `key` must match the executable name (e.g., `"cursor-agent"` not `"cursor"`). `shutil.which(key)` is used for CLI tool checks — mismatches require special-case mappings. IDE-based integrations (`requires_cli: False`) are not subject to this constraint.
|
|
2. **Forgetting context configuration**: The bundled `agent-context` extension reads from `.specify/extensions/agent-context/agent-context-config.yml`. New integrations only need to set `context_file` on the class — markers and dispatcher scripts are managed centrally.
|
|
3. **Incorrect `requires_cli` value**: Set to `True` only for agents that have a CLI tool; set to `False` for IDE-based agents.
|
|
4. **Wrong argument format**: Use `$ARGUMENTS` for Markdown agents, `{{args}}` for TOML agents.
|
|
5. **Skipping registration**: The import and `_register()` call in `_register_builtins()` must both be added.
|
|
|
|
---
|
|
|
|
*This documentation should be updated whenever new integrations are added to maintain accuracy and completeness.*
|