<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>PowerShell on KnightLi Blog</title>
        <link>https://knightli.com/en/tags/powershell/</link>
        <description>Recent content in PowerShell on KnightLi Blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Wed, 01 Jul 2026 10:06:48 +0800</lastBuildDate><atom:link href="https://knightli.com/en/tags/powershell/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Codex vs PowerShell: What the powershell-safe-invocation Skill Solves</title>
        <link>https://knightli.com/en/2026/07/01/codex-vs-powershell-safe-invocation/</link>
        <pubDate>Wed, 01 Jul 2026 10:06:48 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/07/01/codex-vs-powershell-safe-invocation/</guid>
        <description>&lt;p&gt;I recently saw a screenshot with excellent comic timing: Codex was trying to fix a Markdown file in PowerShell. First the here-string did not execute, then CRLF/LF matching failed, then Markdown backticks were parsed by PowerShell, backslashes in paths behaved unstably, and the &lt;code&gt;-split&lt;/code&gt; argument syntax caused yet another detour. The model kept diagnosing itself and patching the script. In the end, the comments gave it a very fitting title: classic GPT 5.5 vs PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://knightli.com/2026/07/01/codex-vs-powershell-safe-invocation/codex-powershell-battle.jpg&#34;
	width=&#34;1080&#34;
	height=&#34;2400&#34;
	srcset=&#34;https://knightli.com/2026/07/01/codex-vs-powershell-safe-invocation/codex-powershell-battle_hu_5b7da40f3bf17d89.jpg 480w, https://knightli.com/2026/07/01/codex-vs-powershell-safe-invocation/codex-powershell-battle_hu_a1711b2e97eccd27.jpg 1024w&#34;
	
		loading=&#34;eager&#34;
		fetchpriority=&#34;high&#34;
		decoding=&#34;sync&#34;
	
	
		alt=&#34;Screenshot of Codex repeatedly fixing a script in PowerShell&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;45&#34;
		data-flex-basis=&#34;108px&#34;
	
&gt;
&lt;/p&gt;
&lt;p&gt;The chain of fixes in the screenshot is funny, but the underlying problems are not rare.&lt;/p&gt;
&lt;p&gt;It lands because it looks so much like a real development session. PowerShell is not simply &amp;ldquo;Bash for Windows.&amp;rdquo; It has its own string rules, parameter binding rules, cmdlet error model, and native command argument passing behavior. Once an agent brings Bash habits into PowerShell, ordinary tasks such as writing files, replacing text, and invoking external programs can turn into a sequence of small failures.&lt;/p&gt;
&lt;p&gt;Misaka-Mikoto-Tech&amp;rsquo;s &lt;a class=&#34;link&#34; href=&#34;https://github.com/Misaka-Mikoto-Tech/agent-skills/tree/main/skills/powershell-safe-invocation&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;powershell-safe-invocation&lt;/a&gt; skill collects these pitfalls into a compact set of rules. It is not about memorizing more PowerShell syntax. It tells an agent to choose invocation forms that are less likely to fail when running commands on Windows.&lt;/p&gt;
&lt;h2 id=&#34;the-main-problem-is-not-that-powershell-is-hard-but-that-agents-treat-it-like-bash&#34;&gt;The main problem is not that PowerShell is hard, but that agents treat it like Bash
&lt;/h2&gt;&lt;p&gt;The screenshot shows several classic problems.&lt;/p&gt;
&lt;p&gt;The first category is strings and line endings. Markdown uses backticks, and PowerShell also treats backticks as escape characters. A document may use CRLF while the script matches LF exactly. If a here-string&amp;rsquo;s opening or closing syntax is off by indentation or quoting, it may not produce the intended text at all.&lt;/p&gt;
&lt;p&gt;The second category is paths and arguments. Windows paths naturally contain backslashes, and directories often include spaces, brackets, or Chinese characters. If a command is built as one large string before execution, an argument may be split unexpectedly, or a path segment may be interpreted as escaping, wildcard syntax, a regular expression, or syntax for another shell.&lt;/p&gt;
&lt;p&gt;The third category is error handling. External programs should be checked through &lt;code&gt;$LASTEXITCODE&lt;/code&gt;; PowerShell cmdlets should rely on terminating errors and &lt;code&gt;$ErrorActionPreference = &#39;Stop&#39;&lt;/code&gt;. If an agent mixes these models, it can end up believing a command succeeded when it did not.&lt;/p&gt;
&lt;p&gt;None of these are huge failures by themselves, but they consume attention. Agents can also keep repairing the wrong assumption simply because &amp;ldquo;a command seemed to have run,&amp;rdquo; and the loop gets messier.&lt;/p&gt;
&lt;h2 id=&#34;the-core-rule-of-this-skill-do-not-build-one-huge-command-string&#34;&gt;The core rule of this skill: do not build one huge command string
&lt;/h2&gt;&lt;p&gt;The most important rule in &lt;code&gt;powershell-safe-invocation&lt;/code&gt; is: do not concatenate the executable, paths, arguments, and quotes into one giant command string.&lt;/p&gt;
&lt;p&gt;When invoking a native program, each argument should be a separate array item:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$exe&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Path With Spaces\tool.exe&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$args&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;--input&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Data Folder\input.json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;--flag&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$exe&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;@args&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$exitCode&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$LASTEXITCODE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$exitCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-ne&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;throw&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$exe&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; failed with exit code &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$exitCode&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This looks more verbose than a one-line command, but it separates the risks: a path is a path, an argument is an argument, and invocation is invocation. The agent no longer has to guess whether a layer of quotes belongs to PowerShell, cmd, or the target program.&lt;/p&gt;
&lt;p&gt;For PowerShell cmdlets, hashtable splatting is usually a better fit:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$params&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;LiteralPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Data[1]\input.txt&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Destination&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Output&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Force&lt;/span&gt;       &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;$true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ErrorAction&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Stop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;Copy-Item&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;@params&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The key detail here is &lt;code&gt;-LiteralPath&lt;/code&gt;. Real file paths should be treated literally by default. Use wildcard-expanding parameters only when wildcard expansion is intentional. For an agent, this is much more reliable than trying to detect whether a path contains &lt;code&gt;[&lt;/code&gt;, &lt;code&gt;]&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, or &lt;code&gt;?&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;do-not-stuff-complex-commands-into--command&#34;&gt;Do not stuff complex commands into &lt;code&gt;-Command&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;Many Windows automation problems start with a command like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cmd.exe /c pwsh.exe -Command &amp;#34;...&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Once JSON, XML, regular expressions, pipelines, redirection, multiline text, non-ASCII paths, or Markdown backticks appear inside it, the escaping layers quickly become hard to reason about. It is difficult for humans to read and even easier for agents to misjudge.&lt;/p&gt;
&lt;p&gt;The skill&amp;rsquo;s recommendation is simple: once the command becomes even a little complex, write a temporary &lt;code&gt;.ps1&lt;/code&gt; file and run it with &lt;code&gt;pwsh.exe -NoLogo -NoProfile -NonInteractive -File script.ps1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This rule is especially suitable for agents. After generating a script file, the agent can inspect the script, run it, and verify file diffs step by step. When everything is crammed into one &lt;code&gt;-Command&lt;/code&gt;, a failure leaves only a knot of quotes and escapes to debug.&lt;/p&gt;
&lt;h2 id=&#34;powershellexe-is-not-pwshexe&#34;&gt;&lt;code&gt;powershell.exe&lt;/code&gt; is not &lt;code&gt;pwsh.exe&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;Another easily missed point is the version.&lt;/p&gt;
&lt;p&gt;Installing PowerShell 7 does not make &lt;code&gt;powershell.exe&lt;/code&gt; become PowerShell 7. Usually:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;powershell.exe&lt;/code&gt; is Windows PowerShell 5.1&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pwsh.exe&lt;/code&gt; is PowerShell 7&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They differ in native command argument passing, default encodings, and other behavior details. If an agent does not know which shell it is running in, it should check first:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$PSVersionTable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;PSVersion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$PSNativeCommandArgumentPassing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This is not ceremony. Many &amp;ldquo;it works locally but fails when the agent runs it&amp;rdquo; issues come from different shell versions and argument passing rules.&lt;/p&gt;
&lt;h2 id=&#34;treat-encoding-and-line-endings-as-first-class-file-writing-concerns&#34;&gt;Treat encoding and line endings as first-class file-writing concerns
&lt;/h2&gt;&lt;p&gt;The most interesting part of the screenshot is how the agent repeatedly circles around failed Markdown replacements. At least three assumptions are hidden there:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the file&amp;rsquo;s actual encoding&lt;/li&gt;
&lt;li&gt;whether the file uses CRLF or LF&lt;/li&gt;
&lt;li&gt;whether the replacement target was changed by PowerShell string syntax&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When a Chinese article, Markdown code blocks, front matter, shortcodes, and backticks are mixed together, it is better not to write the body with an improvised PowerShell here-string. Either use file APIs with explicit encoding, or let the script handle only ASCII control logic and write non-ASCII body text through a more reliable path.&lt;/p&gt;
&lt;p&gt;For agent workflows, there is one extra habit: verify immediately after writing. At minimum, check that the file is readable as UTF-8, front matter is closed, Markdown links are intact, and the body contains no repeated question marks or obvious mojibake. Encoding problems are cheaper the earlier they are found.&lt;/p&gt;
&lt;h2 id=&#34;a-steadier-decision-order&#34;&gt;A steadier decision order
&lt;/h2&gt;&lt;p&gt;The most practical part of this skill is that it gives agents a decision order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use a PowerShell cmdlet when one fits.&lt;/li&gt;
&lt;li&gt;When invoking an external program, use &lt;code&gt;&amp;amp; $exe @args&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When the command is complex, write a &lt;code&gt;.ps1&lt;/code&gt; file and run it with &lt;code&gt;pwsh.exe -File&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When process arguments must be controlled precisely, use &lt;code&gt;ProcessStartInfo.ArgumentList&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Start-Process&lt;/code&gt; only for special behavior such as a new window, elevation, or detached execution.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;cmd.exe /c&lt;/code&gt; only when cmd semantics are actually required.&lt;/li&gt;
&lt;li&gt;Treat &lt;code&gt;Invoke-Expression&lt;/code&gt; as a very constrained last resort.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This order turns &amp;ldquo;it runs&amp;rdquo; into &amp;ldquo;it is explainable, checkable, and reproducible.&amp;rdquo; That matters for human developers, and even more for agents.&lt;/p&gt;
&lt;h2 id=&#34;practical-advice-for-codex&#34;&gt;Practical advice for Codex
&lt;/h2&gt;&lt;p&gt;If I ask Codex to edit files in a Windows repository, I would give it a few hard constraints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do not use Bash-style &lt;code&gt;\&amp;quot;&lt;/code&gt; escaping in PowerShell.&lt;/li&gt;
&lt;li&gt;Do not concatenate paths and arguments into one big string.&lt;/li&gt;
&lt;li&gt;Do not use &lt;code&gt;Start-Process -ArgumentList&lt;/code&gt; for complex arguments.&lt;/li&gt;
&lt;li&gt;Do not wrap ordinary calls with &lt;code&gt;cmd.exe /c&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prefer &lt;code&gt;-LiteralPath&lt;/code&gt; for real file paths.&lt;/li&gt;
&lt;li&gt;Prefer writing a &lt;code&gt;.ps1&lt;/code&gt; file for complex scripts, then run it with &lt;code&gt;pwsh.exe -File&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;After writing Chinese, Japanese, or other non-ASCII content, check encoding and corruption markers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PowerShell is not the enemy of agents. The real problem is that agents too easily fall back to the old habit of &amp;ldquo;concatenate a string and let the shell guess.&amp;rdquo; Once invocation boundaries are made explicit, PowerShell can actually provide strong structured behavior.&lt;/p&gt;
&lt;p&gt;So the conclusion of this &amp;ldquo;Codex vs PowerShell&amp;rdquo; story is not that agents should avoid Windows. It is that they need a tactical manual: gamble less on quotes, use more structure; cram fewer commands into one line, keep more intermediate state that can be inspected.&lt;/p&gt;
&lt;p&gt;The joke is in the screenshot. The lesson is in the rules.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
