DEV Community

Peter Mamrukov
Peter Mamrukov

Posted on AI-assisted

Why your coding agent keeps breaking on Windows, and four fixes that hold

For a while my workflow with AI was: the chat suggests a fix, I paste it into the terminal, run the tests, copy the error back. I was a very slow USB cable between the model and my Windows PC. Agent modes were supposed to end that. On Windows they often don't, and the reasons are fixable.

Two failures you've probably seen

The agent writes a command your shell won't parse. It chains steps with && in Windows PowerShell 5.1, mangles backslashes, or runs a bash-style command that resolves to a different Windows program. A Cursor forum thread calls PowerShell in Cursor "consistently broken", and a Claude Code issue reports that native Windows runs aren't really shell aware: move not found, backslashes broken, find resolving to the Windows binary.

The agent starts a dev server and the chat never comes back. npm run dev doesn't exit, so the tool call waits forever, or the agent decides the server started when it didn't. Kill the terminal and the server often keeps its port; one Cursor user put it as "I have to manually kill it."

Both come from the same place. The agent is handed a terminal and expected to type into it like a person. A person knows which shell they're in and when to stop waiting. A model guesses.

Fix 1: pass a program and its arguments, not a command string

Most quoting bugs disappear when nothing parses a command line. If you write your own agent tools or scripts, start real executables directly:

// Node: no shell in between
import { execFile } from "node:child_process";
execFile("git", ["status", "--short"], { cwd: "C:\\work\\my-app" }, (err, stdout, stderr) => { /* ... */ });
Enter fullscreen mode Exit fullscreen mode
# Python: a list, and no shell=True
subprocess.run(["git", "status", "--short"], cwd=r"C:\work\my-app", check=True)
Enter fullscreen mode Exit fullscreen mode

One Windows catch: npm, npx, pnpm and yarn are usually .cmd shims, and since Node's April 2024 security release, spawning a .cmd or .bat file needs shell: true, so cmd.exe gets involved after all. Keep that safe by refusing arguments that contain cmd metacharacters (& | < > ^ % !) and quoting each argument yourself, or by running node on the tool's JavaScript entry point. If your agent talks to tools over MCP, prefer a command tool that takes command and args as separate fields over one that takes a shell string.

Fix 2: stop PowerShell-only mistakes before they run

A rule in your agent's instructions is a hint; a hook is enforced. In Claude Code, a PreToolUse hook with matcher PowerShell sees each command first, and exit code 2 blocks it and sends your message back to the model:

import json, sys
cmd = json.load(sys.stdin).get("tool_input", {}).get("command", "")
if "<<" in cmd:
    sys.stderr.write("PowerShell has no heredoc. Write the file with the Write tool, or use a @'...'@ here-string.")
    sys.exit(2)
Enter fullscreen mode Exit fullscreen mode

The model reads the message and retries another way. The same pattern catches && on Windows PowerShell 5.1, or helper functions named after built-in aliases such as rd.

Fix 3: treat dev servers as processes, not terminal sessions

Start long-running servers in the background and come back for the log, instead of waiting for them to exit. When one is left behind, the port leads you to it:

netstat -ano | findstr :5173
taskkill /PID <pid> /T /F
Enter fullscreen mode Exit fullscreen mode

The PID is the last column of the LISTENING line. /T stops the process together with everything it started (for Vite that includes esbuild); plain Stop-Process only takes the one PID. And before believing "the server is running", ask it:

curl.exe -s -o NUL -w "%{http_code}" http://localhost:5173/
Enter fullscreen mode Exit fullscreen mode

curl.exe ships with current Windows 10 and 11; a 200 is worth more than a log line that says "ready".

Fix 4: know where your guard rails end

Limiting an agent to certain folders and keeping it away from .env and private keys stops the everyday accidents. People have watched agents read secret files and delete home directories; those are mostly habits, and habits can be blocked.

None of that is a sandbox. If node or python is allowed, a script can do anything your account can do, including deleting files. For a real wall, run the agent's tools in a container, under a separate low-privilege account, or in a VM.

Where these notes come from

I maintain an open-source MCP server, local-commander-mcp-agent (MIT), that packages fixes 1, 3 and part of 4 for agents; it was built around exactly these problems: https://github.com/netbka/local-commander-mcp-agent. If you have a Windows setup that still trips your agent up (unusual paths, non-English usernames, locked-down corporate machines), I'd like to hear about it.

This article was drafted by an AI agent from my project notes and the threads linked above; every command, quote and link was checked before publishing.

Top comments (1)

Collapse
 
benchsmoke profile image
BenchSmoke •

The line about a model guessing when to stop waiting is the core of it. Have you found the hung dev server easier to fix with a hard timeout on the tool call, or by having the agent check the port before it declares the server up?