Use when writing or running PowerShell on Windows, especially native programs, quoted paths, escaping, pwsh, Start-Process, file operations, or shell troubleshooting.
76
95%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Use PowerShell 7 through pwsh.exe unless Windows PowerShell 5.1 is explicitly required.
When the active shell is uncertain, verify:
$PSVersionTable.PSVersion
$PSNativeCommandArgumentPassingDo not assume installing PowerShell 7 makes powershell.exe use PowerShell 7:
pwsh.exe = PowerShell 7powershell.exe = Windows PowerShell 5.1Never construct one large command string when arguments can be passed separately.
Use:
$exe = 'C:\Path With Spaces\tool.exe'
$args = @(
'--input'
'C:\Data Folder\input.json'
'--flag'
)
& $exe @args
$exitCode = $LASTEXITCODE
if ($exitCode -ne 0) {
throw "$exe failed with exit code $exitCode"
}Rules:
&.$LASTEXITCODE immediately.Invoke-Expression.cmd.exe /c layer merely to launch an executable.\" escaping in PowerShell.Use hashtable splatting for PowerShell cmdlets:
$params = @{
LiteralPath = 'C:\Data[1]\input.txt'
Destination = 'C:\Output'
Force = $true
ErrorAction = 'Stop'
}
Copy-Item @paramsUse -LiteralPath for real paths unless wildcard expansion is intentional.
Do not use $LASTEXITCODE to test a PowerShell cmdlet. Use terminating errors:
$ErrorActionPreference = 'Stop'Avoid deeply quoted commands such as:
cmd.exe /c pwsh.exe -Command "..."For multiline code, nested quotes, JSON, XML, regular expressions, pipelines, redirection, or non-ASCII paths:
.ps1 file.pwsh.exe -NoLogo -NoProfile -NonInteractive -File script.ps1Prefer -File over -Command for anything beyond a short, simple expression.
Do not add -ExecutionPolicy Bypass unless execution policy is actually blocking a trusted script.
ConvertTo-Json; do not hand-escape JSON.For normal foreground execution, use:
& $exe @argsUse Start-Process only for elevation, new/hidden windows, detached launch, or shell behavior.
Start-Process -ArgumentList joins values into a command-line string and is not a reliable structured-argument API.
When a separate process is required and arguments are complex, use:
$psi = [System.Diagnostics.ProcessStartInfo]::new()
$psi.FileName = $exe
$psi.UseShellExecute = $false
foreach ($arg in $args) {
$psi.ArgumentList.Add($arg)
}
$process = [System.Diagnostics.Process]::Start($psi)
$process.WaitForExit()
if ($process.ExitCode -ne 0) {
throw "Process failed with exit code $($process.ExitCode)"
}Before recursive delete, move, or overwrite:
Choose the simplest safe option:
& $exe @args..ps1 file with pwsh.exe -File.ProcessStartInfo.ArgumentList.Start-Process when its special behavior is required.cmd.exe /c only when cmd semantics are required.Invoke-Expression only as a tightly controlled last resort.For uncommon cases, prefer the same decision order and simplify the invocation until each parser boundary is explicit.
5b802a8
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.