From 8350bf03d610937ac0fed7bd60103983164ea018 Mon Sep 17 00:00:00 2001 From: Ben Buttigieg <70525+BenBtg@users.noreply.github.com> Date: Mon, 29 Jun 2026 12:46:28 +0100 Subject: [PATCH 1/3] =?UTF-8?q?chore:=20retire=20windsurf=20integration=20?= =?UTF-8?q?=E2=80=94=20absorbed=20into=20Cognition=20Devin=20(#3168)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit windsurf.com now permanently redirects to devin.ai/desktop following acquisition. Remove subpackage, registry/catalog entries, docs, and tests; re-point sample-agent test fixtures to Kilo Code. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/agent_request.yml | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 1 - .github/ISSUE_TEMPLATE/feature_request.yml | 1 - docs/reference/integrations.md | 4 +--- integrations/catalog.json | 9 -------- src/specify_cli/integrations/__init__.py | 2 -- .../integrations/windsurf/__init__.py | 22 ------------------- tests/integrations/test_integration_forge.py | 16 +++++++------- .../integrations/test_integration_windsurf.py | 11 ---------- tests/integrations/test_registry.py | 2 +- tests/test_agent_config_consistency.py | 1 - tests/test_workflows.py | 4 ++-- 12 files changed, 13 insertions(+), 62 deletions(-) delete mode 100644 src/specify_cli/integrations/windsurf/__init__.py delete mode 100644 tests/integrations/test_integration_windsurf.py diff --git a/.github/ISSUE_TEMPLATE/agent_request.yml b/.github/ISSUE_TEMPLATE/agent_request.yml index 69cfd090e6..bd16ffa441 100644 --- a/.github/ISSUE_TEMPLATE/agent_request.yml +++ b/.github/ISSUE_TEMPLATE/agent_request.yml @@ -8,7 +8,7 @@ body: value: | Thanks for requesting a new agent! Before submitting, please check if the agent is already supported. - **Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Hermes Agent, IBM Bob, iFlow CLI, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, Roo Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, Windsurf, ZCode, Zed + **Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Hermes Agent, IBM Bob, iFlow CLI, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, Roo Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, ZCode, Zed - type: input id: agent-name diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 227f98ae1c..f403f85630 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -95,7 +95,6 @@ body: - SHAI - Tabnine CLI - Trae - - Windsurf - ZCode - Zed - Not applicable diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index ca1ecb9c11..d244419eb5 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -89,7 +89,6 @@ body: - SHAI - Tabnine CLI - Trae - - Windsurf - ZCode - Zed - Not applicable diff --git a/docs/reference/integrations.md b/docs/reference/integrations.md index 36829ec8be..5898f7341a 100644 --- a/docs/reference/integrations.md +++ b/docs/reference/integrations.md @@ -39,7 +39,6 @@ The Specify CLI supports a wide range of AI coding agents. When you run `specify | [SHAI (OVHcloud)](https://github.com/ovh/shai) | `shai` | | | [Tabnine CLI](https://docs.tabnine.com/main/getting-started/tabnine-cli) | `tabnine` | | | [Trae](https://www.trae.ai/) | `trae` | Skills-based integration; skills are installed automatically | -| [Windsurf](https://windsurf.com/) | `windsurf` | | | [ZCode](https://zcode.z.ai/) | `zcode` | Skills-based integration; installs skills into `.zcode/skills/` and invokes them as `$speckit-` | | [Zed](https://zed.dev/) | `zed` | Skills-based integration; installs skills into `.agents/skills` and invokes them as `/speckit-` | | Generic | `generic` | Bring your own agent — use `--integration generic --integration-options="--commands-dir "` for AI coding agents not listed above | @@ -200,7 +199,6 @@ The currently declared multi-install safe integrations are: | `shai` | `.shai/commands`, `SHAI.md` | | `tabnine` | `.tabnine/agent/commands`, `TABNINE.md` | | `trae` | `.trae/skills`, `.trae/rules/project_rules.md` | -| `windsurf` | `.windsurf/workflows`, `.windsurf/rules/specify-rules.md` | | `zcode` | `.zcode/skills`, `ZCODE.md` | Integrations that share a context file or command directory with another integration, require dynamic install paths such as `--commands-dir`, or merge shared tool settings are not declared safe by default. They can still be installed alongside another integration with `--force`. @@ -215,7 +213,7 @@ Run `specify integration list` to see all available integrations with their keys ### Do I need the AI coding agent installed to use an integration? -CLI-based integrations (like Claude Code, Gemini CLI) require the tool to be installed. IDE-based integrations (like Windsurf, Cursor) work through the IDE itself. Some agents like GitHub Copilot support both IDE and CLI usage. `specify integration list` shows which type each integration is. +CLI-based integrations (like Claude Code, Gemini CLI) require the tool to be installed. IDE-based integrations (like Cursor) work through the IDE itself. Some agents like GitHub Copilot support both IDE and CLI usage. `specify integration list` shows which type each integration is. ### When should I use `upgrade` vs `switch`? diff --git a/integrations/catalog.json b/integrations/catalog.json index 931df0d974..eca417f220 100644 --- a/integrations/catalog.json +++ b/integrations/catalog.json @@ -48,15 +48,6 @@ "repository": "https://github.com/github/spec-kit", "tags": ["ide"] }, - "windsurf": { - "id": "windsurf", - "name": "Windsurf", - "version": "1.0.0", - "description": "Windsurf IDE workflow integration", - "author": "spec-kit-core", - "repository": "https://github.com/github/spec-kit", - "tags": ["ide"] - }, "amp": { "id": "amp", "name": "Amp", diff --git a/src/specify_cli/integrations/__init__.py b/src/specify_cli/integrations/__init__.py index f394f64a20..bd2611558f 100644 --- a/src/specify_cli/integrations/__init__.py +++ b/src/specify_cli/integrations/__init__.py @@ -81,7 +81,6 @@ def _register_builtins() -> None: from .tabnine import TabnineIntegration from .trae import TraeIntegration from .vibe import VibeIntegration - from .windsurf import WindsurfIntegration from .zcode import ZcodeIntegration from .zed import ZedIntegration @@ -120,7 +119,6 @@ def _register_builtins() -> None: _register(TabnineIntegration()) _register(TraeIntegration()) _register(VibeIntegration()) - _register(WindsurfIntegration()) _register(ZcodeIntegration()) _register(ZedIntegration()) diff --git a/src/specify_cli/integrations/windsurf/__init__.py b/src/specify_cli/integrations/windsurf/__init__.py deleted file mode 100644 index ae5c3301f4..0000000000 --- a/src/specify_cli/integrations/windsurf/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -"""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" - multi_install_safe = True diff --git a/tests/integrations/test_integration_forge.py b/tests/integrations/test_integration_forge.py index f63afb71e2..e20b7376b0 100644 --- a/tests/integrations/test_integration_forge.py +++ b/tests/integrations/test_integration_forge.py @@ -407,7 +407,7 @@ def test_registrar_does_not_affect_other_agents(self, tmp_path): encoding="utf-8" ) - # Register with Windsurf (standard markdown agent without inject_name) + # Register with Kilo Code (standard markdown agent without inject_name) registrar = CommandRegistrar() commands = [ { @@ -417,22 +417,22 @@ def test_registrar_does_not_affect_other_agents(self, tmp_path): ] registrar.register_commands( - "windsurf", + "kilocode", commands, "test-extension", ext_dir, tmp_path ) - # Windsurf uses standard markdown format without name injection. + # Kilo Code uses standard markdown format without name injection. # The format_name callback should not be invoked for non-Forge agents. - windsurf_cmd = tmp_path / ".windsurf" / "workflows" / "speckit.my-extension.example.md" - assert windsurf_cmd.exists() + kilocode_cmd = tmp_path / ".kilocode" / "workflows" / "speckit.my-extension.example.md" + assert kilocode_cmd.exists() - content = windsurf_cmd.read_text(encoding="utf-8") - # Windsurf should NOT have a name field injected + content = kilocode_cmd.read_text(encoding="utf-8") + # Kilo Code should NOT have a name field injected assert "name:" not in content, ( - "Windsurf should not inject name field - format_name callback should be Forge-only" + "Kilo Code should not inject name field - format_name callback should be Forge-only" ) def test_git_extension_command_uses_hyphen_notation(self, tmp_path): diff --git a/tests/integrations/test_integration_windsurf.py b/tests/integrations/test_integration_windsurf.py deleted file mode 100644 index fa8d1e622a..0000000000 --- a/tests/integrations/test_integration_windsurf.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Tests for WindsurfIntegration.""" - -from .test_integration_base_markdown import MarkdownIntegrationTests - - -class TestWindsurfIntegration(MarkdownIntegrationTests): - KEY = "windsurf" - FOLDER = ".windsurf/" - COMMANDS_SUBDIR = "workflows" - REGISTRAR_DIR = ".windsurf/workflows" - CONTEXT_FILE = ".windsurf/rules/specify-rules.md" diff --git a/tests/integrations/test_registry.py b/tests/integrations/test_registry.py index 0110e19ec7..d0bcbca337 100644 --- a/tests/integrations/test_registry.py +++ b/tests/integrations/test_registry.py @@ -23,7 +23,7 @@ # Stage 3 — standard markdown integrations "claude", "qwen", "opencode", "junie", "kilocode", "auggie", "roo", "rovodev", "codebuddy", "qodercli", "amp", "shai", "bob", "trae", - "pi", "iflow", "kiro-cli", "windsurf", "vibe", "cursor-agent", "firebender", + "pi", "iflow", "kiro-cli", "vibe", "cursor-agent", "firebender", # Stage 4 — TOML integrations "gemini", "tabnine", # Stage 5 — skills, generic & option-driven integrations diff --git a/tests/test_agent_config_consistency.py b/tests/test_agent_config_consistency.py index 94496af5ef..60d5554280 100644 --- a/tests/test_agent_config_consistency.py +++ b/tests/test_agent_config_consistency.py @@ -44,7 +44,6 @@ "shai", "tabnine", "trae", - "windsurf", "zcode", "zed", ] diff --git a/tests/test_workflows.py b/tests/test_workflows.py index 988730d783..81b7dadfbd 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -593,8 +593,8 @@ def test_copilot_new_env_var_takes_precedence(self, monkeypatch): assert "--yolo" in args def test_ide_only_returns_none(self): - from specify_cli.integrations.windsurf import WindsurfIntegration - impl = WindsurfIntegration() + from specify_cli.integrations.kilocode import KilocodeIntegration + impl = KilocodeIntegration() assert impl.build_exec_args("test") is None def test_no_model_omits_flag(self): From 369dd1115714cf8b3bb26a3363fd45ac0023e705 Mon Sep 17 00:00:00 2001 From: Ben Buttigieg <70525+BenBtg@users.noreply.github.com> Date: Mon, 29 Jun 2026 17:22:58 +0100 Subject: [PATCH 2/3] docs: remove stale Windsurf support references Assisted-by: GitHub Copilot (model: gpt-5.3-codex, autonomous) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- AGENTS.md | 24 ++++++++++---------- docs/index.md | 2 +- docs/upgrade.md | 4 ++-- presets/ARCHITECTURE.md | 2 +- tests/integrations/test_integration_devin.py | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3d5ea32377..5df2b22614 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ src/specify_cli/integrations/ │ └── __init__.py # ClaudeIntegration class ├── gemini/ # Example: TomlIntegration subclass │ └── __init__.py -├── windsurf/ # Example: MarkdownIntegration subclass +├── kilocode/ # Example: MarkdownIntegration subclass │ └── __init__.py ├── copilot/ # Example: IntegrationBase subclass (custom setup) │ └── __init__.py @@ -52,30 +52,30 @@ Most agents only need `MarkdownIntegration` — a minimal subclass with zero met Create `src/specify_cli/integrations//__init__.py`, where `` is the Python-safe directory name derived from ``: 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):** +**Minimal example — Markdown agent (Kilo Code):** ```python -"""Windsurf IDE integration.""" +"""Kilo Code IDE integration.""" from ..base import MarkdownIntegration -class WindsurfIntegration(MarkdownIntegration): - key = "windsurf" +class KilocodeIntegration(MarkdownIntegration): + key = "kilocode" config = { - "name": "Windsurf", - "folder": ".windsurf/", + "name": "Kilo Code", + "folder": ".kilocode/", "commands_subdir": "workflows", "install_url": None, "requires_cli": False, } registrar_config = { - "dir": ".windsurf/workflows", + "dir": ".kilocode/workflows", "format": "markdown", "args": "$ARGUMENTS", "extension": ".md", } - context_file = ".windsurf/rules/specify-rules.md" + context_file = ".kilocode/rules/specify-rules.md" ``` **TOML agent (Gemini):** @@ -152,7 +152,7 @@ class CodexIntegration(SkillsIntegration): | `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"`). +**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., `"kilocode"`, `"copilot"`). ### 3. Register it @@ -203,8 +203,8 @@ Only add custom setup logic when the agent needs non-standard behavior. Integrat specify init my-project --integration # 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/ +# config["folder"] + config["commands_subdir"] (for example, .kilocode/workflows/) +ls -R my-project/.kilocode/workflows/ # Uninstall cleanly cd my-project && specify integration uninstall diff --git a/docs/index.md b/docs/index.md index 5772d6cc9a..13d5e049ac 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ Define what to build before building it. Rich templates, quality checklists, and ### Use any coding agent -30+ integrations — Copilot, Gemini, Codex, Windsurf, Zed, Claude, Forge, Kiro, and more. Switch freely between agents with a single command. No lock-in. +30+ integrations — Copilot, Gemini, Codex, Kilo Code, Zed, Claude, Forge, Kiro, and more. Switch freely between agents with a single command. No lock-in. Run `specify init` with your agent of choice and Spec Kit sets up the right command files, context rules, and directory structures automatically. If your agent isn't listed, the `generic` integration is an escape hatch for any tool. diff --git a/docs/upgrade.md b/docs/upgrade.md index c28daf396a..9678226559 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -185,7 +185,7 @@ cp -r .specify/scripts .specify/scripts-backup ### 3. Duplicate slash commands (IDE-based agents) -Some IDE-based agents (like Kilo Code, Windsurf) may show **duplicate slash commands** after upgrading—both old and new versions appear. +Some IDE-based agents (like Kilo Code, Roo Code) may show **duplicate slash commands** after upgrading—both old and new versions appear. **Solution:** Manually delete the old command files from your agent's folder. @@ -242,7 +242,7 @@ mv /tmp/constitution-backup.md .specify/memory/constitution.md ### Scenario 3: "I see duplicate slash commands in my IDE" -This happens with IDE-based agents (Kilo Code, Windsurf, Roo Code, etc.). +This happens with IDE-based agents (Kilo Code, Roo Code, Cline, etc.). ```bash # Find the agent folder (example: .kilocode/rules/) diff --git a/presets/ARCHITECTURE.md b/presets/ARCHITECTURE.md index 3a119cbd5f..fc043143bb 100644 --- a/presets/ARCHITECTURE.md +++ b/presets/ARCHITECTURE.md @@ -99,7 +99,7 @@ The `CommandRegistrar` renders commands differently per agent: | Agent | Format | Extension | Arg placeholder | |-------|--------|-----------|-----------------| -| Claude, Cursor, opencode, Windsurf, etc. | Markdown | `.md` | `$ARGUMENTS` | +| Claude, Kilo Code, opencode, Roo Code, etc. | Markdown | `.md` | `$ARGUMENTS` | | Copilot | Markdown | `.agent.md` + `.prompt.md` | `$ARGUMENTS` | | Gemini, Qwen, Tabnine | TOML | `.toml` | `{{args}}` | diff --git a/tests/integrations/test_integration_devin.py b/tests/integrations/test_integration_devin.py index 4acbdac618..713e9e34b1 100644 --- a/tests/integrations/test_integration_devin.py +++ b/tests/integrations/test_integration_devin.py @@ -29,7 +29,7 @@ def test_returns_args_not_none_for_dispatch(self): assert args is not None, ( "DevinIntegration.build_exec_args must not return None. " "None is the codebase sentinel for IDE-only integrations " - "(see WindsurfIntegration); Devin is dispatchable via 'devin -p'." + "(see KilocodeIntegration); Devin is dispatchable via 'devin -p'." ) assert args[:3] == ["devin", "-p", "test prompt"] From 3036df116f56c90c78a83d6633f959e50da5fe4f Mon Sep 17 00:00:00 2001 From: Ben Buttigieg <70525+BenBtg@users.noreply.github.com> Date: Tue, 30 Jun 2026 12:21:59 +0100 Subject: [PATCH 3/3] docs: fix Kilo Code command path in upgrade guide Assisted-by: GitHub Copilot (model: gpt-5.3-codex, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/upgrade.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/upgrade.md b/docs/upgrade.md index 9678226559..6c5f8a6c0f 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -193,7 +193,7 @@ Some IDE-based agents (like Kilo Code, Roo Code) may show **duplicate slash comm ```bash # Navigate to the agent's commands folder -cd .kilocode/rules/ +cd .kilocode/workflows/ # List files and identify duplicates ls -la @@ -245,8 +245,8 @@ mv /tmp/constitution-backup.md .specify/memory/constitution.md This happens with IDE-based agents (Kilo Code, Roo Code, Cline, etc.). ```bash -# Find the agent folder (example: .kilocode/rules/) -cd .kilocode/rules/ +# Find the agent folder (example: .kilocode/workflows/) +cd .kilocode/workflows/ # List all files ls -la