fix(hooks): add Windows .cmd wrapper so extensionless hook resolves and allows shells#2
fix(hooks): add Windows .cmd wrapper so extensionless hook resolves and allows shells#2JillRegan wants to merge 5 commits into
Conversation
| timestamp=$(date +"%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$(date +%s)") | ||
| local log_message="[${timestamp}] [validate-mounted-env-files] $*" | ||
|
|
There was a problem hiding this comment.
The below changes looks to just be formatting changes. No actual script changes were made besides the above fallback for skipping windows. The file was renamed though scripts/validate-mounted-env-files.sh -> scripts/validate-mounted-env-files
| esac | ||
|
|
||
| unset -f _esc 2>/dev/null || true | ||
|
|
There was a problem hiding this comment.
In the case where the shell used is Git Bash I have added this fallback. I read that Cursor's agent could use Git Bash but had trouble executing that on my Windows.
While I was able o set the default terminal to Git Bash, Cursor seemed to consistently use PowerShell. I tested this by running the following in a separate Git Bash terminal to confirm an allow was produced:
echo '{"command":"echo test","workspace_roots":["/c/path/to/some/project"]}' | ./scripts/validate-mounted-env-files
| # On Windows, if Bash runs this file (Git Bash, MSYS, Cygwin, etc.), return allow and skip validation | ||
| # Cursor on Windows normally runs the .cmd file instead; this is for when Bash runs it. | ||
| WIN_SKIP_MSG='1Password Environments are not currently supported on Windows. Environment validation was skipped.' | ||
| _esc() { printf '%s' "$1" | sed 's/\\/\\\\/g;s/"/\\"/g'; } |
There was a problem hiding this comment.
Can we reuse the existing escape_json_string() function?
| case "$(uname -s 2>/dev/null)" in | ||
| MINGW* | MSYS* | CYGWIN*) | ||
| cat >/dev/null 2>&1 || true | ||
| printf '%s\n' "$WIN_SKIP_JSON" | ||
| exit 0 | ||
| ;; | ||
| esac |
There was a problem hiding this comment.
We could actually extend this early-exit logic to any unsupported OS (e.g. FreeBSD) by reusing detect_os() and having a more generic user-facing message. What do you think?
Problem
When installed on Windows the hook pointed at the Bash file, Windows did not run it as a shell hook the way macOS/Linux do. The OS has no native 'run this shebanged Bash file” behaviour, so the command often failed to produce valid hook JSON on stdout (no output). It triggered file association so the
scripts/validate-mounted-env-files.shfile opened in an editor on every command run instead of executing as a hook.Fix
Update the hook command in
hooks.jsonto./scripts/validate-mounted-env-fileswith no file extension (so dropping the .sh). On macOS and Linux still run the Bash validator as before.On Windows the shell resolves that name using
PATHEXTand picksvalidate-mounted-env-files.cmd, a small cmd wrapper that calls PowerShell that reads the hook printsJSONwithpermission: allowand a short message that Environments validation was skipped.scripts/validate-mounted-env-files.cmd:small cmd wrapper that invokes PowerShell and returns allow and a clear skip message.hooks.jsonon./scripts/validate-mounted-env-files(no extension) so one command works on Mac/Linux and windowsRegression Tested on macOS
I followed these steps from cursor on installing the plugin locally to ensure no regressions. Once installed tested with
enviornments.toml, and mounted env. Confirmed both paths still produce expected allow / deny.Windows Testing
I tested this on my personal Windows laptop. Like above I installed the plugin locally and then ran commands via the agent. Confirmed each time an allow was produce in the execution logs, and no file opened in the editor.
How to Test
Follow these steps to install the plugin locally and then test with mounted env files.
~/.cursor/plugins/local/my-plugin.cursor-plugin/plugin.jsonis at the plugin root.