Files
claude-mem/CLAUDE.md
T
Alex Newman c5e68a17c8 refactor: Clean up search architecture, remove experimental contextualize endpoint (#133)
* Refactor code structure for improved readability and maintainability

* Add test results for search API and related functionalities

- Created test result files for various search-related functionalities, including:
  - test-11-search-server-changes.json
  - test-12-context-hook-changes.json
  - test-13-worker-service-changes.json
  - test-14-patterns.json
  - test-15-gotchas.json
  - test-16-discoveries.json
  - test-17-all-bugfixes.json
  - test-18-all-features.json
  - test-19-all-decisions.json
  - test-20-session-search.json
  - test-21-prompt-search.json
  - test-22-decisions-endpoint.json
  - test-23-changes-endpoint.json
  - test-24-how-it-works-endpoint.json
  - test-25-contextualize-endpoint.json
  - test-26-timeline-around-observation.json
  - test-27-multi-param-combo.json
  - test-28-file-type-combo.json

- Each test result file captures specific search failures or outcomes, including issues with undefined properties and successful execution of search queries.
- Enhanced documentation of search architecture and testing strategies, ensuring compliance with established guidelines and improving overall search functionality.

* feat: Enhance unified search API with catch-all parameters and backward compatibility

- Implemented a unified search API at /api/search that accepts catch-all parameters for filtering by type, observation type, concepts, and files.
- Maintained backward compatibility by keeping granular endpoints functional while routing through the same infrastructure.
- Completed comprehensive testing of search capabilities with real-world query scenarios.

fix: Address missing debug output in search API query tests

- Flushed PM2 logs and executed search queries to verify functionality.
- Diagnosed absence of "Raw Chroma" debug messages in worker logs, indicating potential issues with logging or query processing.

refactor: Improve build and deployment pipeline for claude-mem plugin

- Successfully built and synced all hooks and services to the marketplace directory.
- Ensured all dependencies are installed and up-to-date in the deployment location.

feat: Implement hybrid search filters with 90-day recency window

- Enhanced search server to apply a 90-day recency filter to Chroma results before categorizing by document type.

fix: Correct parameter handling in searchUserPrompts method

- Added support for filter-only queries and improved dual-path logic for clarity.

refactor: Rename FTS5 method to clarify fallback status

- Renamed escapeFTS5 to escapeFTS5_fallback_when_chroma_unavailable to indicate its temporary usage.

feat: Introduce contextualize tool for comprehensive project overview

- Added a new tool to fetch recent observations, sessions, and user prompts, providing a quick project overview.

feat: Add semantic shortcut tools for common search patterns

- Implemented 'decisions', 'changes', and 'how_it_works' tools for convenient access to frequently searched observation categories.

feat: Unified timeline tool supports anchor and query modes

- Combined get_context_timeline and get_timeline_by_query into a single interface for timeline exploration.

feat: Unified search tool added to MCP server

- New tool queries all memory types simultaneously, providing combined chronological results for improved search efficiency.

* Refactor search functionality to clarify FTS5 fallback usage

- Updated `worker-service.cjs` to replace FTS5 fallback function with a more descriptive name and improved error handling.
- Enhanced documentation in `SKILL.md` to specify the unified API endpoint and clarify the behavior of the search engine, including the conditions under which FTS5 is used.
- Modified `search-server.ts` to provide clearer logging and descriptions regarding the fallback to FTS5 when UVX/Python is unavailable.
- Renamed and updated the `SessionSearch.ts` methods to reflect the conditions for using FTS5, emphasizing the lack of semantic understanding in fallback scenarios.

* feat: Add ID-based fetch endpoints and simplify mem-search skill

**Problem:**
- Search returns IDs but no way to fetch by ID
- Skill documentation was bloated with too many options
- Claude wasn't using IDs because we didn't tell it how

**Solution:**
1. Added three new HTTP endpoints:
   - GET /api/observation/:id
   - GET /api/session/:id
   - GET /api/prompt/:id

2. Completely rewrote SKILL.md:
   - Stripped complexity down to essentials
   - Clear 3-step prescriptive workflow: Search → Review IDs → Fetch by ID
   - Emphasized ID usage: "The IDs are there for a reason - USE THEM"
   - Removed confusing multi-endpoint documentation
   - Kept only unified search with filters

**Impact:**
- Token efficiency: Claude can now fetch full details only for relevant IDs
- Clarity: One clear workflow instead of 10+ options to choose from
- Usability: IDs are no longer wasted context - they're actionable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: Move internal docs to private directory

Moved POSTMORTEM and planning docs to ./private to exclude from PR reviews.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: Remove experimental contextualize endpoint

- Removed contextualize MCP tool from search-server (saves ~4KB)
- Disabled FTS5 fallback paths in SessionSearch (now vector-first)
- Cleaned up CLAUDE.md documentation
- Removed contextualize-rewrite-plan.md doc

Rationale:
- Contextualize is better suited as a skill (LLM-powered) than an endpoint
- Search API already provides vector search with configurable limits
- Created issue #132 to track future contextualize skill implementation

Changes:
- src/servers/search-server.ts: Removed contextualize tool definition
- src/services/sqlite/SessionSearch.ts: Disabled FTS5 fallback, added deprecation warnings
- CLAUDE.md: Cleaned up outdated skill documentation
- docs/: Removed contextualize plan document

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: Complete FTS5 cleanup - remove all deprecated search code

This completes the FTS5 cleanup work by removing all commented-out
FTS5 search code while preserving database tables for backward compatibility.

Changes:
- Removed 200+ lines of commented FTS5 search code from SessionSearch.ts
- Removed deprecated degraded_search_query__when_uvx_unavailable method
- Updated all method documentation to clarify vector-first architecture
- Updated class documentation to reflect filter-only query support
- Updated CLAUDE.md to remove FTS5 search references
- Clarified that FTS5 tables exist for backward compatibility only
- Updated "Why SQLite FTS5" section to "Why Vector-First Search"

Database impact: NONE - FTS5 tables remain intact for existing installations

Search architecture:
- ChromaDB: All text-based vector search queries
- SQLite: Filter-only queries (date ranges, metadata, no query text)
- FTS5 tables: Maintained but unused (backward compatibility)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: Remove all FTS5 fallback execution code from search-server

Completes the FTS5 cleanup by removing all fallback execution paths
that attempted to use FTS5 when ChromaDB was unavailable.

Changes:
- Removed all FTS5 fallback code execution paths
- When ChromaDB fails or is unavailable, return empty results with helpful error messages
- Updated all deprecated tool descriptions (search_observations, search_sessions, search_user_prompts)
- Changed error messages to indicate FTS5 fallback has been removed
- Added installation instructions for UVX/Python when vector search is unavailable
- Updated comments from "hybrid search" to "vector-first search"
- Removed ~100 lines of dead FTS5 fallback code

Database impact: NONE - FTS5 tables remain intact (backward compatibility)

Search behavior when ChromaDB unavailable:
- Text queries: Return empty results with error explaining ChromaDB is required
- Filter-only queries (no text): Continue to work via direct SQLite

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Address PR 133 review feedback

Critical fixes:
- Remove contextualize endpoint from worker-service (route + handler)
- Fix build script logging to show correct .cjs extension (was .mjs)

Documentation improvements:
- Add comprehensive FTS5 retention rationale documentation
- Include v7.0.0 removal TODO for future cleanup

Testing:
- Build succeeds with correct output logging
- Worker restarts successfully (30th restart)
- Contextualize endpoint properly removed (404 response)
- Search endpoint verified working

This addresses all critical review feedback from PR 133.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-21 18:59:23 -05:00

9.1 KiB

/* To @claude: be vigilant about only leaving evergreen context in this file, claude-mem handles working context separately. */

Claude-Mem: AI Development Instructions

What This Project Is

Claude-mem is a Claude Code plugin providing persistent memory across sessions. It captures tool usage, compresses observations using the Claude Agent SDK, and injects relevant context into future sessions.

Your Role: You are working on the plugin itself. When users interact with Claude Code with this plugin installed, your observations get captured and become their persistent memory.

Current Version: 6.0.9

Critical Architecture Knowledge

The Lifecycle Flow

  1. SessionStart → smart-install.js runs first (pre-hook), then context-hook.ts runs

    • Smart installer checks dependencies (cached, only runs on version changes)
    • Starts PM2 worker if not healthy
    • Injects context from previous sessions (configurable observation count)
  2. UserPromptSubmitnew-hook.ts runs

    • Creates session record in SQLite
    • Saves raw user prompt for vector search
  3. PostToolUsesave-hook.ts runs

    • Captures your tool executions
    • Sends to worker service for AI compression
  4. Summary → Summary hook generates session summaries

  5. SessionEndcleanup-hook.ts runs

    • Marks session complete (graceful, not DELETE)
    • Skips on /clear to preserve ongoing sessions

Note: smart-install.js is a pre-hook script (not a lifecycle hook). It's called before context-hook via command chaining in hooks.json and only runs when dependencies need updating.

Key Components

Hooks (src/hooks/*.ts)

  • Built to plugin/scripts/*-hook.js (ESM format)
  • Must output valid JSON to hookSpecificOutput field
  • Called by Claude Code lifecycle events

Worker Service (src/services/worker-service.ts)

  • Express.js API on port 37777 (configurable via CLAUDE_MEM_WORKER_PORT)
  • Managed by PM2 (auto-started by hooks)
  • Built to plugin/worker-service.cjs (CJS format)
  • Handles AI processing asynchronously to avoid hook timeouts

Database (src/services/sqlite/)

  • SQLite3 with better-sqlite3 (NOT bun:sqlite - that's legacy)
  • Location: ~/.claude-mem/claude-mem.db
  • FTS5 virtual tables maintained for backward compatibility (not used for search)
  • SessionStore = CRUD, SessionSearch = filter-only queries

Mem-Search Skill (plugin/skills/mem-search/SKILL.md)

  • Provides access to all search functionality via HTTP API + skill

Chroma Vector Database (src/services/sync/ChromaSync.ts)

  • Vector-first semantic search architecture
  • Automatic vector embedding synchronization
  • 90-day recency filtering for relevant results
  • SQLite provides filter-only queries for date ranges and metadata filtering

Viewer UI (src/ui/viewer/)

  • React + TypeScript web interface accessible at http://localhost:37777
  • Real-time memory stream visualization via Server-Sent Events (SSE)
  • Infinite scroll pagination for observations, sessions, and user prompts
  • Project filtering and settings persistence
  • Built to plugin/ui/viewer.html (self-contained bundle via esbuild)
  • Auto-reconnection and error recovery

How to Make Changes

When You Modify Hooks

npm run build
npm run sync-marketplace

Changes take effect on next Claude Code session. No worker restart needed.

When You Modify Worker Service

npm run build
npm run sync-marketplace
npm run worker:restart

Must restart PM2 worker for changes to take effect.

When You Modify Search Skill

npm run sync-marketplace

Skill changes take effect immediately on next Claude Code session. No build or restart needed (skills are markdown).

When You Modify Viewer UI

npm run build
npm run sync-marketplace
npm run worker:restart

Changes to React components, styles, or viewer logic require rebuilding and restarting the worker. Refresh browser to see changes.

Build Pipeline

  1. npm run build → Compiles TypeScript, outputs to plugin/
  2. npm run sync-marketplace → Syncs to ~/.claude/plugins/marketplaces/thedotmack/
  3. Changes are live for next session (hooks/skills) or after restart (worker)

Coding Standards

Philosophy: Write the dumb, obvious thing first. Add complexity only when you hit the problem.

Key Principles:

  1. YAGNI: Don't build it until you need it
  2. DRY: Extract patterns after second duplication, not before
  3. Fail Fast: Explicit errors beat silent failures
  4. Simple First: Write the obvious solution, optimize only if needed
  5. Delete Aggressively: Less code = fewer bugs
  6. Semantic Naming: Always name variables, parameters, and API endpoints with verbose, self-documenting names that optimize for comprehension by both humans and LLMs, not brevity (e.g., wait_until_obs_is_saved=true vs wait=true)

Common anti-patterns to avoid:

  • Ceremonial wrapper functions for constants (just export the constant)
  • Unused default parameters (remove if never used)
  • Magic numbers without named constants
  • Silent failures instead of explicit errors
  • Fragile string parsing (use structured JSON output)
  • Copy-pasted promise wrappers (extract helper functions)
  • Overengineered "defensive" code for problems you don't have

Common Tasks

Adding a New Hook

  1. Create src/hooks/new-hook.ts
  2. Add to scripts/build-hooks.js build list
  3. Add configuration to plugin/hooks/hooks.json
  4. Build and sync: npm run build && npm run sync-marketplace

Note: smart-install.js is not a hook - it's a pre-hook dependency checker that runs before context-hook via command chaining.

Modifying Database Schema

  1. Update schema in src/services/sqlite/schema.ts
  2. Update SessionStore/SessionSearch classes
  3. Migration strategy: The plugin currently recreates on schema changes (alpha phase). Production deployments will require proper migration handling.

Debugging Worker Issues

pm2 list                    # Check worker status
npm run worker:logs         # View logs
npm run worker:restart      # Restart if needed
pm2 delete claude-mem-worker # Force clean start

Testing Changes Locally

  1. Make changes in src/
  2. npm run build && npm run sync-marketplace
  3. Start new Claude Code session (hooks) or restart worker (worker changes)
  4. Check ~/.claude-mem/claude-mem.db for database state
  5. Use mem-search skill to verify behavior (auto-invoked when asking about past work)

Version Bumps

Use the version-bump skill (auto-invokes when requesting version updates). It handles:

  • Semantic version increments (patch/minor/major)
  • Updates all version references (package.json, plugin.json, CLAUDE.md, marketplace.json)
  • Creates git tags and GitHub releases
  • Auto-generates CHANGELOG.md from releases

Investigation Best Practices

When investigations fail persistently, use Task agents for comprehensive file analysis instead of repeated grep/search. Deploy agents to read full files and answer specific questions - more efficient than multiple rounds of searching.

Environment Variables

  • CLAUDE_MEM_MODEL - Model for observations/summaries (default: claude-haiku-4-5)
  • CLAUDE_MEM_CONTEXT_OBSERVATIONS - Observations injected at SessionStart (default: 50)
  • CLAUDE_MEM_WORKER_PORT - Worker service port (default: 37777)

Key Design Decisions

Why PM2 Instead of Direct Process

Hooks have strict timeout limits. PM2 manages a persistent background worker, allowing AI processing to continue after hooks complete.

Why Vector-First Search (ChromaDB)

Enables semantic search that understands meaning, not just keywords. ChromaDB handles all text queries. SQLite provides filter-only queries for date ranges and metadata that vector databases can't handle efficiently. FTS5 tables exist for backward compatibility but are no longer used.

Why Graceful Cleanup

Changed from aggressive DELETE requests to marking sessions complete. Prevents interrupting summary generation and other async operations.

Why Smart Install Caching

npm install is expensive (2-5s). Caching version state and only installing on changes makes SessionStart nearly instant (10ms).

Why Web-Based Viewer UI

Real-time visibility into memory stream helps users understand what's being captured and how context is being built. SSE provides instant updates without polling. Self-contained HTML bundle (esbuild) eliminates deployment complexity - everything served from a single file.

File Locations

Source: <project-root>/src/ - TypeScript source files Built Plugin: <project-root>/plugin/ - Compiled JavaScript outputs Installed Plugin: ~/.claude/plugins/marketplaces/thedotmack/ - User's installed plugin location Database: ~/.claude-mem/claude-mem.db - SQLite database with observations, sessions, summaries Chroma Database: ~/.claude-mem/chroma/ - Vector embeddings for semantic search Usage Logs: ~/.claude-mem/usage-logs/usage-YYYY-MM-DD.jsonl - Daily API usage tracking

Quick Reference

Build: npm run build Sync: npm run sync-marketplace Worker Restart: npm run worker:restart Worker Logs: npm run worker:logs Usage Analysis: npm run usage:today Viewer UI: http://localhost:37777 (auto-starts with worker)