xindex 1.0.0 → 1.0.2

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 (29) hide show
  1. package/.ai/research/.gitkeep +0 -0
  2. package/.ai/task/.gitkeep +0 -0
  3. package/README.md +54 -89
  4. package/apps/run.search.ts +0 -3
  5. package/componets/index/formatSearchResults.ts +2 -2
  6. package/media/MEDIUM.md +139 -0
  7. package/media/SOCIAL.md +102 -0
  8. package/package.json +1 -1
  9. package/.ai/research/2026-04-10-file-watching.md +0 -79
  10. package/.ai/research/2026-04-10-mcp-output-format.md +0 -129
  11. package/.ai/task/INDEX.md +0 -12
  12. package/.ai/task/done/INDEX.md +0 -3
  13. package/.ai/task/done/task.2026-04-09-local-ai-research-protos.log.md +0 -98
  14. package/.ai/task/done/task.2026-04-09-local-ai-research-protos.md +0 -102
  15. package/.ai/task/task.2026-04-10-cluster-config.log.md +0 -19
  16. package/.ai/task/task.2026-04-10-cluster-config.md +0 -118
  17. package/.ai/task/task.2026-04-10-dir-indexing.log.md +0 -8
  18. package/.ai/task/task.2026-04-10-dir-indexing.md +0 -92
  19. package/.ai/task/task.2026-04-10-line-clustering.log.md +0 -50
  20. package/.ai/task/task.2026-04-10-line-clustering.md +0 -176
  21. package/.ai/task/task.2026-04-10-object-store.log.md +0 -7
  22. package/.ai/task/task.2026-04-10-object-store.md +0 -81
  23. package/.ai/task/task.2026-04-10-search-config.log.md +0 -46
  24. package/.ai/task/task.2026-04-10-search-config.md +0 -274
  25. package/.ai/task/task.2026-04-10-watch-indexing.log.md +0 -32
  26. package/.ai/task/task.2026-04-10-watch-indexing.md +0 -101
  27. package/.ai/task/task.2026-04-10-xindex-mcp.log.md +0 -5
  28. package/.ai/task/task.2026-04-10-xindex-mcp.md +0 -92
  29. package/.ai/task/task.2026-04-10-xindex-mcp.report.md +0 -113
@@ -1,101 +0,0 @@
1
- # Task: xindex-watch — Continuous Indexing with File Watcher
2
-
3
- ## Context
4
-
5
- Two entry points:
6
- - `xindex-index` — one-time batch job: index all declared paths (default cwd), exit with status
7
- - `xindex-watch` — **new**: index all, then watch for changes continuously, Ctrl+C to stop
8
-
9
- Both default to cwd when no args. Watch handles create, update, move, delete events via a merged stream.
10
-
11
- **Current pipeline** (`apps/indexApp.ts`):
12
- ```
13
- from(walkFiles(inputs))
14
- .pipe(tap(log))
15
- .pipe(map(readFile → extractKeywords → cleanUp → indexContent))
16
- → run()
17
- ```
18
-
19
- **Key pieces already in place:**
20
- - `WalkFiles` (`componets/walkFiles.ts`) — async generator yielding relative paths, .gitignore-aware
21
- - `Writer` (`packages/streamx/src/writer.ts`) — push-based stream writer (backpressure-aware)
22
- - `merge` (`packages/streamx/src/merge.ts`) — combines multiple streams
23
- - `from` / `of` / `run` — streamx core
24
-
25
- **Node.js `fs.watch`** (recursive works on all platforms since Node 22+):
26
- - `fs.watch(dir, {recursive: true})` — macOS (FSEvents), Windows (ReadDirectoryChangesW), Linux (inotify, fd-per-dir)
27
- - Returns `AsyncIterable<FileChangeInfo>` with `.eventType` ("rename" | "change") and `.filename`
28
- - "rename" = create, delete, or move; "change" = content modified
29
- - Need to `stat()` after event to distinguish create vs delete (file exists → create/update; doesn't exist → delete)
30
- - Known issues: duplicate events per save, null filenames possible → handled by batchTimed dedup
31
-
32
- **No external dep needed** — `node:fs/promises` `watch()` returns async iterable directly. If issues arise, chokidar v5 (1 dep, ESM-only) is a drop-in upgrade. See [research](../research/2026-04-10-file-watching.md).
33
-
34
- ## Goal
35
-
36
- Add `xindex-watch` entry point: index all provided paths (or cwd by default), then watch for changes and keep the index up to date continuously. Ctrl+C gracefully stops. Update `xindex-index` to default to cwd but remain a one-time job.
37
-
38
- ## Diagram
39
-
40
- ```
41
- bin/xindex-index → run.index.ts bin/xindex-watch → run.watch.ts
42
- │ one-time, exits │ continuous, SIGINT to stop
43
- │ │
44
- ├─ inputs || [cwd] ├─ inputs || [cwd]
45
- └─ IndexApp(inputs) ├─ SIGINT → app.stop()
46
- │ └─ WatchApp(inputs)
47
- └─ walkFiles → index → exit │
48
- ├── INITIAL: from(walkFiles)
49
- │ → map(path → {type:"index", path})
50
-
51
- ├── WATCH: from(watchFiles)
52
- │ → yields {type:"index"|"remove", path}
53
-
54
- └── merge(initial, watch)
55
-
56
- ├── batchTimed (debounce)
57
- ├── dedup per path
58
- ├── flat()
59
- ├── tap(log)
60
- ├── type:"index" → readFile → extractKeywords → cleanUp → indexContent
61
- ├── type:"remove" → removeContent
62
-
63
-
64
- runs until SIGINT
65
-
66
- Event → Vectra:
67
- created → upsert (add)
68
- updated → upsert (overwrite)
69
- deleted → deleteItem
70
- moved → deleteItem(old) + upsert(new) (two fs.watch events)
71
- ```
72
-
73
- ## Steps
74
-
75
- ### 1. RemoveContent + Wiring
76
- - **RemoveContent HOF** — create `componets/index/removeContent.ts` wrapping Vectra `deleteItem(id)`, matching `indexContent.ts` pattern
77
- - **ContentIndexDriver** — add `removeContent` to interface and factory
78
- - **BuildComponents** — expose `removeContent` in return object
79
-
80
- ### 2. WatchFiles Component
81
- - **FileEvent type** — define `{type: "index"|"remove", path: string}` in `componets/watchFiles.ts` (exported, shared with WatchApp)
82
- - **WatchFiles HOF** — create `componets/watchFiles.ts`, uses `Writer<FileEvent>` + `fs.watch(dir, {recursive:true})`; returns `{stream, stop}`
83
- - **Event mapping** — "change" + stat exists → index; "rename" + stat exists → index; "rename" + stat throws → remove; filter through gitignore rules
84
- - **Stop method** — close FSWatcher handles + `writer.finish()` to end the stream
85
-
86
- ### 3. WatchApp
87
- - **WatchApp HOF** — create `apps/watchApp.ts`: merge walk stream (mapped to FileEvents) + watch stream → `batchTimed(20, 150)` → dedup per path → `flat()` → `tap(log)` → process: "index" → readFile → extractKeywords → cleanUp → indexContent; "remove" → removeContent → `run()`; returns `{run, stop}`
88
-
89
- ### 4. Entry Points
90
- - **run.watch.ts** — new entry point: default to cwd, SIGINT → `app.stop()`, log stats on exit
91
- - **bin/xindex-watch** + package.json — bin shim + scripts entry
92
- - **run.index.ts** — default to cwd instead of error-exit; IndexApp unchanged (one-time job)
93
-
94
- ## Edge Cases
95
-
96
- - **Gitignore changes** — if `.gitignore` itself is modified, watcher should reload rules (or at minimum, not index newly-ignored files)
97
- - **Binary files** — TODO: filter by extension or detect encoding; for now, readFile utf8 on everything (may produce garbage keywords for binaries)
98
- - **Rapid renames** — editor save = delete old + create new; debounce window prevents double-processing
99
- - **Symlinks** — `fs.watch` recursive doesn't follow symlinks; acceptable default
100
- - **Index doesn't have the file** — "remove" for a file not in index should be a no-op (log warning, don't throw)
101
- - **Watching individual files** — `fs.watch` works on single files too; not a primary use case but no issue supporting it
@@ -1,5 +0,0 @@
1
- ### 2026-04-10 — Task created
2
-
3
- - User researched MCP SDK pattern (Server + StdioServerTransport + tool handlers)
4
- - Scope: wrap existing xindex BuildComponents as 2 MCP tools (index + search)
5
- - Integration: add to .claude/settings.json for Claude Code auto-discovery
@@ -1,92 +0,0 @@
1
- # Task: xindex-mcp — MCP Server for Semantic Code Search
2
-
3
- ## Context
4
-
5
- xindex is a working local semantic code search tool (index files → query by meaning). Goal: wrap it as an MCP server so Claude Code can search the codebase directly.
6
-
7
- **Existing xindex pipeline:**
8
- - `extractKeywords` → `cleanUpKeywords` → `embed` (MiniLM-L6) → `vectra` (upsert/query)
9
- - `BuildComponents()` wires everything
10
- - Entry points: `apps/run.index.ts`, `apps/run.search.ts`
11
-
12
- **MCP SDK (modern API — `registerTool` + Zod):**
13
- ```ts
14
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
15
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
16
- import { z } from "zod";
17
-
18
- const server = new McpServer({ name: "xindex", version: "0.1.0" });
19
-
20
- server.registerTool("xindex_search", {
21
- title: "Search codebase",
22
- description: "Semantic search over indexed codebase files",
23
- inputSchema: z.object({
24
- query: z.string().describe("Natural language search query"),
25
- limit: z.number().int().min(1).max(50).default(10).describe("Max results"),
26
- }),
27
- annotations: { readOnlyHint: true },
28
- }, async ({ query, limit }) => {
29
- // call searchContentIndex(query, limit)
30
- return { content: [{ type: "text", text: JSON.stringify(results) }] };
31
- });
32
-
33
- const transport = new StdioServerTransport();
34
- await server.connect(transport);
35
- ```
36
-
37
- **Integration:** `.mcp.json` in project root (project scope — shared via git).
38
-
39
- **Decisions:**
40
- - `BuildComponents()` inits once at startup — just factories, fast
41
- - MCP exposes **search only** — indexing is a separate process (`bin/xindex-index`)
42
- - Future: file watcher daemon to keep index up to date (out of scope for this task)
43
-
44
- ## Goal
45
-
46
- Create an MCP server that exposes `xindex_search` as a tool, so Claude Code can search the codebase semantically. Indexing runs separately via CLI.
47
-
48
- ## Diagram
49
-
50
- ```
51
- ┌─────────────────────────┐
52
- │ bin/xindex-index │
53
- │ (separate process) │
54
- │ indexes files → .xindex│
55
- └──────────┬──────────────┘
56
- │ writes
57
-
58
- .xindex/ (vectra)
59
-
60
- │ reads
61
- ┌──────────┐ stdio ┌───────┴──────────────┐
62
- │Claude Code├──────────┤ xindex-mcp server │
63
- └──────────┘ │ │
64
- │ tool: xindex_search │
65
- │ query → extract │
66
- │ → cleanUp → embed │
67
- │ → vectra query │
68
- │ → IIndexRecord[] │
69
- └───────────────────────┘
70
- ```
71
-
72
- ## Steps
73
-
74
- ### 1. MCP Server Setup
75
- - Install `@modelcontextprotocol/sdk` and `zod` dependencies
76
- - Create `apps/mcp-server.ts` — McpServer + StdioServerTransport
77
- - `BuildComponents()` at top level (once), use `searchContentIndex` in tool handler
78
-
79
- ### 2. Tool: xindex_search
80
- - Input schema: Zod `z.object({query: z.string(), limit: z.number().default(10)})` with `.describe()` on each field
81
- - Handler: call `searchContentIndex(query, limit)` → return `IIndexRecord[]` as text content
82
- - Use `annotations: { readOnlyHint: true }` — search has no side effects
83
-
84
- ### 3. Integration
85
- - Add `bin/xindex-mcp` entry point (`#!/usr/bin/env tsx` + import)
86
- - Add `.mcp.json` to project root: `{"mcpServers": {"xindex": {"command": "npx", "args": ["tsx", "apps/mcp-server.ts"]}}}`
87
- - Test: index codebase via CLI, restart Claude Code, verify tool appears, search it
88
- - Debug with: `npx @modelcontextprotocol/inspector npx tsx apps/mcp-server.ts`
89
-
90
- ## Future (out of scope)
91
- - File watcher daemon — observe fs events, keep index up to date automatically
92
- - `xindex_index` tool — allow Claude to trigger indexing directly
@@ -1,113 +0,0 @@
1
- # Research: How to Build an MCP Server (2026)
2
-
3
- ## Findings
4
-
5
- ### 1. SDK & API
6
-
7
- **Package:** `@modelcontextprotocol/sdk` (latest ^1.0.0)
8
- **Peer dep:** `zod` ^3.22.0
9
-
10
- **Modern API** (use this — old `server.tool()` and `setRequestHandler` are deprecated):
11
-
12
- ```ts
13
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
14
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
15
- import { z } from "zod";
16
-
17
- const server = new McpServer({ name: "xindex", version: "0.1.0" });
18
-
19
- server.registerTool(
20
- "xindex_search",
21
- {
22
- title: "Search codebase",
23
- description: "Semantic search over indexed codebase files",
24
- inputSchema: z.object({
25
- query: z.string().describe("Natural language search query"),
26
- limit: z.number().int().min(1).max(50).default(10).describe("Max results"),
27
- }),
28
- annotations: { readOnlyHint: true },
29
- },
30
- async ({ query, limit }) => {
31
- // call searchContentIndex(query, limit)
32
- return {
33
- content: [{ type: "text", text: JSON.stringify(results) }],
34
- };
35
- }
36
- );
37
-
38
- const transport = new StdioServerTransport();
39
- await server.connect(transport);
40
- ```
41
-
42
- ### 2. Tool naming & annotations
43
-
44
- - **snake_case** with service prefix: `xindex_search`, `xindex_index`
45
- - **annotations**: `readOnlyHint: true` for search (signals no side effects), `destructiveHint: false` for index
46
- - **inputSchema**: Zod objects with `.describe()` on each field — descriptions are shown to Claude
47
-
48
- ### 3. Transport
49
-
50
- **Stdio** is correct for local tools. Server reads JSON-RPC from stdin, writes to stdout. Use `console.error()` for logging (stdout is the protocol channel).
51
-
52
- **Gotcha with tsx**: Works fine as shebang (`#!/usr/bin/env tsx`). No build step needed.
53
-
54
- ### 4. Claude Code Integration
55
-
56
- **Three scopes:**
57
-
58
- | Scope | File | Shared? |
59
- |-------|------|---------|
60
- | Local (default) | `~/.claude.json` under project path | No |
61
- | Project | `.mcp.json` in project root | Yes (git) |
62
- | User | `~/.claude.json` global | No |
63
-
64
- **For this project — use `.mcp.json` (project scope)** so it's checked in and works for anyone who clones.
65
-
66
- ```json
67
- {
68
- "mcpServers": {
69
- "xindex": {
70
- "command": "npx",
71
- "args": ["tsx", "apps/mcp-server.ts"],
72
- "env": {}
73
- }
74
- }
75
- }
76
- ```
77
-
78
- Or add via CLI:
79
- ```bash
80
- claude mcp add --transport stdio --scope project xindex -- npx tsx apps/mcp-server.ts
81
- ```
82
-
83
- ### 5. Package requirements
84
-
85
- - `"type": "module"` in package.json — already have this
86
- - tsconfig: `module` and `moduleResolution` should be `Node16` or `NodeNext` (SDK uses ES module exports with subpath imports)
87
- - Current tsconfig has `"module": "Node16"` — compatible
88
-
89
- ### 6. Testing
90
-
91
- Use MCP Inspector for debugging:
92
- ```bash
93
- npx @modelcontextprotocol/inspector npx tsx apps/mcp-server.ts
94
- ```
95
-
96
- ## Recommendation
97
-
98
- Minimal implementation — single file `apps/mcp-server.ts`:
99
- 1. `BuildComponents()` at top level
100
- 2. `server.registerTool("xindex_search", ...)` calling `searchContentIndex`
101
- 3. `StdioServerTransport` + connect
102
- 4. `.mcp.json` in project root for Claude Code discovery
103
- 5. `bin/xindex-mcp` shebang entry point
104
-
105
- No build step needed (tsx). No express/HTTP needed (stdio only). ~40 lines of code.
106
-
107
- ## Sources
108
-
109
- - [Official TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
110
- - [SDK server docs](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/docs/server.md)
111
- - [Claude Code MCP docs](https://code.claude.com/docs/en/mcp)
112
- - [Anthropic MCP server reference](https://github.com/anthropics/skills/blob/main/skills/mcp-builder/reference/node_mcp_server.md)
113
- - [npm package](https://www.npmjs.com/package/@modelcontextprotocol/sdk)