<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Peter Mamrukov</title>
    <description>The latest articles on DEV Community by Peter Mamrukov (@netbka).</description>
    <link>https://dev.to/netbka</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4191761%2Fe1fe8cb6-436b-4da8-b138-1c345088fea4.jpg</url>
      <title>DEV Community: Peter Mamrukov</title>
      <link>https://dev.to/netbka</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/netbka"/>
    <language>en</language>
    <item>
      <title>Why your coding agent keeps breaking on Windows, and four fixes that hold</title>
      <dc:creator>Peter Mamrukov</dc:creator>
      <pubDate>Sun, 18 Oct 2026 08:44:51 +0000</pubDate>
      <link>https://dev.to/netbka/why-your-coding-agent-keeps-breaking-on-windows-and-four-fixes-that-hold-2poh</link>
      <guid>https://dev.to/netbka/why-your-coding-agent-keeps-breaking-on-windows-and-four-fixes-that-hold-2poh</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two failures you've probably seen
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The agent writes a command your shell won't parse.&lt;/strong&gt; It chains steps with &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; 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 &lt;a href="https://forum.cursor.com/t/powershell-in-cursor-is-consistently-broken-endless-syntax-errors-not-isolated-cases/149548" rel="noopener noreferrer"&gt;PowerShell in Cursor "consistently broken"&lt;/a&gt;, and a Claude Code issue reports that &lt;a href="https://github.com/anthropics/claude-code/issues/5049" rel="noopener noreferrer"&gt;native Windows runs aren't really shell aware&lt;/a&gt;: &lt;code&gt;move&lt;/code&gt; not found, backslashes broken, &lt;code&gt;find&lt;/code&gt; resolving to the Windows binary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The agent starts a dev server and the chat never comes back.&lt;/strong&gt; &lt;code&gt;npm run dev&lt;/code&gt; 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; &lt;a href="https://forum.cursor.com/t/cursor-occupying-ports-and-not-freeing-up-when-the-terminal-window-is-killed/134793" rel="noopener noreferrer"&gt;one Cursor user&lt;/a&gt; put it as "I have to manually kill it."&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 1: pass a program and its arguments, not a command string
&lt;/h2&gt;

&lt;p&gt;Most quoting bugs disappear when nothing parses a command line. If you write your own agent tools or scripts, start real executables directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Node: no shell in between&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;execFile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:child_process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;execFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;git&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--short&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;my-app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python: a list, and no shell=True
&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--short&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;cwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;C:\work\my-app&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  Fix 2: stop PowerShell-only mistakes before they run
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;command&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PowerShell has no heredoc. Write the file with the Write tool, or use a @&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;@ here-string.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  Fix 3: treat dev servers as processes, not terminal sessions
&lt;/h2&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="nb"&gt;netstat&lt;/span&gt; &lt;span class="na"&gt;-ano &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;findstr&lt;/span&gt; :5173
&lt;span class="nb"&gt;taskkill&lt;/span&gt; &lt;span class="na"&gt;/PID &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="na"&gt;/T /F
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl.exe &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; NUL &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; http://localhost:5173/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;curl.exe&lt;/code&gt; ships with current Windows 10 and 11; a &lt;code&gt;200&lt;/code&gt; is worth more than a log line that says "ready".&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 4: know where your guard rails end
&lt;/h2&gt;

&lt;p&gt;Limiting an agent to certain folders and keeping it away from &lt;code&gt;.env&lt;/code&gt; and private keys stops the everyday accidents. People have &lt;a href="https://www.theregister.com/2026/01/28/claude_code_ai_secrets_files/" rel="noopener noreferrer"&gt;watched agents read secret files&lt;/a&gt; and &lt;a href="https://www.docker.com/blog/coding-agent-horror-stories-the-rm-rf-incident/" rel="noopener noreferrer"&gt;delete home directories&lt;/a&gt;; those are mostly habits, and habits can be blocked.&lt;/p&gt;

&lt;p&gt;None of that is a sandbox. If &lt;code&gt;node&lt;/code&gt; or &lt;code&gt;python&lt;/code&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where these notes come from
&lt;/h2&gt;

&lt;p&gt;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: &lt;a href="https://github.com/netbka/local-commander-mcp-agent" rel="noopener noreferrer"&gt;https://github.com/netbka/local-commander-mcp-agent&lt;/a&gt;. 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.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;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.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>windows</category>
      <category>ai</category>
      <category>powershell</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
