You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Idle standby consoles now clean themselves up (#53). When several consoles pile up — e.g. after the AI switches to a new console and the old one is left on standby — an owned console that neither the AI nor you have used for 10 minutes prints a warning (This console will close in 60s without use…) and then closes itself, so the desktop no longer fills with abandoned windows. The most-recently-used console of a session is always kept, so the next command still has a console ready — as is any console you have left text half-typed at the prompt, so a window you are in the middle of using is never closed out from under you. (Text at the prompt only vetoes that console's own close; it deliberately does not count as "most recently used", so a forgotten half-typed line cannot make itself the permanent survivor and reap the console the AI is actually working in.) Typing anything at the prompt, or any AI command, cancels a pending close. A console that is busy, waiting at a prompt, or still holding undrained output is never closed. Coordination is entirely local — each console publishes a small marker file under %LOCALAPPDATA%\PowerShell.MCP (per-user, no admin; falls back to temp only if unavailable) and elects the survivor by reading them, with no extra traffic to the AI. Tune with POWERSHELL_MCP_STANDBY_REAP_MINUTES (default 10; 0 disables) and POWERSHELL_MCP_STANDBY_REAP_GRACE_SECONDS (default 60). Set these where the console itself will see them — a user or system environment variable (Windows: System Properties → Environment Variables, or setx; macOS / Linux: your login-shell profile) — not in your MCP client's env block. Each console is a new terminal window rather than a child of the proxy, so a variable set only on the proxy process generally will not reach it: on Windows the console's environment is rebuilt from your user profile, and on macOS the window is created by Terminal.app. (The Linux headless path — no terminal emulator found — is the one case that inherits the proxy's environment directly.)
Behavior Changes
close_console now refuses the first attempt when someone is typing in the target. If the console has unsubmitted text at its prompt — a human is composing a command in it right now — the first close_console call closes nothing, leaves the console's pending output untouched, and reports what it saw. Calling close_console for the same PID again closes it: the retry is the confirmation, and there is deliberately no force parameter to bypass the check in one step. A console that is merely awaiting_input (a program blocked on Read-Host, with no human mid-keystroke) still closes on the first call — that is the tool's main use case and is unaffected. The check fails open: an unreachable console, a failed probe, or a stale sample all allow the close, because close_console is the escape hatch for a console that is stuck or wedged and a detection failure must never take it away. The pending confirmation expires after 60s, and is dropped if the AI runs a command in that console in the meantime.
A command that cannot parse is now reported as NOT executed (syntax error) (Discussion #52). The whole command is parsed up front, before the execution machinery spins up, and the response leads with a SYNTAX ERRORS section naming every error with its line, column, and ErrorId. Such a command never ran a single statement before either — [scriptblock]::Create compiled the full string up front — but it surfaced as a generic terminating exception under executed with errors, leaving the AI unsure whether earlier statements had taken effect. The console still mimics an interactive session: the command is echoed and its parse errors follow in red.
Bug Fixes
File edits no longer fail — or stay failed — when the target is briefly locked (#55).Add-LinesToFile, Update-LinesInFile, Update-MatchInFile, and Remove-LinesFromFile could print their preview and then fail the final swap with Unable to move the replacement file to the file to be replaced, leaving the file untouched. Three causes, all fixed. The swap now retries up to 3 times with a short backoff, so it rides out a transient holder of the target — an antivirus real-time scan, the search indexer, a cloud-sync client, or an editor mid-save — instead of failing on the first attempt. The scratch backup file is now uniquely named and always removed; previously it used a fixed <filename>.tmp next to the target, which was left behind when the swap failed and then made every later edit of that file fail the same way, so a one-off error became permanent. And when the swap does fail, the error now names all three paths involved plus the Win32 error code, rather than only the .NET sentence that identifies no file at all. Temp-file cleanup can also no longer throw over the original error and hide it.
close_console no longer discards a finished command's output. When you close a console, any output it still holds from an already-finished command is now harvested over the still-live pipe and returned in the close_console response before the console is killed. This includes a busy console that is running a new command while an earlier result sits uncollected in its cache — draining pulls only the already-cached completed result, never the running command's partial output, so it is safe in every state. Previously the kill threw the cached result away silently — so following the awaiting_input / timeout guidance to abandon a console with close_console could lose the output the command had already produced. Draining is best-effort: a console mid-teardown or an unreachable pipe never blocks the close.
Security
The bundled .NET runtime is pinned to a patched 9.0.18 build. The proxy binaries shipped in bin/* are self-contained, so they carry their own copy of the .NET runtime rather than using the machine's. That copy previously came from whatever runtime pack the build resolved by default; it is now pinned to 9.0.18, picking up fixes for the .NET advisories flagged against this repo (CVE-2026-47302, CVE-2026-50524, CVE-2026-50528, CVE-2026-57108). No configuration change is needed — updating the module replaces the bundled binaries.