[BUG] typescript-lsp plugin fails to spawn on Windows (MSYS2/Git Bash) — ENOENT on `typescript-language-server`
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
The typescript-lsp plugin installed via /plugin install typescript-lsp silently fails on Windows with MSYS2/Git Bash. The plugin appears with a green checkmark in /plugin as if everything is fine, but when Claude actually tries to use the LSP tool (e.g. hover, go-to-definition), it fails because the language server process cannot be spawned.
The typescript-language-server binary is installed globally via npm, works perfectly from the shell, but Node.js's child_process.spawn (via libuv uv_spawn) cannot resolve the npm shim script on the PATH.
This likely affects all LSP plugins that reference globally-installed npm binaries on Windows, not just typescript-lsp.
What Should Happen?
The LSP plugin should successfully spawn typescript-language-server and return type information when the LSP tool is invoked (hover, go-to-definition, find-references, etc.).
Additionally, /plugin should surface the spawn failure in its status/errors tab rather than showing a green checkmark for a broken plugin.
Error Messages/Logs
First invocation:
Error performing hover: ENOENT: no such file or directory, uv_spawn 'typescript-language-server'
Subsequent invocations:
Error performing hover: Failed to sync file open <path>: Cannot send notification to LSP server 'plugin:typescript-lsp:typescript': server is error
Steps to Reproduce
- On Windows with MSYS2 or Git Bash as the shell, install the language server globally:
``bash``
npm install -g typescript-language-server typescript
- Verify it works from the shell:
``bash``
typescript-language-server --version
# Output: 5.1.3
- In Claude Code, install the official LSP plugin:
````
/plugin install typescript-lsp
- Run
/plugin— the plugin appears with a green checkmark (misleading) - Ask Claude to use the LSP on any TypeScript file, e.g.:
> "Use the LSP hover on line 25 of src/components/my-component.tsx"
- Observe the ENOENT error
Root cause: On Windows, npm install -g creates shell shim scripts (POSIX .sh, .cmd, .ps1) in %APPDATA%\npm. The POSIX shim looks like:
#!/bin/sh
# ...
exec node "$basedir/node_modules/typescript-language-server/lib/cli.mjs" "$@"
While the shell can execute this shim, uv_spawn cannot resolve it. node itself IS resolvable — only the npm shim is not.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.74 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Windows Terminal
Additional Information
Two separate issues are reported here:
- The spawn failure itself —
uv_spawncannot find npm global shim scripts on Windows. Potential fixes:
- Use
shell: truein spawn options so the shell resolves the shim - Resolve
.cmdextensions when spawning on Windows (the standard way Windows executes npm shims outside POSIX shells) - Allow an
envfield in LSP plugin config to extend PATH - Support absolute paths in the
commandfield
- Silent failure in
/pluginUI — The plugin shows a green checkmark even though the LSP server cannot start. The spawn error only surfaces when the LSP tool is actually invoked by Claude. The error should be visible in/pluginstatus or the Errors tab proactively, so users don't think the setup is working when it isn't.
Workaround:
Create a local marketplace plugin that invokes node directly with the cli.mjs entry point, bypassing PATH resolution:
{
"lspServers": {
"typescript": {
"command": "node",
"args": [
"C:/Users/<USERNAME>/AppData/Roaming/npm/node_modules/typescript-language-server/lib/cli.mjs",
"--stdio"
],
"extensionToLanguage": {
".ts": "typescript",
".tsx": "typescriptreact",
".js": "javascript",
".jsx": "javascriptreact"
}
}
}
}
This requires creating a full local marketplace structure, registering it with /plugin marketplace add, and installing the patched plugin from it.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗