Removes bun-wrapper indirection. Hooks are compiled JavaScript that work perfectly with Node. Worker still uses Bun where performance matters. Fixes#264
Enhancement to process leak fix from v7.1.9 - automatically detects and
kills orphaned chroma-mcp processes when the worker starts.
Changes:
- Added cleanupOrphanedProcesses() method to WorkerService
- Scans for existing chroma-mcp processes on startup
- Kills all found processes before creating new ones
- Logs cleanup activity (process count and PIDs)
- Non-fatal error handling (continues on cleanup failure)
Benefits:
- Automatically recovers from pre-7.1.9 process leaks
- Ensures clean slate on every worker restart
- No manual intervention needed to cleanup orphans
- Prevents accumulation even if v7.1.9 close() fails
Verified working in logs:
[INFO] [SYSTEM] Cleaning up orphaned chroma-mcp processes {count=2, pids=33753,33750}
[INFO] [SYSTEM] Orphaned processes cleaned up {count=2}
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Critical bugfix: ChromaSync now properly cleans up chroma-mcp subprocesses
when the worker is restarted, preventing memory exhaustion from orphaned
processes accumulating over time.
Changes:
- Store reference to StdioClientTransport subprocess
- Explicitly close transport in close() method to kill subprocess
- Add error handling to ensure cleanup even on failures
- Reset all state in finally block
Problem:
Each worker restart spawned a new chroma-mcp process but never killed the
old one. After multiple restarts, orphaned processes accumulated (16+ seen
in production), consuming 900MB+ RAM and eventually causing OOM kills that
silently failed backfills.
Impact:
- Eliminates process accumulation
- Prevents memory exhaustion from leaked subprocesses
- Fixes silent backfill failures caused by OOM kills
- Ensures graceful cleanup on worker shutdown
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Removed the process.type = 'renderer' workaround that was causing libuv
assertion failures on Windows. This hack was attempting to hide console
windows but resulted in crashes when process.title was accessed.
Prioritizing stability over cosmetics - console windows may briefly appear
on Windows until the MCP SDK provides proper window hiding support.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Updated multiple hooks (context-hook, new-hook, save-hook, summary-hook, user-message-hook) to throw errors using `getWorkerRestartInstructions` for improved user guidance on worker connection issues.
- Enhanced `handleWorkerError` function to utilize the new error message generator for consistent error reporting.
- Modified `ensureWorkerRunning` function to provide detailed instructions based on the worker's state, including port information.
- Introduced `getWorkerRestartInstructions` utility in `error-messages.ts` to generate platform-aware error messages for worker failures.
On Windows systems, `localhost` resolves to IPv6 (::1) while the worker
binds to IPv4 (127.0.0.1), causing MCP tool connections to fail.
This change uses the existing getWorkerHost() function which correctly
returns the configured host address (defaulting to 127.0.0.1).
Fixes connection failures on Windows where localhost prefers IPv6.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix: add npm fallback when bun install fails with alias packages
Bun has issues resolving npm alias packages (e.g., string-width-cjs,
strip-ansi-cjs, wrap-ansi-cjs) that are defined in package-lock.json.
When bun fails with 404 errors for these packages, we now fall back
to npm which handles aliases correctly.
This fixes the installation failure that many users are experiencing
where bun install fails with:
error: GET https://registry.npmjs.org/string-width-cjs/-/string-width-cjs-4.2.3.tgz - 404
The fallback is transparent to users - they will see a warning message
and the installation will continue with npm.
Fixes#262
Related: #261, #253🤖 Generated with Claude Code (https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: preserve original code style (single quotes)
---------
Co-authored-by: Jonas Hanisch <jhanisch@matero.de>
Co-authored-by: Claude <noreply@anthropic.com>
Updated built plugin files with latest changes including localhost
binding security improvements and enhanced runtime detection.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Critical improvement for seamless upgrades across all versions.
Changes:
1. Added /api/version endpoint to worker service
- Returns current worker version from package.json
2. Added version checking in worker-utils.ts
- getPluginVersion() - reads plugin's package.json version
- getWorkerVersion() - fetches version from worker API
- ensureWorkerVersionMatches() - compares and restarts if needed
3. Modified ensureWorkerRunning()
- Now calls ensureWorkerVersionMatches() after health check
- Automatically restarts worker when version mismatch detected
- Logs version mismatch for debugging
Impact:
- Users no longer need to manually restart worker after upgrades
- Eliminates connection errors from running old worker code
- Critical for v7.1.1 (Bun auto-install) and all future releases
- Fixes the issue where PR #236 changes weren't applied until manual restart
Testing:
- Version endpoint working: returns {"version":"7.1.0"}
- Worker health check: passing
- Auto-restart logic: triggers on version mismatch
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
CRITICAL FIX: v7.1.0 Bun auto-install broken on Windows 11
Problem:
- hooks.json calls `bun smart-install.js` but if Bun isn't installed,
command fails immediately with "bun is not recognized"
- smart-install.js never runs, so Bun never gets installed
- Chicken-and-egg problem
Root Cause:
- v7.1.0 removed Bun/uv auto-installation logic from smart-install.js
- Assumed Bun would already be available
- Breaks fresh installations on all platforms
Solution:
1. Changed SessionStart hook to use `node` for smart-install.js
(Node.js always available in Claude Code)
2. Restored Bun auto-installation logic:
- isBunInstalled() - check if Bun is in PATH
- installBun() - auto-install via PowerShell (Windows) or curl (Unix/macOS)
- Also restored uv auto-installation for Chroma
After Fix:
- smart-install.js runs with node (always available)
- Detects if Bun is missing and auto-installs it
- Subsequent hooks use bun successfully
- Works on fresh Windows installations
Fixes: User report from Discord - Windows 11 'bun' is not recognized
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Previously skipped Windows PM2 cleanup based on assumption that PM2
wasn't used on Windows. However, this left potential orphaned processes.
Changes:
- Remove platform check (process.platform !== 'win32')
- Run PM2 cleanup on Mac/Linux/Windows consistently
- Create .pm2-migrated marker on all platforms
- Update documentation to reflect cross-platform behavior
Rationale:
- Quality migration should clean up ALL orphaned processes
- Error handling (try/catch) already makes this safe
- Even if PM2 had Windows issues, cleanup won't hurt
- Consistent behavior across platforms is better UX
Impact:
- Windows users will get PM2 cleanup on first hook trigger
- Marker file now created on Windows (prevents repeated attempts)
- No breaking changes (errors caught and ignored)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Implemented a method to check if Bun is available in the system PATH.
- Updated the startWithBun method to return an error if Bun is not found.
- Enhanced PID file parsing to validate required fields and their types.
- Cleaned up stale PID files if the process is no longer alive.
fix(SettingsRoutes): clear port cache after updating settings
- Added a call to clearPortCache after writing updated settings to ensure the application uses the latest configuration.
- Updated shebangs in user-message-hook.js, worker-cli.js, and worker-service.cjs to use Bun instead of Node.
- Modified build-hooks.js to generate Bun-compatible shebangs in built scripts.
- Enhanced sync-marketplace.cjs to trigger a worker restart after syncing files via an HTTP request.
- Improved worker-cli.ts to exit with appropriate status codes after executing commands.
- Added build-worker-binary.js to create a Windows executable for the worker service using Bun's compile feature.
- Replaced hardcoded migration port with dynamic port retrieval using `getWorkerPort()` in worker-cli.ts.
- Updated context generator to clarify error handling comments.
- Introduced timeout constants in ProcessManager for better maintainability.
- Configured SQLite settings using constants for mmap size and cache size in DatabaseManager.
- Added timeout constants for Git and NPM commands in BranchManager.
- Enhanced error logging in FormattingService and SearchManager to provide more context on failures.
- Removed deprecated silentDebug function and replaced its usage with logger.debug.
- Updated tests to use dynamic worker port retrieval instead of hardcoded values.
- Introduced `/api/admin/restart` and `/api/admin/shutdown` endpoints in WorkerService for restarting and shutting down the service.
- Updated error message in hook-error-handler to provide clearer instructions for restarting the worker.
- Refactored worker-utils to remove PM2 dependency and implement ProcessManager for starting the worker service.
- Cleaned up legacy PM2 references and provided new manual start instructions.
- Updated build-hooks.js to remove better-sqlite3 dependency and use bun:sqlite.
- Modified smart-install.js to eliminate checks and installations related to better-sqlite3.
- Refactored Database.ts, SessionSearch.ts, SessionStore.ts, and migrations.ts to import and utilize bun:sqlite.
- Replaced exec and pragma calls with appropriate run methods for bun:sqlite compatibility.
- Removed unnecessary native module verification and installation logic for better-sqlite3.
Critical bug fix:
- Pass project filter to getSessionSummariesByIds() and getUserPromptsByIds() in SearchManager
- Previously only observations were filtered by project, sessions and prompts leaked from other projects
Documentation improvements:
- Update "FTS5 search" to "hybrid search" (accurate terminology)
- Add privacy warning about sensitive data in exports
- Document --project parameter for filtered exports
- Add "Export by Project" examples to advanced usage
Verified with test export using --project=claude-mem filter.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Addressed all 6 bugs identified in code reviews:
CRITICAL FIXES:
1. SessionStore.ts: Fixed concepts filter bug - removed empty params.push()
that was breaking SQL parameter alignment (line 849)
2. import-memories.ts: Removed worker_port and prompt_counter fields from
sdk_sessions insert to fix schema mismatch with fresh databases
3. export-memories.ts: Fixed hardcoded port - now reads from settings via
SettingsDefaultsManager.loadFromFile()
HIGH PRIORITY:
4. export-memories.ts: Added database existence check with clear error
message before opening database connection
5. export-memories.ts: Fixed variable shadowing - renamed local 'query'
variable to 'sessionQuery' (line 90)
MEDIUM PRIORITY:
6. export-memories.ts: Improved type safety - added ObservationRecord,
SdkSessionRecord, SessionSummaryRecord, UserPromptRecord interfaces
All fixes tested and verified:
- Export script successfully exports with project filtering
- Import script works on existing database with duplicate prevention
- Port configuration read from settings.json
- Type safety improvements prevent compile-time errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Fix critical session persistence bug in new-hook
Restores the second POST call to /sessions/:sessionDbId/init that was
incorrectly removed as "duplicate" in the hooks refactor.
The two POST calls serve different purposes:
- POST /api/sessions/init: Creates DB session, saves prompt (no SDK agent)
- POST /sessions/:sessionDbId/init: Starts the SDK agent session
Without the second call, the SDK agent never started, causing:
- First prompts saved to DB but never processed
- Subsequent prompts queued but no agent running to consume them
- Each new prompt creating orphaned sessions instead of continuing
This fix restores proper session continuation across multiple prompts.
Fixes conversation fragmentation reported in production.
* updated agent-sdk
* Skip meta-observations for session-memory file operations
Added a check to skip meta-observations when file operations (Edit, Write, Read, NotebookEdit) are performed on session-memory files. If the file path includes 'session-memory', a debug log is generated and the response indicates that the observation was skipped.
* refactor: Clean up hook-response and new-hook files
- Removed 'PreCompact' hook type and associated logic from hook-response.ts for improved type safety.
- Deleted extensive architecture comments in new-hook.ts to streamline code readability.
- Simplified debug logging in new-hook.ts to reduce verbosity.
- Enhanced ensureWorkerRunning function in worker-utils.ts with a final health check before throwing errors.
- Added a new documentation file outlining the hooks cleanup process and future improvements.
* Refactor cleanup and user message hooks
- Updated cleanup-hook.js to improve error handling and remove unnecessary input checks.
- Simplified user-message-hook.js by removing time-sensitive announcements and streamlining output.
- Enhanced logging functionality in both hooks for better debugging and clarity.
* Refactor error handling in hooks to use centralized error handler
- Introduced `handleWorkerError` function in `src/shared/hook-error-handler.ts` to manage worker-related errors.
- Updated `context-hook.ts`, `new-hook.ts`, `save-hook.ts`, and `summary-hook.ts` to utilize the new error handler, simplifying error management and improving code readability.
- Removed repetitive error handling logic from individual hooks, ensuring consistent user-friendly messages for connection issues.
* Refactor user-message and summary hooks to utilize shared transcript parser; introduce hook exit codes
- Moved user message extraction logic to a new shared module `transcript-parser.ts` for better code reuse.
- Updated `summary-hook.ts` to use the new `extractLastMessage` function for retrieving user and assistant messages.
- Replaced direct exit code usage in `user-message-hook.ts` with constants from `hook-constants.ts` for improved readability and maintainability.
- Added `HOOK_EXIT_CODES` to `hook-constants.ts` to standardize exit codes across hooks.
* Refactor hook input interfaces to enforce required fields
- Updated `SessionStartInput`, `UserPromptSubmitInput`, `PostToolUseInput`, and `StopInput` interfaces to require `session_id`, `transcript_path`, and `cwd` fields, ensuring better type safety and clarity in hook inputs.
- Removed optional index signatures from these interfaces to prevent unintended properties and improve code maintainability.
- Adjusted related hook implementations to align with the new interface definitions.
* Refactor save-hook to remove tool skipping logic; enhance summary-hook to handle spinner stopping with error logging; update SessionRoutes to load skip tools from settings; add CLAUDE_MEM_SKIP_TOOLS to SettingsDefaultsManager for configurable tool exclusion.
* Document CLAUDE_MEM_SKIP_TOOLS setting in public docs
Added documentation for the new CLAUDE_MEM_SKIP_TOOLS configuration
setting in response to PR review feedback. Users can now discover and
customize which tools are excluded from observations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
- Enhanced logging functionality in user-message-hook.js to include better formatting and error handling.
- Updated worker-utils.ts to escape single quotes in PowerShell commands and added checks for global PM2 installation.
- Improved readability and maintainability of the code by restructuring and clarifying variable names.
**Problem:**
Worker service crashed on startup with:
TypeError: Cannot read properties of undefined (reading 'get')
at new Wd (.../worker-service.cjs:52:131469)
**Root Cause:**
Circular dependency between SettingsDefaultsManager and logger:
1. SettingsDefaultsManager imports logger
2. logger imports SettingsDefaultsManager
3. logger constructor calls SettingsDefaultsManager.get() at init time
4. When CommonJS resolves the cycle, SettingsDefaultsManager is undefined
**Solution:**
Break the circular dependency by making logger lazy-load its configuration:
- Change logger.level from initialized in constructor to lazy-loaded
- Add getLevel() method that loads on first access
- Update all level checks to use getLevel()
This allows SettingsDefaultsManager to import logger without triggering
the circular dependency, since logger no longer accesses SettingsDefaultsManager
during module initialization.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Moved SettingsDefaultsManager from worker/settings to shared directory.
- Updated all import paths across the codebase to reflect the new location.
- Removed early-settings.ts as its functionality is now handled by SettingsDefaultsManager.
- Adjusted logger and paths to utilize SettingsDefaultsManager for configuration values.
- Replaced instances of silentDebug with happy_path_error__with_fallback across multiple files to improve error logging and handling.
- Updated the utility function to provide clearer semantics for error handling when expected values are missing.
- Introduced a script to find potential silent failures in the codebase that may need to be addressed with the new error handling approach.
- Introduced a new module `hook-constants.ts` to define timeout constants for various hooks.
- Updated `cleanup-hook.ts`, `context-hook.ts`, `save-hook.ts`, and `summary-hook.ts` to utilize the new `HOOK_TIMEOUTS.DEFAULT` for fetch timeouts instead of hardcoded values.
- Adjusted worker utility timeouts in `worker-utils.ts` to use constants from `hook-constants.ts`, improving maintainability and consistency across the codebase.
- Added silent debugging for settings file loading failures in early-settings.ts.
- Improved error logging in worker-utils.ts for health check and worker startup failures, including detailed error information and context.
- Removed direct database operations in new-hook.ts and replaced them with an HTTP call to initialize sessions.
- Added error handling for HTTP requests and improved logging for session initialization.
- Updated SessionRoutes to handle new session initialization and privacy checks.
- Enhanced privacy tag stripping logic to prevent saving fully private prompts.
- Improved overall error handling and debugging messages throughout the session management process.
- Updated paths in troubleshooting documentation to reflect new settings file location.
- Modified diagnostics and reference files to read from ~/.claude-mem/settings.json.
- Introduced getWorkerPort utility for cleaner worker port retrieval.
- Enhanced ChromaSync and SDKAgent to load Python version and Claude path from settings.
- Updated SettingsRoutes to validate new settings: CLAUDE_MEM_LOG_LEVEL and CLAUDE_MEM_PYTHON_VERSION.
- Added early-settings module to load settings for logger and other early-stage modules.
- Adjusted logger to use early-loaded log level setting.
- Refactored paths to utilize early-loaded data directory setting.
The bundled hook scripts use `external: ['better-sqlite3']` during esbuild,
meaning the dependency must be resolved at runtime. When hooks run from the
cache directory (~/.claude/plugins/cache/thedotmack/claude-mem/X.X.X/),
they couldn't find better-sqlite3 because:
1. Cache directory had no package.json
2. smart-install.js was hardcoded to install in marketplace directory only
This fix:
- Adds plugin/package.json declaring runtime dependencies (better-sqlite3)
- Updates build-hooks.js to auto-generate plugin/package.json from main package.json
- Updates smart-install.js to detect execution context (cache vs marketplace)
and install dependencies in the correct location
The script now detects if it's running from cache (via path pattern matching)
and installs dependencies there, where the hooks actually execute.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This PR addresses issue #193 affecting Windows installations of claude-mem.
## Bug 1: Missing ecosystem.config.cjs in packaged plugin
**Problem**: The ecosystem.config.cjs file was not included in the plugin
package, causing PM2 to fail when trying to start the worker from cache.
**Fix**: Added `plugin/ecosystem.config.cjs` with correct path for packaged
structure (`./scripts/worker-service.cjs` instead of `./plugin/scripts/`).
## Bug 2: Incorrect MCP Server Path (src/services/worker-service.ts)
**Problem**: Path `__dirname, '..', '..', 'plugin', 'scripts', 'mcp-server.cjs'`
only worked in dev structure, failed in packaged plugin.
**Error produced**:
```
Error: Cannot find module 'C:\Users\...\claude-mem\plugin\scripts\mcp-server.cjs'
[ERROR] [SYSTEM] Background initialization failed MCP error -32000: Connection closed
```
**Fix**: Changed to `path.join(__dirname, 'mcp-server.cjs')` since mcp-server.cjs
is in the same directory as worker-service.cjs after bundling.
## Bug 3: Missing smart-install.js in plugin package
**Problem**: smart-install.js was referenced in hooks.json but not included
in the plugin/ directory for cache deployment.
**Fix**: Added `plugin/scripts/smart-install.js` that uses `createRequire()`
to resolve modules from MARKETPLACE_ROOT.
## Bug 4: hooks.json incorrect path
**Problem**: Referenced `/../scripts/smart-install.js` but CLAUDE_PLUGIN_ROOT
points to the plugin/ directory.
**Fix**: Changed to `/scripts/smart-install.js`.
## Bug 5: Windows Worker Startup - Visible Console Windows
**Problem**: PM2 ignores windowsHide option on Windows, opening visible
console windows when starting the worker service.
**Fix**: Use PowerShell `Start-Process -WindowStyle Hidden` on Windows while
keeping PM2 for Unix systems (src/shared/worker-utils.ts).
## Additional Improvements
- Increased worker startup timeouts for Windows (500ms health check, 1000ms
wait between retries, 15 retries = 15s total vs previous 5s)
- Added `windowsHide: true` to root ecosystem.config.cjs for PM2
## Note on Assertion Failure
The Windows libuv assertion failure `!(handle->flags & UV_HANDLE_CLOSING)`
at `src\win\async.c:76` is a known upstream issue in Claude Code (Issue #7579),
triggered by fetch() calls on Windows. This is NOT caused by worker spawning
and cannot be fixed in claude-mem.
Tested on Windows 11 with Node.js v24.
Fixes#193🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated all documentation references from search-server to mcp-server
- Removed legacy search-server.cjs file
- Updated debug log messages to use [mcp-server] prefix
- Updated build output references in docs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Introduced PrivacyCheckValidator class to encapsulate logic for checking if user prompts are private.
- Updated SessionRoutes to utilize PrivacyCheckValidator for determining prompt privacy during observation and summarization operations.
- Removed duplicate privacy check logic from SessionRoutes, improving code maintainability and readability.
- Added SessionEventBroadcaster to handle broadcasting of session lifecycle events, consolidating SSE broadcasting and processing status updates.
- Refactored SessionRoutes to utilize SessionEventBroadcaster for broadcasting events related to new prompts, session starts, and completions.
- Created SessionCompletionHandler to centralize session completion logic, reducing duplication across multiple endpoints.
- Updated WorkerService to initialize SessionEventBroadcaster and pass it to SessionRoutes.