Skip to content

fix(extension): Windows hook dedupe, POSIX node preflight, stale-path prevention#150

Merged
George-iam merged 1 commit into
mainfrom
fix/extension-launch-readiness-20260611
Jun 11, 2026
Merged

fix(extension): Windows hook dedupe, POSIX node preflight, stale-path prevention#150
George-iam merged 1 commit into
mainfrom
fix/extension-launch-readiness-20260611

Conversation

@George-iam

Copy link
Copy Markdown
Contributor

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: Reset used the same filter, so stale entries could never be removed — and after uninstall they pointed at a deleted wrapper, failing forever. Shared isAxmeHookEntry() now matches both command shapes.

Bonus: since installUserHooks already rewrites axme entries on every activation, the fixed filter also makes version-dir paths self-heal after extension updates (observed live: ~/.cursor/hooks.json pointing at the 0.1.0 extension 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 node shim; Cursor spawns the MCP server outside the extension host. macOS/Linux users without Node 20+ (common for non-JS stacks — exactly our audience) saw MCP server does not exist in chat and silently failing hooks, with zero explanation. New activation step node (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 reports bundled.

3. Extension-spawned setup wrote duplicate/stale project config (CRITICAL)

setup --ide cursor spawned by the extension wrote project-level .cursor/mcp.json (same-name axme server with PATH-dependent command — extension-only users have no axme-code on 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 sets AXME_SETUP_FROM_EXTENSION=1; the CLI side (#149) skips both writers when present. Standalone-CLI cursor users are unaffected.

4. ~/.cursor/hooks.json refuse-don't-clobber

A 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 is extension/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 --noEmit clean (extension)
  • Extension builds (out/extension.js)
  • No behavior change for healthy installs: dedupe still preserves user entries verbatim; node preflight is a no-op pass on machines with Node 20+; env var only affects extension-spawned setup
  • CI matrix builds 5 platform .vsix (runs on this PR)

🤖 Generated with Claude Code

… 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>
@George-iam George-iam merged commit 504dc75 into main Jun 11, 2026
12 checks passed
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.

1 participant