Replace Promise.race with new Promise wrapper so timeoutId is assigned
as const before fetch starts. Timer is now cleared on both fetch success
and fetch rejection, not just success.
Replace bare fetch() calls with fetchWithTimeout() using Promise.race
instead of AbortSignal.timeout() which causes libuv assertion crashes
in Bun on Windows.
Applies the already-defined HEALTH_CHECK_TIMEOUT_MS (30s/45s) to
isWorkerHealthy() and getWorkerVersion(), and HOOK_TIMEOUTS.DEFAULT
to the summarize POST. Previously these fetches had no timeout at all,
causing the Stop hook to hang for the full hook timeout (120s) when
the worker was unreachable.
Fixes#963
The /api/context/inject endpoint previously blocked for up to 5 minutes
(300s timeout) waiting for initializationComplete, which includes MCP
connection setup. On Windows, the MCP connection can hang indefinitely,
causing the context hook to never return and blocking Claude Code startup.
This change makes the endpoint fail open: if the worker hasn't finished
initializing, return empty context immediately instead of blocking. The
hook completes fast, and context becomes available on subsequent prompts
once initialization finishes in the background.
Closes#958
Three issues fixed:
1. session-init handler: Worker 500 errors caused `throw`, which
hook-command.ts caught and exited with code 2 (blocking error).
This blocked the user's prompt entirely with:
"Hook error: Error: Session initialization failed: 500"
Fix: Log the failure and return SUCCESS so the prompt proceeds.
2. user-message handler: Referenced nonexistent constant
HOOK_EXIT_CODES.USER_MESSAGE_ONLY (undefined). Also used
console.error() for informational output, which Claude Code
may flag as an error. Fix: Use process.stderr.write() and
return HOOK_EXIT_CODES.SUCCESS explicitly.
3. Both handlers threw on HTTP errors from the worker, causing
exit code 2 (blocking). Memory plugin failures should never
prevent users from using Claude Code. All worker HTTP failures
now log and return gracefully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The user-message handler references HOOK_EXIT_CODES.USER_MESSAGE_ONLY
but the constant was missing from hook-constants.ts, causing it to
return exitCode: undefined. The handler is still registered for Cursor's
afterFileEdit flow.
The user-message hook exits with code 3 (USER_MESSAGE_ONLY), which Claude
Code interprets as a hook failure, displaying "SessionStart:startup hook
error" on every session start. The context hook already handles injecting
context into the conversation, making the user-message hook redundant.
Removing it eliminates the spurious error message and saves ~60 seconds
of potential timeout on systems where the worker is slow to respond.
Closes#905
PR #896 identified a valid XSS concern in TerminalPreview.tsx but was
broken (missing DOMPurify import and dependency). The existing
escapeXML:true on AnsiToHtml already mitigates the vector, but
DOMPurify adds defense-in-depth sanitization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents cross-origin attacks from malicious websites by restricting
CORS to only allow:
- Requests without Origin header (hooks, curl, CLI tools)
- Requests from localhost / 127.0.0.1 origins
Previously, CORS was completely open (cors() without configuration),
allowing any website to access the local API and read session data.
PR #875 used negative logic naming (DISABLE instead of ENABLED), superseded
by PR #913 which uses the established CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED setting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On fresh installations, smart-install.js installs Bun to ~/.bun/bin/bun
but Bun isn't in PATH until terminal restart. Subsequent hooks fail
because they try to run `bun ...` directly.
This fix introduces bun-runner.js - a Node.js script that finds Bun
in common install locations (not just PATH) and runs commands with it.
All hooks now use `node bun-runner.js ...` instead of `bun ...`.
The bun-runner checks:
- PATH (via which/where)
- ~/.bun/bin/bun (default install location)
- /usr/local/bin/bun
- /opt/homebrew/bin/bun (macOS Homebrew)
- /home/linuxbrew/.linuxbrew/bin/bun (Linuxbrew)
- Windows: %LOCALAPPDATA%\bun or fallback paths
Fixes#818
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Health check endpoint fix verified working:
- /api/health responds in ~12ms (well under 15s timeout)
- No timeout errors in worker logs
- Both worker-utils.ts and HealthMonitor.ts use /api/health
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reviewed health check endpoint logic in worker-utils.ts and HealthMonitor.ts.
Both correctly use /api/health (liveness) instead of /api/readiness to avoid
15-second hook timeout during MCP initialization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes the "Worker did not become ready within 15 seconds" timeout issue.
Root cause: isWorkerHealthy() and waitForHealth() were checking /api/readiness
which returns 503 until full initialization completes (including MCP connection
which can take 5+ minutes). Hooks only have 15 seconds timeout.
Solution: Use /api/health (liveness check) which returns 200 as soon as the
HTTP server is listening. This is sufficient for hook communication since
the worker can accept requests while background initialization continues.
Changes:
- src/shared/worker-utils.ts: Change /api/readiness to /api/health in isWorkerHealthy()
- src/services/infrastructure/HealthMonitor.ts: Change /api/readiness to /api/health in waitForHealth()
- tests/infrastructure/health-monitor.test.ts: Update test to expect /api/health
Fixes#811, #772, #729
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Includes PR #745 isolated credentials fix - prevents API key hijacking
from random project .env files by using centralized credentials from
~/.claude-mem/.env
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>