Add installation, troubleshooting, and usage documentation for Claude-Mem plugin
- Created comprehensive installation guide detailing quick start, system requirements, and advanced installation steps. - Developed troubleshooting guide addressing common issues with worker service, hooks, database, and search tools. - Introduced getting started documentation explaining automatic operation, session summaries, and context injection. - Added detailed usage instructions for MCP search tools, including query examples and advanced filtering techniques.
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
# Database Architecture
|
||||
|
||||
Claude-Mem uses SQLite 3 with the better-sqlite3 native module for persistent storage and FTS5 for full-text search.
|
||||
|
||||
## Database Location
|
||||
|
||||
- **Current**: `~/.claude-mem/claude-mem.db`
|
||||
|
||||
**Note**: Despite the README claiming v4.0.0+ moved the database to `${CLAUDE_PLUGIN_ROOT}/data/`, the actual implementation still uses `~/.claude-mem/`.
|
||||
|
||||
## Database Implementation
|
||||
|
||||
**Primary Implementation**: better-sqlite3 (native SQLite module)
|
||||
- Used by: SessionStore and SessionSearch
|
||||
- Format: Synchronous API with better performance
|
||||
- **Note**: Database.ts (using bun:sqlite) is legacy code
|
||||
|
||||
## Core Tables
|
||||
|
||||
### 1. sdk_sessions
|
||||
|
||||
Tracks active and completed sessions.
|
||||
|
||||
```sql
|
||||
CREATE TABLE sdk_sessions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sdk_session_id TEXT UNIQUE NOT NULL,
|
||||
claude_session_id TEXT,
|
||||
project TEXT NOT NULL,
|
||||
prompt_counter INTEGER DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
created_at TEXT NOT NULL,
|
||||
created_at_epoch INTEGER NOT NULL,
|
||||
completed_at TEXT,
|
||||
completed_at_epoch INTEGER,
|
||||
last_activity_at TEXT,
|
||||
last_activity_epoch INTEGER
|
||||
);
|
||||
```
|
||||
|
||||
**Indexes**:
|
||||
- `idx_sdk_sessions_claude_session` on `claude_session_id`
|
||||
- `idx_sdk_sessions_project` on `project`
|
||||
- `idx_sdk_sessions_status` on `status`
|
||||
- `idx_sdk_sessions_created_at` on `created_at_epoch DESC`
|
||||
|
||||
### 2. observations
|
||||
|
||||
Individual tool executions with hierarchical structure.
|
||||
|
||||
```sql
|
||||
CREATE TABLE observations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id TEXT NOT NULL,
|
||||
sdk_session_id TEXT NOT NULL,
|
||||
claude_session_id TEXT,
|
||||
project TEXT NOT NULL,
|
||||
prompt_number INTEGER,
|
||||
tool_name TEXT NOT NULL,
|
||||
correlation_id TEXT,
|
||||
|
||||
-- Hierarchical fields
|
||||
title TEXT,
|
||||
subtitle TEXT,
|
||||
narrative TEXT,
|
||||
text TEXT,
|
||||
facts TEXT,
|
||||
concepts TEXT,
|
||||
type TEXT,
|
||||
files_read TEXT,
|
||||
files_modified TEXT,
|
||||
|
||||
created_at TEXT NOT NULL,
|
||||
created_at_epoch INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY (sdk_session_id) REFERENCES sdk_sessions(sdk_session_id)
|
||||
);
|
||||
```
|
||||
|
||||
**Observation Types**:
|
||||
- `decision` - Architectural or design decisions
|
||||
- `bugfix` - Bug fixes and corrections
|
||||
- `feature` - New features or capabilities
|
||||
- `refactor` - Code refactoring and cleanup
|
||||
- `discovery` - Learnings about the codebase
|
||||
- `change` - General changes and modifications
|
||||
|
||||
**Indexes**:
|
||||
- `idx_observations_session` on `session_id`
|
||||
- `idx_observations_sdk_session` on `sdk_session_id`
|
||||
- `idx_observations_project` on `project`
|
||||
- `idx_observations_tool_name` on `tool_name`
|
||||
- `idx_observations_created_at` on `created_at_epoch DESC`
|
||||
- `idx_observations_type` on `type`
|
||||
|
||||
### 3. session_summaries
|
||||
|
||||
AI-generated session summaries (multiple per session).
|
||||
|
||||
```sql
|
||||
CREATE TABLE session_summaries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sdk_session_id TEXT NOT NULL,
|
||||
claude_session_id TEXT,
|
||||
project TEXT NOT NULL,
|
||||
prompt_number INTEGER,
|
||||
|
||||
-- Summary fields
|
||||
request TEXT,
|
||||
investigated TEXT,
|
||||
learned TEXT,
|
||||
completed TEXT,
|
||||
next_steps TEXT,
|
||||
notes TEXT,
|
||||
|
||||
created_at TEXT NOT NULL,
|
||||
created_at_epoch INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY (sdk_session_id) REFERENCES sdk_sessions(sdk_session_id)
|
||||
);
|
||||
```
|
||||
|
||||
**Indexes**:
|
||||
- `idx_session_summaries_sdk_session` on `sdk_session_id`
|
||||
- `idx_session_summaries_project` on `project`
|
||||
- `idx_session_summaries_created_at` on `created_at_epoch DESC`
|
||||
|
||||
### 4. user_prompts
|
||||
|
||||
Raw user prompts with FTS5 search (as of v4.2.0).
|
||||
|
||||
```sql
|
||||
CREATE TABLE user_prompts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sdk_session_id TEXT NOT NULL,
|
||||
claude_session_id TEXT,
|
||||
project TEXT NOT NULL,
|
||||
prompt_number INTEGER,
|
||||
prompt_text TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL,
|
||||
created_at_epoch INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY (sdk_session_id) REFERENCES sdk_sessions(sdk_session_id)
|
||||
);
|
||||
```
|
||||
|
||||
**Indexes**:
|
||||
- `idx_user_prompts_sdk_session` on `sdk_session_id`
|
||||
- `idx_user_prompts_project` on `project`
|
||||
- `idx_user_prompts_created_at` on `created_at_epoch DESC`
|
||||
|
||||
### Legacy Tables
|
||||
|
||||
- **sessions**: Legacy session tracking (v3.x)
|
||||
- **memories**: Legacy compressed memory chunks (v3.x)
|
||||
- **overviews**: Legacy session summaries (v3.x)
|
||||
|
||||
## FTS5 Full-Text Search
|
||||
|
||||
SQLite FTS5 (Full-Text Search) virtual tables enable fast full-text search across observations, summaries, and user prompts.
|
||||
|
||||
### FTS5 Virtual Tables
|
||||
|
||||
#### observations_fts
|
||||
|
||||
```sql
|
||||
CREATE VIRTUAL TABLE observations_fts USING fts5(
|
||||
title,
|
||||
subtitle,
|
||||
narrative,
|
||||
text,
|
||||
facts,
|
||||
concepts,
|
||||
content='observations',
|
||||
content_rowid='id'
|
||||
);
|
||||
```
|
||||
|
||||
#### session_summaries_fts
|
||||
|
||||
```sql
|
||||
CREATE VIRTUAL TABLE session_summaries_fts USING fts5(
|
||||
request,
|
||||
investigated,
|
||||
learned,
|
||||
completed,
|
||||
next_steps,
|
||||
notes,
|
||||
content='session_summaries',
|
||||
content_rowid='id'
|
||||
);
|
||||
```
|
||||
|
||||
#### user_prompts_fts
|
||||
|
||||
```sql
|
||||
CREATE VIRTUAL TABLE user_prompts_fts USING fts5(
|
||||
prompt_text,
|
||||
content='user_prompts',
|
||||
content_rowid='id'
|
||||
);
|
||||
```
|
||||
|
||||
### Automatic Synchronization
|
||||
|
||||
FTS5 tables stay in sync via triggers:
|
||||
|
||||
```sql
|
||||
-- Insert trigger example
|
||||
CREATE TRIGGER observations_ai AFTER INSERT ON observations BEGIN
|
||||
INSERT INTO observations_fts(rowid, title, subtitle, narrative, text, facts, concepts)
|
||||
VALUES (new.id, new.title, new.subtitle, new.narrative, new.text, new.facts, new.concepts);
|
||||
END;
|
||||
|
||||
-- Update trigger example
|
||||
CREATE TRIGGER observations_au AFTER UPDATE ON observations BEGIN
|
||||
INSERT INTO observations_fts(observations_fts, rowid, title, subtitle, narrative, text, facts, concepts)
|
||||
VALUES('delete', old.id, old.title, old.subtitle, old.narrative, old.text, old.facts, old.concepts);
|
||||
INSERT INTO observations_fts(rowid, title, subtitle, narrative, text, facts, concepts)
|
||||
VALUES (new.id, new.title, new.subtitle, new.narrative, new.text, new.facts, new.concepts);
|
||||
END;
|
||||
|
||||
-- Delete trigger example
|
||||
CREATE TRIGGER observations_ad AFTER DELETE ON observations BEGIN
|
||||
INSERT INTO observations_fts(observations_fts, rowid, title, subtitle, narrative, text, facts, concepts)
|
||||
VALUES('delete', old.id, old.title, old.subtitle, old.narrative, old.text, old.facts, old.concepts);
|
||||
END;
|
||||
```
|
||||
|
||||
### FTS5 Query Syntax
|
||||
|
||||
FTS5 supports rich query syntax:
|
||||
|
||||
- **Simple**: `"error handling"`
|
||||
- **AND**: `"error" AND "handling"`
|
||||
- **OR**: `"bug" OR "fix"`
|
||||
- **NOT**: `"bug" NOT "feature"`
|
||||
- **Phrase**: `"'exact phrase'"`
|
||||
- **Column**: `title:"authentication"`
|
||||
|
||||
### Security
|
||||
|
||||
As of v4.2.3, all FTS5 queries are properly escaped to prevent SQL injection:
|
||||
- Double quotes are escaped: `query.replace(/"/g, '""')`
|
||||
- Comprehensive test suite with 332 injection attack tests
|
||||
|
||||
## Database Classes
|
||||
|
||||
### SessionStore
|
||||
|
||||
CRUD operations for sessions, observations, summaries, and user prompts.
|
||||
|
||||
**Location**: `src/services/sqlite/SessionStore.ts`
|
||||
|
||||
**Methods**:
|
||||
- `createSession()`
|
||||
- `getSession()`
|
||||
- `updateSession()`
|
||||
- `createObservation()`
|
||||
- `getObservations()`
|
||||
- `createSummary()`
|
||||
- `getSummaries()`
|
||||
- `createUserPrompt()`
|
||||
|
||||
### SessionSearch
|
||||
|
||||
FTS5 full-text search with 8 specialized search methods.
|
||||
|
||||
**Location**: `src/services/sqlite/SessionSearch.ts`
|
||||
|
||||
**Methods**:
|
||||
- `searchObservations()` - Full-text search across observations
|
||||
- `searchSessions()` - Full-text search across summaries
|
||||
- `searchUserPrompts()` - Full-text search across user prompts
|
||||
- `findByConcept()` - Find by concept tags
|
||||
- `findByFile()` - Find by file references
|
||||
- `findByType()` - Find by observation type
|
||||
- `getRecentContext()` - Get recent session context
|
||||
- `advancedSearch()` - Combined filters
|
||||
|
||||
## Migrations
|
||||
|
||||
Database schema is managed via migrations in `src/services/sqlite/migrations.ts`.
|
||||
|
||||
**Migration History**:
|
||||
- Migration 001: Initial schema (sessions, memories, overviews, diagnostics, transcript_events)
|
||||
- Migration 002: Hierarchical memory fields (title, subtitle, facts, concepts, files_touched)
|
||||
- Migration 003: SDK sessions and observations
|
||||
- Migration 004: Session summaries
|
||||
- Migration 005: Multi-prompt sessions (prompt_counter, prompt_number)
|
||||
- Migration 006: FTS5 virtual tables and triggers
|
||||
- Migration 007-010: Various improvements and user prompts table
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- **Indexes**: All foreign keys and frequently queried columns are indexed
|
||||
- **FTS5**: Full-text search is significantly faster than LIKE queries
|
||||
- **Triggers**: Automatic synchronization has minimal overhead
|
||||
- **Connection Pooling**: better-sqlite3 reuses connections efficiently
|
||||
- **Synchronous API**: better-sqlite3 uses synchronous API for better performance
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [Troubleshooting - Database Issues](../troubleshooting.md#database-issues) for common problems and solutions.
|
||||
@@ -0,0 +1,196 @@
|
||||
# Plugin Hooks
|
||||
|
||||
Claude-Mem integrates with Claude Code through 5 lifecycle hooks that capture events and inject context.
|
||||
|
||||
## Hook Overview
|
||||
|
||||
| Hook Name | Purpose | Timeout | Script |
|
||||
|---------------------|--------------------------------------|---------|-------------------------|
|
||||
| SessionStart | Inject context from previous sessions| 120s | context-hook.js |
|
||||
| UserPromptSubmit | Create/track new sessions | 120s | new-hook.js |
|
||||
| PostToolUse | Capture tool execution observations | 120s | save-hook.js |
|
||||
| Stop | Generate session summaries | 120s | summary-hook.js |
|
||||
| SessionEnd | Mark sessions complete | 120s | cleanup-hook.js |
|
||||
|
||||
## Hook Configuration
|
||||
|
||||
Hooks are configured in `plugin/hooks/hooks.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "Claude-mem memory system hooks",
|
||||
"hooks": {
|
||||
"SessionStart": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "cd \"${CLAUDE_PLUGIN_ROOT}/..\" && npm install --prefer-offline --no-audit --no-fund --loglevel=error && node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"UserPromptSubmit": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"PostToolUse": [{
|
||||
"matcher": "*",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"Stop": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}],
|
||||
"SessionEnd": [{
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-hook.js",
|
||||
"timeout": 120
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 1. SessionStart Hook (`context-hook.js`)
|
||||
|
||||
**Purpose**: Inject context from previous sessions into Claude's initial context.
|
||||
|
||||
**Behavior**:
|
||||
- Ensures dependencies are installed (runs fast idempotent npm install)
|
||||
- Auto-starts PM2 worker service if not running
|
||||
- Retrieves last 10 session summaries with three-tier verbosity (v4.2.0)
|
||||
- Returns context via `hookSpecificOutput` in JSON format (fixed in v4.1.0)
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"source": "startup"
|
||||
}
|
||||
```
|
||||
|
||||
**Output** (via stdout):
|
||||
```json
|
||||
{
|
||||
"hookSpecificOutput": "# Recent Sessions\n\n## Session 1...\n"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/context.ts` and `src/bin/hooks/context-hook.ts`
|
||||
|
||||
## 2. UserPromptSubmit Hook (`new-hook.js`)
|
||||
|
||||
**Purpose**: Create new session records and initialize session tracking.
|
||||
|
||||
**Behavior**:
|
||||
- Creates new session in database
|
||||
- Initializes session tracking
|
||||
- Saves raw user prompts for full-text search (as of v4.2.0)
|
||||
- Sends init signal to worker service
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"prompt": "User's actual prompt text"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/new.ts` and `src/bin/hooks/new-hook.ts`
|
||||
|
||||
## 3. PostToolUse Hook (`save-hook.js`)
|
||||
|
||||
**Purpose**: Capture tool execution observations.
|
||||
|
||||
**Behavior**:
|
||||
- Fires after EVERY tool execution (Read, Write, Edit, Bash, etc.)
|
||||
- Sends observations to worker service for processing
|
||||
- Includes correlation IDs for tracing
|
||||
- Filters low-value observations
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"tool_name": "Read",
|
||||
"tool_input": {...},
|
||||
"tool_result": "...",
|
||||
"correlation_id": "abc-123"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/save.ts` and `src/bin/hooks/save-hook.ts`
|
||||
|
||||
## 4. Stop Hook (`summary-hook.js`)
|
||||
|
||||
**Purpose**: Generate session summaries when Claude stops.
|
||||
|
||||
**Behavior**:
|
||||
- Triggers final summary generation
|
||||
- Sends summarize request to worker service
|
||||
- Summary includes: request, completed, learned, next_steps
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"source": "user_stop"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/summary.ts` and `src/bin/hooks/summary-hook.ts`
|
||||
|
||||
## 5. SessionEnd Hook (`cleanup-hook.js`)
|
||||
|
||||
**Purpose**: Mark sessions as completed (graceful cleanup as of v4.1.0).
|
||||
|
||||
**Behavior**:
|
||||
- Marks sessions as completed
|
||||
- Skips cleanup on `/clear` commands to preserve ongoing sessions
|
||||
- Allows workers to finish pending operations naturally
|
||||
- Previously sent DELETE requests; now uses graceful completion
|
||||
|
||||
**Input** (via stdin):
|
||||
```json
|
||||
{
|
||||
"session_id": "claude-session-123",
|
||||
"cwd": "/path/to/project",
|
||||
"source": "normal"
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: `src/hooks/cleanup.ts` and `src/bin/hooks/cleanup-hook.ts`
|
||||
|
||||
## Hook Development
|
||||
|
||||
### Adding a New Hook
|
||||
|
||||
1. Create hook implementation in `src/hooks/your-hook.ts`
|
||||
2. Create entry point in `src/bin/hooks/your-hook.ts`
|
||||
3. Add to `plugin/hooks/hooks.json`
|
||||
4. Rebuild with `npm run build`
|
||||
|
||||
### Hook Best Practices
|
||||
|
||||
- **Fast execution**: Hooks should complete quickly (< 1s ideal)
|
||||
- **Graceful degradation**: Don't block Claude if worker is down
|
||||
- **Structured logging**: Use logger for debugging
|
||||
- **Error handling**: Catch and log errors, don't crash
|
||||
- **JSON output**: Use `hookSpecificOutput` for context injection
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [Troubleshooting - Hook Issues](../troubleshooting.md#hook-issues) for common problems and solutions.
|
||||
@@ -0,0 +1,308 @@
|
||||
# MCP Search Server
|
||||
|
||||
Claude-Mem includes a Model Context Protocol (MCP) server that exposes 7 specialized search tools for querying stored observations and sessions.
|
||||
|
||||
## Overview
|
||||
|
||||
- **Location**: `src/servers/search-server.ts`
|
||||
- **Configuration**: `plugin/.mcp.json`
|
||||
- **Transport**: stdio
|
||||
- **Tools**: 7 specialized search functions
|
||||
- **Citations**: All results use `claude-mem://` URI scheme
|
||||
|
||||
## Configuration
|
||||
|
||||
The MCP server is automatically registered via `plugin/.mcp.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"claude-mem-search": {
|
||||
"type": "stdio",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/search-server.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This registers the `claude-mem-search` server with Claude Code, making the 7 search tools available in all sessions. The server is automatically started when Claude Code launches and communicates via stdio transport.
|
||||
|
||||
## Search Tools
|
||||
|
||||
### 1. search_observations
|
||||
|
||||
Full-text search across observation titles, narratives, facts, and concepts.
|
||||
|
||||
**Parameters**:
|
||||
- `query` (required): Search query for FTS5 full-text search
|
||||
- `type`: Filter by observation type(s) (decision, bugfix, feature, refactor, discovery, change)
|
||||
- `concepts`: Filter by concept tags
|
||||
- `files`: Filter by file paths (partial match)
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range (`{start, end}`)
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" for titles/dates only, "full" for complete details)
|
||||
|
||||
**Example**:
|
||||
```
|
||||
search_observations with query="build system" and type="decision"
|
||||
```
|
||||
|
||||
### 2. search_sessions
|
||||
|
||||
Full-text search across session summaries, requests, and learnings.
|
||||
|
||||
**Parameters**:
|
||||
- `query` (required): Search query for FTS5 full-text search
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" or "full")
|
||||
|
||||
**Example**:
|
||||
```
|
||||
search_sessions with query="hooks implementation"
|
||||
```
|
||||
|
||||
### 3. search_user_prompts
|
||||
|
||||
Search raw user prompts with full-text search. Use this to find what the user actually said/requested across all sessions.
|
||||
|
||||
**Parameters**:
|
||||
- `query` (required): Search query for FTS5 full-text search
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" for truncated prompts/dates, "full" for complete prompt text)
|
||||
|
||||
**Example**:
|
||||
```
|
||||
search_user_prompts with query="authentication feature"
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Full context reconstruction from user intent → Claude actions → outcomes
|
||||
- Pattern detection for repeated requests
|
||||
- Improved debugging by tracing from original user words to final implementation
|
||||
|
||||
### 4. find_by_concept
|
||||
|
||||
Find observations tagged with specific concepts.
|
||||
|
||||
**Parameters**:
|
||||
- `concept` (required): Concept tag to search for
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" or "full")
|
||||
|
||||
**Example**:
|
||||
```
|
||||
find_by_concept with concept="architecture"
|
||||
```
|
||||
|
||||
### 5. find_by_file
|
||||
|
||||
Find observations and sessions that reference specific file paths.
|
||||
|
||||
**Parameters**:
|
||||
- `filePath` (required): File path to search for (supports partial matching)
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" or "full")
|
||||
|
||||
**Example**:
|
||||
```
|
||||
find_by_file with filePath="worker-service.ts"
|
||||
```
|
||||
|
||||
### 6. find_by_type
|
||||
|
||||
Find observations by type (decision, bugfix, feature, refactor, discovery, change).
|
||||
|
||||
**Parameters**:
|
||||
- `type` (required): Observation type(s) to filter by (single type or array)
|
||||
- `project`: Filter by project name
|
||||
- `dateRange`: Filter by date range
|
||||
- `orderBy`: Sort order (relevance, date_desc, date_asc)
|
||||
- `limit`: Maximum results (default: 20, max: 100)
|
||||
- `offset`: Number of results to skip
|
||||
- `format`: Output format ("index" or "full")
|
||||
|
||||
**Example**:
|
||||
```
|
||||
find_by_type with type=["decision", "feature"]
|
||||
```
|
||||
|
||||
### 7. get_recent_context
|
||||
|
||||
Get recent session context including summaries and observations for a project.
|
||||
|
||||
**Parameters**:
|
||||
- `project`: Project name (defaults to current working directory basename)
|
||||
- `limit`: Number of recent sessions to retrieve (default: 3, max: 10)
|
||||
|
||||
**Example**:
|
||||
```
|
||||
get_recent_context with limit=5
|
||||
```
|
||||
|
||||
## Output Formats
|
||||
|
||||
All search tools support two output formats:
|
||||
|
||||
### Index Format (Default)
|
||||
|
||||
Returns titles, dates, and source URIs only. Uses ~10x fewer tokens than full format.
|
||||
|
||||
**Always use index format first** to get an overview and identify relevant results.
|
||||
|
||||
**Example Output**:
|
||||
```
|
||||
1. [decision] Implement graceful session cleanup
|
||||
Date: 2025-10-21 14:23:45
|
||||
Source: claude-mem://observation/123
|
||||
|
||||
2. [feature] Add FTS5 full-text search
|
||||
Date: 2025-10-21 13:15:22
|
||||
Source: claude-mem://observation/124
|
||||
```
|
||||
|
||||
### Full Format
|
||||
|
||||
Returns complete observation/summary details including narrative, facts, concepts, files, etc.
|
||||
|
||||
**Only use after reviewing index results** to dive deep into specific items of interest.
|
||||
|
||||
## Search Strategy
|
||||
|
||||
**Recommended Workflow**:
|
||||
|
||||
1. **Initial search**: Use default (index) format to see titles, dates, and sources
|
||||
2. **Review results**: Identify which items are most relevant to your needs
|
||||
3. **Deep dive**: Only then use `format: "full"` on specific items of interest
|
||||
4. **Narrow down**: Use filters (type, dateRange, concepts, files) to refine results
|
||||
|
||||
**Token Efficiency**:
|
||||
- Index format: ~50-100 tokens per result
|
||||
- Full format: ~500-1000 tokens per result
|
||||
- Start with 3-5 results to avoid MCP token limits
|
||||
|
||||
## Citations
|
||||
|
||||
All search results use the `claude-mem://` URI scheme for citations:
|
||||
|
||||
- `claude-mem://observation/{id}` - References specific observations
|
||||
- `claude-mem://session/{id}` - References specific sessions
|
||||
- `claude-mem://user-prompt/{id}` - References specific user prompts
|
||||
|
||||
These citations allow Claude to reference specific historical context in responses.
|
||||
|
||||
## FTS5 Query Syntax
|
||||
|
||||
The `query` parameter supports SQLite FTS5 full-text search syntax:
|
||||
|
||||
- **Simple**: `"error handling"`
|
||||
- **AND**: `"error" AND "handling"`
|
||||
- **OR**: `"bug" OR "fix"`
|
||||
- **NOT**: `"bug" NOT "feature"`
|
||||
- **Phrase**: `"'exact phrase'"`
|
||||
- **Column**: `title:"authentication"`
|
||||
|
||||
## Security
|
||||
|
||||
As of v4.2.3, all FTS5 queries are properly escaped to prevent SQL injection attacks:
|
||||
- Double quotes are escaped: `query.replace(/"/g, '""')`
|
||||
- Comprehensive test suite with 332 injection attack tests
|
||||
- Affects: `search_observations`, `search_sessions`, `search_user_prompts`
|
||||
|
||||
## Example Queries
|
||||
|
||||
```
|
||||
# Find all decisions about build system
|
||||
search_observations with query="build system" and type="decision"
|
||||
|
||||
# Show everything related to worker-service.ts
|
||||
find_by_file with filePath="worker-service.ts"
|
||||
|
||||
# Search what we learned about hooks
|
||||
search_sessions with query="hooks"
|
||||
|
||||
# Show observations tagged with 'architecture'
|
||||
find_by_concept with concept="architecture"
|
||||
|
||||
# Find what user asked about authentication
|
||||
search_user_prompts with query="authentication"
|
||||
|
||||
# Get recent context for debugging
|
||||
get_recent_context with limit=5
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
The MCP search server is implemented using:
|
||||
- `@modelcontextprotocol/sdk` (v1.20.1)
|
||||
- `SessionSearch` service for FTS5 queries
|
||||
- `SessionStore` for database access
|
||||
- `zod-to-json-schema` for parameter validation
|
||||
|
||||
**Source Code**: `src/servers/search-server.ts`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Tool Not Available
|
||||
|
||||
If search tools are not available in Claude Code sessions:
|
||||
|
||||
1. Check MCP configuration:
|
||||
```bash
|
||||
cat plugin/.mcp.json
|
||||
```
|
||||
|
||||
2. Verify search server is built:
|
||||
```bash
|
||||
ls -l plugin/scripts/search-server.js
|
||||
```
|
||||
|
||||
3. Rebuild if needed:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Search Returns No Results
|
||||
|
||||
1. Check database has data:
|
||||
```bash
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT COUNT(*) FROM observations;"
|
||||
```
|
||||
|
||||
2. Verify FTS5 tables exist:
|
||||
```bash
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%_fts';"
|
||||
```
|
||||
|
||||
3. Test query syntax:
|
||||
```bash
|
||||
# Simple query should work
|
||||
search_observations with query="test"
|
||||
```
|
||||
|
||||
### Token Limit Errors
|
||||
|
||||
If you hit MCP token limits:
|
||||
|
||||
1. Use `format: "index"` instead of `format: "full"`
|
||||
2. Reduce `limit` parameter (try 3-5 instead of 20)
|
||||
3. Use more specific filters to narrow results
|
||||
4. Use `offset` to paginate through results
|
||||
@@ -0,0 +1,160 @@
|
||||
# Architecture Overview
|
||||
|
||||
## System Components
|
||||
|
||||
Claude-Mem operates as a Claude Code plugin with four core components:
|
||||
|
||||
1. **Plugin Hooks** - Capture lifecycle events
|
||||
2. **Worker Service** - Process observations via Claude Agent SDK
|
||||
3. **Database Layer** - Store sessions and observations (SQLite + FTS5)
|
||||
4. **MCP Search Server** - Query historical context
|
||||
|
||||
## Technology Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|------------------------|-------------------------------------------|
|
||||
| **Language** | TypeScript (ES2022, ESNext modules) |
|
||||
| **Runtime** | Node.js 18+ |
|
||||
| **Database** | SQLite 3 with better-sqlite3 driver |
|
||||
| **HTTP Server** | Express.js 4.18 |
|
||||
| **AI SDK** | @anthropic-ai/claude-agent-sdk |
|
||||
| **Build Tool** | esbuild (bundles TypeScript) |
|
||||
| **Process Manager** | PM2 |
|
||||
| **Testing** | Node.js built-in test runner |
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Memory Pipeline
|
||||
```
|
||||
Hook (stdin) → Database → Worker Service → SDK Processor → Database → Next Session Hook
|
||||
```
|
||||
|
||||
1. **Input**: Claude Code sends tool execution data via stdin to hooks
|
||||
2. **Storage**: Hooks write observations to SQLite database
|
||||
3. **Processing**: Worker service reads observations, processes via SDK
|
||||
4. **Output**: Processed summaries written back to database
|
||||
5. **Retrieval**: Next session's context hook reads summaries from database
|
||||
|
||||
### Search Pipeline
|
||||
```
|
||||
Claude Request → MCP Server → SessionSearch Service → FTS5 Database → Search Results → Claude
|
||||
```
|
||||
|
||||
1. **Query**: Claude uses MCP search tools (e.g., `search_observations`)
|
||||
2. **Search**: MCP server calls SessionSearch service with query parameters
|
||||
3. **FTS5**: Full-text search executes against FTS5 virtual tables
|
||||
4. **Format**: Results formatted as `search_result` blocks with citations
|
||||
5. **Return**: Claude receives citable search results for analysis
|
||||
|
||||
## Session Lifecycle
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 1. Session Starts → Context Hook Fires │
|
||||
│ Injects summaries from last 3 sessions into Claude's context │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 2. User Types Prompt → UserPromptSubmit Hook Fires │
|
||||
│ Creates SDK session in database, notifies worker service │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3. Claude Uses Tools → PostToolUse Hook Fires (100+ times) │
|
||||
│ Sends observations to worker service for processing │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 4. Worker Processes → Claude Agent SDK Analyzes │
|
||||
│ Extracts structured learnings via iterative AI processing │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 5. Claude Stops → Stop Hook Fires │
|
||||
│ Generates final summary with request, status, next steps │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 6. Session Ends → Cleanup Hook Fires │
|
||||
│ Marks session complete, ready for next session context │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
claude-mem/
|
||||
├── src/
|
||||
│ ├── bin/hooks/ # Entry point scripts for 5 hooks
|
||||
│ │ ├── context-hook.ts # SessionStart
|
||||
│ │ ├── new-hook.ts # UserPromptSubmit
|
||||
│ │ ├── save-hook.ts # PostToolUse
|
||||
│ │ ├── summary-hook.ts # Stop
|
||||
│ │ └── cleanup-hook.ts # SessionEnd
|
||||
│ │
|
||||
│ ├── hooks/ # Hook implementation logic
|
||||
│ │ ├── context.ts
|
||||
│ │ ├── new.ts
|
||||
│ │ ├── save.ts
|
||||
│ │ ├── summary.ts
|
||||
│ │ └── cleanup.ts
|
||||
│ │
|
||||
│ ├── servers/ # MCP servers
|
||||
│ │ └── search-server.ts # MCP search tools server
|
||||
│ │
|
||||
│ ├── sdk/ # Claude Agent SDK integration
|
||||
│ │ ├── prompts.ts # XML prompt builders
|
||||
│ │ ├── parser.ts # XML response parser
|
||||
│ │ └── worker.ts # Main SDK agent loop
|
||||
│ │
|
||||
│ ├── services/
|
||||
│ │ ├── worker-service.ts # Express HTTP service
|
||||
│ │ └── sqlite/ # Database layer
|
||||
│ │ ├── SessionStore.ts # CRUD operations
|
||||
│ │ ├── SessionSearch.ts # FTS5 search service
|
||||
│ │ ├── migrations.ts
|
||||
│ │ └── types.ts
|
||||
│ │
|
||||
│ ├── shared/ # Shared utilities
|
||||
│ │ ├── config.ts
|
||||
│ │ ├── paths.ts
|
||||
│ │ └── storage.ts
|
||||
│ │
|
||||
│ └── utils/
|
||||
│ ├── logger.ts
|
||||
│ ├── platform.ts
|
||||
│ └── port-allocator.ts
|
||||
│
|
||||
├── plugin/ # Plugin distribution
|
||||
│ ├── .claude-plugin/
|
||||
│ │ └── plugin.json
|
||||
│ ├── .mcp.json # MCP server configuration
|
||||
│ ├── hooks/
|
||||
│ │ └── hooks.json
|
||||
│ └── scripts/ # Built executables
|
||||
│ ├── context-hook.js
|
||||
│ ├── new-hook.js
|
||||
│ ├── save-hook.js
|
||||
│ ├── summary-hook.js
|
||||
│ ├── cleanup-hook.js
|
||||
│ ├── worker-service.cjs # Background worker
|
||||
│ └── search-server.js # MCP search server
|
||||
│
|
||||
├── tests/ # Test suite
|
||||
├── docs/ # Documentation
|
||||
└── ecosystem.config.cjs # PM2 configuration
|
||||
```
|
||||
|
||||
## Component Details
|
||||
|
||||
### 1. Plugin Hooks
|
||||
See [hooks.md](hooks.md) for detailed hook documentation.
|
||||
|
||||
### 2. Worker Service
|
||||
See [worker-service.md](worker-service.md) for HTTP API and endpoints.
|
||||
|
||||
### 3. Database Layer
|
||||
See [database.md](database.md) for schema and FTS5 search.
|
||||
|
||||
### 4. MCP Search Server
|
||||
See [mcp-search.md](mcp-search.md) for search tools and examples.
|
||||
@@ -0,0 +1,243 @@
|
||||
# Worker Service
|
||||
|
||||
The worker service is a long-running HTTP API built with Express.js and managed by PM2. It processes observations through the Claude Agent SDK separately from hook execution to prevent timeout issues.
|
||||
|
||||
## Overview
|
||||
|
||||
- **Technology**: Express.js HTTP server
|
||||
- **Process Manager**: PM2
|
||||
- **Port**: Fixed port 37777 (configurable via `CLAUDE_MEM_WORKER_PORT`)
|
||||
- **Location**: `src/services/worker-service.ts`
|
||||
- **Built Output**: `plugin/scripts/worker-service.cjs`
|
||||
- **Model**: Configurable via `CLAUDE_MEM_MODEL` environment variable (default: claude-sonnet-4-5)
|
||||
|
||||
## REST API Endpoints
|
||||
|
||||
The worker service exposes 6 HTTP endpoints:
|
||||
|
||||
### 1. Health Check
|
||||
```
|
||||
GET /health
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 12345,
|
||||
"port": 37777
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Initialize Session
|
||||
```
|
||||
POST /sessions/:sessionDbId/init
|
||||
```
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"sdk_session_id": "abc-123",
|
||||
"project": "my-project"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"session_id": "abc-123"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Add Observation
|
||||
```
|
||||
POST /sessions/:sessionDbId/observations
|
||||
```
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"tool_name": "Read",
|
||||
"tool_input": {...},
|
||||
"tool_result": "...",
|
||||
"correlation_id": "xyz-789"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"observation_id": 123
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Generate Summary
|
||||
```
|
||||
POST /sessions/:sessionDbId/summarize
|
||||
```
|
||||
|
||||
**Request Body**:
|
||||
```json
|
||||
{
|
||||
"trigger": "stop"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"summary_id": 456
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Session Status
|
||||
```
|
||||
GET /sessions/:sessionDbId/status
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"session_id": "abc-123",
|
||||
"status": "active",
|
||||
"observation_count": 42,
|
||||
"summary_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Delete Session
|
||||
```
|
||||
DELETE /sessions/:sessionDbId
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: As of v4.1.0, the cleanup hook no longer calls this endpoint. Sessions are marked complete instead of deleted to allow graceful worker shutdown.
|
||||
|
||||
## PM2 Management
|
||||
|
||||
### Configuration
|
||||
|
||||
The worker is configured via `ecosystem.config.cjs`:
|
||||
|
||||
```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'
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
### Commands
|
||||
|
||||
```bash
|
||||
# Start worker (auto-starts on first session)
|
||||
npm run worker:start
|
||||
|
||||
# Stop worker
|
||||
npm run worker:stop
|
||||
|
||||
# Restart worker
|
||||
npm run worker:restart
|
||||
|
||||
# View logs
|
||||
npm run worker:logs
|
||||
|
||||
# Check status
|
||||
npm run worker:status
|
||||
```
|
||||
|
||||
### Auto-Start Behavior
|
||||
|
||||
As of v4.0.0, the worker service auto-starts when the SessionStart hook fires. Manual start is optional.
|
||||
|
||||
## Claude Agent SDK Integration
|
||||
|
||||
The worker service routes observations to the Claude Agent SDK for AI-powered processing:
|
||||
|
||||
### Processing Flow
|
||||
|
||||
1. **Observation Queue**: Observations accumulate in memory
|
||||
2. **SDK Processing**: Observations sent to Claude via Agent SDK
|
||||
3. **XML Parsing**: Responses parsed for structured data
|
||||
4. **Database Storage**: Processed observations stored in SQLite
|
||||
|
||||
### SDK Components
|
||||
|
||||
- **Prompts** (`src/sdk/prompts.ts`): Builds XML-structured prompts
|
||||
- **Parser** (`src/sdk/parser.ts`): Parses Claude's XML responses
|
||||
- **Worker** (`src/sdk/worker.ts`): Main SDK agent loop
|
||||
|
||||
### Model Configuration
|
||||
|
||||
Set the AI model used for processing via environment variable:
|
||||
|
||||
```bash
|
||||
export CLAUDE_MEM_MODEL=claude-sonnet-4-5
|
||||
```
|
||||
|
||||
Available models:
|
||||
- `claude-haiku-4-5` - Fast, cost-efficient
|
||||
- `claude-sonnet-4-5` - Balanced (default)
|
||||
- `claude-opus-4` - Most capable
|
||||
- `claude-3-7-sonnet` - Alternative version
|
||||
|
||||
## Port Allocation
|
||||
|
||||
The worker uses a fixed port (37777 by default) for consistent communication:
|
||||
|
||||
- **Default**: Port 37777
|
||||
- **Override**: Set `CLAUDE_MEM_WORKER_PORT` environment variable
|
||||
- **Port File**: `${CLAUDE_PLUGIN_ROOT}/data/worker.port` tracks current port
|
||||
|
||||
If port 37777 is in use, the worker will fail to start. Set a custom port via environment variable.
|
||||
|
||||
## Data Storage
|
||||
|
||||
The worker service stores data in the plugin data directory:
|
||||
|
||||
```
|
||||
${CLAUDE_PLUGIN_ROOT}/data/
|
||||
├── claude-mem.db # SQLite database
|
||||
├── worker.port # Current worker port file
|
||||
└── logs/
|
||||
├── worker-out.log # Worker stdout logs
|
||||
└── worker-error.log # Worker stderr logs
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The worker implements graceful degradation:
|
||||
|
||||
- **Database Errors**: Logged but don't crash the service
|
||||
- **SDK Errors**: Retried with exponential backoff
|
||||
- **Network Errors**: Logged and skipped
|
||||
- **Invalid Input**: Validated and rejected with error response
|
||||
|
||||
## Performance
|
||||
|
||||
- **Async Processing**: Observations processed asynchronously
|
||||
- **In-Memory Queue**: Fast observation accumulation
|
||||
- **Batch Processing**: Multiple observations processed together
|
||||
- **Connection Pooling**: SQLite connections reused
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [Troubleshooting - Worker Issues](../troubleshooting.md#worker-service-issues) for common problems and solutions.
|
||||
Reference in New Issue
Block a user