PowerShell Safe Commands
Copyright
Copyright (c) 2026 Ninthless. All rights reserved. This skill may not be copied, modified, redistributed, or used to create derivative works without prior written permission.
Triggers
- The task will run shell commands in PowerShell, Windows Terminal, Codex CLI, or an agent shell whose outer shell may be PowerShell.
- A command contains
$, $_, $env:, ${...}, $(...), @{...}, unquoted Windows paths like C:\Users\name, backticks, regex replacements, script blocks, here-strings, nested quotes, or pipes into ForEach-Object / Where-Object.
- The user reports that PowerShell ate a token, a one-liner failed,
$_ disappeared, @{u} became a hashtable, C:\Users\... caused ExpectedValueExpression, quoting broke, or an edit had to be redone in Python.
- The agent is about to use
powershell -Command, pwsh -Command, cmd /c, bash -lc, or another wrapper around a command string.
- The task edits files from the shell, especially with inline PowerShell replacement commands.
Purpose
Use this skill to avoid the common Windows failure mode where an outer PowerShell parser consumes syntax before the intended program sees it. The fix is usually not clever escaping. The fix is to remove one shell layer, call the executable directly, or move non-trivial logic into a temporary script.
Default Ladder
Stop at the first safe option that works:
- Call the target executable directly, without wrapping it in
powershell -Command.
- For file edits or structured transforms, write a tiny Python script file and run it directly; avoid stuffing multiline scripts into
python -c.
- For reusable JavaScript transforms, use Node directly.
- If PowerShell is actually needed, put the script in a temporary
.ps1 file and run that file.
- Only for tiny commands, use inline PowerShell with single quotes around the nested command string.
- If none of those fit, use
-EncodedCommand and show the decoded script in the transcript before running it.
Prefer option 1 or 2. They are boring and survive nested shells.
Hard Rules
- Do not retry a failed quoting-heavy PowerShell one-liner by adding more backslashes at random.
- Do not use inline PowerShell for edits that include
$, $_, regex captures, unquoted Windows paths in expressions, or nested quotes.
- Do not wrap a command in
powershell -Command when the current shell is already PowerShell unless there is a concrete reason.
- Quote git revision syntax such as
@{u} in PowerShell: git rev-parse --abbrev-ref --symbolic-full-name '@{u}'.
- In Windows PowerShell 5, use
; instead of &&.
- Honor project command prefixes such as
rtk; put the prefix before the real executable, not before a PowerShell cmdlet that is not on PATH.
- For non-trivial shell logic, leave one small verification command that proves the intended token reached the intended program.
Safe Patterns
Direct executable
Use this when possible:
git -C E:\Projects\repo status -sb
python scripts\edit_file.py
node scripts\check.mjs
Avoid this if the wrapper adds no value:
powershell -Command "git -C E:\Projects\repo status -sb"
Pipeline automatic variables
Unsafe when nested in a double-quoted outer command:
powershell -Command "Get-ChildItem | Where-Object { $_.Name -match 'txt' }"
Safer:
powershell -Command 'Get-ChildItem | Where-Object { $_.Name -match "txt" }'
Safest for agents when the logic grows:
powershell -File .\work\filter-files.ps1
Python -c is not a multiline transport
Do not combine PowerShell here-strings, Python -c, and embedded multiline raw strings. That creates three parsers before the file is even written. If the Python code is more than one expression, save it as work/<name>.py and run python work/<name>.py.
Environment paths are values, not syntax
Do not generate PowerShell like Write-Output ('USERPROFILE=' + C:\Users\name). C:\Users\name is not a string literal, so PowerShell parses it as broken syntax. Keep the lookup inside PowerShell: Write-Output "USERPROFILE=$env:USERPROFILE", or use [Environment]::GetFolderPath(...) for known folders. If a path value is already known, quote it as a string.
File edits
Use Python for edits that include replacements, captures, or multiple lines:
python work\edit.py
Keep the script short and delete it only if the user asked for no artifacts. In challenge or debugging work, keeping the script under work/ is often better because it makes the edit replayable.
Recovery After a Quoting Failure
- Stop retrying the same one-liner.
- Identify the token that was eaten or reinterpreted.
- Replace the command with a direct executable call or a temporary script.
- Run the smallest verification that proves the token survived.
- Continue with the original task.
Output Style
When this skill changes the command strategy, say it briefly:
PowerShell 会吃这里的 $_,我改用 Python 临时脚本做同一个编辑。
Do not turn every command into a lecture. Fix the command and move on.
1---2name: powershell-safe-commands3description: Author or repair PowerShell commands safely on Windows when shell parsing can change meaning. Use for $, $_, $env:, @{u}, $(...), nested powershell -Command, here-strings, regex replacements, quoted paths, file edits from shell, generated one-liners, or failures such as $ 被吃了, PowerShell 外层吃了, unterminated strings, and ExpectedValueExpression. Trigger before rerunning a command affected by interpolation, quoting, or wrapper layers, and prefer direct executables, Python, or temporary scripts when safer. Do not use for simple direct commands with no PowerShell-specific syntax, conceptual explanations only, or non-Windows shells.4---56# PowerShell Safe Commands78## Copyright910Copyright (c) 2026 Ninthless. All rights reserved. This skill may not be copied, modified, redistributed, or used to create derivative works without prior written permission.1112## Triggers1314- The task will run shell commands in PowerShell, Windows Terminal, Codex CLI, or an agent shell whose outer shell may be PowerShell.15- A command contains `$`, `$_`, `$env:`, `${...}`, `$(...)`, `@{...}`, unquoted Windows paths like `C:\Users\name`, backticks, regex replacements, script blocks, here-strings, nested quotes, or pipes into `ForEach-Object` / `Where-Object`.16- The user reports that PowerShell ate a token, a one-liner failed, `$_` disappeared, `@{u}` became a hashtable, `C:\Users\...` caused `ExpectedValueExpression`, quoting broke, or an edit had to be redone in Python.17- The agent is about to use `powershell -Command`, `pwsh -Command`, `cmd /c`, `bash -lc`, or another wrapper around a command string.18- The task edits files from the shell, especially with inline PowerShell replacement commands.1920## Purpose2122Use this skill to avoid the common Windows failure mode where an outer PowerShell parser consumes syntax before the intended program sees it. The fix is usually not clever escaping. The fix is to remove one shell layer, call the executable directly, or move non-trivial logic into a temporary script.2324## Default Ladder2526Stop at the first safe option that works:27281. Call the target executable directly, without wrapping it in `powershell -Command`.292. For file edits or structured transforms, write a tiny Python script file and run it directly; avoid stuffing multiline scripts into `python -c`.303. For reusable JavaScript transforms, use Node directly.314. If PowerShell is actually needed, put the script in a temporary `.ps1` file and run that file.325. Only for tiny commands, use inline PowerShell with single quotes around the nested command string.336. If none of those fit, use `-EncodedCommand` and show the decoded script in the transcript before running it.3435Prefer option 1 or 2. They are boring and survive nested shells.3637## Hard Rules3839- Do not retry a failed quoting-heavy PowerShell one-liner by adding more backslashes at random.40- Do not use inline PowerShell for edits that include `$`, `$_`, regex captures, unquoted Windows paths in expressions, or nested quotes.41- Do not wrap a command in `powershell -Command` when the current shell is already PowerShell unless there is a concrete reason.42- Quote git revision syntax such as `@{u}` in PowerShell: `git rev-parse --abbrev-ref --symbolic-full-name '@{u}'`.43- In Windows PowerShell 5, use `;` instead of `&&`.44- Honor project command prefixes such as `rtk`; put the prefix before the real executable, not before a PowerShell cmdlet that is not on PATH.45- For non-trivial shell logic, leave one small verification command that proves the intended token reached the intended program.4647## Safe Patterns4849### Direct executable5051Use this when possible:5253~~~powershell54git -C E:\Projects\repo status -sb55python scripts\edit_file.py56node scripts\check.mjs57~~~5859Avoid this if the wrapper adds no value:6061~~~powershell62powershell -Command "git -C E:\Projects\repo status -sb"63~~~6465### Pipeline automatic variables6667Unsafe when nested in a double-quoted outer command:6869~~~powershell70powershell -Command "Get-ChildItem | Where-Object { $_.Name -match 'txt' }"71~~~7273Safer:7475~~~powershell76powershell -Command 'Get-ChildItem | Where-Object { $_.Name -match "txt" }'77~~~7879Safest for agents when the logic grows:8081~~~powershell82powershell -File .\work\filter-files.ps183~~~8485### Python `-c` is not a multiline transport8687Do not combine PowerShell here-strings, Python `-c`, and embedded multiline raw strings. That creates three parsers before the file is even written. If the Python code is more than one expression, save it as `work/<name>.py` and run `python work/<name>.py`.8889### Environment paths are values, not syntax9091Do not generate PowerShell like `Write-Output ('USERPROFILE=' + C:\Users\name)`. `C:\Users\name` is not a string literal, so PowerShell parses it as broken syntax. Keep the lookup inside PowerShell: `Write-Output "USERPROFILE=$env:USERPROFILE"`, or use `[Environment]::GetFolderPath(...)` for known folders. If a path value is already known, quote it as a string.9293### File edits9495Use Python for edits that include replacements, captures, or multiple lines:9697~~~powershell98python work\edit.py99~~~100101Keep the script short and delete it only if the user asked for no artifacts. In challenge or debugging work, keeping the script under `work/` is often better because it makes the edit replayable.102103## Recovery After a Quoting Failure1041051. Stop retrying the same one-liner.1062. Identify the token that was eaten or reinterpreted.1073. Replace the command with a direct executable call or a temporary script.1084. Run the smallest verification that proves the token survived.1095. Continue with the original task.110111## Output Style112113When this skill changes the command strategy, say it briefly:114115~~~text116PowerShell 会吃这里的 $_,我改用 Python 临时脚本做同一个编辑。117~~~118119Do not turn every command into a lecture. Fix the command and move on.