diff --git a/.github/ISSUE_TEMPLATE/agent_request.yml b/.github/ISSUE_TEMPLATE/agent_request.yml index 3d3253c523..a9ef072592 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, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, ZCode, Zed + **Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Command Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Hermes Agent, IBM Bob, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen 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 b71d90cdab..5363287383 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -66,6 +66,7 @@ body: - Antigravity - Auggie CLI - Claude Code + - Command Code - Cline - CodeBuddy - Codex CLI diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 76566a18fc..9f418fc7a4 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -60,6 +60,7 @@ body: - Antigravity - Auggie CLI - Claude Code + - Command Code - Cline - CodeBuddy - Codex CLI diff --git a/README.md b/README.md index c759f6e05e..fd48351f78 100644 --- a/README.md +++ b/README.md @@ -388,6 +388,7 @@ In an interactive terminal, you will be prompted to select the coding agent inte ```bash specify init --integration copilot +specify init --integration cmdc specify init --integration gemini specify init --integration codex diff --git a/docs/installation.md b/docs/installation.md index 744423b29c..19f75c8f4c 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -3,7 +3,7 @@ ## Prerequisites - **Linux/macOS** (or Windows; PowerShell scripts now supported without WSL) -- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [CodeBuddy CLI](https://www.codebuddy.cn/docs/cli/installation), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Pi Coding Agent](https://pi.dev), or [Oh My Pi](https://www.npmjs.com/package/@oh-my-pi/pi-coding-agent) +- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Command Code](https://commandcode.ai), [CodeBuddy CLI](https://www.codebuddy.cn/docs/cli/installation), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Pi Coding Agent](https://pi.dev), or [Oh My Pi](https://www.npmjs.com/package/@oh-my-pi/pi-coding-agent) - [uv](https://docs.astral.sh/uv/) for package management (recommended) or [pipx](https://pipx.pypa.io/) for persistent installation - [Python 3.11+](https://www.python.org/downloads/) - [Git](https://git-scm.com/downloads) _(optional — required only when the git extension is enabled)_ @@ -49,6 +49,7 @@ You can proactively specify your coding agent integration during initialization: specify init --integration claude specify init --integration gemini specify init --integration copilot +specify init --integration cmdc specify init --integration codebuddy specify init --integration pi specify init --integration omp diff --git a/integrations/catalog.json b/integrations/catalog.json index 601ae0ad92..6d529c7abf 100644 --- a/integrations/catalog.json +++ b/integrations/catalog.json @@ -3,59 +3,97 @@ "updated_at": "2026-06-23T00:00:00Z", "catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/integrations/catalog.json", "integrations": { - "claude": { - "id": "claude", - "name": "Claude Code", + "agy": { + "id": "agy", + "name": "Antigravity", "version": "1.0.0", - "description": "Anthropic Claude Code CLI integration", + "description": "Antigravity IDE skills-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "anthropic"] + "tags": [ + "ide", + "skills" + ] }, - "cline": { - "id": "cline", - "name": "Cline", + "amp": { + "id": "amp", + "name": "Amp", "version": "1.0.0", - "description": "Cline IDE integration", + "description": "Amp CLI integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["ide"] + "tags": [ + "cli" + ] }, - "copilot": { - "id": "copilot", - "name": "GitHub Copilot", + "auggie": { + "id": "auggie", + "name": "Auggie CLI", "version": "1.0.0", - "description": "GitHub Copilot IDE integration with agent commands and prompt files", + "description": "Auggie CLI integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["ide", "github"] + "tags": [ + "cli" + ] }, - "gemini": { - "id": "gemini", - "name": "Gemini CLI", + "bob": { + "id": "bob", + "name": "IBM Bob", "version": "1.0.0", - "description": "Google Gemini CLI integration with TOML command format", + "description": "IBM Bob IDE integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "google"] + "tags": [ + "ide", + "ibm" + ] }, - "cursor-agent": { - "id": "cursor-agent", - "name": "Cursor", + "claude": { + "id": "claude", + "name": "Claude Code", "version": "1.0.0", - "description": "Cursor IDE integration", + "description": "Anthropic Claude Code CLI integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["ide"] + "tags": [ + "cli", + "anthropic" + ] }, - "amp": { - "id": "amp", - "name": "Amp", + "cline": { + "id": "cline", + "name": "Cline", "version": "1.0.0", - "description": "Amp CLI integration", + "description": "Cline IDE integration", + "author": "spec-kit-core", + "repository": "https://github.com/github/spec-kit", + "tags": [ + "ide" + ] + }, + "cmdc": { + "id": "cmdc", + "name": "Command Code", + "version": "1.0.0", + "description": "Command Code CLI skills-based integration", + "author": "spec-kit-core", + "repository": "https://github.com/github/spec-kit", + "tags": [ + "cli", + "skills" + ] + }, + "codebuddy": { + "id": "codebuddy", + "name": "CodeBuddy", + "version": "1.0.0", + "description": "CodeBuddy CLI integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli" + ] }, "codex": { "id": "codex", @@ -64,34 +102,45 @@ "description": "Codex CLI skills-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "skills"] + "tags": [ + "cli", + "skills" + ] }, - "devin": { - "id": "devin", - "name": "Devin for Terminal", + "copilot": { + "id": "copilot", + "name": "GitHub Copilot", "version": "1.0.0", - "description": "Devin for Terminal CLI skills-based integration", + "description": "GitHub Copilot IDE integration with agent commands and prompt files", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "skills"] + "tags": [ + "ide", + "github" + ] }, - "qwen": { - "id": "qwen", - "name": "Qwen Code", + "cursor-agent": { + "id": "cursor-agent", + "name": "Cursor", "version": "1.0.0", - "description": "Alibaba Qwen Code CLI integration", + "description": "Cursor IDE integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "alibaba"] + "tags": [ + "ide" + ] }, - "opencode": { - "id": "opencode", - "name": "opencode", + "devin": { + "id": "devin", + "name": "Devin for Terminal", "version": "1.0.0", - "description": "opencode CLI integration", + "description": "Devin for Terminal CLI skills-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli", + "skills" + ] }, "firebender": { "id": "firebender", @@ -100,7 +149,9 @@ "description": "Firebender IDE integration for Android Studio / IntelliJ", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["ide"] + "tags": [ + "ide" + ] }, "forge": { "id": "forge", @@ -109,52 +160,67 @@ "description": "Forge CLI integration with parameter-based commands", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli" + ] }, - "kiro-cli": { - "id": "kiro-cli", - "name": "Kiro CLI", + "gemini": { + "id": "gemini", + "name": "Gemini CLI", "version": "1.0.0", - "description": "Kiro CLI prompt-based integration", + "description": "Google Gemini CLI integration with TOML command format", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli", + "google" + ] }, - "junie": { - "id": "junie", - "name": "Junie", + "generic": { + "id": "generic", + "name": "Generic (bring your own agent)", "version": "1.0.0", - "description": "Junie by JetBrains CLI integration", + "description": "Generic integration for any agent via --integration-options=\"--commands-dir \"", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "jetbrains"] + "tags": [ + "generic" + ] }, - "auggie": { - "id": "auggie", - "name": "Auggie CLI", + "goose": { + "id": "goose", + "name": "Goose", "version": "1.0.0", - "description": "Auggie CLI integration", + "description": "Goose CLI integration with YAML recipe format", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli" + ] }, - "shai": { - "id": "shai", - "name": "SHAI", + "hermes": { + "id": "hermes", + "name": "Hermes Agent", "version": "1.0.0", - "description": "SHAI CLI integration", + "description": "Hermes Agent skills-based integration by Nous Research", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli", + "skills" + ] }, - "tabnine": { - "id": "tabnine", - "name": "Tabnine CLI", + "junie": { + "id": "junie", + "name": "Junie", "version": "1.0.0", - "description": "Tabnine CLI integration with TOML command format", + "description": "Junie by JetBrains CLI integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli", + "jetbrains" + ] }, "kilocode": { "id": "kilocode", @@ -163,70 +229,66 @@ "description": "Kilo Code IDE workflow integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["ide"] - }, - "rovodev": { - "id": "rovodev", - "name": "RovoDev ACLI", - "version": "1.0.0", - "description": "Atlassian RovoDev integration", - "author": "spec-kit-core", - "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "atlassian"] - }, - "bob": { - "id": "bob", - "name": "IBM Bob", - "version": "1.0.0", - "description": "IBM Bob IDE integration", - "author": "spec-kit-core", - "repository": "https://github.com/github/spec-kit", - "tags": ["ide", "ibm"] + "tags": [ + "ide" + ] }, - "trae": { - "id": "trae", - "name": "Trae", + "kimi": { + "id": "kimi", + "name": "Kimi Code", "version": "1.0.0", - "description": "Trae IDE rules-based integration", + "description": "Kimi Code CLI skills-based integration by Moonshot AI", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["ide"] + "tags": [ + "cli", + "skills" + ] }, - "codebuddy": { - "id": "codebuddy", - "name": "CodeBuddy", + "kiro-cli": { + "id": "kiro-cli", + "name": "Kiro CLI", "version": "1.0.0", - "description": "CodeBuddy CLI integration", + "description": "Kiro CLI prompt-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli" + ] }, - "qodercli": { - "id": "qodercli", - "name": "Qoder CLI", + "lingma": { + "id": "lingma", + "name": "Lingma", "version": "1.0.0", - "description": "Qoder CLI integration", + "description": "Lingma IDE skills-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "ide", + "skills" + ] }, - "kimi": { - "id": "kimi", - "name": "Kimi Code", + "omp": { + "id": "omp", + "name": "Oh My Pi", "version": "1.0.0", - "description": "Kimi Code CLI skills-based integration by Moonshot AI", + "description": "Oh My Pi (omp) terminal coding agent prompt-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "skills"] + "tags": [ + "cli" + ] }, - "lingma": { - "id": "lingma", - "name": "Lingma", + "opencode": { + "id": "opencode", + "name": "opencode", "version": "1.0.0", - "description": "Lingma IDE skills-based integration", + "description": "opencode CLI integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["ide", "skills"] + "tags": [ + "cli" + ] }, "pi": { "id": "pi", @@ -235,61 +297,89 @@ "description": "Pi terminal coding agent prompt-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli" + ] }, - "omp": { - "id": "omp", - "name": "Oh My Pi", + "qodercli": { + "id": "qodercli", + "name": "Qoder CLI", "version": "1.0.0", - "description": "Oh My Pi (omp) terminal coding agent prompt-based integration", + "description": "Qoder CLI integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli" + ] }, - "vibe": { - "id": "vibe", - "name": "Mistral Vibe", + "qwen": { + "id": "qwen", + "name": "Qwen Code", "version": "1.0.0", - "description": "Mistral Vibe CLI prompt-based integration", + "description": "Alibaba Qwen Code CLI integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "mistral"] + "tags": [ + "cli", + "alibaba" + ] }, - "agy": { - "id": "agy", - "name": "Antigravity", + "rovodev": { + "id": "rovodev", + "name": "RovoDev ACLI", "version": "1.0.0", - "description": "Antigravity IDE skills-based integration", + "description": "Atlassian RovoDev integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["ide", "skills"] + "tags": [ + "cli", + "atlassian" + ] }, - "generic": { - "id": "generic", - "name": "Generic (bring your own agent)", + "shai": { + "id": "shai", + "name": "SHAI", "version": "1.0.0", - "description": "Generic integration for any agent via --integration-options=\"--commands-dir \"", + "description": "SHAI CLI integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["generic"] + "tags": [ + "cli" + ] }, - "goose": { - "id": "goose", - "name": "Goose", + "tabnine": { + "id": "tabnine", + "name": "Tabnine CLI", "version": "1.0.0", - "description": "Goose CLI integration with YAML recipe format", + "description": "Tabnine CLI integration with TOML command format", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli"] + "tags": [ + "cli" + ] }, - "hermes": { - "id": "hermes", - "name": "Hermes Agent", + "trae": { + "id": "trae", + "name": "Trae", "version": "1.0.0", - "description": "Hermes Agent skills-based integration by Nous Research", + "description": "Trae IDE rules-based integration", + "author": "spec-kit-core", + "repository": "https://github.com/github/spec-kit", + "tags": [ + "ide" + ] + }, + "vibe": { + "id": "vibe", + "name": "Mistral Vibe", + "version": "1.0.0", + "description": "Mistral Vibe CLI prompt-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "skills"] + "tags": [ + "cli", + "mistral" + ] }, "zcode": { "id": "zcode", @@ -298,7 +388,11 @@ "description": "Z.AI ZCode CLI skills-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["cli", "skills", "z-ai"] + "tags": [ + "cli", + "skills", + "z-ai" + ] }, "zed": { "id": "zed", @@ -307,7 +401,10 @@ "description": "Zed editor skills-based integration", "author": "spec-kit-core", "repository": "https://github.com/github/spec-kit", - "tags": ["ide", "skills"] + "tags": [ + "ide", + "skills" + ] } } } diff --git a/src/specify_cli/integrations/__init__.py b/src/specify_cli/integrations/__init__.py index e0bab66735..4e4aeab5a8 100644 --- a/src/specify_cli/integrations/__init__.py +++ b/src/specify_cli/integrations/__init__.py @@ -52,6 +52,7 @@ def _register_builtins() -> None: from .auggie import AuggieIntegration from .bob import BobIntegration from .claude import ClaudeIntegration + from .cmdc import CmcIntegration from .cline import ClineIntegration from .codebuddy import CodebuddyIntegration from .codex import CodexIntegration @@ -88,6 +89,7 @@ def _register_builtins() -> None: _register(AuggieIntegration()) _register(BobIntegration()) _register(ClaudeIntegration()) + _register(CmcIntegration()) _register(ClineIntegration()) _register(CodebuddyIntegration()) _register(CodexIntegration()) diff --git a/src/specify_cli/integrations/cmdc/__init__.py b/src/specify_cli/integrations/cmdc/__init__.py new file mode 100644 index 0000000000..8736678787 --- /dev/null +++ b/src/specify_cli/integrations/cmdc/__init__.py @@ -0,0 +1,61 @@ +"""Command Code (cmdc) integration — skills-based agent. + +Command Code uses the ``.commandcode/skills/speckit-/SKILL.md`` layout +following the agentskills.io spec. Commands are invoked as ``/speckit-`` +slash commands within the Command Code interactive session. +""" + +from __future__ import annotations + +from ..base import IntegrationOption, SkillsIntegration + + +class CmcIntegration(SkillsIntegration): + """Integration for Command Code CLI.""" + + key = "cmdc" + config = { + "name": "Command Code", + "folder": ".commandcode/", + "commands_subdir": "skills", + "install_url": "https://commandcode.ai", + "requires_cli": True, + } + registrar_config = { + "dir": ".commandcode/skills", + "format": "markdown", + "args": "$ARGUMENTS", + "extension": "/SKILL.md", + } + dev_no_symlink = True + multi_install_safe = True + + @classmethod + def options(cls) -> list[IntegrationOption]: + return [ + IntegrationOption( + "--skills", + is_flag=True, + default=True, + help="Install as agent skills (default for Command Code)", + ), + ] + + def build_exec_args( + self, + prompt: str, + *, + model: str | None = None, + output_json: bool = True, + ) -> list[str] | None: + """CMDC uses ``cmdc -p "prompt"`` for non-interactive mode. + + The ``-p`` / ``--print`` flag runs cmdc in headless mode, + outputting the response and exiting. The ``--model`` flag + selects a specific model when provided. + """ + args: list[str] = [self._resolve_executable(), "-p", prompt] + self._apply_extra_args_env_var(args) + if model: + args.extend(["--model", model]) + return args diff --git a/tests/integrations/test_integration_cmdc.py b/tests/integrations/test_integration_cmdc.py new file mode 100644 index 0000000000..927fcfb847 --- /dev/null +++ b/tests/integrations/test_integration_cmdc.py @@ -0,0 +1,51 @@ +"""Tests for CmcIntegration.""" + +from specify_cli.integrations import get_integration +from specify_cli.integrations.manifest import IntegrationManifest + +from .test_integration_base_skills import SkillsIntegrationTests + + +class TestCmcIntegration(SkillsIntegrationTests): + KEY = "cmdc" + FOLDER = ".commandcode/" + COMMANDS_SUBDIR = "skills" + REGISTRAR_DIR = ".commandcode/skills" + + +class TestCmcInitFlow: + """--integration cmdc creates expected files.""" + + def test_integration_cmdc_creates_skills(self, tmp_path): + """--integration cmdc should create skills in .commandcode/skills.""" + from typer.testing import CliRunner + from specify_cli import app + + runner = CliRunner() + target = tmp_path / "test-proj" + result = runner.invoke(app, [ + "init", str(target), "--integration", "cmdc", + "--ignore-agent-tools", "--script", "sh", + ]) + + assert result.exit_code == 0, ( + f"init --integration cmdc failed: {result.output}" + ) + assert ( + target / ".commandcode" / "skills" / "speckit-plan" / "SKILL.md" + ).exists() + + def test_slash_command_refs_use_hyphens(self, tmp_path): + """CMDC slash commands must use /speckit- (hyphens).""" + integration = get_integration("cmdc") + manifest = IntegrationManifest("cmdc", tmp_path) + integration.setup(tmp_path, manifest, script_type="sh") + + plan_skill = ( + tmp_path / ".commandcode" / "skills" / "speckit-plan" / "SKILL.md" + ) + content = plan_skill.read_text(encoding="utf-8") + assert "/speckit-" in content + assert "/speckit." not in content, ( + "CMDC skills must use /speckit- not /speckit." + ) diff --git a/tests/test_agent_config_consistency.py b/tests/test_agent_config_consistency.py index b4ef85c319..5ca161e687 100644 --- a/tests/test_agent_config_consistency.py +++ b/tests/test_agent_config_consistency.py @@ -15,6 +15,7 @@ "agy", "auggie", "claude", + "cmdc", "cline", "codebuddy", "codex",