* Add enforceable anti-pattern detection for try-catch abuse
PROBLEM:
- Overly-broad try-catch blocks waste 10+ hours of debugging time
- Empty catch blocks silently swallow errors
- AI assistants use try-catch to paper over uncertainty instead of doing research
SOLUTION:
1. Created detect-error-handling-antipatterns.ts test
- Detects empty catch blocks (45 CRITICAL found)
- Detects catch without logging (45 CRITICAL total)
- Detects large try blocks (>10 lines)
- Detects generic catch without type checking
- Detects catch-and-continue on critical paths
- Exit code 1 if critical issues found
2. Updated CLAUDE.md with MANDATORY ERROR HANDLING RULES
- 5-question pre-flight checklist before any try-catch
- FORBIDDEN patterns with examples
- ALLOWED patterns with examples
- Meta-rule: UNCERTAINTY TRIGGERS RESEARCH, NOT TRY-CATCH
- Critical path protection list
3. Created comprehensive try-catch audit report
- Documents all 96 try-catch blocks in worker service
- Identifies critical issue at worker-service.ts:748-750
- Categorizes patterns and provides recommendations
This is enforceable via test, not just instructions that can be ignored.
Current state: 163 anti-patterns detected (45 critical, 47 high, 71 medium)
Next: Fix critical issues identified by test
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: add logging to 5 critical empty catch blocks (Wave 1)
Wave 1 of error handling cleanup - fixing empty catch blocks that
silently swallow errors without any trace.
Fixed files:
- src/bin/import-xml-observations.ts:80 - Log skipped invalid JSON
- src/utils/bun-path.ts:33 - Log when bun not in PATH
- src/utils/cursor-utils.ts:44 - Log failed registry reads
- src/utils/cursor-utils.ts:149 - Log corrupt MCP config
- src/shared/worker-utils.ts:128 - Log failed health checks
All catch blocks now have proper logging with context and error details.
Progress: 41 → 39 CRITICAL issues remaining
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: add logging to promise catches on critical paths (Wave 2)
Wave 2 of error handling cleanup - fixing empty promise catch handlers
that silently swallow errors on critical code paths. These are the
patterns that caused the 10-hour debugging session.
Fixed empty promise catches:
- worker-service.ts:642 - Background initialization failures
- SDKAgent.ts:372,446 - Session processor errors
- GeminiAgent.ts:408,475 - Finalization failures
- OpenRouterAgent.ts:451,518 - Finalization failures
- SessionManager.ts:289 - Generator promise failures
Added justification comments to catch-and-continue blocks:
- worker-service.ts:68 - PID file removal (cleanup, non-critical)
- worker-service.ts:130 - Cursor context update (non-critical)
All promise rejection handlers now log errors with context, preventing
silent failures that were nearly impossible to debug.
Note: The anti-pattern detector only tracks try-catch blocks, not
standalone promise chains. These fixes address the root cause of the
original 10-hour debugging session even though the detector count
remains unchanged.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: add logging and documentation to error handling patterns (Wave 3)
Wave 3 of error handling cleanup - comprehensive review and fixes for
remaining critical issues identified by the anti-pattern detector.
Changes organized by severity:
**Wave 3.1: Fixed 2 EMPTY_CATCH blocks**
- worker-service.ts:162 - Health check polling now logs failures
- worker-service.ts:610 - Process cleanup logs failures
**Wave 3.2: Reviewed 12 CATCH_AND_CONTINUE patterns**
- Verified all are correct (log errors AND exit/return HTTP errors)
- Added justification comment to session recovery (line 829)
- All patterns properly notify callers of failures
**Wave 3.3: Fixed 29 NO_LOGGING_IN_CATCH issues**
Added logging to 16 catch blocks:
- UI layer: useSettings.ts, useContextPreview.ts (console logging)
- Servers: mcp-server.ts health checks and tool execution
- Worker: version fetch, cleanup, config corruption
- Routes: error handler, session recovery, settings validation
- Services: branch checkout, timeline queries
Documented 13 intentional exceptions with comments explaining why:
- Hot paths (port checks, process checks in tight loops)
- Error accumulation (transcript parser collects for batch retrieval)
- Special cases (logger can't log its own failures)
- Fallback parsing (JSON parse in optional data structures)
All changes follow error handling guidelines from CLAUDE.md:
- Appropriate log levels (error/warn/debug)
- Context objects with relevant details
- Descriptive messages explaining failures
- Error extraction pattern for Error instances
Progress: 41 → 29 detector warnings
Remaining warnings are conservative flags on verified-correct patterns
(catch-and-continue blocks that properly log + notify callers).
Build verified successful. All error handling now provides visibility
for debugging while avoiding excessive logging on hot paths.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat: add queue:clear command to remove failed messages
Added functionality to clear failed messages from the observation queue:
**Changes:**
- PendingMessageStore: Added clearFailed() method to delete failed messages
- DataRoutes: Added DELETE /api/pending-queue/failed endpoint
- CLI: Created scripts/clear-failed-queue.ts for interactive queue clearing
- package.json: Added npm run queue:clear script
**Usage:**
npm run queue:clear # Interactive - prompts for confirmation
npm run queue:clear -- --force # Non-interactive - clears without prompt
Failed messages are observations that exceeded max retry count. They
remain in the queue for debugging but won't be processed. This command
removes them to clean up the queue.
Works alongside existing queue:check and queue:process commands to
provide complete queue management capabilities.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat: add --all flag to queue:clear for complete queue reset
Extended queue clearing functionality to support clearing all messages,
not just failed ones.
**Changes:**
- PendingMessageStore: Added clearAll() method to clear pending, processing, and failed
- DataRoutes: Added DELETE /api/pending-queue/all endpoint
- clear-failed-queue.ts: Added --all flag to clear everything
- Updated help text and UI to distinguish between failed-only and all-clear modes
**Usage:**
npm run queue:clear # Clear failed only (interactive)
npm run queue:clear -- --all # Clear ALL messages (interactive)
npm run queue:clear -- --all --force # Clear all without confirmation
The --all flag provides a complete queue reset, removing pending,
processing, and failed messages. Useful when you want a fresh start
or need to cancel stuck sessions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat: add comprehensive documentation for session ID architecture and validation tests
* feat: add logs viewer with clear functionality to UI
- Add LogsRoutes API endpoint for fetching and clearing worker logs
- Create LogsModal component with auto-refresh and clear button
- Integrate logs viewer button into Header component
- Add comprehensive CSS styling for logs modal
- Logs accessible via new document icon button in header
Logs viewer features:
- Display last 1000 lines of current day's log file
- Auto-refresh toggle (2s interval)
- Clear logs button with confirmation
- Monospace font for readable log output
- Responsive modal design matching existing UI
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* refactor: redesign logs as Chrome DevTools-style console drawer
Major UX improvements to match Chrome DevTools console:
- Convert from modal to bottom drawer that slides up
- Move toggle button to bottom-left corner (floating button)
- Add draggable resize handle for height adjustment
- Use plain monospace font (SF Mono/Monaco/Consolas) instead of Monaspace
- Simplify controls with icon-only buttons
- Add Console tab UI matching DevTools aesthetic
Changes:
- Renamed LogsModal to LogsDrawer with drawer implementation
- Added resize functionality with mouse drag
- Removed logs button from header
- Added floating console toggle button in bottom-left
- Updated all CSS to match Chrome console styling
- Minimum height: 150px, maximum: window height - 100px
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: suppress /api/logs endpoint logging to reduce noise
Skip logging GET /api/logs requests in HTTP middleware to prevent
log spam from auto-refresh polling (every 2s). Keeps the auto-refresh
feature functional while eliminating the repetitive log entries.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* refactor: enhance error handling guidelines with approved overrides for justified exceptions
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
- Removed unnecessary logging for aborted sessions in WorkerService.
- Simplified the finally block in WorkerService by removing crash recovery logging.
- Cleaned up the try-catch structure in SDKAgent's startSession method, removing redundant error handling.
- Improved logging for session aborts and unexpected exits.
- Introduced a variable to track if the session was aborted for clarity.
- Added logic to create a new AbortController when restarting the generator after a crash.
- Implemented a mechanism to abort the session if there are no pending tasks after a natural completion.
- Ensured that errors during recovery checks lead to session abortion to prevent resource leaks.
* fix: make migration 17 idempotent and standardize column names
Migration 17 renamed columns from sdk_session_id to memory_session_id,
but the migration wasn't fully idempotent - it could fail on databases
in intermediate states. This caused errors like:
- "no such column: sdk_session_id" (when columns already renamed)
- "table observations has no column named memory_session_id" (when not renamed)
Changes:
- Rewrite renameSessionIdColumns() to check each table individually
- Use safeRenameColumn() helper that handles all edge cases gracefully
- Deprecate migration 19 (repair migration) since 17 is now idempotent
- Update maintenance scripts to use memory_session_id column name
- Update test files to use new column names
Fixes column mismatch bug in v8.2.6+
* Merge origin/main into column-mismatch
---------
Co-authored-by: Alex Newman <thedotmack@gmail.com>
🎉 Major release introducing full Cursor IDE support
New Features:
- Cursor IDE integration with native hook system
- Interactive setup wizard (bun run cursor:setup)
- Works without Claude Code using Gemini (free) or OpenRouter
- Cross-platform: macOS, Linux, Windows (PowerShell)
- Context injection via .cursor/rules directory
- Project registry for multi-workspace support
- MCP search tools for Cursor
Documentation:
- Full docs at docs.claude-mem.ai/cursor
- Gemini and OpenRouter setup guides
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated environment check to verify Claude Code presence.
- Improved provider selection process with clearer options and descriptions.
- Added functionality to keep current settings during provider configuration.
- Introduced installation scope selection for cursor hooks (project/user/skip).
- Implemented MCP server configuration in Cursor's mcp.json with error handling.
- Added utility functions to find MCP server script path and manage configurations.
Complete Windows parity with bash scripts:
- Create 7 PowerShell scripts mirroring bash functionality
- Update installer to detect platform and install appropriate scripts
- Generate platform-specific hooks.json with PowerShell invocation
- Add enterprise support for Windows (ProgramData/Cursor)
- Update findCursorHooksDir to check for both .sh and .ps1
- Add comprehensive Windows documentation to STANDALONE-SETUP.md
Scripts added: common.ps1, session-init.ps1, context-inject.ps1,
save-observation.ps1, save-file-edit.ps1, session-summary.ps1, user-message.ps1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 2 implementation: Enhanced CLI UX with guided first-run experience.
- Add `npm run cursor:setup` command for interactive wizard
- Auto-detect Claude Code installation
- Guide provider selection (Gemini recommended for free tier)
- Configure API keys interactively with settings persistence
- Auto-start worker and install hooks
- Clear instructions for next steps
This enables Cursor users without Claude Code to easily configure
claude-mem with free-tier providers like Gemini.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated `context-inject.sh` to refresh context before prompt submission and ensure worker is running.
- Added functionality to register and unregister projects for automatic context updates in `worker-service.ts`.
- Implemented methods to read and write the cursor project registry, allowing for better management of installed hooks.
- Integrated context updates into the `GeminiAgent`, `OpenRouterAgent`, and `SDKAgent` to ensure the latest context is available during sessions.
This update improves the integration of Claude-Mem with Cursor, ensuring that context is consistently updated and accessible across sessions.
- Introduced functionality for installing, uninstalling, and checking the status of Cursor hooks.
- Added a new command structure for managing hooks with detailed usage instructions.
- Implemented a method to locate the cursor-hooks directory across different environments.
- Updated build-hooks script to inform users about the location of Cursor hooks.
This enhancement streamlines the integration of Claude-Mem with Cursor, improving user experience and accessibility of hooks.
When the plugin updates but the worker was already running on the old version,
hooks would fail with 400 errors because the new hook scripts tried to call
APIs that don't exist in the old worker.
Changes:
- /api/version now returns BUILT_IN_VERSION (compiled at build time) instead
of reading from disk at runtime
- worker-service start command now checks for version mismatch and
auto-restarts if the running worker version differs from plugin version
- Downgraded hook version mismatch warning to debug logging (now handled
by auto-restart)
Fixes#484🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit simplifies worker startup coordination and addresses Windows-specific issues:
**Lock Removal**:
- Removed entire file-based locking system (~100 lines)
- Replaced with health-check-first approach
- Port binding provides natural mutual exclusion - multiple spawns fail cleanly
**Windows Stability**:
- Removed all AbortSignal.timeout() calls to reduce Bun libuv assertion errors
- Added 500ms shutdown delays on Windows to prevent zombie ports
- Worker service has its own timeouts, so client-side timeouts are redundant
**Package.json Updates**:
- Updated worker scripts to use worker-service.cjs directly
- Removed references to deleted worker-cli.js and worker-wrapper.cjs
**Key Changes**:
- src/services/worker-service.ts: Lock removal, shutdown delays, simplified start logic
- src/hooks/*.ts: Removed AbortSignal.timeout from all HTTP requests
- src/shared/worker-utils.ts: Removed AbortSignal.timeout from health checks
- package.json: Updated worker:* scripts
Resolves startup hangs, reduces assertion errors, and prevents zombie port issues.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Addresses review feedback to register signal handlers earlier in the
lifecycle. Previously handlers were registered in start() after HTTP
server initialization, leaving a vulnerability window.
Benefits:
- Signal handlers now active immediately after WorkerService construction
- Protects against signals received during initialization (DB setup,
HTTP server binding, background initialization)
- Prevents orphaned chroma-mcp processes even if killed during startup
- shutdown() method is defensive and safe to call at any stage
This closes the gap where a SIGTERM/SIGINT during initializeBackground()
could leave chroma-mcp subprocess running without cleanup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Addresses code review feedback from PR #489:
1. Moved PID file cleanup into shutdown() method to ensure it's always
cleaned up regardless of how shutdown is triggered
2. Removed duplicate signal handlers in main() function that were
redundant with the handlers in start() method
This eliminates the race condition where both sets of handlers could
trigger, and ensures consistent PID file cleanup behavior.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add BEGIN/COMMIT/ROLLBACK to session ID column rename migration
- Update claude-desktop.mdx to reflect streamlined MCP tools
- Remove obsolete skill zip download instructions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Removed unused tool endpoints and schemas to streamline the codebase.
- Consolidated tool descriptions to emphasize a 3-layer workflow for memory search.
- Updated input schemas and handler functions for clarity and efficiency.
- Enhanced documentation within tool descriptions for better user guidance.
- Updated SQL queries in cleanup-duplicates.ts and context-generator.ts to use memory_session_id.
- Modified interfaces in context-generator.ts to reflect the new session ID naming.
- Implemented a repair migration in SessionStore.ts to rename columns in existing tables.
- Adjusted FormattingService.ts and SDKAgent.ts to utilize memory_session_id for session handling.
- Ensured SearchManager.ts retrieves summaries and observations using the updated memory_session_id.
This commit fixes the session ID confusion identified in PR #475:
PROBLEM:
- Using contentSessionId (user's Claude Code session) for SDK resume was wrong
- Memory agent conversation should persist across the entire user session
- Each SDK call was starting fresh, losing memory agent continuity
SOLUTION:
1. Semantic Renaming (clarity):
- claudeSessionId → contentSessionId (user's observed session)
- sdkSessionId → memorySessionId (memory agent's session for resume)
- Database migration 17 renames columns accordingly
2. Memory Session ID Capture:
- SDKAgent captures session_id from first SDK message
- Persists to database via updateMemorySessionId()
- SessionManager loads memorySessionId on session init
3. Resume Logic Fixed:
- Only resume if memorySessionId captured from previous interaction
- Enables memory agent continuity across user prompts
Files changed: 33 (types, database, agents, hooks, routes)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement auto-recovery of orphaned queues on startup in WorkerService.
- Introduce startSessionWithAutoRestart method for continuous processing of pending work.
- Modify SDKAgent to prevent session deletion during processing to avoid race conditions.
- Update SessionManager to allow continued processing after yielding summaries.
- Add logic in SessionRoutes to mark processing messages as failed upon generator errors.
- Create detailed documentation for the queue system logic, including recovery mechanisms and potential issues.
- Implement retry logic for acquiring file lock with a maximum of 3 attempts.
- Improve error handling for ENOENT errors by ensuring the directory exists before retrying.
- Update context injection handler to delegate to SearchRoutes, reducing code duplication and preventing "headers already sent" errors.
- Add checks for headersSent in error responses to avoid sending multiple responses.
- Log warnings when the port does not free up after shutdown, and handle forced shutdown scenarios more gracefully.
- Modified the logger to check if the data is an instance of Error.
- If it is an Error, the logger now formats the output to include the message and stack trace in debug mode, or just the message otherwise.
- Retained the existing behavior for other object types in debug mode.
- Removed the linger timeout mechanism to streamline the waiting process for new messages.
- Updated the message handling logic to use a single event listener for new messages.
- Improved abort handling by ensuring the session exits cleanly when aborted.
- Changed the order of operations in session initialization to first create/get the SDK session with the original prompt.
- Introduced a new step to clean the prompt of privacy tags after determining the session ID.
- Updated logging to reflect the new flow and ensure clarity on session creation and prompt number calculation.
The bugfix/session-continuity branch introduced a regression that broke
the privacy fix from PR #463 (commit 63fd158). Privacy tags must be
stripped BEFORE creating the session, not after.
CORRECT order:
1. Strip privacy tags
2. Create session with cleaned prompt
3. Get prompt number
BROKEN order (what was on main):
1. Create session with RAW prompt (stores private content!)
2. Get prompt number
3. Strip privacy tags (too late)
This commit restores the correct order from commit 63fd158.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replaced console.log and console.error statements with logger.info and logger.error in new-hook.ts, SDKAgent.ts, SessionManager.ts, and SessionRoutes.ts for consistent logging.
- Introduced log file creation and management in logger.ts, ensuring logs are saved to a file with a date-based naming convention.
- Enhanced error handling in logger to prevent crashes if log file operations fail.
Added comprehensive diagnostic logging to trace session ID and prompt number flow through the entire system. This is Phase 1 of the session continuity regression fix.
Changes:
- Added logging in src/hooks/new-hook.ts (4 log points)
- Added logging in src/services/worker/http/routes/SessionRoutes.ts (4 log points)
- Added logging in src/services/worker/SessionManager.ts (4 log points)
- Added logging in src/services/worker/SDKAgent.ts (2 log points)
The logging will help identify where the session ID propagation breaks and whether prompt numbers are being calculated correctly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Updated SDKAgent to include session.claudeSessionId in the options for resuming sessions.
- Added comprehensive logging across multiple files to trace session ID and prompt number flow, aiding in diagnosing session continuity issues.
- Introduced a detailed plan for addressing session continuity regression, outlining phases for logging, testing, and implementing fixes.
- Added functions for acquiring and releasing locks using a lock file.
- Implemented cleanup of stale locks from crashed processes.
- Modified 'start', 'stop', and 'restart' commands to use the locking mechanism.
- Ensured proper handling of concurrent operations and improved logging.
- Added logging for empty responses in GeminiAgent and OpenRouterAgent to track potential session context issues.
- Refactored settings file path usage in OpenRouterAgent to use a constant for better maintainability.
- Improved error handling in SessionRoutes to log generator failures with detailed context.
- Implemented JSON parsing error handling in SettingsRoutes to manage corrupted settings files gracefully.
- Added validation for CLAUDE_MEM_OPENROUTER_MAX_CONTEXT_MESSAGES, CLAUDE_MEM_OPENROUTER_MAX_TOKENS, and CLAUDE_MEM_OPENROUTER_SITE_URL in SettingsRoutes to ensure valid configuration.
Settings persistence was broken because 7 setting keys were missing from
the settingKeys array in SettingsRoutes.ts handleUpdateSettings():
- CLAUDE_MEM_GEMINI_RATE_LIMITING_ENABLED
- CLAUDE_MEM_OPENROUTER_API_KEY
- CLAUDE_MEM_OPENROUTER_MODEL
- CLAUDE_MEM_OPENROUTER_SITE_URL
- CLAUDE_MEM_OPENROUTER_APP_NAME
- CLAUDE_MEM_OPENROUTER_MAX_CONTEXT_MESSAGES
- CLAUDE_MEM_OPENROUTER_MAX_TOKENS
Phase 1/5 of PR #448 fix plan.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>