diff --git a/src/specify_cli/integrations/copilot/__init__.py b/src/specify_cli/integrations/copilot/__init__.py index c7456ce7f0..4e8f6e16b9 100644 --- a/src/specify_cli/integrations/copilot/__init__.py +++ b/src/specify_cli/integrations/copilot/__init__.py @@ -24,6 +24,16 @@ from ..manifest import IntegrationManifest +def _copilot_executable() -> str: + """Return the executable name for Copilot CLI on this platform. + + On Windows, subprocess invocation is reliable with `copilot.cmd`. + """ + if os.name == "nt": + return "copilot.cmd" + return "copilot" + + def _allow_all() -> bool: """Return True if the Copilot CLI should run with full permissions. @@ -138,7 +148,7 @@ def build_exec_args( # Controlled by SPECKIT_COPILOT_ALLOW_ALL_TOOLS env var # (default: enabled). The deprecated SPECKIT_ALLOW_ALL_TOOLS # is also honoured as a fallback. - args = ["copilot", "-p", prompt] + args = [_copilot_executable(), "-p", prompt] if _allow_all(): args.append("--yolo") if model: @@ -206,7 +216,7 @@ def dispatch_command( agent_name = f"speckit.{stem}" prompt = args or "" - cli_args = ["copilot", "-p", prompt] + cli_args = [_copilot_executable(), "-p", prompt] if not skills_mode: cli_args.extend(["--agent", agent_name]) if _allow_all(): diff --git a/tests/test_workflows.py b/tests/test_workflows.py index 3b42bf9106..e01ae4457a 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -13,6 +13,7 @@ from __future__ import annotations import json +import os import shutil import tempfile from pathlib import Path @@ -373,7 +374,8 @@ def test_copilot_exec_args(self, monkeypatch): from specify_cli.integrations.copilot import CopilotIntegration impl = CopilotIntegration() args = impl.build_exec_args("do stuff", model="claude-sonnet-4-20250514") - assert args[0] == "copilot" + expected_exec = "copilot.cmd" if os.name == "nt" else "copilot" + assert args[0] == expected_exec assert "-p" in args assert "--yolo" in args assert "--model" in args