Compare commits

...

4 Commits

Author SHA1 Message Date
Jesse Vincent
d2d6cf4852 Release v4.3.1: Cursor support, Windows hook fix
- Add Cursor plugin manifest and hook response compatibility
- Restore polyglot wrapper for Windows SessionStart reliability
- Fix 6 Windows issues: #518, #504, #491, #487, #466, #440
2026-02-21 11:07:05 -08:00
Jesse Vincent
394cf85013 Merge pull request #523 from obra/fix/windows-hooks-4.3.1
fix: restore polyglot wrapper for Windows hook compatibility (4.3.1)
2026-02-21 13:50:36 -05:00
Jesse Vincent
31bbbe2dbb fix: quote CLAUDE_PLUGIN_ROOT for spaces, use POSIX-safe path resolution
- Quote ${CLAUDE_PLUGIN_ROOT} in hooks.json to handle paths with spaces
  (e.g. "C:\Users\Robert Zimmermann\...")
- Replace bash-only ${BASH_SOURCE[0]:-$0} with POSIX-safe $0 in
  run-hook.cmd so the Unix path doesn't break on dash (/bin/sh)

Addresses: #518 (spaces in path), Ubuntu/Debian compatibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 10:40:30 -08:00
Jesse Vincent
5fbefbd0a9 fix: restore polyglot wrapper to fix Windows hook window spawning
Claude Code spawns hook commands with shell:true + windowsHide:true,
but on Windows the execution chain cmd.exe -> bash.exe causes Git
Bash (MSYS2) to allocate its own console window, bypassing the hide
flag. This creates visible terminal windows that steal focus on every
SessionStart event (startup, resume, clear, compact).

The fix:
- Rename session-start.sh to session-start (no extension) so Claude
  Code's .sh auto-detection regex doesn't fire and prepend "bash"
- Restore run-hook.cmd polyglot wrapper to control bash invocation
  on Windows (tries known Git Bash paths, then PATH, then exits
  silently if no bash found)
- On Unix, the polyglot's shell portion runs the script directly

This avoids Claude Code's broken .sh auto-prepend, gives us control
over how bash is invoked on Windows, and gracefully handles missing
bash instead of erroring.

Addresses: #440, #414, #354, #417, #293
Upstream: anthropics/claude-code#14828
2026-02-21 10:29:26 -08:00
8 changed files with 58 additions and 32 deletions

View File

@@ -9,7 +9,7 @@
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "4.3.0",
"version": "4.3.1",
"source": "./",
"author": {
"name": "Jesse Vincent",

View File

@@ -1,7 +1,7 @@
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "4.3.0",
"version": "4.3.1",
"author": {
"name": "Jesse Vincent",
"email": "jesse@fsck.com"

View File

@@ -2,7 +2,7 @@
"name": "superpowers",
"displayName": "Superpowers",
"description": "Core skills library: TDD, debugging, collaboration patterns, and proven techniques",
"version": "4.3.0",
"version": "4.3.1",
"author": {
"name": "Jesse Vincent",
"email": "jesse@fsck.com"

1
.gitattributes vendored
View File

@@ -1,5 +1,6 @@
# Ensure shell scripts always have LF line endings
*.sh text eol=lf
hooks/session-start text eol=lf
# Ensure the polyglot wrapper keeps LF (it's parsed by both cmd and bash)
*.cmd text eol=lf

View File

@@ -1,5 +1,27 @@
# Superpowers Release Notes
## v4.3.1 (2026-02-21)
### Added
**Cursor support**
Superpowers now works with Cursor's plugin system. Includes a `.cursor-plugin/plugin.json` manifest and Cursor-specific installation instructions in the README. The SessionStart hook output now includes an `additional_context` field alongside the existing `hookSpecificOutput.additionalContext` for Cursor hook compatibility.
### Fixed
**Windows: Restored polyglot wrapper for reliable hook execution (#518, #504, #491, #487, #466, #440)**
Claude Code's `.sh` auto-detection on Windows was prepending `bash` to the hook command, breaking execution. The fix:
- Renamed `session-start.sh` to `session-start` (extensionless) so auto-detection doesn't interfere
- Restored `run-hook.cmd` polyglot wrapper with multi-location bash discovery (standard Git for Windows paths, then PATH fallback)
- Exits silently if no bash is found rather than erroring
- On Unix, the wrapper runs the script directly via `exec bash`
- Uses POSIX-safe `dirname "$0"` path resolution (works on dash/sh, not just bash)
This fixes SessionStart failures on Windows with spaces in paths, missing WSL, `set -euo pipefail` fragility on MSYS, and backslash mangling.
## v4.3.0 (2026-02-12)
This fix should dramatically improve superpowers skills compliance and should reduce the chances of Claude entering its native plan mode unintentionally.

View File

@@ -6,7 +6,7 @@
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh",
"command": "'${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd' session-start",
"async": false
}
]

View File

@@ -1,43 +1,46 @@
: << 'CMDBLOCK'
@echo off
REM ============================================================================
REM DEPRECATED: This polyglot wrapper is no longer used as of Claude Code 2.1.x
REM ============================================================================
REM Cross-platform polyglot wrapper for hook scripts.
REM On Windows: cmd.exe runs the batch portion, which finds and calls bash.
REM On Unix: the shell interprets this as a script (: is a no-op in bash).
REM
REM Claude Code 2.1.x changed the Windows execution model for hooks:
REM Hook scripts use extensionless filenames (e.g. "session-start" not
REM "session-start.sh") so Claude Code's Windows auto-detection -- which
REM prepends "bash" to any command containing .sh -- doesn't interfere.
REM
REM Before (2.0.x): Hooks ran with shell:true, using the system default shell.
REM This wrapper provided cross-platform compatibility by
REM being both a valid .cmd file (Windows) and bash script.
REM
REM After (2.1.x): Claude Code now auto-detects .sh files in hook commands
REM and prepends "bash " on Windows. This broke the wrapper
REM because the command:
REM "run-hook.cmd" session-start.sh
REM became:
REM bash "run-hook.cmd" session-start.sh
REM ...and bash cannot execute a .cmd file.
REM
REM The fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x
REM handles the bash invocation automatically on Windows.
REM
REM This file is kept for reference and potential backward compatibility.
REM ============================================================================
REM
REM Original purpose: Polyglot wrapper to run .sh scripts cross-platform
REM Usage: run-hook.cmd <script-name> [args...]
REM The script should be in the same directory as this wrapper
if "%~1"=="" (
echo run-hook.cmd: missing script name >&2
exit /b 1
)
"C:\Program Files\Git\bin\bash.exe" -l "%~dp0%~1" %2 %3 %4 %5 %6 %7 %8 %9
exit /b
set "HOOK_DIR=%~dp0"
REM Try Git for Windows bash in standard locations
if exist "C:\Program Files\Git\bin\bash.exe" (
"C:\Program Files\Git\bin\bash.exe" "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
exit /b %ERRORLEVEL%
)
if exist "C:\Program Files (x86)\Git\bin\bash.exe" (
"C:\Program Files (x86)\Git\bin\bash.exe" "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
exit /b %ERRORLEVEL%
)
REM Try bash on PATH (e.g. user-installed Git Bash, MSYS2, Cygwin)
where bash >nul 2>nul
if %ERRORLEVEL% equ 0 (
bash "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9
exit /b %ERRORLEVEL%
)
REM No bash found - exit silently rather than error
REM (plugin still works, just without SessionStart context injection)
exit /b 0
CMDBLOCK
# Unix shell runs from here
# Unix: run the named script directly
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SCRIPT_NAME="$1"
shift
"${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"
exec bash "${SCRIPT_DIR}/${SCRIPT_NAME}" "$@"