SessionStart hook 'gstack-session-update' triggers Windows 'Select an app' popup every session
- Dominant language
- TypeScript
- Stars
- 133k
- Forks
- 19.9k
- Avg merge
- 18h 46m
- Merged PRs (30d)
- 26
Description
### Summary
On Windows, the `SessionStart` hook command emitted by gstack setup points directly at the bare shebang script `gstack-session-update` (no extension). Claude Code's Windows hook runner cannot honor the `#!/usr/bin/env bash` shebang, so the OS falls back to ShellExecute and pops the "Select an app to open 'gstack-session-update'" dialog on every Claude Code session start.
Net effect for the user: a modal Windows file-association dialog appears every time a session starts, the script never runs, and auto-upgrade silently fails.
### Environment
- OS: Windows 11
- gstack: v1.48.0.0 (`~/.claude/skills/gstack/VERSION`)
- Install type: global-git at `~/.claude/skills/gstack`
- `auto_upgrade: true`, `update_check: true`
- Shell: Git Bash (`bash` resolves to `/usr/bin/bash` on PATH)
- Claude Code (with `superpowers` and `elements-of-style` plugins active)
### Reproduce
1. Install gstack on Windows
2. Enable auto-upgrade (`gstack-config set auto_upgrade true`) — or choose "Always keep me up to date" when prompted by any skill preamble
3. Setup writes the following block to `~/.claude/settings.json`:
```json
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "C:/Users/jeffr/.claude/skills/gstack/bin/gstack-session-update"
}
]
}
]
}
```
4. Start a new Claude Code session
### Expected
`gstack-session-update` runs silently, throttle-checks, and forks the auto-upgrade in the background. No UI.
### Actual
Windows pops:
> **Select an app to open 'gstack-session-update'**
> [Adobe Acrobat] [Audacity] [Cursor] [Firefox] [GIMP] [Microsoft Visual Studio Version Selector] [Notepad] ...
> [ Just once ]
Dismissing it lets the session continue, but the script never executed. Auto-upgrade is effectively disabled on Windows until the hook is fixed.
### Diagnosis
`gstack-session-update` is an extensionless bash script. Claude Code on Windows invokes hook commands via the OS shell, which doesn't process Unix shebangs. With no `.cmd` / `.bat` / `.ps1` / `.sh` extension and no registered handler for extensionless executables, Windows falls through to the file-association picker.
### Workaround (verified)
Edit `~/.claude/settings.json` to wrap the hook command in `bash`:
```json
"command": "bash C:/Users/jeffr/.claude/skills/gstack/bin/gstack-session-update"
```
This routes the script through Git Bash explicitly. Popup goes away, auto-upgrade resumes working. No change needed to the script itself.
### Suggested fixes (pick what fits)
- **A) Setup writes a platform-aware hook command.** On Windows, register the hook as `bash ` (or `"C:/Program Files/Git/bin/bash.exe" `). On macOS/Linux, register the bare script path as today. Single change in whatever code writes the SessionStart hook block in `~/.claude/settings.json`.
- **B) Ship a `.cmd` wrapper.** Create `gstack-session-update.cmd` alongside the bash script; it does `@bash "%~dp0gstack-session-update" %*`. Register the `.cmd` on Windows so Windows can launch it natively. Slightly more code but more robust if `bash` ever isn't on PATH.
- **C) Rename the script to `gstack-session-update.sh`.** Add an association hint, register `.sh` → bash. Cleanest if other tooling already handles `.sh` on Windows; risks breaking the existing convention of extensionless `bin/` scripts.
(A) feels lowest-risk and ships fastest. Happy to PR if you'd like — say the word and I'll target whichever branch you prefer.
### Severity
Low for the broader install base, but a hard block on Windows users who turn on `auto_upgrade`. Manual `/gstack-upgrade` still works fine.
Contributor guide
Assessment
This issue has not been assessed yet.