Skip to content

fix(mcp): find code and claude .cmd shims on Windows - #286

Open
riglar wants to merge 3 commits into
devfrom
fix/mcp-install-windows-cmd
Open

riglar wants to merge 3 commits into
devfrom
fix/mcp-install-windows-cmd

Conversation

@riglar

@riglar riglar commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #281.

Problem

On Windows, dcd mcp install vscode and dcd mcp install claude-code say code / claude isn't on PATH, even when it is.

VS Code's command line on Windows is code.cmd, and npm installs Claude Code as claude.cmd. runTool called spawnSync without a shell. Node then searches PATH only for .com and .exe, so it gets ENOENT. Recent Node versions also refuse to start a .cmd without a shell (CVE-2024-27980).

Fix

New src/utils/tool-spawn.ts, used by runTool:

  • Not Windows: the command is spawned as before.
  • Windows: we search PATH with PATHEXT ourselves.
    • An .exe is run directly.
    • A .cmd / .bat is run as cmd.exe /d /s /c "..." with windowsVerbatimArguments. Each argument is quoted for the program's own parser, then each cmd special character is caret-escaped twice: once for the cmd /c line, and once for the batch file's %*, which cmd parses again.
    • Not found: undefined, so the existing "isn't on PATH" message still shows.

We start cmd.exe ourselves, so this doesn't depend on how Node or Bun resolve .cmd files. The npm install and the standalone binary should behave the same.

Tests

test/unit/tool-spawn.test.ts covers the PATH search and the spawn shape. It also models cmd's two parse passes and CommandLineToArgvW, and checks that arguments come through unchanged. That includes the --add-mcp JSON with spaces and (x86) in its paths, and arguments with &, |, %, ^, quotes and trailing backslashes. The model treats an unescaped &, |, < or > as an error, and the test fails if the second escape pass is removed.

Not yet verified

  • A real run on Windows of dcd mcp install vscode and dcd mcp install claude-code, with an npm install.
  • The same with the bun-compiled binary. This also confirms that Bun honours windowsVerbatimArguments.

🤖 Generated with Claude Code

On Windows, VS Code's command line is code.cmd and npm installs Claude
Code as claude.cmd. Node's spawn without a shell skips .cmd files on
PATH and refuses to start them, so `dcd mcp install vscode` and
`dcd mcp install claude-code` said the command wasn't on PATH.

Find the command on PATH with PATHEXT ourselves. Run an .exe directly,
and a .cmd or .bat through cmd.exe with each argument escaped for both
of cmd's parse passes, so the --add-mcp JSON arrives unchanged.

Fixes #281

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread src/commands/mcp.ts Dismissed
@claude

claude Bot commented Nov 2, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

riglar and others added 2 commits November 2, 2026 09:50
A line break ends cmd's command line, so caret escaping can't protect
an argument that holds one. No argument we pass can contain one today,
but refuse it rather than rely on that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@finalerock44 finalerock44 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested on windows 10; working as intended @riglar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dcd mcp install can't find code or claude on Windows (.cmd shims)

3 participants