Environment
- OS: Windows 11
- Python: 3.12.10
- Package:
github-copilot-sdk v0.1.14
- Copilot CLI Version: 0.0.388
Description
On Windows, the CopilotClient fails to start with FileNotFoundError: [WinError 2] The system cannot find the file specified when the copilot CLI is installed as a .cmd or .bat file (which is standard for npm global installs on Windows).
Steps to Reproduce
- Install
copilot CLI via npm on Windows: npm install -g @anthropic/copilot-cli
- Verify it's on PATH:
where copilot returns C:\.tools\.npm\prefix\copilot.cmd
- Use the Python SDK:
from copilot import CopilotClient
async def main():
client = CopilotClient()
await client.start() # Raises WinError 2
Expected Behavior
The SDK should find and execute the copilot CLI when it's on PATH, regardless of file extension.
Actual Behavior
FileNotFoundError: [WinError 2] The system cannot find the file specified
Full traceback:
File "...\copilot\client.py", line 645, in _start_cli_server
self._process = subprocess.Popen(
^^^^^^^^^^^^^^^^^
File "...\subprocess.py", line 1026, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "...\subprocess.py", line 1538, in _execute_child
hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [WinError 2] The system cannot find the file specified
NOTE: Bellow is generated by copilot, so who even knows. Also for some reason it worked for a bit then it stopped and weirdly enough my VSCode has some arcane issues with path which it (maybe) passed down on it's child processes started from its terminal. So maybe it's all a big misunderstanding.
Root Cause
In client.py line ~645, subprocess.Popen is called with the command name directly:
self._process = subprocess.Popen(
args, # args[0] is "copilot" or cli_path
...
)
On Windows, subprocess.Popen without shell=True:
- Does not use
PATHEXT to resolve extensions (.cmd, .bat, .exe)
- Cannot directly execute
.cmd/.bat files by name alone
- Does not behave like a shell when searching PATH
Workaround
Users can work around this by using shutil.which() to resolve the full path:
import shutil
from copilot import CopilotClient
cli_path = shutil.which("copilot") # Returns full path with extension
client = CopilotClient({"cli_path": cli_path})
await client.start() # Works
Suggested Fix
In client.py, before calling subprocess.Popen, use shutil.which() to resolve the CLI path:
import shutil
async def _start_cli_server(self) -> None:
cli_path = self.options["cli_path"]
# Resolve the full path on Windows (handles .cmd/.bat files)
resolved_path = shutil.which(cli_path)
if resolved_path:
cli_path = resolved_path
args = ["--server", "--log-level", self.options["log_level"]]
# ... rest of the code
Alternatively, on Windows, use shell=True when the cli_path doesn't contain a path separator (indicating it needs PATH resolution).
Additional Context
This affects any Windows user where copilot is installed via npm, as npm creates .cmd wrapper scripts for global packages.
Environment
github-copilot-sdkv0.1.14Description
On Windows, the
CopilotClientfails to start withFileNotFoundError: [WinError 2] The system cannot find the file specifiedwhen thecopilotCLI is installed as a.cmdor.batfile (which is standard for npm global installs on Windows).Steps to Reproduce
copilotCLI via npm on Windows:npm install -g @anthropic/copilot-cliwhere copilotreturnsC:\.tools\.npm\prefix\copilot.cmdExpected Behavior
The SDK should find and execute the
copilotCLI when it's on PATH, regardless of file extension.Actual Behavior
Full traceback:
NOTE: Bellow is generated by copilot, so who even knows. Also for some reason it worked for a bit then it stopped and weirdly enough my VSCode has some arcane issues with path which it (maybe) passed down on it's child processes started from its terminal. So maybe it's all a big misunderstanding.
Root Cause
In
client.pyline ~645,subprocess.Popenis called with the command name directly:On Windows,
subprocess.Popenwithoutshell=True:PATHEXTto resolve extensions (.cmd,.bat,.exe).cmd/.batfiles by name aloneWorkaround
Users can work around this by using
shutil.which()to resolve the full path:Suggested Fix
In
client.py, before callingsubprocess.Popen, useshutil.which()to resolve the CLI path:Alternatively, on Windows, use
shell=Truewhen the cli_path doesn't contain a path separator (indicating it needs PATH resolution).Additional Context
This affects any Windows user where
copilotis installed via npm, as npm creates.cmdwrapper scripts for global packages.