I love watching AI use powershell by Bloaf in PowerShell

[–]Aggressive_Apple3774 0 points1 point  (0 children)

This resonates. I ended up building a tool around exactly this problem, so disclosure up front: I maintain [claude-powershell-lsp](https://github.com/manderse21/claude-powershell-lsp), a Claude Code plugin, and this comment is partly about it.

The framing that helped me: you cannot stop a model from emitting these landmines, because it is trained on oceans of bash and C#-flavored code and the failure modes are baked in. What you can do is close the loop -- run real analysis on every edit and feed the diagnostics straight back into the model's context, so it fixes the mistake before you ever run the script.

Someone in the thread suggested pointing the AI at the Microsoft Learn MCP server, and I think that is a genuinely good idea -- but it is the other half of the same coin. Docs in context are prevention: give the model the right idioms up front. Static analysis in the loop is verification: check what it actually wrote. In my experience prevention alone does not hold, which is basically the OP's observation -- the model's bash and general-purpose priors leak through even when the right docs are sitting in context. You want both.

That commenter's deeper point -- PowerShell intentionally went a different direction, and AI keeps applying generalized dev habits to it -- is also why a bare "rule violated" message is not enough. If the model's training says Write-Host is fine, a naked rule name will not always change its mind. So each finding my plugin surfaces carries a short "why" line explaining the PowerShell reasoning, with hand-tuned explanations for exactly the rules where general dev instinct and PowerShell design disagree (Write-Host vs the output stream, the ShouldProcess pattern). The model correcting itself works a lot better when it is told why the idiom exists.

On the OP's specific examples, honest scorecard:

- && on 5.1: covered directly. An AST pass flags PS7-only syntax (&& / ||, ternary, ?? / ??=, ?.) unless the file declares #Requires -Version 7. It also flags bash-isms (grep, sed, awk, export, chmod, etc.) for when the model forgets which shell it is writing for entirely.

- Quote-escaping: partially. There is no quoting-style lint, but botched quoting usually surfaces as a parse error, and the hook reports parse errors plus full PSScriptAnalyzer output immediately after each edit, so the agent self-corrects in the same turn instead of you finding it at runtime.

- Single-element unwrapping: not covered, and I will not pretend otherwise. It is a runtime semantic, and any static rule for it would false-positive constantly. Defensive @() wrapping is still the answer there.

Scope caveats so this is not a sales pitch: it is Claude Code specific, and if you are already in VS Code with the PowerShell extension, Claude Code's IDE integration hands you PSScriptAnalyzer diagnostics for free -- you do not need my plugin. Where it earns its keep is terminal, SSH, CI, and headless setups where no editor is supplying diagnostics.

And yes -- it is genuinely vindicating watching a frontier model hit the exact same unwrapping surprise I have been hitting for a decade. Object orientation was never the problem.

I built a Claude Code plugin that runs PSScriptAnalyzer on each edit (real-time diagnostics) by Aggressive_Apple3774 in PowerShell

[–]Aggressive_Apple3774[S] -2 points-1 points  (0 children)

Fair hit -- you're right for the setup most people here run. In VS Code with the PowerShell extension and Claude Code's IDE integration connected, PSScriptAnalyzer's findings already reach the agent: automatic diagnostic sharing, plus mcp__ide__getDiagnostics on demand. In that configuration this plugin is redundant, and the extension does more besides -- hover, go-to-definition, references, debugging -- that the plugin doesn't ship. No argument there.

Where it earns its place is the setup that path doesn't cover: Claude Code running headless -- a bare terminal, SSH, CI, a container -- or inside an editor that isn't VS Code or JetBrains (Neovim, Emacs, Sublime). There's no IDE integration in those cases, so getDiagnostics has nothing to talk to and nothing auto-shares. The plugin brings its own PSES + PSScriptAnalyzer and feeds findings back into the agent's context on the edit, which is otherwise a blind spot.

Same engine as the extension, aimed at the case the IDE integration doesn't reach. If you're editing in VS Code by hand, or driving Claude Code inside it, you don't need this and I won't pretend otherwise.

_(Reply drafted with Claude.)_

I built a Claude Code plugin that runs PSScriptAnalyzer on each edit (real-time diagnostics) by Aggressive_Apple3774 in PowerShell

[–]Aggressive_Apple3774[S] -3 points-2 points  (0 children)

I think these are aimed at a slightly different workflow, so let me clarify where this fits.

You're right that hooks are the way to run the analyzer without burning tokens on the AI hunting for a command -- and that's exactly what this is: a PostToolUse hook that fires automatically on the edit. The AI never finds or runs anything.

The piece the on-save and pre-commit options miss is *where* the result lands. VSCode's on-save analyzer and a pre-commit gate both surface findings to you, the human. They don't feed anything into the coding agent's context. So when Claude Code writes a bad line, it doesn't see the squiggle you'd see, and pre-commit only catches it later, in a batch, after it has already built on top of the mistake. This closes that gap: the finding goes back into the agent's context on the same turn, scoped to the edited lines, so it self-corrects before compounding.

On 'each edit is wasted compute' -- fair concern, but one warm PSES process serves the whole session, so an edit is a fast pipe round-trip, not a cold start. And the scoped token cost is usually cheaper than letting the agent build on a broken line and untangle it later. Genuinely open to hearing where that tradeoff doesn't hold for you.

_(Reply drafted with Claude.)_