Skip to content

Comments

feat: Add Windows compatibility guide and installer support#704

Open
chrisglick wants to merge 1 commit intodanielmiessler:mainfrom
chrisglick:windows-compatibility
Open

feat: Add Windows compatibility guide and installer support#704
chrisglick wants to merge 1 commit intodanielmiessler:mainfrom
chrisglick:windows-compatibility

Conversation

@chrisglick
Copy link
Contributor

Summary

  • Windows Compatibility Guide (Releases/v3.0/WINDOWS_COMPATIBILITY.md) — comprehensive manual installation steps, known issues, and workarounds for running PAI on Windows
  • Installer Windows detectioninstall.sh now detects MINGW/MSYS/CYGWIN and directs users to the compatibility guide instead of failing with "Unsupported platform"
  • Install-time hook path resolutionresolveHookPaths() in actions.ts resolves ${PAI_DIR} in hook commands on Windows only (complete no-op on macOS/Linux), since cmd.exe doesn't expand ${VAR} syntax

Problem

Claude Code hooks on Windows fail with Module not found "${PAI_DIR}/hooks/..." because:

  1. ${PAI_DIR} in hook command strings is expanded by /bin/sh on macOS/Linux, but Windows hooks execute through cmd.exe which uses %VAR% syntax
  2. .ts hook files have #!/usr/bin/env bun shebangs that work on Unix but not Windows — they need explicit bun prefixing

Changes

File Change
Releases/v3.0/WINDOWS_COMPATIBILITY.md New: manual install guide, known issues, workarounds
Releases/v3.0/.claude/PAI-Install/engine/actions.ts Added resolveHookPaths() — Windows-only, no-op on macOS/Linux
Releases/v3.0/.claude/PAI-Install/install.sh Added MINGW/MSYS/CYGWIN detection with helpful error message
README.md Added one-line Windows reference pointing to guide
Releases/v3.0/README.md Added one-line Windows reference pointing to guide

Design Decisions

  • Zero Mac/Linux impact: resolveHookPaths() returns immediately on non-win32 platforms. No behavioral changes for existing users.
  • Template stays generic: The template settings.json still uses ${PAI_DIR} — resolution happens at install time only, so the template remains portable.
  • Forward slashes on Windows: All resolved paths use / separators since both Bun and Node.js handle them correctly on Windows.

Test plan

  • Verify install.sh on macOS/Linux still works unchanged
  • Verify install.sh on Windows (Git Bash/MSYS) shows compatibility guide message
  • Run TypeScript installer on Windows — confirm hooks resolve correctly
  • Confirm resolveHookPaths() is a no-op when process.platform !== "win32"

Closes #440, #543, #385

🤖 Generated with Claude Code

…essler#440, danielmiessler#543, danielmiessler#385)

Claude Code does not expand ${VAR} in hook command strings — only in
.mcp.json. On macOS/Linux the shell handles expansion, but on Windows
cmd.exe ignores ${VAR} syntax entirely, causing all hooks to fail with
"Module not found".

Changes:
- Add resolveHookPaths() to installer config step — resolves ${PAI_DIR}
  to absolute paths and adds "bun" prefix for .ts files (Windows only,
  no-op on macOS/Linux to preserve dynamic env var flexibility)
- Add MINGW/MSYS/CYGWIN detection to install.sh with friendly redirect
  to the compatibility guide instead of a generic error
- Add Releases/v3.0/WINDOWS_COMPATIBILITY.md covering manual install,
  known issues (stdin, colons, voice), and workarounds
- Reference the guide from root README and v3.0 release README

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chrisglick
Copy link
Contributor Author

Research Note: Why Install-Time Resolution Is Correct

While reviewing this PR, I investigated whether we could use %PAI_DIR% (cmd.exe runtime expansion) instead of hardcoding absolute paths at install time — preserving the same flexibility that ${PAI_DIR} provides on macOS/Linux.

Finding: It won't work. There's a known Claude Code bug:

  • #20112 (duplicate of #11927): Environment variables from settings.json's env section are not injected into hook command execution on Windows. The PAI_DIR value defined in env never reaches the shell that runs hook commands.

Even if the bug were fixed, there's a shell ambiguity problem:

  • %PAI_DIR% only works in cmd.exe
  • PowerShell needs $env:PAI_DIR
  • Bash/MSYS needs ${PAI_DIR}
  • Claude Code's official Windows hook examples use powershell.exe -Command "..." explicitly, but don't guarantee which shell runs hook commands

Conclusion: resolveHookPaths() doing install-time absolute path resolution is the correct approach for Windows. It sidesteps both the env var injection bug and the shell syntax ambiguity. When #11927 is fixed, this could potentially be simplified to a syntax swap (${PAI_DIR}%PAI_DIR%) rather than full path resolution — but that's a future optimization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failed install with Claude Code on Windows

1 participant