pindex 1.0.0

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.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +767 -0
  3. package/dist/cli/daemon.d.ts +13 -0
  4. package/dist/cli/daemon.d.ts.map +1 -0
  5. package/dist/cli/daemon.js +70 -0
  6. package/dist/cli/daemon.js.map +1 -0
  7. package/dist/cli/index.d.ts +4 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +212 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/init.d.ts +44 -0
  12. package/dist/cli/init.d.ts.map +1 -0
  13. package/dist/cli/init.js +301 -0
  14. package/dist/cli/init.js.map +1 -0
  15. package/dist/cli/project-detector.d.ts +44 -0
  16. package/dist/cli/project-detector.d.ts.map +1 -0
  17. package/dist/cli/project-detector.js +144 -0
  18. package/dist/cli/project-detector.js.map +1 -0
  19. package/dist/cli/setup.d.ts +9 -0
  20. package/dist/cli/setup.d.ts.map +1 -0
  21. package/dist/cli/setup.js +110 -0
  22. package/dist/cli/setup.js.map +1 -0
  23. package/dist/db/database.d.ts +5 -0
  24. package/dist/db/database.d.ts.map +1 -0
  25. package/dist/db/database.js +19 -0
  26. package/dist/db/database.js.map +1 -0
  27. package/dist/db/migrations.d.ts +6 -0
  28. package/dist/db/migrations.d.ts.map +1 -0
  29. package/dist/db/migrations.js +32 -0
  30. package/dist/db/migrations.js.map +1 -0
  31. package/dist/db/queries.d.ts +132 -0
  32. package/dist/db/queries.d.ts.map +1 -0
  33. package/dist/db/queries.js +222 -0
  34. package/dist/db/queries.js.map +1 -0
  35. package/dist/db/schema.d.ts +5 -0
  36. package/dist/db/schema.d.ts.map +1 -0
  37. package/dist/db/schema.js +179 -0
  38. package/dist/db/schema.js.map +1 -0
  39. package/dist/gui/index.d.ts +3 -0
  40. package/dist/gui/index.d.ts.map +1 -0
  41. package/dist/gui/index.js +56 -0
  42. package/dist/gui/index.js.map +1 -0
  43. package/dist/gui/server.d.ts +31 -0
  44. package/dist/gui/server.d.ts.map +1 -0
  45. package/dist/gui/server.js +729 -0
  46. package/dist/gui/server.js.map +1 -0
  47. package/dist/index.d.ts +3 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +93 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/indexer/index.d.ts +38 -0
  52. package/dist/indexer/index.d.ts.map +1 -0
  53. package/dist/indexer/index.js +283 -0
  54. package/dist/indexer/index.js.map +1 -0
  55. package/dist/indexer/parser.d.ts +20 -0
  56. package/dist/indexer/parser.d.ts.map +1 -0
  57. package/dist/indexer/parser.js +431 -0
  58. package/dist/indexer/parser.js.map +1 -0
  59. package/dist/indexer/summarizer.d.ts +15 -0
  60. package/dist/indexer/summarizer.d.ts.map +1 -0
  61. package/dist/indexer/summarizer.js +24 -0
  62. package/dist/indexer/summarizer.js.map +1 -0
  63. package/dist/indexer/watcher.d.ts +25 -0
  64. package/dist/indexer/watcher.d.ts.map +1 -0
  65. package/dist/indexer/watcher.js +54 -0
  66. package/dist/indexer/watcher.js.map +1 -0
  67. package/dist/monitoring/estimator.d.ts +20 -0
  68. package/dist/monitoring/estimator.d.ts.map +1 -0
  69. package/dist/monitoring/estimator.js +94 -0
  70. package/dist/monitoring/estimator.js.map +1 -0
  71. package/dist/monitoring/server.d.ts +20 -0
  72. package/dist/monitoring/server.d.ts.map +1 -0
  73. package/dist/monitoring/server.js +86 -0
  74. package/dist/monitoring/server.js.map +1 -0
  75. package/dist/monitoring/token-logger.d.ts +26 -0
  76. package/dist/monitoring/token-logger.d.ts.map +1 -0
  77. package/dist/monitoring/token-logger.js +47 -0
  78. package/dist/monitoring/token-logger.js.map +1 -0
  79. package/dist/server.d.ts +18 -0
  80. package/dist/server.d.ts.map +1 -0
  81. package/dist/server.js +310 -0
  82. package/dist/server.js.map +1 -0
  83. package/dist/tools/find_usages.d.ts +4 -0
  84. package/dist/tools/find_usages.d.ts.map +1 -0
  85. package/dist/tools/find_usages.js +13 -0
  86. package/dist/tools/find_usages.js.map +1 -0
  87. package/dist/tools/get_context.d.ts +6 -0
  88. package/dist/tools/get_context.d.ts.map +1 -0
  89. package/dist/tools/get_context.js +36 -0
  90. package/dist/tools/get_context.js.map +1 -0
  91. package/dist/tools/get_dependencies.d.ts +4 -0
  92. package/dist/tools/get_dependencies.d.ts.map +1 -0
  93. package/dist/tools/get_dependencies.js +16 -0
  94. package/dist/tools/get_dependencies.js.map +1 -0
  95. package/dist/tools/get_doc_chunk.d.ts +4 -0
  96. package/dist/tools/get_doc_chunk.d.ts.map +1 -0
  97. package/dist/tools/get_doc_chunk.js +32 -0
  98. package/dist/tools/get_doc_chunk.js.map +1 -0
  99. package/dist/tools/get_file_summary.d.ts +4 -0
  100. package/dist/tools/get_file_summary.d.ts.map +1 -0
  101. package/dist/tools/get_file_summary.js +23 -0
  102. package/dist/tools/get_file_summary.js.map +1 -0
  103. package/dist/tools/get_project_overview.d.ts +5 -0
  104. package/dist/tools/get_project_overview.d.ts.map +1 -0
  105. package/dist/tools/get_project_overview.js +60 -0
  106. package/dist/tools/get_project_overview.js.map +1 -0
  107. package/dist/tools/get_symbol.d.ts +4 -0
  108. package/dist/tools/get_symbol.d.ts.map +1 -0
  109. package/dist/tools/get_symbol.js +21 -0
  110. package/dist/tools/get_symbol.js.map +1 -0
  111. package/dist/tools/get_token_stats.d.ts +4 -0
  112. package/dist/tools/get_token_stats.d.ts.map +1 -0
  113. package/dist/tools/get_token_stats.js +6 -0
  114. package/dist/tools/get_token_stats.js.map +1 -0
  115. package/dist/tools/reindex.d.ts +5 -0
  116. package/dist/tools/reindex.d.ts.map +1 -0
  117. package/dist/tools/reindex.js +21 -0
  118. package/dist/tools/reindex.js.map +1 -0
  119. package/dist/tools/save_context.d.ts +4 -0
  120. package/dist/tools/save_context.d.ts.map +1 -0
  121. package/dist/tools/save_context.js +17 -0
  122. package/dist/tools/save_context.js.map +1 -0
  123. package/dist/tools/search_docs.d.ts +4 -0
  124. package/dist/tools/search_docs.d.ts.map +1 -0
  125. package/dist/tools/search_docs.js +42 -0
  126. package/dist/tools/search_docs.js.map +1 -0
  127. package/dist/tools/search_symbols.d.ts +5 -0
  128. package/dist/tools/search_symbols.d.ts.map +1 -0
  129. package/dist/tools/search_symbols.js +36 -0
  130. package/dist/tools/search_symbols.js.map +1 -0
  131. package/dist/tools/start_comparison.d.ts +4 -0
  132. package/dist/tools/start_comparison.d.ts.map +1 -0
  133. package/dist/tools/start_comparison.js +15 -0
  134. package/dist/tools/start_comparison.js.map +1 -0
  135. package/dist/types.d.ts +318 -0
  136. package/dist/types.d.ts.map +1 -0
  137. package/dist/types.js +3 -0
  138. package/dist/types.js.map +1 -0
  139. package/package.json +69 -0
package/README.md ADDED
@@ -0,0 +1,767 @@
1
+ # PindeX – MCP Codebase Indexer
2
+
3
+ **Structural codebase indexing for AI coding assistants — 80–90% fewer tokens per session.**
4
+
5
+ PindeX is an [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that parses your TypeScript/JavaScript project with `tree-sitter`, stores symbols, imports, and dependency graphs in a local SQLite database, and exposes 13 targeted tools so AI assistants can answer questions about your code — and your documentation — without reading entire files.
6
+
7
+ ---
8
+
9
+ ## Contents
10
+
11
+ - [How It Works](#how-it-works)
12
+ - [Requirements](#requirements)
13
+ - [Installation](#installation)
14
+ - [Quick Start](#quick-start)
15
+ - [Multi-Project & Federation](#multi-project--federation)
16
+ - [MCP Tools](#mcp-tools)
17
+ - [Code tools](#code-tools)
18
+ - [Document & context tools](#document--context-tools)
19
+ - [Environment Variables](#environment-variables)
20
+ - [Integrations](#integrations)
21
+ - [Claude Code](#claude-code)
22
+ - [Goose](#goose)
23
+ - [CLI Reference](#cli-reference)
24
+ - [Monitoring Dashboard](#monitoring-dashboard)
25
+ - [Development](#development)
26
+ - [Project Structure](#project-structure)
27
+
28
+ ---
29
+
30
+ ## How It Works
31
+
32
+ ```
33
+ Your project files
34
+
35
+ ├── .ts/.js ──► tree-sitter AST ──► symbols, imports, dependencies
36
+ │ │
37
+ └── .md/.yaml/.txt ──► chunker ──────────► documents (heading/line chunks)
38
+
39
+ Claude calls save_context(…) ──────────────────► context_entries
40
+
41
+
42
+ SQLite (FTS5) ← stored in ~/.pindex/projects/{hash}/index.db
43
+ ├── files (path, hash, language, token estimate)
44
+ ├── symbols (name, kind, signature, lines) ─► search_symbols
45
+ ├── dependencies (import graph) ─► get_dependencies
46
+ ├── usages (symbol → call sites) ─► find_usages
47
+ ├── documents (text chunks from .md/.yaml/.txt) ─► search_docs
48
+ ├── context_entries (notes saved by Claude mid-session) ─► search_docs
49
+ └── token_log (per-session metrics)
50
+
51
+
52
+ 13 MCP tools ──── stdio ────► Claude Code / Goose / any MCP client
53
+ ```
54
+
55
+ Instead of sending full file contents to the AI, PindeX lets it call `search_symbols`, `search_docs`, `get_context`, or `get_file_summary` — returning only what it actually needs.
56
+ Claude can also persist important facts across sessions with `save_context`, then retrieve them later with `search_docs` instead of re-reading large files.
57
+ Token savings are tracked per session and visible in a live web dashboard.
58
+
59
+ ---
60
+
61
+ ## Requirements
62
+
63
+ | Dependency | Version |
64
+ |---|---|
65
+ | Node.js | ≥ 18.0.0 |
66
+ | npm | ≥ 8 |
67
+ | Operating System | macOS, Linux, Windows (WSL recommended) |
68
+
69
+ > **Note:** `better-sqlite3` ships prebuilt binaries for most platforms. If your environment is unusual, `npm install` will compile from source — you'll need `python3` and a C++ compiler (`build-essential` / Xcode CLT).
70
+
71
+ ---
72
+
73
+ ## Installation
74
+
75
+ ### Install globally from source
76
+
77
+ ```bash
78
+ git clone https://github.com/phash/PindeX.git
79
+ cd PindeX
80
+ npm install
81
+ npm run build
82
+ npm install -g .
83
+ ```
84
+
85
+ This makes three commands available globally:
86
+
87
+ | Command | Purpose |
88
+ |---|---|
89
+ | `pindex` | CLI — init, federation, status |
90
+ | `pindex-server` | MCP stdio server (Claude Code spawns this automatically) |
91
+ | `pindex-gui` | Aggregated dashboard for all projects |
92
+
93
+ > **Note:** PindeX is not yet published on npm. Use `npm install -g .` from the cloned repo to install globally.
94
+
95
+ ---
96
+
97
+ ## Quick Start
98
+
99
+ ### 1. Set up a project
100
+
101
+ Run `pindex` (with no arguments) in any project directory:
102
+
103
+ ```bash
104
+ cd /my/project
105
+ pindex
106
+ ```
107
+
108
+ PindeX will:
109
+ 1. Walk upward from your current directory to find the project root (`package.json`, `.git`, etc.)
110
+ 2. Assign a dedicated monitoring port for this project
111
+ 3. Write `.mcp.json` into the project root with absolute paths
112
+ 4. Register the project in `~/.pindex/registry.json`
113
+
114
+ Output:
115
+ ```
116
+ ╔══════════════════════════════════════════╗
117
+ ║ PindeX – Ready ║
118
+ ╚══════════════════════════════════════════╝
119
+
120
+ Project : /my/project
121
+ Index : ~/.pindex/projects/a3f8b2c1/index.db
122
+ Port : 7856
123
+ Config : .mcp.json (written)
124
+
125
+ ── Next steps ─────────────────────────────
126
+ 1. Restart Claude Code in this directory
127
+ 2. Open the dashboard: pindex-gui
128
+ ```
129
+
130
+ ### 2. Restart Claude Code
131
+
132
+ Claude Code auto-discovers `.mcp.json`. On the next startup it will spawn `pindex-server` with the correct `PROJECT_ROOT` — the index is built automatically in the background.
133
+
134
+ ### 3. Use the tools
135
+
136
+ Once connected, your AI assistant can call tools like:
137
+
138
+ ```
139
+ search_symbols("AuthService")
140
+ get_file_summary("src/auth/service.ts")
141
+ get_context("src/auth/service.ts", 42, 20)
142
+ find_usages("validateToken")
143
+ get_dependencies("src/api/routes.ts", "both")
144
+
145
+ # Documentation and context memory:
146
+ search_docs("authentication JWT") # search CLAUDE.md, README.md, …
147
+ get_doc_chunk("CLAUDE.md", 2) # read one section only
148
+ save_context("Decision: use JWT …", "auth") # store for future sessions
149
+ ```
150
+
151
+ ### 4. Open the dashboard
152
+
153
+ ```bash
154
+ pindex-gui
155
+ ```
156
+
157
+ Opens `http://localhost:7842` — an aggregated dashboard showing token savings, symbol counts, and session stats for **all** registered projects.
158
+
159
+ ---
160
+
161
+ ## Multi-Project & Federation
162
+
163
+ ### Multiple independent projects
164
+
165
+ Each project gets its own `.mcp.json` (pointing to its own `PROJECT_ROOT`) and its own SQLite database at `~/.pindex/projects/{hash}/index.db`. When Claude Code opens Project A, it spawns `pindex-server` with `PROJECT_ROOT=/path/to/project-a` — it never touches Project B's index.
166
+
167
+ ```bash
168
+ cd /project-a && pindex # registers project-a
169
+ cd /project-b && pindex # registers project-b, different port + different DB
170
+ ```
171
+
172
+ ### Linking repos (federation)
173
+
174
+ If you work on a monorepo split into separate repositories, or if one project imports types from another, you can link them:
175
+
176
+ ```bash
177
+ cd /project-a
178
+ pindex add /project-b
179
+ ```
180
+
181
+ This updates `/project-a/.mcp.json` with `FEDERATION_REPOS=/project-b`. After restarting Claude Code in Project A, the MCP tools search **both** codebases:
182
+
183
+ - `search_symbols` returns results from both projects (federated results include a `project` field)
184
+ - `get_project_overview` shows stats for all linked projects
185
+
186
+ Add more repos at any time:
187
+
188
+ ```bash
189
+ pindex add /project-c # links a third repo
190
+ ```
191
+
192
+ Remove a link:
193
+
194
+ ```bash
195
+ pindex remove /project-b
196
+ ```
197
+
198
+ ### View all projects
199
+
200
+ ```bash
201
+ pindex status
202
+ ```
203
+
204
+ ```
205
+ 3 registered project(s):
206
+
207
+ [idle] project-a + 1 federated repo
208
+ /home/user/project-a
209
+ port: 7856 index: ~/.pindex/projects/a3f8b2c1/
210
+
211
+ [idle] project-b
212
+ /home/user/project-b
213
+ port: 7901 index: ~/.pindex/projects/f1e2d3c4/
214
+ ...
215
+ ```
216
+
217
+ ---
218
+
219
+ ## MCP Tools
220
+
221
+ All 13 tools are available over stdio transport.
222
+
223
+ ### Code tools
224
+
225
+ ### `search_symbols`
226
+
227
+ Full-text search across all indexed symbols (names, signatures, summaries) using SQLite FTS5.
228
+ When federation is active, results from linked repos include a `project` field.
229
+
230
+ | Parameter | Type | Required | Description |
231
+ |---|---|---|---|
232
+ | `query` | string | ✓ | Search term (supports FTS5 syntax) |
233
+ | `limit` | number | | Max results per project (default: 20) |
234
+
235
+ **Returns:** List of matching symbols with name, kind, signature, file path, and line number.
236
+
237
+ ---
238
+
239
+ ### `get_symbol`
240
+
241
+ Detailed information about a specific symbol including its signature, location, and the files it depends on.
242
+
243
+ | Parameter | Type | Required | Description |
244
+ |---|---|---|---|
245
+ | `name` | string | ✓ | Symbol name |
246
+ | `file` | string | | Narrow results to a specific file path |
247
+
248
+ **Returns:** Symbol record + file-level dependency list.
249
+
250
+ ---
251
+
252
+ ### `get_context`
253
+
254
+ Read a slice of a source file centred around a given line. Files are read from disk at call time — only metadata lives in the DB.
255
+
256
+ | Parameter | Type | Required | Description |
257
+ |---|---|---|---|
258
+ | `file` | string | ✓ | File path (relative to `PROJECT_ROOT`) |
259
+ | `line` | number | ✓ | Centre line |
260
+ | `range` | number | | Lines above and below (default: 30) |
261
+
262
+ **Returns:** Code snippet with detected language and line numbers.
263
+
264
+ ---
265
+
266
+ ### `get_file_summary`
267
+
268
+ High-level overview of a file without loading its full content.
269
+
270
+ | Parameter | Type | Required | Description |
271
+ |---|---|---|---|
272
+ | `file` | string | ✓ | File path |
273
+
274
+ **Returns:** Language, summary text, all symbols (with kind + signature), imports, and exports.
275
+
276
+ ---
277
+
278
+ ### `find_usages`
279
+
280
+ All locations in the codebase where a symbol is referenced.
281
+
282
+ | Parameter | Type | Required | Description |
283
+ |---|---|---|---|
284
+ | `symbol` | string | ✓ | Symbol name to look up |
285
+
286
+ **Returns:** List of `{ file, line, context }` entries.
287
+
288
+ ---
289
+
290
+ ### `get_dependencies`
291
+
292
+ Import graph for a file — what it imports, what imports it, or both.
293
+
294
+ | Parameter | Type | Required | Description |
295
+ |---|---|---|---|
296
+ | `target` | string | ✓ | File path |
297
+ | `direction` | `"imports"` \| `"imported_by"` \| `"both"` | | Default: `"both"` |
298
+
299
+ **Returns:** Dependency list with resolved file paths and imported symbol names.
300
+
301
+ ---
302
+
303
+ ### `get_project_overview`
304
+
305
+ Project-wide statistics — no parameters required.
306
+ When federation is active, also includes stats for each linked repository.
307
+
308
+ **Returns:** Total file count, dominant language, entry points (`index`, `main`, `app` files), module list with symbol counts, and (if federated) per-repo breakdowns.
309
+
310
+ ---
311
+
312
+ ### `reindex`
313
+
314
+ Rebuild the index for a single file or the entire project.
315
+
316
+ | Parameter | Type | Required | Description |
317
+ |---|---|---|---|
318
+ | `target` | string | | File path or omit for full project reindex |
319
+
320
+ **Returns:** Count of indexed / updated / error files.
321
+
322
+ ---
323
+
324
+ ### `get_token_stats`
325
+
326
+ Token usage and savings statistics for a session.
327
+
328
+ | Parameter | Type | Required | Description |
329
+ |---|---|---|---|
330
+ | `session_id` | string | | Defaults to `"default"` |
331
+
332
+ **Returns:** Total tokens used, estimated tokens without the index, net savings, and savings percentage.
333
+
334
+ ---
335
+
336
+ ### `start_comparison`
337
+
338
+ Create a labelled A/B testing session to compare indexed vs. baseline token usage.
339
+
340
+ | Parameter | Type | Required | Description |
341
+ |---|---|---|---|
342
+ | `label` | string | ✓ | Human-readable session name |
343
+ | `mode` | `"indexed"` \| `"baseline"` | ✓ | Tracking mode |
344
+
345
+ **Returns:** `session_id` and the monitoring dashboard URL.
346
+
347
+ ---
348
+
349
+ ### Document & context tools
350
+
351
+ These three tools extend PindeX beyond code: documentation files are indexed automatically alongside source files, and Claude can persist notes to a persistent knowledge store.
352
+
353
+ **What gets indexed as documents:**
354
+
355
+ | File type | Chunking strategy |
356
+ |---|---|
357
+ | `.md` / `.markdown` | Split at `#` / `##` / `###` heading boundaries — each section is one chunk |
358
+ | `.yaml` / `.yml` | Fixed 50-line chunks |
359
+ | `.txt` | Fixed 50-line chunks |
360
+
361
+ Documents are discovered by `indexAll()` and kept in sync by the same MD5-hash incremental indexer used for code files.
362
+
363
+ ---
364
+
365
+ ### `search_docs`
366
+
367
+ Full-text search (FTS5) across indexed document chunks **and** saved context entries.
368
+ Use this instead of loading entire documentation files.
369
+
370
+ | Parameter | Type | Required | Description |
371
+ |---|---|---|---|
372
+ | `query` | string | ✓ | Search term |
373
+ | `limit` | number | | Max results (default: 20) |
374
+ | `type` | `"docs"` \| `"context"` \| `"all"` | | Filter by source (default: `"all"`) |
375
+
376
+ **Returns:** List of matches, each with:
377
+ - `type` — `"doc"` (from a file) or `"context"` (saved by Claude)
378
+ - `content_preview` — first 200 characters of the chunk
379
+ - `file`, `heading`, `start_line` — for `"doc"` results, enables precise navigation
380
+ - `tags`, `session_id`, `created_at` — for `"context"` results
381
+
382
+ ---
383
+
384
+ ### `get_doc_chunk`
385
+
386
+ Retrieve the full content of one or all chunks of an indexed document.
387
+ More token-efficient than `get_context` for large documentation files because it returns pre-segmented sections.
388
+
389
+ | Parameter | Type | Required | Description |
390
+ |---|---|---|---|
391
+ | `file` | string | ✓ | File path (project-relative) |
392
+ | `chunk_index` | number | | Specific chunk to retrieve — omit for all chunks |
393
+
394
+ **Returns:** `{ file, total_chunks, chunks: [{ index, heading, start_line, end_line, content }] }`
395
+
396
+ **Typical workflow:**
397
+
398
+ ```
399
+ search_docs("authentication JWT")
400
+ → { file: "CLAUDE.md", heading: "Authentication", start_line: 12, chunk_index: 2 }
401
+
402
+ get_doc_chunk("CLAUDE.md", 2)
403
+ → full text of the Authentication section only
404
+ ```
405
+
406
+ ---
407
+
408
+ ### `save_context`
409
+
410
+ Persist an important fact, decision, or snippet to the context store.
411
+ Entries are searchable across all future sessions via `search_docs`.
412
+
413
+ Use this to offload information from the context window — instead of keeping a long summary in the prompt, write it once and retrieve it on demand.
414
+
415
+ | Parameter | Type | Required | Description |
416
+ |---|---|---|---|
417
+ | `content` | string | ✓ | The text to store |
418
+ | `tags` | string | | Comma-separated keywords for better retrieval (e.g. `"auth,jwt,security"`) |
419
+
420
+ **Returns:** `{ id, session_id, created_at }`
421
+
422
+ **Example — saving a decision:**
423
+
424
+ ```
425
+ save_context(
426
+ "JWT expiry: access=1h, refresh=7d. Refresh stored in Redis. See src/auth/tokens.ts.",
427
+ "auth,jwt,redis"
428
+ )
429
+ ```
430
+
431
+ **Example — retrieving it in a later session:**
432
+
433
+ ```
434
+ search_docs("JWT expiry", type: "context")
435
+ → { content_preview: "JWT expiry: access=1h, refresh=7d …", tags: "auth,jwt,redis" }
436
+ ```
437
+
438
+ ---
439
+
440
+ ## Environment Variables
441
+
442
+ These are set automatically in the generated `.mcp.json` — you rarely need to change them by hand.
443
+
444
+ | Variable | Default | Description |
445
+ |---|---|---|
446
+ | `PROJECT_ROOT` | `.` | Root directory of the project to index |
447
+ | `INDEX_PATH` | `~/.pindex/projects/{hash}/index.db` | Path to the SQLite database |
448
+ | `LANGUAGES` | `typescript,javascript` | Comma-separated list of languages to index |
449
+ | `AUTO_REINDEX` | `true` | Watch for file changes and reindex automatically |
450
+ | `MONITORING_PORT` | assigned per-project | Port for the live dashboard + WebSocket |
451
+ | `MONITORING_AUTO_OPEN` | `false` | Open the dashboard in the browser on startup |
452
+ | `BASELINE_MODE` | `false` | Disable the index entirely (for A/B baseline sessions) |
453
+ | `GENERATE_SUMMARIES` | `false` | Generate LLM summaries per symbol (stub — not yet wired) |
454
+ | `TOKEN_PRICE_PER_MILLION` | `3.00` | USD price per million tokens — used for cost estimates |
455
+ | `FEDERATION_REPOS` | _(empty)_ | Colon-separated absolute paths to linked repositories |
456
+ | `DOCUMENT_PATTERNS` | `**/*.md,**/*.markdown,**/*.yaml,**/*.yml,**/*.txt` | Glob patterns for document files to index alongside code |
457
+
458
+ ---
459
+
460
+ ## Integrations
461
+
462
+ ### Claude Code
463
+
464
+ Run `pindex` in each project you want to index. The command writes `.mcp.json` automatically:
465
+
466
+ ```bash
467
+ cd /my/project
468
+ pindex
469
+ # → .mcp.json written
470
+ # restart Claude Code → pindex-server starts automatically
471
+ ```
472
+
473
+ The `.mcp.json` format (auto-generated, do not edit by hand):
474
+
475
+ ```json
476
+ {
477
+ "mcpServers": {
478
+ "pindex": {
479
+ "command": "pindex-server",
480
+ "args": [],
481
+ "env": {
482
+ "PROJECT_ROOT": "/absolute/path/to/project",
483
+ "INDEX_PATH": "/home/user/.pindex/projects/a3f8b2c1/index.db",
484
+ "MONITORING_PORT": "7856",
485
+ "AUTO_REINDEX": "true",
486
+ "GENERATE_SUMMARIES": "false",
487
+ "MONITORING_AUTO_OPEN": "false",
488
+ "BASELINE_MODE": "false",
489
+ "TOKEN_PRICE_PER_MILLION": "3.00"
490
+ }
491
+ }
492
+ }
493
+ }
494
+ ```
495
+
496
+ With federation (`pindex add /other/project`):
497
+
498
+ ```json
499
+ {
500
+ "mcpServers": {
501
+ "pindex": {
502
+ "command": "pindex-server",
503
+ "args": [],
504
+ "env": {
505
+ "PROJECT_ROOT": "/absolute/path/to/project",
506
+ "FEDERATION_REPOS": "/absolute/path/to/other/project",
507
+ "..."
508
+ }
509
+ }
510
+ }
511
+ }
512
+ ```
513
+
514
+ ---
515
+
516
+ ### Goose
517
+
518
+ [Goose](https://block.github.io/goose/) reads extensions from `~/.config/goose/config.yaml`.
519
+
520
+ **Step 1 — Install PindeX:**
521
+
522
+ ```bash
523
+ git clone https://github.com/phash/PindeX.git
524
+ cd PindeX && npm install && npm run build && npm install -g .
525
+ ```
526
+
527
+ **Step 2 — Run `pindex` in your project** to get the assigned hash and port:
528
+
529
+ ```bash
530
+ cd /my/project && pindex
531
+ ```
532
+
533
+ **Step 3 — Edit `~/.config/goose/config.yaml`:**
534
+
535
+ ```yaml
536
+ extensions:
537
+ pindex:
538
+ name: PindeX
539
+ type: stdio
540
+ cmd: pindex-server
541
+ args: []
542
+ envs:
543
+ PROJECT_ROOT: /absolute/path/to/project
544
+ INDEX_PATH: /home/user/.pindex/projects/{hash}/index.db
545
+ LANGUAGES: typescript,javascript
546
+ AUTO_REINDEX: "true"
547
+ GENERATE_SUMMARIES: "false"
548
+ MONITORING_PORT: "{port}"
549
+ MONITORING_AUTO_OPEN: "false"
550
+ BASELINE_MODE: "false"
551
+ TOKEN_PRICE_PER_MILLION: "3.00"
552
+ enabled: true
553
+ timeout: 300
554
+ ```
555
+
556
+ Replace `{hash}` and `{port}` with the values shown by `pindex`. A ready-to-copy template is available in [`goose-extension.yaml`](./goose-extension.yaml).
557
+
558
+ **Step 4 — Restart Goose:**
559
+
560
+ ```bash
561
+ goose session start
562
+ ```
563
+
564
+ ---
565
+
566
+ ## CLI Reference
567
+
568
+ ```
569
+ pindex [command] [options]
570
+ ```
571
+
572
+ | Command | Description |
573
+ |---|---|
574
+ | _(no args)_ / `init` | Set up this project: write `.mcp.json`, register globally |
575
+ | `add <path>` | Link another repo for cross-repo search (federation) |
576
+ | `remove [path]` | Remove a federated repo link, or deregister the current project |
577
+ | `setup` | One-time global setup (autostart config) |
578
+ | `status` | Show all registered projects and their status |
579
+ | `list` | List all registered projects (compact) |
580
+ | `index [path]` | Manually index a directory (default: current directory) |
581
+ | `index --force` | Force full reindex, bypassing MD5 hash checks |
582
+ | `gui` | Open the aggregated monitoring dashboard in the browser |
583
+ | `stats` | Print a short stats summary |
584
+ | `uninstall` | Stop all daemons (data stays in `~/.pindex`) |
585
+
586
+ **Examples:**
587
+
588
+ ```bash
589
+ # Set up a new project
590
+ cd /my/project && pindex
591
+
592
+ # Link project-b for cross-repo search
593
+ pindex add /my/project-b
594
+
595
+ # Check all registered projects
596
+ pindex status
597
+
598
+ # Manually force a full reindex
599
+ pindex index --force
600
+
601
+ # Open the dashboard
602
+ pindex-gui
603
+ ```
604
+
605
+ ---
606
+
607
+ ## Monitoring Dashboard
608
+
609
+ ### Per-project dashboard
610
+
611
+ Each `pindex-server` instance starts a monitoring server on its assigned port. Open it at:
612
+
613
+ ```
614
+ http://localhost:{MONITORING_PORT}
615
+ ```
616
+
617
+ Or let it open automatically on startup:
618
+
619
+ ```bash
620
+ MONITORING_AUTO_OPEN=true node dist/index.js
621
+ ```
622
+
623
+ ### Aggregated dashboard (all projects)
624
+
625
+ ```bash
626
+ pindex-gui
627
+ ```
628
+
629
+ Opens `http://localhost:7842` — reads **all** registered project databases directly and shows:
630
+
631
+ - Token savings per project (bar chart)
632
+ - Indexed file and symbol counts
633
+ - Session history
634
+ - Average savings % across all projects
635
+
636
+ The GUI refreshes automatically every 15 seconds and works even when no `pindex-server` is running.
637
+
638
+ **Dashboard features (both dashboards):**
639
+ - Real-time chart (Chart.js) of tokens used vs. estimated cost without index
640
+ - Per-tool breakdown: which tools are used most and how much they save
641
+ - Session comparison: side-by-side indexed vs. baseline A/B data
642
+ - REST API at `/api/sessions` and `/api/sessions/:id` for programmatic access
643
+
644
+ ---
645
+
646
+ ## Development
647
+
648
+ ### Setup
649
+
650
+ ```bash
651
+ git clone https://github.com/phash/PindeX.git
652
+ cd PindeX
653
+ npm install
654
+ ```
655
+
656
+ ### Build
657
+
658
+ ```bash
659
+ npm run build # compile src/ → dist/
660
+ npm run build:watch # watch mode
661
+ ```
662
+
663
+ ### Tests
664
+
665
+ ```bash
666
+ npm test # run full test suite (vitest, pool: forks)
667
+ npm run test:watch # watch mode
668
+ npm run test:coverage # coverage report — threshold: 80%
669
+ ```
670
+
671
+ > Tests use `pool: 'forks'` — required because `better-sqlite3` uses native bindings that cannot share a process with the vitest worker pool.
672
+
673
+ ### Lint / Type-check
674
+
675
+ ```bash
676
+ npm run lint # tsc --noEmit (type errors only, no output files)
677
+ ```
678
+
679
+ ### Test structure
680
+
681
+ ```
682
+ tests/
683
+ ├── setup.ts # global mocks (tree-sitter, chokidar, open)
684
+ ├── helpers/ # createTestDb(), fixtures, test server
685
+ ├── db/ # schema, migrations, queries
686
+ ├── indexer/ # parser, indexer, watcher
687
+ ├── tools/ # one file per MCP tool (13 total)
688
+ ├── monitoring/ # estimator, token-logger, Express server
689
+ ├── cli/ # project-detector, setup, daemon
690
+ └── integration/
691
+ ├── mcp-server.test.ts # MCP server wiring smoke tests
692
+ └── doc-indexing.test.ts # full document + context memory workflow
693
+ ```
694
+
695
+ ---
696
+
697
+ ## Project Structure
698
+
699
+ ```
700
+ src/
701
+ ├── index.ts # Entry point — MCP stdio server + FEDERATION_REPOS
702
+ ├── server.ts # Tool registration (13 tools, FederatedDb interface)
703
+ ├── types.ts # Shared TypeScript interfaces
704
+
705
+ ├── db/
706
+ │ ├── schema.ts # SQLite schema + FTS5 tables + triggers (v2)
707
+ │ ├── queries.ts # Typed query helpers
708
+ │ ├── database.ts # Connection management
709
+ │ └── migrations.ts # Schema versioning (PRAGMA user_version)
710
+
711
+ ├── indexer/
712
+ │ ├── index.ts # Orchestrator — code + document file discovery
713
+ │ ├── parser.ts # tree-sitter AST → symbols; text → doc chunks
714
+ │ ├── summarizer.ts # LLM summary stub (not yet active)
715
+ │ └── watcher.ts # chokidar file watcher → auto-reindex
716
+
717
+ ├── tools/ # One file per MCP tool
718
+ │ ├── search_symbols.ts # FTS5 symbol search — supports federated DBs
719
+ │ ├── get_symbol.ts
720
+ │ ├── get_context.ts
721
+ │ ├── get_file_summary.ts
722
+ │ ├── find_usages.ts
723
+ │ ├── get_dependencies.ts
724
+ │ ├── get_project_overview.ts # federation-aware stats
725
+ │ ├── reindex.ts
726
+ │ ├── get_token_stats.ts
727
+ │ ├── start_comparison.ts
728
+ │ ├── search_docs.ts # FTS5 across documents + context entries
729
+ │ ├── get_doc_chunk.ts # retrieve specific document section(s)
730
+ │ └── save_context.ts # persist a fact/decision to context store
731
+
732
+ ├── monitoring/
733
+ │ ├── server.ts # Express + WebSocket (per-project instance)
734
+ │ ├── token-logger.ts # Per-call token logging
735
+ │ ├── estimator.ts # "without index" heuristic
736
+ │ └── ui/ # Dashboard HTML / CSS / Chart.js
737
+
738
+ ├── gui/
739
+ │ ├── index.ts # pindex-gui entry point
740
+ │ └── server.ts # Aggregated Express app (reads all project DBs)
741
+
742
+ └── cli/
743
+ ├── index.ts # CLI router
744
+ ├── init.ts # initProject(), writeMcpJson(), addFederatedRepo()
745
+ ├── setup.ts # One-time setup (pindex setup)
746
+ ├── daemon.ts # Per-project PID-file daemon management
747
+ └── project-detector.ts # getPindexHome(), findProjectRoot(), GlobalRegistry
748
+ ```
749
+
750
+ ### Key implementation notes
751
+
752
+ - **ES Modules** — all relative imports use `.js` extensions (TypeScript ESM / NodeNext resolution).
753
+ - **FTS5 sync** — `symbols`, `documents`, and `context_entries` are all kept in sync by SQLite `AFTER INSERT/UPDATE/DELETE` triggers; no application-level bookkeeping needed.
754
+ - **Incremental reindexing** — MD5 hash per file; unchanged files are skipped for both code and document indexing.
755
+ - **Document chunking** — markdown splits at `#`/`##`/`###` heading boundaries; all other text files use fixed 50-line windows. Empty chunks are filtered out before storage.
756
+ - **Context memory** — `save_context` writes to `context_entries` keyed by `session_id`. Entries are never scoped to a single session — `search_docs` always searches the full history, enabling cross-session knowledge retrieval.
757
+ - **Live context** — `get_context` reads from disk at call time so it always returns the current file state, not a stale cache.
758
+ - **Testability** — `createMonitoringApp()` (returns the Express `app`) and `startMonitoringServer()` (binds the HTTP/WebSocket server) are separate functions so tests can mount the app without binding a port.
759
+ - **Per-project ports** — assigned deterministically as `7842 + (parseInt(hash.slice(0,4), 16) % 2000)` and stored in `registry.json` so they never change.
760
+ - **`pindex-gui` reads DBs directly** — no running server required; works as a standalone dashboard even when Claude Code is not open.
761
+ - **Migration** — `getPindexHome()` automatically renames `~/.mcp-indexer` → `~/.pindex` on first call if the old directory exists.
762
+
763
+ ---
764
+
765
+ ## License
766
+
767
+ MIT