fix(extension): Windows hook dedupe, POSIX node preflight, stale-path prevention#150
Merged
Merged
Conversation
… prevention
Companion to the core launch-readiness PR. Four fixes for fresh installs:
- Hook dedupe matches axme-hook.cmd: the install/uninstall filter only
looked for "axme-code" in the command string, but the Windows command
is `"%USERPROFILE%\.cursor\axme-hook.cmd" hook <name> --ide cursor` —
no match. Every Cursor restart APPENDED three fresh entries (N
restarts -> N× hook fan-out per tool call) and uninstall/Reset could
never remove them; after uninstall they pointed at a deleted wrapper
and failed forever. Shared isAxmeHookEntry() now matches both shapes.
With the filter fixed, the existing rewrite-on-every-activation also
self-heals stale version-dir paths after extension updates.
- ~/.cursor/hooks.json refuse-don't-clobber: a malformed user file was
silently overwritten ("will overwrite"), destroying the user's own
hooks. Now throws an actionable error that runStep() surfaces as a
visible warning with recovery steps.
- POSIX system-Node preflight: the bundled CLI is a #!/usr/bin/env node
shim and Cursor spawns the MCP server outside the extension host —
macOS/Linux users without Node 20+ got "MCP server does not exist" in
chat with zero explanation. New activation step (soft-fail) surfaces
an actionable error with an Open-nodejs.org button; Windows reports
"bundled". New "node" StepKind in the activation report.
- Setup spawn sets AXME_SETUP_FROM_EXTENSION=1: the CLI's cursor-writers
(core PR) skip project-level .cursor/{mcp,hooks}.json when set — those
files duplicated the extension's API-registered MCP server under the
same name with a PATH-dependent command, double-fired hooks, and
embedded version-numbered extension paths that went stale on every
update (observed live: hooks pointing at 0.1.0 dir with 0.1.4
installed).
- Error texts referenced extension/bin/node-windows-x64.exe; the real
bundled path is extension/bin/node-runtime/node.exe. Fixed in
spawn-binary, mcp-register, hooks-install (incl. doc comment).
tsc clean; extension builds.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Companion to #149 (core CLI launch-readiness). Fixes the extension-channel blockers from the pre-launch audit — all reproduced against the shipped 0.1.5 .vsix or live machine state.
Fixes
1. Windows: hooks duplicated on every restart and were unremovable (CRITICAL, shipped in 0.1.5)
The install/uninstall dedupe filter matched
\"axme-code\"in the command string — but the Windows command is\"%USERPROFILE%\\.cursor\\axme-hook.cmd\" hook <name> --ide cursor, which never contains it. Every Cursor restart appended 3 fresh entries (N restarts → N× hook fan-out on every tool call);uninstall/AXME: Resetused the same filter, so stale entries could never be removed — and after uninstall they pointed at a deleted wrapper, failing forever. SharedisAxmeHookEntry()now matches both command shapes.Bonus: since
installUserHooksalready rewrites axme entries on every activation, the fixed filter also makes version-dir paths self-heal after extension updates (observed live:~/.cursor/hooks.jsonpointing at the0.1.0extension dir with 0.1.4 installed).2. POSIX: Node-less users got an undebuggable dead extension (CRITICAL)
The bundled CLI is a
#!/usr/bin/env nodeshim; Cursor spawns the MCP server outside the extension host. macOS/Linux users without Node 20+ (common for non-JS stacks — exactly our audience) sawMCP server does not existin chat and silently failing hooks, with zero explanation. New activation stepnode(POSIX only, soft-fail — a false negative must not brick a working install): actionable error with an Open nodejs.org button, recorded in the activation report and reflected in the status bar. Windows reportsbundled.3. Extension-spawned setup wrote duplicate/stale project config (CRITICAL)
setup --ide cursorspawned by the extension wrote project-level.cursor/mcp.json(same-nameaxmeserver with PATH-dependent command — extension-only users have noaxme-codeon PATH) and.cursor/hooks.json(absolute paths into the version-numbered extension dir, never rewritten → stale after every update, plus double-firing on top of user-level hooks). The spawn now setsAXME_SETUP_FROM_EXTENSION=1; the CLI side (#149) skips both writers when present. Standalone-CLI cursor users are unaffected.4.
~/.cursor/hooks.jsonrefuse-don't-clobberA malformed user file was silently overwritten ("will overwrite"), destroying the user's own hooks — same bug class as the config clobbering fixed in #149. Now throws an actionable error that the activation report surfaces as a visible warning with recovery steps.
5. Misleading bundled-Node error texts
Three error messages (and a doc comment) referenced
extension/bin/node-windows-x64.exe; the real path isextension/bin/node-runtime/node.exe. Users checking the "missing" file found it present and got stuck.Order of merge
Either order works, but full effect of fix 3 requires both this PR and #149 (env producer here, consumer there). Ship both in v0.6.1 / extension-v0.1.6.
Verification
tsc --noEmitclean (extension)out/extension.js)🤖 Generated with Claude Code