Skip to content

Windows: PowerShell 7 execution and runtime portability #36

Description

@Yuzu02

Context

Upstream PR #34 already changes command handles from MCP-session scope to workspace scope. This issue tracks the remaining Windows runtime work on top of that branch; it no longer proposes a second shared-process registry or an opt-in --shared-exec-sessions mode.

Problems addressed

  1. Windows string commands otherwise inherit subprocess(..., shell=True) behavior and fall through to cmd.exe, which cannot execute native PowerShell syntax.
  2. Safe-mode scanning does not recognize PowerShell network cmdlets or recursive deletion aliases/abbreviations.
  3. Windows environment variables are case-insensitive, but minimal child environments can contain duplicate casing and omit PATHEXT, preventing executable resolution.
  4. Several tests encode POSIX-only shell, newline, home-directory, permission-bit, and cleanup assumptions.
  5. Existing Windows typeshed paths expose a small set of Mypy issues.

Implemented design

  • PowerShell 7 is required for Windows string commands.
  • The server resolves pwsh.exe only from its own trusted environment or the absolute operator setting CODING_TOOLS_MCP_PWSH_PATH.
  • No silent cmd.exe fallback.
  • PowerShell runs with -NoLogo -NoProfile -NonInteractive.
  • Safe mode blocks PowerShell network cmdlets and recursive deletion aliases.
  • Windows command environments are normalized case-insensitively and gain a default PATHEXT when needed.
  • Cross-platform tests use equivalent native commands and deterministic byte fixtures without changing lossless file semantics.

Validation

Windows 11, PowerShell 7, Python 3.13:

  • 217 tests passed
  • 0 failures, 0 errors
  • 87 explicit POSIX/Linux-only skips
  • Ruff clean
  • Mypy clean across 16 source files
  • uv lock --check clean

Contribution and stack

GitHub's stacked-PR public preview currently requires every branch to live in the same repository, so it cannot create an upstream stack from a contributor fork. The fork stack preserves the focused diffs; layer 2 can be retargeted upstream after #37 lands or if the branches are adopted upstream.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions