claude-eidetic 0.1.2 β†’ 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,333 +1,333 @@
1
- # claude-eidetic
2
-
3
-
4
- [![tests](https://img.shields.io/github/actions/workflow/status/eidetics/claude-eidetic/ci.yml?style=flat-square&label=tests)](https://github.com/eidetics/claude-eidetic/actions/workflows/ci.yml)
5
- [![npm](https://img.shields.io/npm/v/claude-eidetic)](https://www.npmjs.com/package/claude-eidetic)
6
- [![MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
-
8
- Semantic code search, persistent memory, and session continuity for Claude Code. One plugin, not three.
9
-
10
- ---
11
-
12
- ## πŸš€ Quick Start
13
-
14
- ```bash
15
- claude plugin install eidetics/claude-eidetic
16
- ```
17
-
18
- ```bash
19
- export OPENAI_API_KEY=sk-... # for embeddings (default)
20
- export ANTHROPIC_API_KEY=sk-ant-... # for memory extraction (default)
21
- ```
22
-
23
- Index your codebase once, then search by meaning:
24
-
25
- ```
26
- index_codebase(path="/your/project")
27
- search_code("how does authentication work")
28
- ```
29
-
30
- ---
31
-
32
- ## ✨ Features
33
-
34
- ### πŸ” Semantic Code Search
35
-
36
- **Find code by meaning, not keywords.** Search across your entire codebase with natural language, returning the most relevant functions and classes, not a list of files to read.
37
-
38
- ```
39
- search_code("how does the retry logic work")
40
- search_code("authentication middleware", extensionFilter=[".ts"])
41
- search_code(project="backend", query="auth flow")
42
- ```
43
-
44
- ### πŸ—οΈ Architecture at a Glance
45
-
46
- **Get every class, function, and method in one call.** `browse_structure` returns a condensed map of your codebase with signatures, grouped by file, replacing a Glob + Read cascade with a single tool call.
47
-
48
- ```
49
- browse_structure(path="/my/project", kind="class")
50
- list_symbols(path="/my/project", nameFilter="handle")
51
- ```
52
-
53
- ### πŸ“š Documentation Cache
54
-
55
- **Fetch docs once, search them forever.** Cache external documentation as searchable embeddings. Retrieve relevant passages instantly, far cheaper than re-fetching the same page each session.
56
-
57
- ```
58
- index_document(content=..., library="react", topic="hooks", source="https://...")
59
- search_documents("React useCallback dependencies", library="react")
60
- ```
61
-
62
- ### 🧠 Persistent Memory
63
-
64
- **Claude remembers your preferences between sessions.** `add_memory` uses an LLM to extract structured facts from conversation text (coding style, architecture decisions, debugging insights) and deduplicates them semantically. Not a static config file you forget to update.
65
-
66
- ```
67
- add_memory("Always use absolute imports, never relative")
68
- search_memory("how does this team handle errors")
69
- ```
70
-
71
- ### πŸ”„ Session Continuity
72
-
73
- **Every session picks up where the last one left off.** When a session ends (or context compacts mid-session), Eidetic automatically writes a structured note capturing files changed, tasks, commands, and decisions. `/catchup` at the start of a new session reconstructs exactly where you were. No user action required.
74
-
75
- ### πŸ‘» Invisible Optimizations
76
-
77
- Eight hook events fire automatically, nudging toward cheaper tools, redirecting file reads for 15-20% token savings, tracking changed files, and saving session state on exit.
78
-
79
- <details>
80
- <summary><strong>Hook event details</strong></summary>
81
-
82
- | Hook | Trigger | What it does |
83
- |---|---|---|
84
- | `SessionStart` | Session opens | Validates config, injects last-session context |
85
- | `UserPromptSubmit` | Every message | Nudges toward `search_code` over Grep/Explore for conceptual queries |
86
- | `PreToolUse` (Read) | Before every Read | Blocks Read for text files, redirects to `read_file` for 15-20% token savings |
87
- | `PreToolUse` (WebFetch / query-docs) | Before doc fetches | Suggests `search_documents` if library is cached (allows fetch either way) |
88
- | `PostToolUse` (Write / Edit) | After every file write | Tracks changed files in a shadow git index |
89
- | `Stop` | After Claude responds | Commits shadow index; triggers targeted re-index of changed files only |
90
- | `PreCompact` | Before context compaction | Captures session state to notes before memory is lost |
91
- | `SessionEnd` | Session closes | Writes session note (files, tasks, commands); extracts developer memories via LLM |
92
-
93
- </details>
94
-
95
- ---
96
-
97
- ## πŸ—ΊοΈ When to Use What
98
-
99
- | Need | Use | Notes |
100
- |---|---|---|
101
- | Find implementations by concept | `search_code` | Semantic, natural language queries |
102
- | Exact string or regex match | Grep | Grep wins for exact matches |
103
- | Find file by exact name | Glob | Glob wins for name patterns |
104
- | Understand module structure | `browse_structure` | One call vs Glob + Read cascade |
105
- | Read a specific known file | `read_file` | Cheaper than built-in Read for code files |
106
- | Search cached documentation | `search_documents` | Far cheaper than re-fetching |
107
- | Recall project conventions | `search_memory` | Global across all projects and sessions |
108
-
109
- ---
110
-
111
- ## πŸ“– Skills Reference
112
-
113
- | Skill | What it does |
114
- |---|---|
115
- | `/search` | Guided semantic search with best-practice prompts |
116
- | `/index` | Index or re-index a codebase with dry-run option |
117
- | `/cache-docs` | Fetch and cache external documentation |
118
- | `/catchup` | Search session notes and reconstruct where you left off |
119
- | `/wrapup` | Extract decisions, rationale, open questions, and next actions from the conversation |
120
-
121
- ---
122
-
123
- <details>
124
- <summary><strong>πŸ”₯ Why does this exist? (The Problem)</strong></summary>
125
-
126
- Every new Claude Code session starts cold. You re-explain the architecture. You re-fetch the same docs. Claude reads the same files repeatedly, burning tokens just to get back to where you were.
127
-
128
- | Task | Without Eidetic | With Eidetic |
129
- |---|---|---|
130
- | Find where auth errors are handled | Grep cascade, read 8 files, ~10,700 tokens | `search_code("auth error handling")` ~220 tokens |
131
- | Resume after context compaction | Re-explain 20 min of context, ~2,000 tokens | `/catchup` ~200 tokens |
132
- | Look up React hooks docs | Fetch docs page, ~5,000 tokens | `search_documents("React useEffect")` ~20 tokens |
133
- | Read a 400-line file | Built-in Read with line numbers, ~900 tokens | `read_file(path)` ~740 tokens |
134
-
135
- </details>
136
-
137
- ---
138
-
139
- ## πŸ“¦ Installation
140
-
141
- ### Plugin (recommended)
142
-
143
- ```bash
144
- claude plugin install eidetics/claude-eidetic
145
- ```
146
-
147
- The plugin auto-starts the MCP server, installs skills, and configures hooks.
148
-
149
- ### npx (manual MCP config)
150
-
151
- Add to your `.mcp.json`:
152
-
153
- ```json
154
- {
155
- "mcpServers": {
156
- "claude-eidetic": {
157
- "command": "npx",
158
- "args": ["-y", "claude-eidetic"],
159
- "env": {
160
- "OPENAI_API_KEY": "sk-...",
161
- "ANTHROPIC_API_KEY": "sk-ant-..."
162
- }
163
- }
164
- }
165
- }
166
- ```
167
-
168
- `ANTHROPIC_API_KEY` is needed for the memory LLM (default provider). Omit it if using `MEMORY_LLM_PROVIDER=openai` or `ollama`.
169
-
170
- ### Global install
171
-
172
- ```bash
173
- npm install -g claude-eidetic
174
- ```
175
-
176
- ### From source
177
-
178
- ```bash
179
- git clone https://github.com/eidetics/claude-eidetic
180
- cd claude-eidetic
181
- npm install && npx tsc && npm start
182
- ```
183
-
184
- ### Requirements
185
-
186
- - Node.js >= 20.0.0
187
- - An API key (OpenAI for embeddings, Anthropic for memory extraction, or Ollama for both free)
188
- - Docker (optional): Qdrant auto-provisions via Docker if not already running
189
- - C/C++ build tools: required by tree-sitter native bindings (`node-gyp`)
190
-
191
- ---
192
-
193
- ## βš™οΈ Configuration
194
-
195
- All configuration is via environment variables. No config files.
196
-
197
- ### Using Ollama (free, local)
198
-
199
- ```bash
200
- export EMBEDDING_PROVIDER=ollama
201
- export MEMORY_LLM_PROVIDER=ollama
202
- # No API keys needed
203
- ```
204
-
205
- <details>
206
- <summary><strong>Full configuration reference</strong></summary>
207
-
208
- | Variable | Default | Description |
209
- |---|---|---|
210
- | `OPENAI_API_KEY` | _(required for openai)_ | OpenAI API key for embeddings and/or memory |
211
- | `ANTHROPIC_API_KEY` | _(required for anthropic memory)_ | Anthropic API key for memory LLM |
212
- | `EMBEDDING_PROVIDER` | `openai` | `openai`, `ollama`, or `local` |
213
- | `EMBEDDING_MODEL` | `text-embedding-3-small` (openai) / `nomic-embed-text` (ollama) | Embedding model name |
214
- | `EMBEDDING_BATCH_SIZE` | `100` | Batch size for embedding requests (1-2048) |
215
- | `INDEXING_CONCURRENCY` | `8` | Parallel file indexing workers (1-32) |
216
- | `OPENAI_BASE_URL` | _(none)_ | Custom OpenAI-compatible endpoint |
217
- | `OLLAMA_BASE_URL` | `http://localhost:11434/v1` | Ollama server URL |
218
- | `VECTORDB_PROVIDER` | `qdrant` | `qdrant` or `milvus` |
219
- | `QDRANT_URL` | `http://localhost:6333` | Qdrant server URL |
220
- | `QDRANT_API_KEY` | _(none)_ | Qdrant API key (for remote/cloud instances) |
221
- | `MILVUS_ADDRESS` | `localhost:19530` | Milvus server address |
222
- | `MILVUS_TOKEN` | _(none)_ | Milvus authentication token |
223
- | `EIDETIC_DATA_DIR` | `~/.eidetic/` | Data root for snapshots, memory DB, registry |
224
- | `CUSTOM_EXTENSIONS` | `[]` | JSON array of extra file extensions to index (e.g., `[".dart",".arb"]`) |
225
- | `CUSTOM_IGNORE_PATTERNS` | `[]` | JSON array of glob patterns to exclude |
226
- | `MEMORY_LLM_PROVIDER` | `anthropic` | `anthropic`, `openai`, or `ollama` |
227
- | `MEMORY_LLM_MODEL` | `claude-haiku-4-5-20251001` (anthropic) / `gpt-4o-mini` (openai) / `llama3.2` (ollama) | Model for memory extraction |
228
- | `MEMORY_LLM_BASE_URL` | _(none)_ | Custom base URL for memory LLM |
229
- | `MEMORY_LLM_API_KEY` | _(none)_ | API key override for memory LLM |
230
-
231
- </details>
232
-
233
- ---
234
-
235
- <details>
236
- <summary><strong>πŸ”§ Tool Reference</strong></summary>
237
-
238
- ### πŸ” Code Search
239
-
240
- | Tool | Description |
241
- |---|---|
242
- | `search_code` | Hybrid semantic search over indexed codebase. Returns compact results by default. |
243
- | `index_codebase` | Index a directory. Supports `dryRun`, `force`, `customExtensions`, `customIgnorePatterns`. |
244
- | `list_indexed` | List all indexed codebases with file/chunk counts and status. |
245
- | `get_indexing_status` | Check indexing progress for a path or project. |
246
- | `clear_index` | Remove the search index for a codebase. |
247
- | `cleanup_vectors` | Remove orphaned vectors for deleted files. No re-embedding cost. |
248
- | `browse_structure` | Condensed structural map: classes, functions, methods with signatures, grouped by file. |
249
- | `list_symbols` | Compact symbol table with name/kind/file/line. Supports name, kind, and path filters. |
250
-
251
- ### πŸ“„ File Reading
252
-
253
- | Tool | Description |
254
- |---|---|
255
- | `read_file` | Read file without line-number overhead. Cheaper than built-in Read for code files. |
256
-
257
- ### πŸ“š Documentation Cache
258
-
259
- | Tool | Description |
260
- |---|---|
261
- | `index_document` | Cache external documentation for semantic search. Supports TTL for staleness tracking. |
262
- | `search_documents` | Search cached docs. Far cheaper than re-fetching the same page. |
263
-
264
- ### 🧠 Memory
265
-
266
- | Tool | Description |
267
- |---|---|
268
- | `add_memory` | LLM-extracted facts from text. Auto-deduplicates. Seven categories. |
269
- | `search_memory` | Semantic search over stored memories. Filterable by category. |
270
- | `list_memories` | List all memories, optionally filtered by category. |
271
- | `delete_memory` | Delete a specific memory by UUID. |
272
- | `memory_history` | View change history for a memory (additions, updates, deletions). |
273
-
274
- </details>
275
-
276
- ---
277
-
278
- ## 🌐 Supported Languages
279
-
280
- **AST-aware** (functions and classes chunked intact):
281
-
282
- <p>
283
- <img src="https://img.shields.io/badge/JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=black" alt="JavaScript"/>
284
- <img src="https://img.shields.io/badge/TypeScript-3178C6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript"/>
285
- <img src="https://img.shields.io/badge/React_(JSX/TSX)-61DAFB?style=flat-square&logo=react&logoColor=black" alt="JSX/TSX"/>
286
- <img src="https://img.shields.io/badge/Python-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python"/>
287
- <img src="https://img.shields.io/badge/Go-00ADD8?style=flat-square&logo=go&logoColor=white" alt="Go"/>
288
- <img src="https://img.shields.io/badge/Java-ED8B00?style=flat-square&logo=openjdk&logoColor=white" alt="Java"/>
289
- <img src="https://img.shields.io/badge/Rust-000000?style=flat-square&logo=rust&logoColor=white" alt="Rust"/>
290
- <img src="https://img.shields.io/badge/C-A8B9CC?style=flat-square&logo=c&logoColor=black" alt="C"/>
291
- <img src="https://img.shields.io/badge/C++-00599C?style=flat-square&logo=cplusplus&logoColor=white" alt="C++"/>
292
- <img src="https://img.shields.io/badge/C%23-512BD4?style=flat-square&logo=csharp&logoColor=white" alt="C#"/>
293
- </p>
294
-
295
- **Line-based fallback** (sliding window chunking for everything else):
296
-
297
- <p>
298
- <img src="https://img.shields.io/badge/Markdown-000000?style=flat-square&logo=markdown&logoColor=white" alt="Markdown"/>
299
- <img src="https://img.shields.io/badge/YAML-CB171E?style=flat-square&logo=yaml&logoColor=white" alt="YAML"/>
300
- <img src="https://img.shields.io/badge/JSON-000000?style=flat-square&logo=json&logoColor=white" alt="JSON"/>
301
- <img src="https://img.shields.io/badge/Ruby-CC342D?style=flat-square&logo=ruby&logoColor=white" alt="Ruby"/>
302
- <img src="https://img.shields.io/badge/PHP-777BB4?style=flat-square&logo=php&logoColor=white" alt="PHP"/>
303
- <img src="https://img.shields.io/badge/Swift-F05138?style=flat-square&logo=swift&logoColor=white" alt="Swift"/>
304
- <img src="https://img.shields.io/badge/Kotlin-7F52FF?style=flat-square&logo=kotlin&logoColor=white" alt="Kotlin"/>
305
- <img src="https://img.shields.io/badge/and_more...-30363d?style=flat-square" alt="and more"/>
306
- </p>
307
-
308
- ---
309
-
310
- ## πŸ› οΈ Development
311
-
312
- ```bash
313
- npm install && npx tsc # install and build
314
- npm run dev # watch mode (tsx)
315
- npm test # unit tests (no external services needed)
316
- npm run test:integration # requires Qdrant at localhost:6333 + OPENAI_API_KEY
317
- ```
318
-
319
- **Commit format:** `type(scope): description`
320
- Types: `feat`, `fix`, `docs`, `refactor`, `perf`, `chore`, `test`
321
- Scopes: `embedding`, `vectordb`, `splitter`, `indexer`, `mcp`, `infra`, `config`
322
-
323
- ---
324
-
325
- ## πŸ™ Acknowledgements
326
-
327
- Heavily inspired by [mem0](https://github.com/mem0ai/mem0), [claude-mem](https://github.com/thedotmack/claude-mem), and [claude-context](https://github.com/zilliztech/claude-context). Documentation retrieval powered by [context7](https://github.com/upstash/context7).
328
-
329
- ---
330
-
331
- ## πŸ“„ License
332
-
333
- MIT
1
+ # claude-eidetic
2
+
3
+
4
+ [![tests](https://img.shields.io/github/actions/workflow/status/eidetics/claude-eidetic/ci.yml?style=flat-square&label=tests)](https://github.com/eidetics/claude-eidetic/actions/workflows/ci.yml)
5
+ [![npm](https://img.shields.io/npm/v/claude-eidetic)](https://www.npmjs.com/package/claude-eidetic)
6
+ [![MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+
8
+ Semantic code search, persistent memory, and session continuity for Claude Code. One plugin, not three.
9
+
10
+ ---
11
+
12
+ ## πŸš€ Quick Start
13
+
14
+ ```bash
15
+ claude plugin install eidetics/claude-eidetic
16
+ ```
17
+
18
+ ```bash
19
+ export OPENAI_API_KEY=sk-... # for embeddings (default)
20
+ export ANTHROPIC_API_KEY=sk-ant-... # for memory extraction (default)
21
+ ```
22
+
23
+ Index your codebase once, then search by meaning:
24
+
25
+ ```
26
+ index_codebase(path="/your/project")
27
+ search_code("how does authentication work")
28
+ ```
29
+
30
+ ---
31
+
32
+ ## ✨ Features
33
+
34
+ ### πŸ” Semantic Code Search
35
+
36
+ **Find code by meaning, not keywords.** Search across your entire codebase with natural language, returning the most relevant functions and classes, not a list of files to read.
37
+
38
+ ```
39
+ search_code("how does the retry logic work")
40
+ search_code("authentication middleware", extensionFilter=[".ts"])
41
+ search_code(project="backend", query="auth flow")
42
+ ```
43
+
44
+ ### πŸ—οΈ Architecture at a Glance
45
+
46
+ **Get every class, function, and method in one call.** `browse_structure` returns a condensed map of your codebase with signatures, grouped by file, replacing a Glob + Read cascade with a single tool call.
47
+
48
+ ```
49
+ browse_structure(path="/my/project", kind="class")
50
+ list_symbols(path="/my/project", nameFilter="handle")
51
+ ```
52
+
53
+ ### πŸ“š Documentation Cache
54
+
55
+ **Fetch docs once, search them forever.** Cache external documentation as searchable embeddings. Retrieve relevant passages instantly, far cheaper than re-fetching the same page each session.
56
+
57
+ ```
58
+ index_document(content=..., library="react", topic="hooks", source="https://...")
59
+ search_documents("React useCallback dependencies", library="react")
60
+ ```
61
+
62
+ ### 🧠 Persistent Memory
63
+
64
+ **Claude remembers your preferences between sessions.** `add_memory` uses an LLM to extract structured facts from conversation text (coding style, architecture decisions, debugging insights) and deduplicates them semantically. Not a static config file you forget to update.
65
+
66
+ ```
67
+ add_memory("Always use absolute imports, never relative")
68
+ search_memory("how does this team handle errors")
69
+ ```
70
+
71
+ ### πŸ”„ Session Continuity
72
+
73
+ **Every session picks up where the last one left off.** When a session ends (or context compacts mid-session), Eidetic automatically writes a structured note capturing files changed, tasks, commands, and decisions. `/catchup` at the start of a new session reconstructs exactly where you were. No user action required.
74
+
75
+ ### πŸ‘» Invisible Optimizations
76
+
77
+ Eight hook events fire automatically, nudging toward cheaper tools, redirecting file reads for 15-20% token savings, tracking changed files, and saving session state on exit.
78
+
79
+ <details>
80
+ <summary><strong>Hook event details</strong></summary>
81
+
82
+ | Hook | Trigger | What it does |
83
+ |---|---|---|
84
+ | `SessionStart` | Session opens | Validates config, injects last-session context |
85
+ | `UserPromptSubmit` | Every message | Nudges toward `search_code` over Grep/Explore for conceptual queries |
86
+ | `PreToolUse` (Read) | Before every Read | Blocks Read for text files, redirects to `read_file` for 15-20% token savings |
87
+ | `PreToolUse` (WebFetch / query-docs) | Before doc fetches | Suggests `search_documents` if library is cached (allows fetch either way) |
88
+ | `PostToolUse` (Write / Edit) | After every file write | Tracks changed files in a shadow git index |
89
+ | `Stop` | After Claude responds | Commits shadow index; triggers targeted re-index of changed files only |
90
+ | `PreCompact` | Before context compaction | Captures session state to notes before memory is lost |
91
+ | `SessionEnd` | Session closes | Writes session note (files, tasks, commands); extracts developer memories via LLM |
92
+
93
+ </details>
94
+
95
+ ---
96
+
97
+ ## πŸ—ΊοΈ When to Use What
98
+
99
+ | Need | Use | Notes |
100
+ |---|---|---|
101
+ | Find implementations by concept | `search_code` | Semantic, natural language queries |
102
+ | Exact string or regex match | Grep | Grep wins for exact matches |
103
+ | Find file by exact name | Glob | Glob wins for name patterns |
104
+ | Understand module structure | `browse_structure` | One call vs Glob + Read cascade |
105
+ | Read a specific known file | `read_file` | Cheaper than built-in Read for code files |
106
+ | Search cached documentation | `search_documents` | Far cheaper than re-fetching |
107
+ | Recall project conventions | `search_memory` | Global across all projects and sessions |
108
+
109
+ ---
110
+
111
+ ## πŸ“– Skills Reference
112
+
113
+ | Skill | What it does |
114
+ |---|---|
115
+ | `/search` | Guided semantic search with best-practice prompts |
116
+ | `/index` | Index or re-index a codebase with dry-run option |
117
+ | `/cache-docs` | Fetch and cache external documentation |
118
+ | `/catchup` | Search session notes and reconstruct where you left off |
119
+ | `/wrapup` | Extract decisions, rationale, open questions, and next actions from the conversation |
120
+
121
+ ---
122
+
123
+ <details>
124
+ <summary><strong>πŸ”₯ Why does this exist? (The Problem)</strong></summary>
125
+
126
+ Every new Claude Code session starts cold. You re-explain the architecture. You re-fetch the same docs. Claude reads the same files repeatedly, burning tokens just to get back to where you were.
127
+
128
+ | Task | Without Eidetic | With Eidetic |
129
+ |---|---|---|
130
+ | Find where auth errors are handled | Grep cascade, read 8 files, ~10,700 tokens | `search_code("auth error handling")` ~220 tokens |
131
+ | Resume after context compaction | Re-explain 20 min of context, ~2,000 tokens | `/catchup` ~200 tokens |
132
+ | Look up React hooks docs | Fetch docs page, ~5,000 tokens | `search_documents("React useEffect")` ~20 tokens |
133
+ | Read a 400-line file | Built-in Read with line numbers, ~900 tokens | `read_file(path)` ~740 tokens |
134
+
135
+ </details>
136
+
137
+ ---
138
+
139
+ ## πŸ“¦ Installation
140
+
141
+ ### Plugin (recommended)
142
+
143
+ ```bash
144
+ claude plugin install eidetics/claude-eidetic
145
+ ```
146
+
147
+ The plugin auto-starts the MCP server, installs skills, and configures hooks.
148
+
149
+ ### npx (manual MCP config)
150
+
151
+ Add to your `.mcp.json`:
152
+
153
+ ```json
154
+ {
155
+ "mcpServers": {
156
+ "claude-eidetic": {
157
+ "command": "npx",
158
+ "args": ["-y", "claude-eidetic"],
159
+ "env": {
160
+ "OPENAI_API_KEY": "sk-...",
161
+ "ANTHROPIC_API_KEY": "sk-ant-..."
162
+ }
163
+ }
164
+ }
165
+ }
166
+ ```
167
+
168
+ `ANTHROPIC_API_KEY` is needed for the memory LLM (default provider). Omit it if using `MEMORY_LLM_PROVIDER=openai` or `ollama`.
169
+
170
+ ### Global install
171
+
172
+ ```bash
173
+ npm install -g claude-eidetic
174
+ ```
175
+
176
+ ### From source
177
+
178
+ ```bash
179
+ git clone https://github.com/eidetics/claude-eidetic
180
+ cd claude-eidetic
181
+ npm install && npx tsc && npm start
182
+ ```
183
+
184
+ ### Requirements
185
+
186
+ - Node.js >= 20.0.0
187
+ - An API key (OpenAI for embeddings, Anthropic for memory extraction, or Ollama for both free)
188
+ - Docker (optional): Qdrant auto-provisions via Docker if not already running
189
+ - C/C++ build tools: required by tree-sitter native bindings (`node-gyp`)
190
+
191
+ ---
192
+
193
+ ## βš™οΈ Configuration
194
+
195
+ All configuration is via environment variables. No config files.
196
+
197
+ ### Using Ollama (free, local)
198
+
199
+ ```bash
200
+ export EMBEDDING_PROVIDER=ollama
201
+ export MEMORY_LLM_PROVIDER=ollama
202
+ # No API keys needed
203
+ ```
204
+
205
+ <details>
206
+ <summary><strong>Full configuration reference</strong></summary>
207
+
208
+ | Variable | Default | Description |
209
+ |---|---|---|
210
+ | `OPENAI_API_KEY` | _(required for openai)_ | OpenAI API key for embeddings and/or memory |
211
+ | `ANTHROPIC_API_KEY` | _(required for anthropic memory)_ | Anthropic API key for memory LLM |
212
+ | `EMBEDDING_PROVIDER` | `openai` | `openai`, `ollama`, or `local` |
213
+ | `EMBEDDING_MODEL` | `text-embedding-3-small` (openai) / `nomic-embed-text` (ollama) | Embedding model name |
214
+ | `EMBEDDING_BATCH_SIZE` | `100` | Batch size for embedding requests (1-2048) |
215
+ | `INDEXING_CONCURRENCY` | `8` | Parallel file indexing workers (1-32) |
216
+ | `OPENAI_BASE_URL` | _(none)_ | Custom OpenAI-compatible endpoint |
217
+ | `OLLAMA_BASE_URL` | `http://localhost:11434/v1` | Ollama server URL |
218
+ | `VECTORDB_PROVIDER` | `qdrant` | `qdrant` or `milvus` |
219
+ | `QDRANT_URL` | `http://localhost:6333` | Qdrant server URL |
220
+ | `QDRANT_API_KEY` | _(none)_ | Qdrant API key (for remote/cloud instances) |
221
+ | `MILVUS_ADDRESS` | `localhost:19530` | Milvus server address |
222
+ | `MILVUS_TOKEN` | _(none)_ | Milvus authentication token |
223
+ | `EIDETIC_DATA_DIR` | `~/.eidetic/` | Data root for snapshots, memory DB, registry |
224
+ | `CUSTOM_EXTENSIONS` | `[]` | JSON array of extra file extensions to index (e.g., `[".dart",".arb"]`) |
225
+ | `CUSTOM_IGNORE_PATTERNS` | `[]` | JSON array of glob patterns to exclude |
226
+ | `MEMORY_LLM_PROVIDER` | `anthropic` | `anthropic`, `openai`, or `ollama` |
227
+ | `MEMORY_LLM_MODEL` | `claude-haiku-4-5-20251001` (anthropic) / `gpt-4o-mini` (openai) / `llama3.2` (ollama) | Model for memory extraction |
228
+ | `MEMORY_LLM_BASE_URL` | _(none)_ | Custom base URL for memory LLM |
229
+ | `MEMORY_LLM_API_KEY` | _(none)_ | API key override for memory LLM |
230
+
231
+ </details>
232
+
233
+ ---
234
+
235
+ <details>
236
+ <summary><strong>πŸ”§ Tool Reference</strong></summary>
237
+
238
+ ### πŸ” Code Search
239
+
240
+ | Tool | Description |
241
+ |---|---|
242
+ | `search_code` | Hybrid semantic search over indexed codebase. Returns compact results by default. |
243
+ | `index_codebase` | Index a directory. Supports `dryRun`, `force`, `customExtensions`, `customIgnorePatterns`. |
244
+ | `list_indexed` | List all indexed codebases with file/chunk counts and status. |
245
+ | `get_indexing_status` | Check indexing progress for a path or project. |
246
+ | `clear_index` | Remove the search index for a codebase. |
247
+ | `cleanup_vectors` | Remove orphaned vectors for deleted files. No re-embedding cost. |
248
+ | `browse_structure` | Condensed structural map: classes, functions, methods with signatures, grouped by file. |
249
+ | `list_symbols` | Compact symbol table with name/kind/file/line. Supports name, kind, and path filters. |
250
+
251
+ ### πŸ“„ File Reading
252
+
253
+ | Tool | Description |
254
+ |---|---|
255
+ | `read_file` | Read file without line-number overhead. Cheaper than built-in Read for code files. |
256
+
257
+ ### πŸ“š Documentation Cache
258
+
259
+ | Tool | Description |
260
+ |---|---|
261
+ | `index_document` | Cache external documentation for semantic search. Supports TTL for staleness tracking. |
262
+ | `search_documents` | Search cached docs. Far cheaper than re-fetching the same page. |
263
+
264
+ ### 🧠 Memory
265
+
266
+ | Tool | Description |
267
+ |---|---|
268
+ | `add_memory` | LLM-extracted facts from text. Auto-deduplicates. Seven categories. |
269
+ | `search_memory` | Semantic search over stored memories. Filterable by category. |
270
+ | `list_memories` | List all memories, optionally filtered by category. |
271
+ | `delete_memory` | Delete a specific memory by UUID. |
272
+ | `memory_history` | View change history for a memory (additions, updates, deletions). |
273
+
274
+ </details>
275
+
276
+ ---
277
+
278
+ ## 🌐 Supported Languages
279
+
280
+ **AST-aware** (functions and classes chunked intact):
281
+
282
+ <p>
283
+ <img src="https://img.shields.io/badge/JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=black" alt="JavaScript"/>
284
+ <img src="https://img.shields.io/badge/TypeScript-3178C6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript"/>
285
+ <img src="https://img.shields.io/badge/React_(JSX/TSX)-61DAFB?style=flat-square&logo=react&logoColor=black" alt="JSX/TSX"/>
286
+ <img src="https://img.shields.io/badge/Python-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python"/>
287
+ <img src="https://img.shields.io/badge/Go-00ADD8?style=flat-square&logo=go&logoColor=white" alt="Go"/>
288
+ <img src="https://img.shields.io/badge/Java-ED8B00?style=flat-square&logo=openjdk&logoColor=white" alt="Java"/>
289
+ <img src="https://img.shields.io/badge/Rust-000000?style=flat-square&logo=rust&logoColor=white" alt="Rust"/>
290
+ <img src="https://img.shields.io/badge/C-A8B9CC?style=flat-square&logo=c&logoColor=black" alt="C"/>
291
+ <img src="https://img.shields.io/badge/C++-00599C?style=flat-square&logo=cplusplus&logoColor=white" alt="C++"/>
292
+ <img src="https://img.shields.io/badge/C%23-512BD4?style=flat-square&logo=csharp&logoColor=white" alt="C#"/>
293
+ </p>
294
+
295
+ **Line-based fallback** (sliding window chunking for everything else):
296
+
297
+ <p>
298
+ <img src="https://img.shields.io/badge/Markdown-000000?style=flat-square&logo=markdown&logoColor=white" alt="Markdown"/>
299
+ <img src="https://img.shields.io/badge/YAML-CB171E?style=flat-square&logo=yaml&logoColor=white" alt="YAML"/>
300
+ <img src="https://img.shields.io/badge/JSON-000000?style=flat-square&logo=json&logoColor=white" alt="JSON"/>
301
+ <img src="https://img.shields.io/badge/Ruby-CC342D?style=flat-square&logo=ruby&logoColor=white" alt="Ruby"/>
302
+ <img src="https://img.shields.io/badge/PHP-777BB4?style=flat-square&logo=php&logoColor=white" alt="PHP"/>
303
+ <img src="https://img.shields.io/badge/Swift-F05138?style=flat-square&logo=swift&logoColor=white" alt="Swift"/>
304
+ <img src="https://img.shields.io/badge/Kotlin-7F52FF?style=flat-square&logo=kotlin&logoColor=white" alt="Kotlin"/>
305
+ <img src="https://img.shields.io/badge/and_more...-30363d?style=flat-square" alt="and more"/>
306
+ </p>
307
+
308
+ ---
309
+
310
+ ## πŸ› οΈ Development
311
+
312
+ ```bash
313
+ npm install && npx tsc # install and build
314
+ npm run dev # watch mode (tsx)
315
+ npm test # unit tests (no external services needed)
316
+ npm run test:integration # requires Qdrant at localhost:6333 + OPENAI_API_KEY
317
+ ```
318
+
319
+ **Commit format:** `type(scope): description`
320
+ Types: `feat`, `fix`, `docs`, `refactor`, `perf`, `chore`, `test`
321
+ Scopes: `embedding`, `vectordb`, `splitter`, `indexer`, `mcp`, `infra`, `config`
322
+
323
+ ---
324
+
325
+ ## πŸ™ Acknowledgements
326
+
327
+ Heavily inspired by [mem0](https://github.com/mem0ai/mem0), [claude-mem](https://github.com/thedotmack/claude-mem), and [claude-context](https://github.com/zilliztech/claude-context). Documentation retrieval powered by [context7](https://github.com/upstash/context7).
328
+
329
+ ---
330
+
331
+ ## πŸ“„ License
332
+
333
+ MIT
package/dist/index.js CHANGED
@@ -21,48 +21,48 @@ import { getSetupErrorMessage } from './setup-message.js';
21
21
  import { MemoryStore } from './memory/store.js';
22
22
  import { MemoryHistory } from './memory/history.js';
23
23
  import { getMemoryDbPath } from './paths.js';
24
- const WORKFLOW_GUIDANCE = `# Eidetic Code Search Workflow
25
-
26
- **Before searching:** Ensure the codebase is indexed.
27
- - \`list_indexed\` β†’ see what's already indexed
28
- - \`index_codebase(path="...", dryRun=true)\` β†’ preview before indexing
29
- - \`index_codebase(path="...")\` β†’ index (incremental, only re-embeds changed files)
30
-
31
- **Searching efficiently:**
32
- - \`search_code(query="...")\` β†’ returns compact table by default (~20 tokens/result)
33
- - Review the table, then use Read tool to fetch full code for interesting results
34
- - Add \`compact=false\` only when you need all code snippets immediately
35
- - Use \`extensionFilter\` to narrow by file type
36
- - Use \`project\` param instead of \`path\` for convenience
37
- - Start with specific queries, broaden if no results
38
-
39
- **Reading files efficiently:**
40
- - \`read_file(path="...")\` β†’ raw content without line-number overhead (~15-20% fewer tokens for code, more for short-line files)
41
- - Use \`offset\` and \`limit\` to page through large files
42
- - Add \`lineNumbers=true\` only when you need line references for editing
43
-
44
- **After first index:**
45
- - Re-indexing is incremental (only changed files re-embedded)
46
- - Use \`project\` param instead of \`path\` for convenience
47
- - Use \`get_indexing_status\` to check progress during long indexes
48
- - Use \`cleanup_vectors(path="...", dryRun=true)\` to preview stale vectors, then without dryRun to remove them (no embedding cost)
49
-
50
- **Cross-project search:**
51
- - Index multiple projects, each with its own path
52
- - Search across any indexed project regardless of current working directory
53
-
54
- **Documentation caching (saves ~5K tokens per repeated doc fetch):**
55
- - After fetching docs via query-docs or WebFetch, cache them: \`index_document(content="...", source="<url>", library="<name>", topic="<topic>")\`
56
- - Next time you need the same docs: \`search_documents(query="...", library="<name>")\` (~20 tokens/result)
57
- - Docs are grouped by library β€” one collection per library, searchable across topics
58
- - Stale docs (past TTL) still return results but are flagged \`[STALE]\`
59
-
60
- **Persistent memory (cross-session developer knowledge):**
61
- - \`add_memory(content="...")\` β†’ extracts facts about coding style, tools, architecture, etc.
62
- - \`search_memory(query="...")\` β†’ find relevant memories by semantic search
63
- - \`list_memories()\` β†’ see all stored memories grouped by category
64
- - \`delete_memory(id="...")\` β†’ remove a specific memory
65
- - \`memory_history(id="...")\` β†’ view change log for a memory
24
+ const WORKFLOW_GUIDANCE = `# Eidetic Code Search Workflow
25
+
26
+ **Before searching:** Ensure the codebase is indexed.
27
+ - \`list_indexed\` β†’ see what's already indexed
28
+ - \`index_codebase(path="...", dryRun=true)\` β†’ preview before indexing
29
+ - \`index_codebase(path="...")\` β†’ index (incremental, only re-embeds changed files)
30
+
31
+ **Searching efficiently:**
32
+ - \`search_code(query="...")\` β†’ returns compact table by default (~20 tokens/result)
33
+ - Review the table, then use Read tool to fetch full code for interesting results
34
+ - Add \`compact=false\` only when you need all code snippets immediately
35
+ - Use \`extensionFilter\` to narrow by file type
36
+ - Use \`project\` param instead of \`path\` for convenience
37
+ - Start with specific queries, broaden if no results
38
+
39
+ **Reading files efficiently:**
40
+ - \`read_file(path="...")\` β†’ raw content without line-number overhead (~15-20% fewer tokens for code, more for short-line files)
41
+ - Use \`offset\` and \`limit\` to page through large files
42
+ - Add \`lineNumbers=true\` only when you need line references for editing
43
+
44
+ **After first index:**
45
+ - Re-indexing is incremental (only changed files re-embedded)
46
+ - Use \`project\` param instead of \`path\` for convenience
47
+ - Use \`get_indexing_status\` to check progress during long indexes
48
+ - Use \`cleanup_vectors(path="...", dryRun=true)\` to preview stale vectors, then without dryRun to remove them (no embedding cost)
49
+
50
+ **Cross-project search:**
51
+ - Index multiple projects, each with its own path
52
+ - Search across any indexed project regardless of current working directory
53
+
54
+ **Documentation caching (saves ~5K tokens per repeated doc fetch):**
55
+ - After fetching docs via query-docs or WebFetch, cache them: \`index_document(content="...", source="<url>", library="<name>", topic="<topic>")\`
56
+ - Next time you need the same docs: \`search_documents(query="...", library="<name>")\` (~20 tokens/result)
57
+ - Docs are grouped by library β€” one collection per library, searchable across topics
58
+ - Stale docs (past TTL) still return results but are flagged \`[STALE]\`
59
+
60
+ **Persistent memory (cross-session developer knowledge):**
61
+ - \`add_memory(content="...")\` β†’ extracts facts about coding style, tools, architecture, etc.
62
+ - \`search_memory(query="...")\` β†’ find relevant memories by semantic search
63
+ - \`list_memories()\` β†’ see all stored memories grouped by category
64
+ - \`delete_memory(id="...")\` β†’ remove a specific memory
65
+ - \`memory_history(id="...")\` β†’ view change log for a memory
66
66
  - Memories are automatically deduplicated β€” adding similar facts updates existing ones`;
67
67
  async function main() {
68
68
  const config = loadConfig();
@@ -7,24 +7,24 @@ export class MemoryHistory {
7
7
  mkdirSync(dirname(dbPath), { recursive: true });
8
8
  this.db = new Database(dbPath);
9
9
  this.db.pragma('journal_mode = WAL');
10
- this.db.exec(`
11
- CREATE TABLE IF NOT EXISTS memory_history (
12
- id INTEGER PRIMARY KEY AUTOINCREMENT,
13
- memory_id TEXT NOT NULL,
14
- previous_value TEXT,
15
- new_value TEXT,
16
- event TEXT NOT NULL,
17
- created_at TEXT NOT NULL,
18
- updated_at TEXT,
19
- source TEXT
20
- )
10
+ this.db.exec(`
11
+ CREATE TABLE IF NOT EXISTS memory_history (
12
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
13
+ memory_id TEXT NOT NULL,
14
+ previous_value TEXT,
15
+ new_value TEXT,
16
+ event TEXT NOT NULL,
17
+ created_at TEXT NOT NULL,
18
+ updated_at TEXT,
19
+ source TEXT
20
+ )
21
21
  `);
22
22
  }
23
23
  log(memoryId, event, newValue, previousValue = null, source = null, updatedAt = null) {
24
24
  this.db
25
- .prepare(`
26
- INSERT INTO memory_history (memory_id, previous_value, new_value, event, created_at, updated_at, source)
27
- VALUES (?, ?, ?, ?, ?, ?, ?)
25
+ .prepare(`
26
+ INSERT INTO memory_history (memory_id, previous_value, new_value, event, created_at, updated_at, source)
27
+ VALUES (?, ?, ?, ?, ?, ?, ?)
28
28
  `)
29
29
  .run(memoryId, previousValue, newValue, event, new Date().toISOString(), updatedAt, source);
30
30
  }
@@ -1,30 +1,30 @@
1
- export const FACT_EXTRACTION_SYSTEM_PROMPT = `You are a developer knowledge extractor. Your job is to extract discrete, factual statements from conversations about software development.
2
-
3
- Extract facts about:
4
- - **coding_style**: Formatting preferences (tabs/spaces, naming conventions, line length), code style rules
5
- - **tools**: Preferred tools, frameworks, libraries, test runners, bundlers, linters, editors
6
- - **architecture**: Design patterns, architectural decisions, system design preferences
7
- - **conventions**: Project conventions, commit message formats, branch naming, PR workflows
8
- - **debugging**: Solutions to specific bugs, debugging techniques, known issues
9
- - **workflow**: Development habits, deployment processes, review preferences
10
- - **preferences**: General preferences, opinions, requirements that don't fit other categories
11
-
12
- Rules:
13
- 1. Extract only factual, concrete statements β€” not vague observations
14
- 2. Each fact should be a single, self-contained statement
15
- 3. Use third person ("The user prefers..." or state the fact directly)
16
- 4. If the input contains no extractable facts, return an empty array
17
- 5. Do NOT extract facts about the conversation itself (e.g., "the user asked about...")
18
- 6. Do NOT extract temporary or session-specific information
19
- 7. Prefer specific facts over general ones
20
-
21
- Respond with JSON: { "facts": [{ "fact": "...", "category": "..." }] }
22
-
1
+ export const FACT_EXTRACTION_SYSTEM_PROMPT = `You are a developer knowledge extractor. Your job is to extract discrete, factual statements from conversations about software development.
2
+
3
+ Extract facts about:
4
+ - **coding_style**: Formatting preferences (tabs/spaces, naming conventions, line length), code style rules
5
+ - **tools**: Preferred tools, frameworks, libraries, test runners, bundlers, linters, editors
6
+ - **architecture**: Design patterns, architectural decisions, system design preferences
7
+ - **conventions**: Project conventions, commit message formats, branch naming, PR workflows
8
+ - **debugging**: Solutions to specific bugs, debugging techniques, known issues
9
+ - **workflow**: Development habits, deployment processes, review preferences
10
+ - **preferences**: General preferences, opinions, requirements that don't fit other categories
11
+
12
+ Rules:
13
+ 1. Extract only factual, concrete statements β€” not vague observations
14
+ 2. Each fact should be a single, self-contained statement
15
+ 3. Use third person ("The user prefers..." or state the fact directly)
16
+ 4. If the input contains no extractable facts, return an empty array
17
+ 5. Do NOT extract facts about the conversation itself (e.g., "the user asked about...")
18
+ 6. Do NOT extract temporary or session-specific information
19
+ 7. Prefer specific facts over general ones
20
+
21
+ Respond with JSON: { "facts": [{ "fact": "...", "category": "..." }] }
22
+
23
23
  Categories: coding_style, tools, architecture, conventions, debugging, workflow, preferences`;
24
- export const FACT_EXTRACTION_USER_TEMPLATE = `Extract developer knowledge facts from this text:
25
-
26
- <text>
27
- {content}
24
+ export const FACT_EXTRACTION_USER_TEMPLATE = `Extract developer knowledge facts from this text:
25
+
26
+ <text>
27
+ {content}
28
28
  </text>`;
29
29
  export function buildSystemPrompt() {
30
30
  const today = new Date().toISOString().slice(0, 10);
@@ -1,58 +1,58 @@
1
- const READ_FILE_DESCRIPTION = `\
2
- Read a file and return raw content without line-number overhead (~15-20% fewer tokens than built-in Read for code, more for short-line files).
3
-
4
- Use offset and limit to page through large files. \
1
+ const READ_FILE_DESCRIPTION = `\
2
+ Read a file and return raw content without line-number overhead (~15-20% fewer tokens than built-in Read for code, more for short-line files).
3
+
4
+ Use offset and limit to page through large files. \
5
5
  Add lineNumbers=true only when you need line references for editing.`;
6
- const INDEX_DOCUMENT_DESCRIPTION = `\
7
- Cache external documentation (from query-docs, WebFetch, etc.) for cheap semantic search later.
8
-
9
- After fetching documentation from an external source, call this tool to store it. \
10
- Subsequent queries about the same library will use search_documents (~20 tokens/result) \
11
- instead of re-fetching (~5K+ tokens).
12
-
13
- The content is split into chunks, embedded, and stored in a vector collection grouped by library. \
6
+ const INDEX_DOCUMENT_DESCRIPTION = `\
7
+ Cache external documentation (from query-docs, WebFetch, etc.) for cheap semantic search later.
8
+
9
+ After fetching documentation from an external source, call this tool to store it. \
10
+ Subsequent queries about the same library will use search_documents (~20 tokens/result) \
11
+ instead of re-fetching (~5K+ tokens).
12
+
13
+ The content is split into chunks, embedded, and stored in a vector collection grouped by library. \
14
14
  A TTL tracks staleness β€” stale docs still return results but are flagged.`;
15
- const SEARCH_DOCUMENTS_DESCRIPTION = `\
16
- Search cached documentation using natural language queries.
17
-
18
- Returns results from previously cached documentation (via index_document). \
19
- Much cheaper than re-fetching docs (~20 tokens/result vs ~5K+ tokens/fetch).
20
-
21
- If a specific library is provided, searches only that library's collection. \
15
+ const SEARCH_DOCUMENTS_DESCRIPTION = `\
16
+ Search cached documentation using natural language queries.
17
+
18
+ Returns results from previously cached documentation (via index_document). \
19
+ Much cheaper than re-fetching docs (~20 tokens/result vs ~5K+ tokens/fetch).
20
+
21
+ If a specific library is provided, searches only that library's collection. \
22
22
  Otherwise searches across all cached documentation. Results include staleness indicators.`;
23
- const CLEANUP_DESCRIPTION = `\
24
- Remove orphaned vectors for files that no longer exist on disk. Lightweight alternative to re-indexing β€” no embedding cost.
25
-
26
- Provide either \`path\` (absolute) or \`project\` (name). Use \`list_indexed\` to see registered projects.
27
-
23
+ const CLEANUP_DESCRIPTION = `\
24
+ Remove orphaned vectors for files that no longer exist on disk. Lightweight alternative to re-indexing β€” no embedding cost.
25
+
26
+ Provide either \`path\` (absolute) or \`project\` (name). Use \`list_indexed\` to see registered projects.
27
+
28
28
  Use \`dryRun=true\` first to preview which files would be cleaned without making any changes.`;
29
- const INDEX_DESCRIPTION = `\
30
- Index a codebase directory to enable semantic search using a configurable code splitter.
31
-
32
- Provide either \`path\` (absolute) or \`project\` (name). Use \`list_indexed\` to see registered projects.
33
-
34
- Usage Guidance:
35
- - Use dryRun=true first to preview what files would be indexed and catch configuration issues before committing to a full index.
36
- - This tool is typically used when search fails due to an unindexed codebase.
37
- - If indexing is attempted on an already indexed path, and a conflict is detected, \
29
+ const INDEX_DESCRIPTION = `\
30
+ Index a codebase directory to enable semantic search using a configurable code splitter.
31
+
32
+ Provide either \`path\` (absolute) or \`project\` (name). Use \`list_indexed\` to see registered projects.
33
+
34
+ Usage Guidance:
35
+ - Use dryRun=true first to preview what files would be indexed and catch configuration issues before committing to a full index.
36
+ - This tool is typically used when search fails due to an unindexed codebase.
37
+ - If indexing is attempted on an already indexed path, and a conflict is detected, \
38
38
  you MUST prompt the user to confirm whether to proceed with a force index.`;
39
- const SEARCH_DESCRIPTION = `\
40
- Search the indexed codebase using natural language queries.
41
- Prefer over Grep for conceptual/semantic queries β€” returns ~20 tokens/result vs ~100+ for Grep.
42
- Try before launching an Explore agent β€” faster and cheaper for understanding code.
43
-
44
- Provide either \`path\` (absolute) or \`project\` (name). Use \`list_indexed\` to see registered projects.
45
-
46
- When to Use:
47
- - Code search: Find specific functions, classes, or implementations
48
- - Context-aware assistance: Gather relevant code context before making changes
49
- - Issue identification: Locate problematic code sections or bugs
50
- - Code review: Understand existing implementations and patterns
51
- - Refactoring: Find all related code pieces that need to be updated
52
- - Feature development: Understand existing architecture and similar implementations
53
- - Duplicate detection: Identify redundant or duplicated code patterns
54
-
55
- If the codebase is not indexed, this tool will return a clear error message \
39
+ const SEARCH_DESCRIPTION = `\
40
+ Search the indexed codebase using natural language queries.
41
+ Prefer over Grep for conceptual/semantic queries β€” returns ~20 tokens/result vs ~100+ for Grep.
42
+ Try before launching an Explore agent β€” faster and cheaper for understanding code.
43
+
44
+ Provide either \`path\` (absolute) or \`project\` (name). Use \`list_indexed\` to see registered projects.
45
+
46
+ When to Use:
47
+ - Code search: Find specific functions, classes, or implementations
48
+ - Context-aware assistance: Gather relevant code context before making changes
49
+ - Issue identification: Locate problematic code sections or bugs
50
+ - Code review: Understand existing implementations and patterns
51
+ - Refactoring: Find all related code pieces that need to be updated
52
+ - Feature development: Understand existing architecture and similar implementations
53
+ - Duplicate detection: Identify redundant or duplicated code patterns
54
+
55
+ If the codebase is not indexed, this tool will return a clear error message \
56
56
  indicating that indexing is required first.`;
57
57
  export const TOOL_DEFINITIONS = [
58
58
  {
package/messages.yaml CHANGED
@@ -1,50 +1,50 @@
1
- # Eidetic user-facing messages β€” edit here, everything else reads from this file.
2
-
3
- setup:
4
- missing:
5
- header: "Eidetic setup required: No API key configured."
6
- diagnosis: >
7
- `OPENAI_API_KEY` is not set and no alternative provider is configured.
8
- step1: "**Get an API key**: https://platform.openai.com/api-keys"
9
-
10
- invalid:
11
- header: "Eidetic setup failed: {error}"
12
- diagnosis: >
13
- Key/provider is configured but initialization failed.
14
- The key may be invalid, expired, or the provider may be unreachable.
15
- step1: "**Verify your key** is valid and has embedding permissions"
16
-
17
- unknown:
18
- header: "Eidetic setup failed: {error}"
19
- diagnosis: ""
20
- step1: "**Get an API key**: https://platform.openai.com/api-keys"
21
-
22
- # Shared across all contexts
23
- config_instructions: |
24
- ### Windows
25
- ```
26
- setx OPENAI_API_KEY sk-your-key-here
27
- ```
28
-
29
- ### macOS / Linux
30
- Add to your shell profile (`~/.bashrc`, `~/.zshrc`, etc.):
31
- ```
32
- export OPENAI_API_KEY="sk-your-key-here"
33
- ```
34
-
35
- ### Manual
36
-
37
- Edit `~/.claude/plugins/claude-eidetic/config.json`:
38
- ```json
39
- {
40
- "env": {
41
- "OPENAI_API_KEY": "sk-your-key-here"
42
- }
43
- }
44
- ```
45
-
46
- ### Using Ollama instead (free, local)
47
-
48
- Set `EMBEDDING_PROVIDER=ollama` in the same env block (requires Ollama running locally with `nomic-embed-text`).
49
-
50
- footer: "**Restart Claude Code** for changes to take effect."
1
+ # Eidetic user-facing messages β€” edit here, everything else reads from this file.
2
+
3
+ setup:
4
+ missing:
5
+ header: "Eidetic setup required: No API key configured."
6
+ diagnosis: >
7
+ `OPENAI_API_KEY` is not set and no alternative provider is configured.
8
+ step1: "**Get an API key**: https://platform.openai.com/api-keys"
9
+
10
+ invalid:
11
+ header: "Eidetic setup failed: {error}"
12
+ diagnosis: >
13
+ Key/provider is configured but initialization failed.
14
+ The key may be invalid, expired, or the provider may be unreachable.
15
+ step1: "**Verify your key** is valid and has embedding permissions"
16
+
17
+ unknown:
18
+ header: "Eidetic setup failed: {error}"
19
+ diagnosis: ""
20
+ step1: "**Get an API key**: https://platform.openai.com/api-keys"
21
+
22
+ # Shared across all contexts
23
+ config_instructions: |
24
+ ### Windows
25
+ ```
26
+ setx OPENAI_API_KEY sk-your-key-here
27
+ ```
28
+
29
+ ### macOS / Linux
30
+ Add to your shell profile (`~/.bashrc`, `~/.zshrc`, etc.):
31
+ ```
32
+ export OPENAI_API_KEY="sk-your-key-here"
33
+ ```
34
+
35
+ ### Manual
36
+
37
+ Edit `~/.claude/plugins/claude-eidetic/config.json`:
38
+ ```json
39
+ {
40
+ "env": {
41
+ "OPENAI_API_KEY": "sk-your-key-here"
42
+ }
43
+ }
44
+ ```
45
+
46
+ ### Using Ollama instead (free, local)
47
+
48
+ Set `EMBEDDING_PROVIDER=ollama` in the same env block (requires Ollama running locally with `nomic-embed-text`).
49
+
50
+ footer: "**Restart Claude Code** for changes to take effect."
package/package.json CHANGED
@@ -1,87 +1,87 @@
1
- {
2
- "name": "claude-eidetic",
3
- "version": "0.1.2",
4
- "description": "Semantic code search MCP server β€” lean, correct, fast",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "bin": {
8
- "claude-eidetic": "dist/index.js"
9
- },
10
- "files": [
11
- "dist/**/*.js",
12
- "dist/**/*.d.ts",
13
- "!dist/**/*.test.*",
14
- "!dist/__tests__/**",
15
- "!dist/**/tests/**",
16
- "!dist/e2e/**",
17
- "messages.yaml"
18
- ],
19
- "scripts": {
20
- "build": "tsc",
21
- "dev": "tsx --watch src/index.ts",
22
- "start": "node dist/index.js",
23
- "clean": "rimraf dist",
24
- "lint": "eslint src/",
25
- "lint:fix": "eslint src/ --fix",
26
- "format": "prettier --write \"src/**/*.ts\"",
27
- "format:check": "prettier --check \"src/**/*.ts\"",
28
- "typecheck": "tsc --noEmit",
29
- "test": "vitest run",
30
- "test:watch": "vitest",
31
- "test:coverage": "vitest run --coverage",
32
- "test:integration": "vitest run --config vitest.integration.config.ts",
33
- "test:all": "vitest run && vitest run --config vitest.integration.config.ts",
34
- "test:eval": "tsx scripts/eval/recall-at-k.ts && tsx scripts/eval/fusion-lift.ts && tsx scripts/eval/ndcg.ts",
35
- "test:eval:generate": "tsx scripts/eval/generate-queries.ts",
36
- "prepublishOnly": "npm run clean && npm run build",
37
- "release": "bash scripts/release.sh"
38
- },
39
- "dependencies": {
40
- "@anthropic-ai/sdk": "^0.78.0",
41
- "@modelcontextprotocol/sdk": "^1.12.1",
42
- "@qdrant/js-client-rest": "^1.13.0",
43
- "better-sqlite3": "^12.6.2",
44
- "glob": "^11.0.0",
45
- "openai": "^5.1.1",
46
- "tree-sitter": "^0.21.1",
47
- "tree-sitter-c-sharp": "^0.21.0",
48
- "tree-sitter-cpp": "^0.22.0",
49
- "tree-sitter-go": "^0.21.0",
50
- "tree-sitter-java": "^0.21.0",
51
- "tree-sitter-javascript": "^0.21.0",
52
- "tree-sitter-python": "^0.21.0",
53
- "tree-sitter-rust": "^0.21.0",
54
- "tree-sitter-typescript": "^0.21.0",
55
- "yaml": "^2.8.2",
56
- "zod": "^3.25.0"
57
- },
58
- "optionalDependencies": {
59
- "@zilliz/milvus2-sdk-node": "^2.5.10"
60
- },
61
- "devDependencies": {
62
- "@eslint/js": "^9.39.3",
63
- "@types/better-sqlite3": "^7.6.13",
64
- "@types/node": "^20.0.0",
65
- "@vitest/coverage-v8": "^4.0.18",
66
- "eslint": "^9.39.3",
67
- "eslint-config-prettier": "^10.1.8",
68
- "prettier": "^3.8.1",
69
- "rimraf": "^6.0.1",
70
- "tsx": "^4.19.4",
71
- "typescript": "^5.8.3",
72
- "typescript-eslint": "^8.56.0",
73
- "vitest": "^4.0.18"
74
- },
75
- "overrides": {
76
- "minimatch": "^10.2.1",
77
- "@grpc/grpc-js": "^1.8.22"
78
- },
79
- "engines": {
80
- "node": ">=20.0.0"
81
- },
82
- "repository": {
83
- "type": "git",
84
- "url": "https://github.com/eidetics/claude-eidetic"
85
- },
86
- "license": "MIT"
87
- }
1
+ {
2
+ "name": "claude-eidetic",
3
+ "version": "0.1.3",
4
+ "description": "Semantic code search MCP server β€” lean, correct, fast",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "claude-eidetic": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist/**/*.js",
12
+ "dist/**/*.d.ts",
13
+ "!dist/**/*.test.*",
14
+ "!dist/__tests__/**",
15
+ "!dist/**/tests/**",
16
+ "!dist/e2e/**",
17
+ "messages.yaml"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "dev": "tsx --watch src/index.ts",
22
+ "start": "node dist/index.js",
23
+ "clean": "rimraf dist",
24
+ "lint": "eslint src/",
25
+ "lint:fix": "eslint src/ --fix",
26
+ "format": "prettier --write \"src/**/*.ts\"",
27
+ "format:check": "prettier --check \"src/**/*.ts\"",
28
+ "typecheck": "tsc --noEmit",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest",
31
+ "test:coverage": "vitest run --coverage",
32
+ "test:integration": "vitest run --config vitest.integration.config.ts",
33
+ "test:all": "vitest run && vitest run --config vitest.integration.config.ts",
34
+ "test:eval": "tsx scripts/eval/recall-at-k.ts && tsx scripts/eval/fusion-lift.ts && tsx scripts/eval/ndcg.ts",
35
+ "test:eval:generate": "tsx scripts/eval/generate-queries.ts",
36
+ "prepublishOnly": "npm run clean && npm run build",
37
+ "release": "bash scripts/release.sh"
38
+ },
39
+ "dependencies": {
40
+ "@anthropic-ai/sdk": "^0.78.0",
41
+ "@modelcontextprotocol/sdk": "^1.12.1",
42
+ "@qdrant/js-client-rest": "^1.13.0",
43
+ "better-sqlite3": "^12.6.2",
44
+ "glob": "^11.0.0",
45
+ "openai": "^5.1.1",
46
+ "tree-sitter": "^0.21.1",
47
+ "tree-sitter-c-sharp": "^0.21.0",
48
+ "tree-sitter-cpp": "^0.22.0",
49
+ "tree-sitter-go": "^0.21.0",
50
+ "tree-sitter-java": "^0.21.0",
51
+ "tree-sitter-javascript": "^0.21.0",
52
+ "tree-sitter-python": "^0.21.0",
53
+ "tree-sitter-rust": "^0.21.0",
54
+ "tree-sitter-typescript": "^0.21.0",
55
+ "yaml": "^2.8.2",
56
+ "zod": "^3.25.0"
57
+ },
58
+ "optionalDependencies": {
59
+ "@zilliz/milvus2-sdk-node": "^2.5.10"
60
+ },
61
+ "devDependencies": {
62
+ "@eslint/js": "^9.39.3",
63
+ "@types/better-sqlite3": "^7.6.13",
64
+ "@types/node": "^20.0.0",
65
+ "@vitest/coverage-v8": "^4.0.18",
66
+ "eslint": "^9.39.3",
67
+ "eslint-config-prettier": "^10.1.8",
68
+ "prettier": "^3.8.1",
69
+ "rimraf": "^6.0.1",
70
+ "tsx": "^4.19.4",
71
+ "typescript": "^5.8.3",
72
+ "typescript-eslint": "^8.56.0",
73
+ "vitest": "^4.0.18"
74
+ },
75
+ "overrides": {
76
+ "minimatch": "^10.2.1",
77
+ "@grpc/grpc-js": "^1.8.22"
78
+ },
79
+ "engines": {
80
+ "node": ">=20.0.0"
81
+ },
82
+ "repository": {
83
+ "type": "git",
84
+ "url": "https://github.com/eidetics/claude-eidetic"
85
+ },
86
+ "license": "MIT"
87
+ }