Releases: thedotmack/claude-mem
v10.3.1
Fix: Prevent Duplicate Worker Daemons and Zombie Processes
Three root causes of chroma-mcp timeouts identified and fixed:
PID-based daemon guard
Exit immediately on startup if PID file points to a live process. Prevents the race condition where hooks firing simultaneously could start multiple daemons before either wrote a PID file.
Port-based daemon guard
Exit if port 37777 is already bound — runs before WorkerService constructor registers keepalive signal handlers that previously prevented exit on EADDRINUSE.
Guaranteed process.exit() after HTTP shutdown
HTTP shutdown (POST /api/admin/shutdown) now calls process.exit(0) in a try/finally block. Previously, zombie workers stayed alive after shutdown, and background tasks reconnected to chroma-mcp, spawning duplicate subprocesses contending for the same data directory.
v10.3.0
Replace WASM Embeddings with Persistent chroma-mcp MCP Connection
Highlights
- New: ChromaMcpManager — Singleton stdio MCP client communicating with chroma-mcp via
uvx, replacing the previous ChromaServerManager (npx chroma run+chromadbnpm + ONNX/WASM) - Eliminates native binary issues — No more segfaults, WASM embedding failures, or cross-platform install headaches
- Graceful subprocess lifecycle — Wired into GracefulShutdown for clean teardown; zombie process prevention with kill-on-failure and stale
onclosehandler guards - Connection backoff — 10-second reconnect backoff prevents chroma-mcp spawn storms
- SQL injection guards — Added parameterization to ChromaSync ID exclusion queries
- Simplified ChromaSync — Reduced complexity by delegating embedding concerns to chroma-mcp
Breaking Changes
None — backward compatible. ChromaDB data is preserved; only the connection mechanism changed.
Files Changed
src/services/sync/ChromaMcpManager.ts(new) — MCP client singletonsrc/services/sync/ChromaServerManager.ts(deleted) — Old WASM/native approachsrc/services/sync/ChromaSync.ts— Simplified to use MCP clientsrc/services/worker-service.ts— Updated startup sequencesrc/services/infrastructure/GracefulShutdown.ts— Subprocess cleanup integration
v10.2.6
Bug Fixes
Zombie Process Prevention (#1168, #1175)
Observer Claude CLI subprocesses were accumulating as zombies — processes that never exited after their session ended, causing massive resource leaks on long-running systems.
Root cause: When observer sessions ended (via idle timeout, abort, or error), the spawned Claude CLI subprocesses were not being reliably killed. The existing ensureProcessExit() in SDKAgent only covered the happy path; sessions terminated through SessionRoutes or worker-service bypassed process cleanup entirely.
Fix — dual-layer approach:
- Immediate cleanup: Added
ensureProcessExit()calls to thefinallyblocks in bothSessionRoutes.tsandworker-service.ts, ensuring every session exit path kills its subprocess - Periodic reaping: Added
reapStaleSessions()toSessionManager— a background interval that scans~/.claude-mem/observer-sessions/for stale PID files, verifies the process is still running, and kills any orphans with SIGKILL escalation
This ensures no observer subprocess survives beyond its session lifetime, even in crash scenarios.
v10.2.5
Bug Fixes
- Self-healing message queue: Renamed
claimAndDelete→claimNextMessagewith atomic self-healing — automatically resets stale processing messages (>60s) back to pending before claiming, eliminating stuck messages from generator crashes without external timers - Removed redundant idle-timeout reset: The
resetStaleProcessingMessages()call during idle timeout in worker-service was removed (startup reset kept), since the atomic self-healing inclaimNextMessagenow handles recovery inline - TypeScript diagnostic fix: Added
QUEUEto loggerComponenttype
Tests
- 5 new tests for self-healing behavior (stuck recovery, active protection, atomicity, empty queue, session isolation)
- 1 new integration test for stuck recovery in zombie-prevention suite
- All existing queue tests updated for renamed method
v10.2.4
Chroma Vector DB Backfill Fix
Fixes the Chroma backfill system to correctly sync all SQLite observations into the vector database on worker startup.
Bug Fixes
-
Backfill all projects on startup —
backfillAllProjects()now runs on worker startup, iterating all projects in SQLite and syncing missing observations to Chroma. PreviouslyensureBackfilled()existed but was never called, leaving Chroma with incomplete data after cache clears. -
Fixed critical collection routing bug — Backfill now uses the shared
cm__claude-memcollection (matching how DatabaseManager and SearchManager operate) instead of creating per-project orphan collections that no search path reads from. -
Hardened collection name sanitization — Project names with special characters (e.g., "YC Stuff") are sanitized for Chroma's naming constraints, including stripping trailing non-alphanumeric characters.
-
Eliminated shared mutable state —
ensureBackfilled()andgetExistingChromaIds()now accept project as a parameter instead of mutating instance state, keeping a single Chroma connection while avoiding fragile property mutation across iterations. -
Chroma readiness guard — Backfill waits for Chroma server readiness before running, preventing spurious error logs when Chroma fails to start.
Changed Files
src/services/sync/ChromaSync.ts— Core backfill logic, sanitization, parameter passingsrc/services/worker-service.ts— Startup backfill trigger + readiness guardsrc/utils/logger.ts— AddedCHROMA_SYNClog component
v10.2.3
Fix Chroma ONNX Model Cache Corruption
Addresses the persistent embedding pipeline failures reported across #1104, #1105, #1110, and subsequent sessions. Three root causes identified and fixed:
Changes
- Removed nuclear
bun pm cache rmfrom bothsmart-install.jsandsync-marketplace.cjs. This was added in v10.2.2 for the now-removed sharp dependency but destroyed all cached packages, breaking the ONNX resolution chain. - Added
bun installin plugin cache directory after marketplace sync. The cache directory had apackage.jsonwith@chroma-core/default-embedas a dependency but never ran install, so the worker couldn't resolve it at runtime. - Moved HuggingFace model cache to
~/.claude-mem/models/outsidenode_modules. The ~23MB ONNX model was stored insidenode_modules/@huggingface/transformers/.cache/, so any reinstall or cache clear corrupted it. - Added self-healing retry for Protobuf parsing failures. If the downloaded model is corrupted, the cache is cleared and re-downloaded automatically on next use.
Files Changed
scripts/smart-install.js— removedbun pm cache rmscripts/sync-marketplace.cjs— removedbun pm cache rm, addedbun installin cache dirsrc/services/sync/ChromaSync.ts— moved model cache, added corruption recovery
v10.2.2
Bug Fixes
- Removed
node-addon-apidev dependency — was only needed forsharp, which was already removed in v10.2.1 - Simplified native module cache clearing in
smart-install.jsandsync-marketplace.cjs— replaced targeted@img/sharpdirectory deletion and lockfile removal withbun pm cache rm - Reduced ~30 lines of brittle file system manipulation to a clean Bun CLI command
v10.2.1
Bug Fixes
- Bun install & sharp native modules: Fixed stale native module cache issues on Bun updates, added
node-addon-apias a dev dependency required by sharp (#1140) - PendingMessageStore consolidation: Deduplicated PendingMessageStore initialization in worker-service; added session-scoped filtering to
resetStaleProcessingMessagesto prevent cross-session message resets (#1140) - Gemini empty response handling: Fixed silent message deletion when Gemini returns empty summary responses — now logs a warning and preserves the original message (#1138)
- Idle timeout session scoping: Fixed idle timeout handler to only reset messages for the timed-out session instead of globally resetting all sessions (#1138)
- Shell injection in sync-marketplace: Replaced
execSyncwithspawnSyncfor rsync calls to eliminate command injection via gitignore patterns (#1138) - Sharp cache invalidation: Added cache clearing for sharp's native bindings when Bun version changes (#1138)
- Marketplace install: Switched marketplace sync from npm to bun for package installation consistency (#1140)
v10.1.0
SessionStart System Message & Cleaner Defaults
New Features
-
SessionStart
systemMessagesupport — Hooks can now display user-visible ANSI-colored messages directly in the CLI via a newsystemMessagefield onHookResult. The SessionStart hook uses this to render a colored timeline summary (separate from the markdown context injected for Claude), giving users an at-a-glance view of recent activity every time they start a session. -
"View Observations Live" link — Each session start now appends a clickable
http://localhost:{port}URL so users can jump straight to the live observation viewer.
Performance
- Truly parallel context fetching — The SessionStart handler now uses
Promise.allto fetch both the markdown context (for Claude) and the ANSI-colored timeline (for user display) simultaneously, eliminating the serial fetch overhead.
Defaults Changes
-
Cleaner out-of-box experience — New installs now default to a streamlined context display:
- Read tokens column: hidden (
CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS: false) - Work tokens column: hidden (
CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS: false) - Savings amount: hidden (
CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT: false) - Full observation expansion: disabled (
CLAUDE_MEM_CONTEXT_FULL_COUNT: 0) - Savings percentage remains visible by default
Existing users are unaffected — your
~/.claude-mem/settings.jsonoverrides these defaults. - Read tokens column: hidden (
Technical Details
- Added
systemMessage?: stringtoHookResultinterface (src/cli/types.ts) - Claude Code adapter now forwards
systemMessagein hook output (src/cli/adapters/claude-code.ts) - Context handler refactored for parallel fetch with graceful fallback (
src/cli/handlers/context.ts) - Default settings tuned in
SettingsDefaultsManager(src/shared/SettingsDefaultsManager.ts)
v10.0.8
Bug Fixes
Orphaned Subprocess Cleanup
- Add explicit subprocess cleanup after SDK query loop using existing
ProcessRegistryinfrastructure (getProcessBySession+ensureProcessExit), preventing orphaned Claude subprocesses from accumulating - Closes #1010, #1089, #1090, #1068
Chroma Binary Resolution
- Replace
npx chroma runwith absolute binary path resolution viarequire.resolve, falling back tonpxwith explicitcwdwhen the binary isn't found directly - Closes #1120