Comprehensive Windows bug fixes release. Thanks to @kat-bell for the
excellent contributions fixing Windows plugin installation and worker
startup issues.
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>
Fix: Ensure worker is running at the beginning of all hook files
- Move ensureWorkerRunning to the start of all hook functions
- Replace waitForPort with ensureWorkerRunning in context-hook
- Ensures worker is started before any other hook logic executes
- Improves error messages when worker fails to start
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Introduced comprehensive documentation for integrating claude-mem into VSCode extensions, IDE plugins, and CLI tools.
- Detailed worker service basics, including environment variables and build commands.
- Provided an overview of worker architecture and request flow.
- Documented API reference for session lifecycle, data retrieval, search operations, and settings configuration.
- Included integration patterns, error handling strategies, and development workflow guidelines.
- Added critical implementation notes and additional resources for developers.
Rewrote architecture/hooks.mdx with complete technical reference including:
- 5-stage lifecycle overview with ASCII architecture diagram
- Detailed input/output specs for each hook
- Processing steps with TypeScript code examples
- Data flow diagram showing complete request lifecycle
- Session ID threading explanation
- Privacy tag stripping pipeline
- SDK agent processing details
- Implementation checklist for other platforms
- Common pitfalls and solutions table
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resolved conflicts:
- SearchManager.ts: Keep refactored class version (main had old search-server.ts startup code)
- worker-service.cjs, search-server.cjs: Keep our built versions
- package-lock.json: Take main's version
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Delete empty SearchRoutes.ts.new leftover file
- Standardize on 127.0.0.1 in context-hook.ts (avoids DNS lookup)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 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.
- Introduced SettingsDefaultsManager to centralize default settings and loading logic.
- Updated context-generator, SDKAgent, SettingsRoutes, and worker-utils to utilize the new manager for loading settings.
- Removed redundant code for reading settings from files and environment variables.
- Ensured fallback to default values when settings file is missing or invalid.
- Introduced BaseRouteHandler class to centralize error handling and response management.
- Updated SettingsRoutes to use wrapHandler for automatic error logging and response.
- Refactored ViewerRoutes to extend BaseRouteHandler and utilize wrapHandler for health check and UI serving.
- Enhanced error handling in SettingsRoutes and ViewerRoutes for better maintainability and readability.
Created database.ts with proper database result types and replaced 38+ 'as any' casts throughout the codebase with proper type annotations.
Changes:
- Created src/types/database.ts with TableColumnInfo, IndexInfo, and database record types
- Fixed all type casts in SessionStore.ts (migrations, query results)
- Fixed type casts in SessionSearch.ts, SettingsManager.ts, SettingsRoutes.ts
- Improved MCP server JSON schema typing
All builds pass and worker service runs successfully.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove cleanupOrphanedProcesses() method that was solving an old problem and is no longer needed. This method was platform-specific (crashes on Windows) and adds unnecessary complexity.
Changes:
- Delete cleanupOrphanedProcesses() method (28 lines)
- Remove call from initializeBackground()
- Worker starts cleanly without attempting process cleanup
Benefits:
- Simpler startup sequence
- Cross-platform compatibility (no pgrep/pkill)
- Reduced code complexity (YAGNI principle)
- No functional impact (orphaned processes indicate separate issues)
Phase 4 of Worker Service Quality Improvements Plan
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extracted SQL query from handleSessionInit route handler into SessionStore.getLatestUserPrompt()
method to fix abstraction leak and improve type safety.
Changes:
- Added getLatestUserPrompt() method to SessionStore with proper return type
- Replaced raw SQL query in SessionRoutes with type-safe method call
- Removed direct database access through dbManager.getSessionStore().db
- Improved separation of concerns (data layer vs HTTP layer)
Benefits:
- Type safety: Explicit return type instead of 'as any' cast
- Maintainability: SQL query logic belongs in data layer
- Testability: Can test query logic independently from HTTP layer
- Consistency: Follows existing pattern of query methods in SessionStore
Phase 3 Complete: SQL abstraction leak fixed in session init endpoint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extracted duplicated generator auto-start logic (44 lines × 4 occurrences) into
single private method ensureGeneratorRunning() that accepts source parameter.
Benefits:
- Reduced code duplication from 72 lines to 24 lines (net -48 lines)
- Single source of truth for generator lifecycle management
- Improved maintainability - changes only needed in one place
- Better logging with parameterized source tracking
Phase 2 Complete: All 4 handler methods now use shared method:
- handleObservations (legacy endpoint)
- handleSummarize (legacy endpoint)
- handleObservationsByClaudeId (new endpoint)
- handleSummarizeByClaudeId (new endpoint)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Changed searchRoutes property to be of type SearchRoutes | null.
- Initialized searchRoutes to null instead of using a temporary type assertion.
- Removed conditional setup for searchRoutes in setupRoutes method, as it will be handled after database initialization.
- Added optional chaining and nullish coalescing to handle potential undefined values in Chroma results and timeline items.
- Updated logging statements to provide clearer information when no results are found.
- Refactored destructuring of parameters in findByConcept and findByFile methods for consistency.
- Introduced SearchManager to handle search operations directly instead of proxying to MCP server.
- Updated WorkerService to initialize SearchManager after database setup.
- Modified SearchRoutes to call SearchManager methods for search operations.
- Adjusted SearchManager to manage timeline and formatting services.
- Enhanced error handling and logging for search operations.
- Extracted timeline-related functionality from mcp-server.ts to a dedicated TimelineService class.
- Added methods to build, filter, and format timeline items based on observations, sessions, and prompts.
- Introduced interfaces for TimelineItem and TimelineData to standardize data structures.
- Implemented sorting and grouping of timeline items by date, with markdown formatting for output.
- Included utility methods for date and time formatting, as well as token estimation.
- Updated logging in `search-server.ts` to use `silentDebug` for non-critical messages, reducing console noise.
- Added a health check endpoint in `worker-service.ts` to improve service monitoring.
- Modified the worker service startup process to start the HTTP server immediately and perform slow initialization in the background.
- Refactored database initialization in `Database.ts` to use the correct `Database` class.
- Implemented a port availability check in `context-hook.ts` to ensure the worker service is ready before making requests.
The dual stderr/stdout pattern was breaking context injection in Claude Code sessions.
Claude Code expects clean JSON on stdout only. Stderr output was interfering with
JSON parsing, causing context to fail loading even though the hook worked from CLI.
Changes:
- Remove process.stderr.write() when running as hook
- Add --colors flag support (matching main branch behavior)
- Output only JSON to stdout for hook execution
- Keep formatted output for manual terminal runs (TTY or --colors)
Co-authored-by: Alex Newman <thedotmack@users.noreply.github.com>
The /api/context/inject endpoint was using an incorrect relative import
path for context-generator.cjs. Since SearchRoutes is in
src/services/worker/http/routes/, the correct path to reach
src/services/context-generator.ts is ../../../context-generator.js
This fixes the session start context injection issue where the hook
would print correctly but no context would load in the session.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Alex Newman <thedotmack@users.noreply.github.com>
Major architectural improvements to the worker service:
- Extracted monolithic WorkerService (~1900 lines) into organized route classes
- New HTTP layer with dedicated route handlers:
- SessionRoutes: Session lifecycle operations
- DataRoutes: Data retrieval endpoints
- SearchRoutes: Search/MCP proxy operations
- SettingsRoutes: Settings and configuration
- ViewerRoutes: Health, UI, and SSE streaming
- Added comprehensive README documenting worker architecture
- Improved build script to handle worker service compilation
- Added context-generator for hook context operations
This is Phase 1 of worker refactoring - pure code reorganization with zero
functional changes. All existing behavior preserved while improving
maintainability and code organization.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implemented session cleanup tests to ensure proper handling of session completions and cleanup operations.
- Added session initialization tests to verify session creation and observation queuing on first tool use.
- Created session summary tests to validate summary generation from conversation context upon session pause or stop.
- Developed integration tests to cover the full observation lifecycle, including context injection, observation queuing, and error recovery.
- Introduced reusable mock factories and scenarios for consistent testing across different test files.
Architecture transformation: Hooks → HTTP → Worker → Database
**context-hook.ts** (843 → 104 lines, 88% reduction)
- Remove all database imports and raw SQL queries
- HTTP GET to /api/context/inject
- Returns both formatted (stderr) and unformatted (stdout) context
- Dual output: colored display for users, plain text for model
**user-message-hook.ts** (updated, 113 lines)
- HTTP GET to /api/context/inject with colors=true
- Displays formatted context to users via stderr
- No database dependencies
**save-hook.ts** (418 → 99 lines, 76% reduction)
- Remove all SessionStore database methods
- HTTP POST to /api/sessions/observations
- Worker handles privacy checks and observation creation
- Fire-and-forget pattern with 2s timeout
**summary-hook.ts** (435 → 200 lines, 54% reduction)
- Remove all SessionStore database methods
- Keep local transcript parsing (hook has file access)
- HTTP POST to /api/sessions/summarize
- Worker handles privacy checks and summary generation
**cleanup-hook.ts** (414 → 90 lines, 78% reduction)
- Remove all SessionStore database methods
- HTTP POST to /api/sessions/complete
- Worker handles session completion and DB cleanup
- Non-fatal if worker unavailable
**Benefits:**
- Zero native module dependencies in hooks (Node.js or Bun compatible)
- Hooks can run in any runtime without recompilation
- All database operations centralized in worker service
- Simpler, more maintainable hook code
- Complete separation of concerns: I/O vs business logic
- Add /api/context/inject endpoint (uses context-generator service)
- Add /api/sessions/observations endpoint (handles observations by claudeSessionId)
- Add /api/sessions/summarize endpoint (handles summaries by claudeSessionId)
- Add /api/sessions/complete endpoint (handles cleanup by claudeSessionId)
- Import stripMemoryTagsFromJson for privacy tag handling
- All endpoints accept claudeSessionId in request body (not path params)
- Enables hooks to become pure HTTP clients with zero database dependencies