feat(ProcessManager): add Bun availability check and improve PID file validation

- 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.
This commit is contained in:
Alex Newman
2025-12-12 17:48:41 -05:00
parent 9f1745bdec
commit 1491123706
27 changed files with 247 additions and 316 deletions
+3 -3
View File
@@ -109,7 +109,7 @@ npx mintlify dev
- **[Architecture Evolution](https://docs.claude-mem.ai/architecture-evolution)** - The journey from v3 to v5 - **[Architecture Evolution](https://docs.claude-mem.ai/architecture-evolution)** - The journey from v3 to v5
- **[Hooks Architecture](https://docs.claude-mem.ai/hooks-architecture)** - How Claude-Mem uses lifecycle hooks - **[Hooks Architecture](https://docs.claude-mem.ai/hooks-architecture)** - How Claude-Mem uses lifecycle hooks
- **[Hooks Reference](https://docs.claude-mem.ai/architecture/hooks)** - 7 hook scripts explained - **[Hooks Reference](https://docs.claude-mem.ai/architecture/hooks)** - 7 hook scripts explained
- **[Worker Service](https://docs.claude-mem.ai/architecture/worker-service)** - HTTP API & PM2 management - **[Worker Service](https://docs.claude-mem.ai/architecture/worker-service)** - HTTP API & Bun management
- **[Database](https://docs.claude-mem.ai/architecture/database)** - SQLite schema & FTS5 search - **[Database](https://docs.claude-mem.ai/architecture/database)** - SQLite schema & FTS5 search
- **[Search Architecture](https://docs.claude-mem.ai/architecture/search-architecture)** - Hybrid search with Chroma vector database - **[Search Architecture](https://docs.claude-mem.ai/architecture/search-architecture)** - Hybrid search with Chroma vector database
@@ -149,7 +149,7 @@ npx mintlify dev
1. **5 Lifecycle Hooks** - SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd (6 hook scripts) 1. **5 Lifecycle Hooks** - SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd (6 hook scripts)
2. **Smart Install** - Cached dependency checker (pre-hook script, not a lifecycle hook) 2. **Smart Install** - Cached dependency checker (pre-hook script, not a lifecycle hook)
3. **Worker Service** - HTTP API on port 37777 with web viewer UI and 10 search endpoints, managed by PM2 3. **Worker Service** - HTTP API on port 37777 with web viewer UI and 10 search endpoints, managed by Bun
4. **SQLite Database** - Stores sessions, observations, summaries with FTS5 full-text search 4. **SQLite Database** - Stores sessions, observations, summaries with FTS5 full-text search
5. **mem-search Skill** - Natural language queries with progressive disclosure (~2,250 token savings vs MCP) 5. **mem-search Skill** - Natural language queries with progressive disclosure (~2,250 token savings vs MCP)
6. **Chroma Vector Database** - Hybrid semantic + keyword search for intelligent context retrieval 6. **Chroma Vector Database** - Hybrid semantic + keyword search for intelligent context retrieval
@@ -263,7 +263,7 @@ See [CHANGELOG.md](CHANGELOG.md) for complete version history.
- **Node.js**: 18.0.0 or higher - **Node.js**: 18.0.0 or higher
- **Claude Code**: Latest version with plugin support - **Claude Code**: Latest version with plugin support
- **PM2**: Process manager (bundled - no global install required) - **Bun**: JavaScript runtime and process manager (auto-installed if missing)
- **SQLite 3**: For persistent storage (bundled) - **SQLite 3**: For persistent storage (bundled)
--- ---
+11 -11
View File
@@ -34,7 +34,7 @@ isWorkerHealthy() → fetch /health endpoint
└─ [UNHEALTHY] → startWorker() └─ [UNHEALTHY] → startWorker()
├─ [Windows] → PowerShell Start-Process (hidden window) ├─ [Windows] → PowerShell Start-Process (hidden window)
└─ [Unix] → PM2 start ecosystem.config.cjs └─ [Unix] → Bun start ecosystem.config.cjs
Wait for health check (15 retries × 1000ms) Wait for health check (15 retries × 1000ms)
@@ -116,7 +116,7 @@ spawnSync('powershell.exe', [
**Issues:** **Issues:**
1. **PowerShell Dependency:** Assumes PowerShell is available and in PATH 1. **PowerShell Dependency:** Assumes PowerShell is available and in PATH
2. **Command Injection Risk:** Worker script path inserted directly into command string without escaping 2. **Command Injection Risk:** Worker script path inserted directly into command string without escaping
3. **Process Monitoring:** Windows approach launches detached process with no PM2 monitoring - harder to debug/restart 3. **Process Monitoring:** Windows approach launches detached process with no Bun monitoring - harder to debug/restart
4. **Health Check Timeout:** Comment says "Windows needs longer timeouts" but timeout is same for all platforms (500ms) 4. **Health Check Timeout:** Comment says "Windows needs longer timeouts" but timeout is same for all platforms (500ms)
**Edge Cases:** **Edge Cases:**
@@ -127,16 +127,16 @@ spawnSync('powershell.exe', [
**Unix Implementation:** **Unix Implementation:**
```typescript ```typescript
const localPm2Base = path.join(MARKETPLACE_ROOT, 'node_modules', '.bin', 'pm2'); const localBunBase = path.join(MARKETPLACE_ROOT, 'node_modules', '.bin', 'bun');
const pm2Command = existsSync(localPm2Base) ? localPm2Base : 'pm2'; const bunCommand = existsSync(localBunBase) ? localBunBase : 'bun';
``` ```
**Issues:** **Issues:**
1. **PM2 Dependency:** Falls back to global pm2 if local not found, but doesn't verify it exists 1. **Bun Dependency:** Falls back to global bun if local not found, but doesn't verify it exists
2. **Silent Failure:** If PM2 not installed globally, spawnSync will fail with cryptic ENOENT error 2. **Silent Failure:** If Bun not installed globally, spawnSync will fail with cryptic ENOENT error
**Recommendation:** **Recommendation:**
- Add pm2 existence check before spawn - Add bun existence check before spawn
- Implement consistent process monitoring across platforms - Implement consistent process monitoring across platforms
- Add path escaping for Windows command construction - Add path escaping for Windows command construction
- Actually implement longer timeout for Windows if needed - Actually implement longer timeout for Windows if needed
@@ -414,7 +414,7 @@ if (!existsSync(join(commandsDir, 'save.md'))) {
### Missing Edge Case Handling ⚠️ ### Missing Edge Case Handling ⚠️
1. **curl Failure:** context-hook.ts has no error handling for curl failures 1. **curl Failure:** context-hook.ts has no error handling for curl failures
2. **PM2 Not Installed:** worker-utils.ts assumes pm2 exists globally 2. **Bun Not Installed:** worker-utils.ts assumes bun exists globally
3. **PowerShell Restrictions:** worker-utils.ts doesn't check execution policy 3. **PowerShell Restrictions:** worker-utils.ts doesn't check execution policy
4. **Concurrent Worker Starts:** No locking to prevent multiple hooks from starting worker simultaneously 4. **Concurrent Worker Starts:** No locking to prevent multiple hooks from starting worker simultaneously
5. **Port Already In Use:** No detection or recovery if worker port is taken 5. **Port Already In Use:** No detection or recovery if worker port is taken
@@ -442,7 +442,7 @@ if (!existsSync(join(commandsDir, 'save.md'))) {
### Medium Priority 🟡 ### Medium Priority 🟡
4. **Verify PM2 availability** before attempting to use it 4. **Verify Bun availability** before attempting to use it
- Check existence before spawn - Check existence before spawn
- Provide clear error message if missing - Provide clear error message if missing
@@ -494,7 +494,7 @@ if (!existsSync(join(commandsDir, 'save.md'))) {
1. **Cold Start:** First run with no existing data 1. **Cold Start:** First run with no existing data
2. **Corrupt Settings:** Invalid JSON in settings.json 2. **Corrupt Settings:** Invalid JSON in settings.json
3. **Missing Dependencies:** No PM2, no git, no curl 3. **Missing Dependencies:** No Bun, no git, no curl
4. **Port Conflicts:** Worker port already in use 4. **Port Conflicts:** Worker port already in use
5. **Rapid Hook Invocations:** Multiple hooks trying to start worker simultaneously 5. **Rapid Hook Invocations:** Multiple hooks trying to start worker simultaneously
6. **Permission Issues:** Read-only filesystem, restricted execution 6. **Permission Issues:** Read-only filesystem, restricted execution
@@ -525,7 +525,7 @@ if (!existsSync(join(commandsDir, 'save.md'))) {
- Duplicate health endpoints - Duplicate health endpoints
- curl dependency when fetch available - curl dependency when fetch available
- PM2 dependency on Unix but not Windows (inconsistent monitoring) - Bun dependency on Unix but not Windows (inconsistent monitoring)
- First-run detection using node_modules existence - First-run detection using node_modules existence
- Hardcoded timeout values - Hardcoded timeout values
+5 -5
View File
@@ -68,9 +68,9 @@ CLAUDE_MEM_PYTHON_VERSION=3.13 # Python version for chroma-mcp
```bash ```bash
npm run build # Compile TypeScript (hooks + worker) npm run build # Compile TypeScript (hooks + worker)
npm run sync-marketplace # Copy to ~/.claude/plugins npm run sync-marketplace # Copy to ~/.claude/plugins
npm run worker:restart # Restart PM2 worker npm run worker:restart # Restart Bun worker
npm run worker:logs # View worker logs npm run worker:logs # View worker logs
pm2 list # Check worker status bun list # Check worker status
``` ```
--- ---
@@ -918,8 +918,8 @@ esbuild.build({
npm run watch npm run watch
# Terminal 2: Check worker status # Terminal 2: Check worker status
pm2 list bun list
pm2 logs claude-mem-worker bun logs claude-mem-worker
# Terminal 3: Test API manually # Terminal 3: Test API manually
curl http://localhost:37777/api/health curl http://localhost:37777/api/health
@@ -1020,7 +1020,7 @@ describe('Worker Integration', () => {
### Manual Testing Checklist ### Manual Testing Checklist
**Phase 1: Connection & Health** **Phase 1: Connection & Health**
- [ ] Worker starts successfully (`pm2 list`) - [ ] Worker starts successfully (`bun list`)
- [ ] Health endpoint responds (`curl http://localhost:37777/api/health`) - [ ] Health endpoint responds (`curl http://localhost:37777/api/health`)
- [ ] SSE stream connects (`curl http://localhost:37777/stream`) - [ ] SSE stream connects (`curl http://localhost:37777/stream`)
+8 -15
View File
@@ -46,22 +46,15 @@ const ThemeProvider = ({ children }) => {
**Why It Matters**: Users working in different lighting conditions can now customize the viewer for comfort. **Why It Matters**: Users working in different lighting conditions can now customize the viewer for comfort.
### v5.1.1: PM2 Windows Fix (November 2025) ### v5.1.1: Worker Startup Fix (November 2025) - Now Deprecated
**The Problem**: PM2 startup failed on Windows with ENOENT error **Note**: This section describes a historical PM2-based approach that has been replaced with Bun in later versions.
**Root Cause**: **The Problem**: Worker startup failed on Windows with ENOENT error when using PM2
```typescript
// ❌ Failed on Windows - PM2 not in PATH
execSync('pm2 start ecosystem.config.cjs');
```
**The Fix**: **Historical Solution**: Used full path to PM2 binary instead of relying on PATH
```typescript
// ✅ Use full path to PM2 binary **Current Approach**: The project now uses Bun for process management, which provides better cross-platform compatibility and eliminates these PATH-related issues.
const PM2_PATH = join(PLUGIN_ROOT, 'node_modules', '.bin', 'pm2');
execSync(`"${PM2_PATH}" start "${ECOSYSTEM_CONFIG}"`);
```
**Impact**: Cross-platform compatibility restored, Windows users can now use claude-mem without issues. **Impact**: Cross-platform compatibility restored, Windows users can now use claude-mem without issues.
@@ -203,7 +196,7 @@ async function ensureWorkerHealthy() {
**Key Fixes**: **Key Fixes**:
- Fixed race conditions in observation queue processing - Fixed race conditions in observation queue processing
- Improved error handling in SDK worker - Improved error handling in SDK worker
- Better cleanup of stale PM2 processes - Better cleanup of stale worker processes
- Enhanced logging for debugging - Enhanced logging for debugging
### v5.0.0: Hybrid Search Architecture (October 2025) ### v5.0.0: Hybrid Search Architecture (October 2025)
@@ -520,7 +513,7 @@ const response = query({
**Key change from v3:** **Key change from v3:**
- ✅ Stores raw prompts for search - ✅ Stores raw prompts for search
- ✅ Auto-starts PM2 worker - ✅ Auto-starts worker service
</Tab> </Tab>
<Tab title="PostToolUse"> <Tab title="PostToolUse">
+2 -2
View File
@@ -446,7 +446,7 @@ sequenceDiagram
else Tool allowed else Tool allowed
SaveHook->>SaveHook: Strip privacy tags from input/response SaveHook->>SaveHook: Strip privacy tags from input/response
SaveHook->>SaveHook: Ensure worker running<br/>(PM2 health check) SaveHook->>SaveHook: Ensure worker running<br/>(health check)
SaveHook->>Worker: POST /api/sessions/observations<br/>{ claudeSessionId, tool_name, tool_input, tool_response, cwd }<br/>(fire-and-forget, 2s timeout) SaveHook->>Worker: POST /api/sessions/observations<br/>{ claudeSessionId, tool_name, tool_input, tool_response, cwd }<br/>(fire-and-forget, 2s timeout)
@@ -906,7 +906,7 @@ For developers implementing this pattern on other platforms:
### Worker Service ### Worker Service
- [ ] HTTP server on configurable port (default 37777) - [ ] HTTP server on configurable port (default 37777)
- [ ] PM2 or equivalent process management - [ ] Bun runtime for process management
- [ ] 3 core services: SessionManager, SDKAgent, DatabaseManager - [ ] 3 core services: SessionManager, SDKAgent, DatabaseManager
### Hook Implementation ### Hook Implementation
+5 -5
View File
@@ -29,7 +29,7 @@ Claude-Mem operates as a Claude Code plugin with five core components:
| **UI Framework** | React + TypeScript | | **UI Framework** | React + TypeScript |
| **AI SDK** | @anthropic-ai/claude-agent-sdk | | **AI SDK** | @anthropic-ai/claude-agent-sdk |
| **Build Tool** | esbuild (bundles TypeScript) | | **Build Tool** | esbuild (bundles TypeScript) |
| **Process Manager** | PM2 | | **Process Manager** | Bun |
| **Testing** | Node.js built-in test runner | | **Testing** | Node.js built-in test runner |
## Data Flow ## Data Flow
@@ -70,7 +70,7 @@ User Query → mem-search Skill Invoked → HTTP API → SessionSearch Service
┌─────────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────┐
│ 1. Session Starts → Context Hook Fires │ │ 1. Session Starts → Context Hook Fires │
│ Starts PM2 worker if needed, injects context from previous │ │ Starts Bun worker if needed, injects context from previous │
│ sessions (configurable observation count) │ │ sessions (configurable observation count) │
└─────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────┘
@@ -177,13 +177,13 @@ claude-mem/
├── tests/ # Test suite ├── tests/ # Test suite
├── docs/ # Documentation ├── docs/ # Documentation
└── ecosystem.config.cjs # PM2 configuration └── ecosystem.config.cjs # Process configuration (deprecated)
``` ```
## Component Details ## Component Details
### 1. Plugin Hooks (6 Hooks) ### 1. Plugin Hooks (6 Hooks)
- **context-hook.js** - SessionStart: Starts PM2 worker, injects context - **context-hook.js** - SessionStart: Starts Bun worker, injects context
- **user-message-hook.js** - UserMessage: Debugging hook - **user-message-hook.js** - UserMessage: Debugging hook
- **new-hook.js** - UserPromptSubmit: Creates session, saves prompt - **new-hook.js** - UserPromptSubmit: Creates session, saves prompt
- **save-hook.js** - PostToolUse: Captures tool executions - **save-hook.js** - PostToolUse: Captures tool executions
@@ -200,7 +200,7 @@ Express.js HTTP server on port 37777 (configurable) with:
- 8 viewer UI HTTP/SSE endpoints - 8 viewer UI HTTP/SSE endpoints
- Async observation processing via Claude Agent SDK - Async observation processing via Claude Agent SDK
- Real-time updates via Server-Sent Events - Real-time updates via Server-Sent Events
- Auto-managed by PM2 process manager - Auto-managed by Bun
See [Worker Service](/architecture/worker-service) for HTTP API and endpoints. See [Worker Service](/architecture/worker-service) for HTTP API and endpoints.
@@ -415,7 +415,7 @@ Claude translates to appropriate API call.
If searches fail, check worker service: If searches fail, check worker service:
```bash ```bash
pm2 list # Check status npm run worker:status # Check status
npm run worker:restart # Restart worker npm run worker:restart # Restart worker
npm run worker:logs # View logs npm run worker:logs # View logs
``` ```
+3 -33
View File
@@ -181,33 +181,9 @@ Claude-Mem supports switching between stable and beta versions via the web viewe
See [Beta Features](beta-features) for details on what's available in beta. See [Beta Features](beta-features) for details on what's available in beta.
## PM2 Configuration ## Worker Service Management
Worker service is managed by PM2 via `ecosystem.config.cjs`: Worker service is managed by Bun as a background process. The worker auto-starts on first session and runs continuously in the background.
```javascript
module.exports = {
apps: [{
name: 'claude-mem-worker',
script: './plugin/scripts/worker-service.cjs',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
NODE_ENV: 'production',
FORCE_COLOR: '1'
}
}]
};
```
### PM2 Settings
- **instances**: 1 (single instance)
- **autorestart**: true (auto-restart on crash)
- **watch**: false (no file watching)
- **max_memory_restart**: 1G (restart if memory exceeds 1GB)
## Context Injection Configuration ## Context Injection Configuration
@@ -402,13 +378,7 @@ Recommended values:
### Worker Memory Limit ### Worker Memory Limit
Modify PM2 memory limit in `ecosystem.config.cjs`: The worker service is managed by Bun and will automatically restart if it encounters issues. Memory usage is typically low (~100-200MB).
```javascript
{
max_memory_restart: '2G' // Increase if needed
}
```
### Logging Verbosity ### Logging Verbosity
+1 -1
View File
@@ -650,7 +650,7 @@ rm -rf plugin/scripts/*.js plugin/scripts/*.cjs
1. Kill existing process: 1. Kill existing process:
```bash ```bash
pm2 delete claude-mem-worker npm run worker:stop
``` ```
2. Check port: 2. Check port:
+20 -36
View File
@@ -87,7 +87,7 @@ Claude-Mem uses 6 lifecycle hook scripts across 5 lifecycle events, plus 1 pre-h
- Version changed in package.json - Version changed in package.json
- Critical dependency missing (better-sqlite3) - Critical dependency missing (better-sqlite3)
3. Provides Windows-specific error messages 3. Provides Windows-specific error messages
4. Starts PM2 worker service 4. Starts Bun worker service
**Configuration:** **Configuration:**
```json ```json
@@ -215,7 +215,7 @@ Claude-Mem uses 6 lifecycle hook scripts across 5 lifecycle events, plus 1 pre-h
1. Reads user prompt and session ID from stdin 1. Reads user prompt and session ID from stdin
2. Creates new session record in SQLite 2. Creates new session record in SQLite
3. Saves raw user prompt for full-text search (v4.2.0+) 3. Saves raw user prompt for full-text search (v4.2.0+)
4. Starts PM2 worker service if not running 4. Starts Bun worker service if not running
5. Returns immediately (non-blocking) 5. Returns immediately (non-blocking)
**Configuration:** **Configuration:**
@@ -512,49 +512,33 @@ sequenceDiagram
└─────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────┘
``` ```
### PM2 Process Management ### Bun Process Management
**Technology:** PM2 (process manager for Node.js) **Technology:** Bun (JavaScript runtime and process manager)
**Why PM2:** **Why Bun:**
- Auto-restart on failure - Auto-restart on failure
- Log management - Fast startup and low memory footprint
- Process monitoring - Built-in TypeScript support
- Cross-platform (works on macOS, Linux, Windows) - Cross-platform (works on macOS, Linux, Windows)
- No systemd/launchd needed - No separate process manager needed
**Configuration:**
```javascript
// ecosystem.config.cjs
module.exports = {
apps: [{
name: 'claude-mem-worker',
script: './plugin/scripts/worker-service.cjs',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '500M',
env: {
NODE_ENV: 'production',
CLAUDE_MEM_WORKER_PORT: 37777
}
}]
};
```
**Worker lifecycle:** **Worker lifecycle:**
```bash ```bash
# Started by new-hook (if not running) # Started by hooks automatically (if not running)
pm2 start ecosystem.config.cjs npm run worker:start
# Status check # Status check
pm2 status claude-mem-worker npm run worker:status
# View logs # View logs
pm2 logs claude-mem-worker npm run worker:logs
# Restart # Restart
pm2 restart claude-mem-worker npm run worker:restart
# Stop
npm run worker:stop
``` ```
### Worker HTTP API ### Worker HTTP API
@@ -632,7 +616,7 @@ try {
**Failure modes:** **Failure modes:**
- Database locked → Skip observation, log error - Database locked → Skip observation, log error
- Worker crashed → Auto-restart via PM2 - Worker crashed → Auto-restart via Bun
- Network issue → Retry with exponential backoff - Network issue → Retry with exponential backoff
- Disk full → Warn user, disable memory - Disk full → Warn user, disable memory
@@ -708,8 +692,8 @@ claude --debug
**Debugging:** **Debugging:**
1. Check database: `sqlite3 ~/.claude-mem/claude-mem.db "SELECT * FROM observation_queue"` 1. Check database: `sqlite3 ~/.claude-mem/claude-mem.db "SELECT * FROM observation_queue"`
2. Verify session exists: `SELECT * FROM sdk_sessions` 2. Verify session exists: `SELECT * FROM sdk_sessions`
3. Check worker status: `pm2 status` 3. Check worker status: `npm run worker:status`
4. View worker logs: `pm2 logs claude-mem-worker` 4. View worker logs: `npm run worker:logs`
</Accordion> </Accordion>
</AccordionGroup> </AccordionGroup>
@@ -761,7 +745,7 @@ claude --debug
**Why smart-install is sometimes slow:** **Why smart-install is sometimes slow:**
- First-time: Full npm install (2-5 seconds) - First-time: Full npm install (2-5 seconds)
- Cached: Version check only (~10ms) - Cached: Version check only (~10ms)
- Version change: Full npm install + PM2 restart - Version change: Full npm install + worker restart
**Optimization (v5.0.3):** **Optimization (v5.0.3):**
- Version caching with `.install-version` marker - Version caching with `.install-version` marker
+2 -2
View File
@@ -16,7 +16,7 @@ Install Claude-Mem directly from the plugin marketplace:
That's it! The plugin will automatically: That's it! The plugin will automatically:
- Download prebuilt binaries (no compilation needed) - Download prebuilt binaries (no compilation needed)
- Install all dependencies (including PM2 and SQLite binaries) - Install all dependencies (including SQLite binaries)
- Configure hooks for session lifecycle management - Configure hooks for session lifecycle management
- Auto-start the worker service on first session - Auto-start the worker service on first session
@@ -26,7 +26,7 @@ Start a new Claude Code session and you'll see context from previous sessions au
- **Node.js**: 18.0.0 or higher - **Node.js**: 18.0.0 or higher
- **Claude Code**: Latest version with plugin support - **Claude Code**: Latest version with plugin support
- **PM2**: Process manager (bundled with plugin - no global install required) - **Bun**: JavaScript runtime and process manager (auto-installed if missing)
- **SQLite 3**: For persistent storage (bundled) - **SQLite 3**: For persistent storage (bundled)
## Advanced Installation ## Advanced Installation
+2 -2
View File
@@ -58,7 +58,7 @@ Restart Claude Code. Context from previous sessions will automatically appear in
**Core Components:** **Core Components:**
1. **5 Lifecycle Hooks** - SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd (6 hook scripts) 1. **5 Lifecycle Hooks** - SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd (6 hook scripts)
2. **Smart Install** - Cached dependency checker (pre-hook script) 2. **Smart Install** - Cached dependency checker (pre-hook script)
3. **Worker Service** - HTTP API on port 37777 managed by PM2 3. **Worker Service** - HTTP API on port 37777 managed by Bun
4. **SQLite Database** - Stores sessions, observations, summaries with FTS5 search 4. **SQLite Database** - Stores sessions, observations, summaries with FTS5 search
5. **mem-search Skill** - Query historical context with natural language 5. **mem-search Skill** - Query historical context with natural language
6. **Web Viewer UI** - Real-time visualization with SSE and infinite scroll 6. **Web Viewer UI** - Real-time visualization with SSE and infinite scroll
@@ -69,7 +69,7 @@ See [Architecture Overview](architecture/overview) for details.
- **Node.js**: 18.0.0 or higher - **Node.js**: 18.0.0 or higher
- **Claude Code**: Latest version with plugin support - **Claude Code**: Latest version with plugin support
- **PM2**: Process manager (bundled - no global install required) - **Bun**: JavaScript runtime and process manager (auto-installed if missing)
- **SQLite 3**: For persistent storage (bundled) - **SQLite 3**: For persistent storage (bundled)
## What's New ## What's New
+5 -5
View File
@@ -57,9 +57,9 @@ CLAUDE_MEM_PYTHON_VERSION=3.13 # Python version for chroma-mcp
```bash ```bash
npm run build # Compile TypeScript (hooks + worker) npm run build # Compile TypeScript (hooks + worker)
npm run sync-marketplace # Copy to ~/.claude/plugins npm run sync-marketplace # Copy to ~/.claude/plugins
npm run worker:restart # Restart PM2 worker npm run worker:restart # Restart worker
npm run worker:logs # View worker logs npm run worker:logs # View worker logs
pm2 list # Check worker status npm run worker:status # Check worker status
``` ```
## Worker Architecture ## Worker Architecture
@@ -1132,8 +1132,8 @@ esbuild.build({
</Step> </Step>
<Step title="Terminal 2: Check worker status"> <Step title="Terminal 2: Check worker status">
```bash ```bash
pm2 list npm run worker:status
pm2 logs claude-mem-worker npm run worker:logs
``` ```
</Step> </Step>
<Step title="Terminal 3: Test API manually"> <Step title="Terminal 3: Test API manually">
@@ -1238,7 +1238,7 @@ describe('Worker Integration', () => {
<AccordionGroup> <AccordionGroup>
<Accordion title="Phase 1: Connection & Health"> <Accordion title="Phase 1: Connection & Health">
- [ ] Worker starts successfully (`pm2 list`) - [ ] Worker starts successfully (`npm run worker:status`)
- [ ] Health endpoint responds (`curl http://localhost:37777/api/health`) - [ ] Health endpoint responds (`curl http://localhost:37777/api/health`)
- [ ] SSE stream connects (`curl http://localhost:37777/stream`) - [ ] SSE stream connects (`curl http://localhost:37777/stream`)
</Accordion> </Accordion>
+24 -55
View File
@@ -10,7 +10,7 @@ description: "Common issues and solutions for Claude-Mem"
Describe any issues you're experiencing to Claude, and the troubleshoot skill will automatically activate to provide diagnosis and fixes. Describe any issues you're experiencing to Claude, and the troubleshoot skill will automatically activate to provide diagnosis and fixes.
The troubleshoot skill will: The troubleshoot skill will:
- ✅ Check PM2 worker status and health - ✅ Check worker status and health
- ✅ Verify database existence and integrity - ✅ Verify database existence and integrity
- ✅ Test worker service connectivity - ✅ Test worker service connectivity
- ✅ Validate dependencies installation - ✅ Validate dependencies installation
@@ -170,39 +170,18 @@ The skill includes comprehensive diagnostics, automated repair sequences, and de
4. Restart Claude Code after manual install 4. Restart Claude Code after manual install
### PM2 ENOENT Error on Windows (v5.1.1 Fix)
**Symptoms**: Worker fails to start with "ENOENT" error on Windows.
**Solutions**:
1. This was fixed in v5.1.1 - update to latest version:
```bash
/plugin update claude-mem
```
2. If still experiencing issues, verify PM2 path:
```bash
cd ~/.claude/plugins/marketplaces/thedotmack
dir node_modules\.bin\pm2.cmd
```
3. Manual PM2 install if needed:
```bash
npm install pm2@latest
```
## Worker Service Issues ## Worker Service Issues
### Worker Service Not Starting ### Worker Service Not Starting
**Symptoms**: Worker doesn't start, or `pm2 status` shows no processes. **Symptoms**: Worker doesn't start, or worker status shows it's not running.
**Solutions**: **Solutions**:
1. Check if PM2 is running: 1. Check worker status:
```bash ```bash
pm2 status npm run worker:status
``` ```
2. Try starting manually: 2. Try starting manually:
@@ -217,14 +196,14 @@ The skill includes comprehensive diagnostics, automated repair sequences, and de
4. Full reset: 4. Full reset:
```bash ```bash
pm2 delete claude-mem-worker npm run worker:stop
npm run worker:start npm run worker:start
``` ```
5. Verify PM2 is installed: 5. Verify Bun is installed:
```bash ```bash
which pm2 which bun
npm list pm2 bun --version
``` ```
### Port Allocation Failed ### Port Allocation Failed
@@ -256,7 +235,7 @@ The skill includes comprehensive diagnostics, automated repair sequences, and de
### Worker Keeps Crashing ### Worker Keeps Crashing
**Symptoms**: Worker restarts repeatedly, PM2 shows high restart count. **Symptoms**: Worker restarts repeatedly or fails to stay running.
**Solutions**: **Solutions**:
@@ -265,23 +244,21 @@ The skill includes comprehensive diagnostics, automated repair sequences, and de
npm run worker:logs npm run worker:logs
``` ```
2. Check memory usage: 2. Check worker status:
```bash ```bash
pm2 status npm run worker:status
``` ```
3. Increase memory limit in `ecosystem.config.cjs`: 3. Check database for corruption:
```javascript
{
max_memory_restart: '2G' // Increase if needed
}
```
4. Check database for corruption:
```bash ```bash
sqlite3 ~/.claude-mem/claude-mem.db "PRAGMA integrity_check;" sqlite3 ~/.claude-mem/claude-mem.db "PRAGMA integrity_check;"
``` ```
4. Verify Bun installation:
```bash
bun --version
```
### Worker Not Processing Observations ### Worker Not Processing Observations
**Symptoms**: Observations saved but not processed, no summaries generated. **Symptoms**: Observations saved but not processed, no summaries generated.
@@ -424,7 +401,7 @@ The skill includes comprehensive diagnostics, automated repair sequences, and de
1. Close all connections: 1. Close all connections:
```bash ```bash
pm2 stop claude-mem-worker npm run worker:stop
``` ```
2. Check for stale locks: 2. Check for stale locks:
@@ -656,29 +633,21 @@ The skill includes comprehensive diagnostics, automated repair sequences, and de
### High Memory Usage ### High Memory Usage
**Symptoms**: Worker uses too much memory, frequent restarts. **Symptoms**: Worker uses too much memory.
**Solutions**: **Solutions**:
1. Check current usage: 1. Check current usage:
```bash ```bash
pm2 status npm run worker:status
``` ```
2. Increase memory limit: 2. Restart worker:
```javascript
// In ecosystem.config.cjs
{
max_memory_restart: '2G'
}
```
3. Restart worker:
```bash ```bash
npm run worker:restart npm run worker:restart
``` ```
4. Clean up old data (see "Database Too Large" above) 3. Clean up old data (see "Database Too Large" above)
## Installation Issues ## Installation Issues
@@ -773,10 +742,10 @@ sqlite3 ~/.claude-mem/claude-mem.db "
```bash ```bash
# Check if worker is running # Check if worker is running
pm2 status npm run worker:status
# View logs # View logs
pm2 logs claude-mem-worker npm run worker:logs
# Check port file # Check port file
cat ~/.claude-mem/worker.port cat ~/.claude-mem/worker.port
+1 -1
View File
@@ -175,7 +175,7 @@ This design ensures that private content never reaches the database, search indi
1. Verify correct syntax: `<private>content</private>` 1. Verify correct syntax: `<private>content</private>`
2. Check `~/.claude-mem/silent.log` for errors 2. Check `~/.claude-mem/silent.log` for errors
3. Ensure worker is running: `pm2 list` 3. Ensure worker is running: `npm run worker:status`
4. Restart worker: `npm run worker:restart` 4. Restart worker: `npm run worker:restart`
### Partial Content Stored ### Partial Content Stored
+1 -1
View File
@@ -364,7 +364,7 @@ search_sessions with query="[YOUR PROJECT NAME]" and orderBy="date_desc"
If search isn't working, check the worker service: If search isn't working, check the worker service:
```bash ```bash
pm2 list # Check worker status npm run worker:status # Check worker status
npm run worker:restart # Restart if needed npm run worker:restart # Restart if needed
npm run worker:logs # View logs npm run worker:logs # View logs
``` ```
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+28 -3
View File
@@ -1,7 +1,7 @@
import { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync } from 'fs'; import { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync } from 'fs';
import { createWriteStream } from 'fs'; import { createWriteStream } from 'fs';
import { join } from 'path'; import { join } from 'path';
import { spawn } from 'child_process'; import { spawn, spawnSync } from 'child_process';
import { homedir } from 'os'; import { homedir } from 'os';
import { DATA_DIR } from '../../shared/paths.js'; import { DATA_DIR } from '../../shared/paths.js';
@@ -47,7 +47,23 @@ export class ProcessManager {
return this.startWithBun(workerScript, logFile, port); return this.startWithBun(workerScript, logFile, port);
} }
private static isBunAvailable(): boolean {
try {
const result = spawnSync('bun', ['--version'], { stdio: 'pipe', timeout: 5000 });
return result.status === 0;
} catch {
return false;
}
}
private static async startWithBun(script: string, logFile: string, port: number): Promise<{ success: boolean; pid?: number; error?: string }> { private static async startWithBun(script: string, logFile: string, port: number): Promise<{ success: boolean; pid?: number; error?: string }> {
if (!this.isBunAvailable()) {
return {
success: false,
error: 'Bun is required but not found in PATH. Install from https://bun.sh'
};
}
try { try {
const isWindows = process.platform === 'win32'; const isWindows = process.platform === 'win32';
@@ -129,7 +145,11 @@ export class ProcessManager {
static async isRunning(): Promise<boolean> { static async isRunning(): Promise<boolean> {
const info = this.getPidInfo(); const info = this.getPidInfo();
if (!info) return false; if (!info) return false;
return this.isProcessAlive(info.pid); const alive = this.isProcessAlive(info.pid);
if (!alive) {
this.removePidFile(); // Clean up stale PID file
}
return alive;
} }
// Helper methods // Helper methods
@@ -137,7 +157,12 @@ export class ProcessManager {
try { try {
if (!existsSync(PID_FILE)) return null; if (!existsSync(PID_FILE)) return null;
const content = readFileSync(PID_FILE, 'utf-8'); const content = readFileSync(PID_FILE, 'utf-8');
return JSON.parse(content) as PidInfo; const parsed = JSON.parse(content);
// Validate required fields have correct types
if (typeof parsed.pid !== 'number' || typeof parsed.port !== 'number') {
return null;
}
return parsed as PidInfo;
} catch { } catch {
return null; return null;
} }
@@ -21,6 +21,7 @@ import {
} from '../../../../constants/observation-metadata.js'; } from '../../../../constants/observation-metadata.js';
import { BaseRouteHandler } from '../BaseRouteHandler.js'; import { BaseRouteHandler } from '../BaseRouteHandler.js';
import { SettingsDefaultsManager } from '../../../../shared/SettingsDefaultsManager.js'; import { SettingsDefaultsManager } from '../../../../shared/SettingsDefaultsManager.js';
import { clearPortCache } from '../../../../shared/worker-utils.js';
export class SettingsRoutes extends BaseRouteHandler { export class SettingsRoutes extends BaseRouteHandler {
constructor( constructor(
@@ -162,6 +163,9 @@ export class SettingsRoutes extends BaseRouteHandler {
// Write back // Write back
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8'); writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
// Clear port cache to force re-reading from updated settings
clearPortCache();
logger.info('WORKER', 'Settings updated'); logger.info('WORKER', 'Settings updated');
res.json({ success: true, message: 'Settings updated successfully' }); res.json({ success: true, message: 'Settings updated successfully' });
}); });