* feat: add smart-file-read module for token-optimized semantic code search
- Created package.json for the smart-file-read module with dependencies and scripts.
- Implemented parser.ts for code structure parsing using tree-sitter, supporting multiple languages.
- Developed search.ts for searching code files and symbols with grep-style and structural matching.
- Added test-run.mjs for testing search and outline functionalities.
- Configured TypeScript with tsconfig.json for strict type checking and module resolution.
* fix: update .gitignore to include _tree-sitter and remove unused subproject
* feat: add preliminary results and skill recommendation for smart-explore module
* chore: remove outdated plan.md file detailing session start hook issues
* feat: update Smart File Read integration plan and skill documentation for smart-explore
* feat: migrate Smart File Read to web-tree-sitter WASM for cross-platform compatibility
* refactor: switch to tree-sitter CLI for parsing and enhance search functionality
- Updated `parser.ts` to utilize the tree-sitter CLI for AST extraction instead of native bindings, improving compatibility and performance.
- Removed grammar loading logic and replaced it with a path resolution for grammar packages.
- Implemented batch parsing in `parseFilesBatch` to handle multiple files in a single CLI call, enhancing search speed.
- Refactored `searchCodebase` to collect files and parse them in batches, streamlining the search process.
- Adjusted symbol extraction logic to accommodate the new parsing method and ensure accurate symbol matching.
* feat: update Smart File Read integration plan to utilize tree-sitter CLI for improved performance and cross-platform compatibility
* feat: add smart-file-read parser and search to src/services
Copy validated tree-sitter CLI-based parser and search modules from
smart-file-read prototype into the claude-mem source tree for MCP
tool integration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: register smart_search, smart_unfold, smart_outline MCP tools
Add 3 tree-sitter AST-based code exploration tools to the MCP server.
Direct execution (no HTTP delegation) — they call parser/search
functions directly for sub-second response times.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add tree-sitter CLI deps to build system and plugin runtime
Externalize tree-sitter packages in esbuild MCP server build. Add
10 grammar packages + CLI to plugin package.json for runtime install.
Remove unused @chroma-core/default-embed from plugin deps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: create smart-explore skill with 3-layer workflow docs
Progressive disclosure workflow: search -> outline -> unfold.
Documents all 3 MCP tools with parameters and token economics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add comprehensive documentation for the smart-explore feature
- Introduced a detailed technical reference covering the architecture, parser, search engine, and tool registration for the smart-explore feature in claude-mem.
- Documented the three-layer workflow: search, outline, and unfold, along with their respective MCP tools.
- Explained the parsing process using tree-sitter, including language support, query patterns, and symbol extraction.
- Outlined the search module's functionality, including file discovery, batch parsing, and relevance scoring.
- Provided insights into build system integration and token economics for efficient code exploration.
* chore: remove experiment artifacts, prototypes, and plan files
Remove A/B test docs, prototype smart-file-read directory, and
implementation plans. Keep only production code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: simplify hooks configuration and remove setup script
* fix: use execFileSync to prevent command injection in tree-sitter parser
Replaces execSync shell string with execFileSync + argument array,
eliminating shell interpretation of file paths. Also corrects
file_pattern description from "Glob pattern" to "Substring filter".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: replace WASM embeddings with persistent chroma-mcp MCP connection
Replace ChromaServerManager (npx chroma run + chromadb npm + ONNX/WASM)
with ChromaMcpManager, a singleton stdio MCP client that communicates with
chroma-mcp via uvx. This eliminates native binary issues, segfaults, and
WASM embedding failures that plagued cross-platform installs.
Key changes:
- Add ChromaMcpManager: singleton MCP client with lazy connect, auto-reconnect,
connection lock, and Zscaler SSL cert support
- Rewrite ChromaSync to use MCP tool calls instead of chromadb npm client
- Handle chroma-mcp's non-JSON responses (plain text success/error messages)
- Treat "collection already exists" as idempotent success
- Wire ChromaMcpManager into GracefulShutdown for clean subprocess teardown
- Delete ChromaServerManager (no longer needed)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address PR review — connection guard leak, timer leak, async reset
- Clear connecting guard in finally block to prevent permanent reconnection block
- Clear timeout after successful connection to prevent timer leak
- Make reset() async to await stop() before nullifying instance
- Delete obsolete chroma-server-manager test (imports deleted class)
- Update graceful-shutdown test to use chromaMcpManager property name
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: prevent chroma-mcp spawn storm — zombie cleanup, stale onclose guard, reconnect backoff
Three bugs caused chroma-mcp processes to accumulate (92+ observed):
1. Zombie on timeout: failed connections left subprocess alive because
only the timer was cleared, not the transport. Now catch block
explicitly closes transport+client before rethrowing.
2. Stale onclose race: old transport's onclose handler captured `this`
and overwrote the current connection reference after reconnect,
orphaning the new subprocess. Now guarded with reference check.
3. No backoff: every failure triggered immediate reconnect. With
backfill doing hundreds of MCP calls, this created rapid-fire
spawning. Added 10s backoff on both connection failure and
unexpected process death.
Also includes ChromaSync fixes from PR review:
- queryChroma deduplication now preserves index-aligned arrays
- SQL injection guard on backfill ID exclusion lists
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sharp was an explicit dependency but nothing in the codebase imports it.
Chroma embeddings use ONNX Runtime via @chroma-core/default-embed, not sharp.
Sharp's native binary has a persistent Bun node_modules layout bug where
@img/sharp-libvips-* isn't placed alongside @img/sharp-darwin-* causing
ERR_DLOPEN_FAILED on every install.
- Remove sharp, @img/sharp-libvips-darwin-arm64, node-gyp from deps
- Remove node-addon-api from devDeps
- Remove @img cache clearing hacks from smart-install.js and sync-marketplace.cjs
- Replace with simple `bun pm cache rm` before install as general cache hygiene
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use bun install in sync, add node-addon-api for sharp, consolidate PendingMessageStore
- Switch sync-marketplace from npm to bun install
- Add node-addon-api as dev dep so sharp builds under bun
- Consolidate duplicate PendingMessageStore instantiation in worker-service finally block
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* build assets
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Chroma requires client-side embeddings — the server is storage only.
The previous commit incorrectly removed @chroma-core/default-embed.
Uses DefaultEmbeddingFunction({ wasm: true }) which forces the WASM
backend instead of native ONNX binaries. Same model (all-MiniLM-L6-v2),
same embeddings, but works on all platforms without segfaults or
ENOENT errors (#1104, #1105, #1110).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve conflicts between Chroma HTTP server PR and main branch changes
(folder CLAUDE.md, exclusion settings, Zscaler SSL, transport cleanup).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add docs/i18n/README.zh-tw.md with Taiwan Traditional Chinese translation
- Update language links in README.md and all i18n translations
- Add 🇹🇼 繁體中文 link after 🇨🇳 中文 in language selector
PR #896 identified a valid XSS concern in TerminalPreview.tsx but was
broken (missing DOMPurify import and dependency). The existing
escapeXML:true on AnsiToHtml already mitigates the vector, but
DOMPurify adds defense-in-depth sanitization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Includes PR #745 isolated credentials fix - prevents API key hijacking
from random project .env files by using centralized credentials from
~/.claude-mem/.env
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: add idle timeout to prevent zombie observer processes
Root cause fix for zombie observer accumulation. The SessionQueueProcessor
iterator now exits gracefully after 3 minutes of inactivity instead of
waiting forever for messages.
Changes:
- Add IDLE_TIMEOUT_MS constant (3 minutes)
- waitForMessage() now returns boolean and accepts timeout parameter
- createIterator() tracks lastActivityTime and exits on idle timeout
- Graceful exit via return (not throw) allows SDK to complete cleanly
This addresses the root cause that PR #848 worked around with pattern
matching. Observer processes now self-terminate, preventing accumulation
when session-complete hooks don't fire.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: trigger abort on idle timeout to actually kill subprocess
The previous implementation only returned from the iterator on idle timeout,
but this doesn't terminate the Claude subprocess - it just stops yielding
messages. The subprocess stays alive as a zombie because:
1. Returning from createIterator() ends the generator
2. The SDK closes stdin via transport.endInput()
3. But the subprocess may not exit on stdin EOF
4. No abort signal is sent to kill it
Fix: Add onIdleTimeout callback that SessionManager uses to call
session.abortController.abort(). This sends SIGTERM to the subprocess
via the SDK's ProcessTransport abort handler.
Verified by Codex analysis of the SDK internals:
- abort() triggers ProcessTransport abort handler → SIGTERM
- transport.close() sends SIGTERM → escalates to SIGKILL after 5s
- Just closing stdin is NOT sufficient to guarantee subprocess exit
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: add idle timeout to prevent zombie observer processes
Also cleaned up hooks.json to remove redundant start commands.
The hook command handler now auto-starts the worker if not running,
which is how it should have been since we changed to auto-start.
This maintenance change was done manually.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: resolve race condition in session queue idle timeout detection
- Reset timer on spurious wakeup when queue is empty but duration check fails
- Use optional chaining for onIdleTimeout callback
- Include threshold value in idle timeout log message for better diagnostics
- Add comprehensive unit tests for SessionQueueProcessor
Fixes PR #856 review feedback.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: migrate installer to Setup hook
- Add plugin/scripts/setup.sh for one-time dependency setup
- Add Setup hook to hooks.json (triggers via claude --init)
- Remove smart-install.js from SessionStart hook
- Keep smart-install.js as manual fallback for Windows/auto-install
Setup hook handles:
- Bun detection with fallback locations
- uv detection (optional, for Chroma)
- Version marker to skip redundant installs
- Clear error messages with install instructions
* feat: add np for one-command npm releases
- Add np as dev dependency
- Add release, release:patch, release:minor, release:major scripts
- Add prepublishOnly hook to run build before publish
- Configure np (no yarn, include all contents, run tests)
* fix: reduce PostToolUse hook timeout to 30s
PostToolUse runs on every tool call, 120s was excessive and could cause
hangs. Reduced to 30s for responsive behavior.
* docs: add PR shipping report
Analyzed 6 PRs for shipping readiness:
- #856: Ready to merge (idle timeout fix)
- #700, #722, #657: Have conflicts, need rebase
- #464: Contributor PR, too large (15K+ lines)
- #863: Needs manual review
Includes shipping strategy and conflict resolution order.
* MAESTRO: Verify PR #856 test suite passes
All 797 tests pass (3 skipped, 0 failures). The 11 SessionQueueProcessor
idle timeout tests all pass with 20 expect() assertions verified.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* MAESTRO: Verify PR #856 build passes
- Ran npm run build successfully with no TypeScript errors
- All artifacts generated (worker-service, mcp-server, context-generator, viewer UI)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* MAESTRO: Code review PR #856 implementation verified
Verified all requirements in SessionQueueProcessor.ts:
- IDLE_TIMEOUT_MS = 180000ms (3 minutes)
- waitForMessage() accepts timeout parameter
- lastActivityTime reset on spurious wakeup (race condition fix)
- Graceful exit logs include thresholdMs parameter
- 11 comprehensive test cases in SessionQueueProcessor.test.ts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: bigph00t <166455923+bigph00t@users.noreply.github.com>
Co-authored-by: root <root@srv1317155.hstgr.cloud>
- Added @chroma-core/default-embed dependency for local embeddings
- Updated ChromaSync to use DefaultEmbeddingFunction with collections
- Added isServerReachable() async method for reliable server detection
- Fixed start() to detect and reuse existing Chroma servers
- Updated build script to externalize native ONNX binaries
- Added runtime dependency to plugin/package.json
The embedding function uses all-MiniLM-L6-v2 model locally via ONNX,
eliminating need for external embedding API calls.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated chromadb from ^1.9.2 to ^3.2.2 (includes CLI binary)
- Changed heartbeat endpoint from /api/v1 to /api/v2
The 1.9.x version did not include the CLI, causing `npx chroma run` to fail.
Version 3.2.2 includes the chroma CLI and uses the v2 API.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace MCP subprocess approach with persistent Chroma HTTP server for
improved performance and reliability. This re-enables Chroma on Windows
by eliminating the subprocess spawning that caused console popups.
Changes:
- NEW: ChromaServerManager.ts - Manages local Chroma server lifecycle
via `npx chroma run`
- REFACTOR: ChromaSync.ts - Uses chromadb npm package's ChromaClient
instead of MCP subprocess (removes Windows disabling)
- UPDATE: worker-service.ts - Starts Chroma server on initialization
- UPDATE: GracefulShutdown.ts - Stops Chroma server on shutdown
- UPDATE: SettingsDefaultsManager.ts - New Chroma configuration options
- UPDATE: build-hooks.js - Mark optional chromadb deps as external
Benefits:
- Eliminates subprocess spawn latency on first query
- Single server process instead of per-operation subprocesses
- No Python/uvx dependency for local mode
- Re-enables Chroma vector search on Windows
- Future-ready for cloud-hosted Chroma (claude-mem pro)
- Cross-platform: Linux, macOS, Windows
Configuration:
CLAUDE_MEM_CHROMA_MODE=local|remote
CLAUDE_MEM_CHROMA_HOST=127.0.0.1
CLAUDE_MEM_CHROMA_PORT=8000
CLAUDE_MEM_CHROMA_SSL=false
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>