xindex 1.0.14 → 1.0.16
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/.xindex.json +15 -1
- package/CLAUDE.md +1 -1
- package/README.md +2 -2
- package/apps/mcpApp.ts +13 -10
- package/components/walkFiles.ts +8 -2
- package/package.json +5 -2
package/.xindex.json
CHANGED
|
@@ -87,7 +87,21 @@
|
|
|
87
87
|
],
|
|
88
88
|
"ignoreFiles": [
|
|
89
89
|
".xindex",
|
|
90
|
-
"
|
|
90
|
+
"*.png",
|
|
91
|
+
"*.jpg",
|
|
92
|
+
"*.jpeg",
|
|
93
|
+
"*.gif",
|
|
94
|
+
"*.svg",
|
|
95
|
+
"*.ico",
|
|
96
|
+
"*.woff",
|
|
97
|
+
"*.woff2",
|
|
98
|
+
"*.ttf",
|
|
99
|
+
"*.eot",
|
|
100
|
+
"*.otf",
|
|
101
|
+
".gitkeep",
|
|
102
|
+
"package-lock.json",
|
|
103
|
+
"yarn.lock",
|
|
104
|
+
"*.mp4"
|
|
91
105
|
],
|
|
92
106
|
"maxLines": 30,
|
|
93
107
|
"maxFileBytes": 100000,
|
package/CLAUDE.md
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
- **Section splitting**: large `.md` files → `*.1.*`, `*.2.*` parts. Original becomes index with bullet summaries.
|
|
29
29
|
- **Detail expansion**: reread task → research every step (files, APIs, deps) → expand with concrete details (paths, functions, tables, exact changes) → preserve NxM shape → no info loss → update diagram → keep balanced detail density
|
|
30
30
|
- **Context recovery**: when chat compacts, reread active task's log to recover direction
|
|
31
|
-
- **Completed tasks**: move done tasks (+ their logs, maps, reports) to `.ai/task/done/`.
|
|
31
|
+
- **Completed tasks**: move done tasks (+ their logs, maps, reports) to `.ai/task/done/`. Use xindex search for discovery instead of manual index documents.
|
|
32
32
|
|
|
33
33
|
## Code Patterns
|
|
34
34
|
|
package/README.md
CHANGED
|
@@ -107,9 +107,9 @@ argument-hint: "[question]"
|
|
|
107
107
|
Surface-level codebase discovery via xindex. Tool: `xindex_search` (natural-language, meaning-based).
|
|
108
108
|
|
|
109
109
|
**Steps:**
|
|
110
|
-
1. Draft
|
|
110
|
+
1. Draft 1–5 queries from $ARGUMENTS (entry points, routing, config, tests, patterns); run `xindex_search` in parallel.
|
|
111
111
|
2. If empty/sparse/stale → scoped `xindex_index` on relevant root folders (one path per call, e.g. `src`, `skills`, `agents`), then re-search. Prefer scoped over full-repo.
|
|
112
|
-
3.
|
|
112
|
+
3. Think, then run 2+ narrower follow-ups in parallel based on round-1 hits.
|
|
113
113
|
4. Return file paths + brief keywords showing why each matched.
|
|
114
114
|
|
|
115
115
|
Output = file links + keywords, not analysis. **Escalate to `/ask-cursor` by default** (cheap codebase reasoning); only go to `/ask-claude` for multi-file/pattern analysis or `/ask-claude-opus` for trade-offs. For reset or full re-index, delegate to `/xindex` (owns safety rules).
|
package/apps/mcpApp.ts
CHANGED
|
@@ -34,16 +34,19 @@ export function McpApp({
|
|
|
34
34
|
config: IXindexConfig,
|
|
35
35
|
}): IMcpApp {
|
|
36
36
|
return async function mcpApp() {
|
|
37
|
-
const server = new McpServer({name: "xindex", version: "
|
|
37
|
+
const server = new McpServer({name: "xindex", version: "1.0.0"}, {
|
|
38
|
+
instructions: "@xi triggers this. Run `xindex_search` at session/task start. 1–5 parallel queries → think → 2+ follow-ups; empty → `xindex_index` scoped root.",
|
|
39
|
+
});
|
|
38
40
|
|
|
39
41
|
// --- search ---
|
|
40
42
|
|
|
41
43
|
server.registerTool("xindex_search", {
|
|
42
44
|
title: "Search codebase (semantic)",
|
|
43
|
-
description: "Semantic codebase search
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
45
|
+
description: "Semantic codebase search by meaning. " +
|
|
46
|
+
"@xi triggers this; run at session/task start. " +
|
|
47
|
+
"1–5 parallel queries → think → 2+ narrower follow-ups. " +
|
|
48
|
+
"Returns ranked file paths + keywords (links, not analysis). " +
|
|
49
|
+
"If sparse, `xindex_index` scoped root first (one path per call).",
|
|
47
50
|
inputSchema: z.object({
|
|
48
51
|
query: z.string()
|
|
49
52
|
.describe("Natural language search query"),
|
|
@@ -68,9 +71,9 @@ export function McpApp({
|
|
|
68
71
|
|
|
69
72
|
server.registerTool("xindex_index", {
|
|
70
73
|
title: "Index files or directories",
|
|
71
|
-
description: "Index
|
|
72
|
-
"Prefer scoped
|
|
73
|
-
"
|
|
74
|
+
description: "Index paths recursively; respects .gitignore. " +
|
|
75
|
+
"Prefer scoped (`src`, `apps`) over `['.']` (reserve for first-time/cross-cutting). " +
|
|
76
|
+
"Stale results → `xindex_reset` → `xindex_index`.",
|
|
74
77
|
inputSchema: z.object({
|
|
75
78
|
inputs: z.array(z.string()).min(1)
|
|
76
79
|
.describe("File or directory paths to index (one path per call preferred; scoped over full-repo)"),
|
|
@@ -94,8 +97,8 @@ export function McpApp({
|
|
|
94
97
|
|
|
95
98
|
server.registerTool("xindex_reset", {
|
|
96
99
|
title: "Reset index (destructive)",
|
|
97
|
-
description: "Wipe
|
|
98
|
-
"if ambiguous, don't run.
|
|
100
|
+
description: "Wipe the semantic index. **Destructive** — require explicit confirmation; " +
|
|
101
|
+
"if ambiguous, don't run. After: `xindex_index(['.'])`.",
|
|
99
102
|
inputSchema: z.object({}),
|
|
100
103
|
annotations: {destructiveHint: true},
|
|
101
104
|
}, async () => {
|
package/components/walkFiles.ts
CHANGED
|
@@ -20,6 +20,12 @@ export function WalkFiles({cwd, log, ignoreFiles = [], followSymlinks = false}:
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
const HARD_SKIP = new Set([".git", ".xindex"]);
|
|
24
|
+
|
|
25
|
+
function isHardlySkipped(name: string): boolean {
|
|
26
|
+
return HARD_SKIP.has(name);
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
const visited = new Set<string>();
|
|
24
30
|
|
|
25
31
|
async function* walk(dir: string, parentRules: string[]): AsyncIterable<string> {
|
|
@@ -45,7 +51,7 @@ export function WalkFiles({cwd, log, ignoreFiles = [], followSymlinks = false}:
|
|
|
45
51
|
visited.add(real);
|
|
46
52
|
const s = await stat(real);
|
|
47
53
|
if (s.isDirectory()) {
|
|
48
|
-
if (entry.name
|
|
54
|
+
if (isHardlySkipped(entry.name)) continue;
|
|
49
55
|
if (ig.ignores(rel + "/")) continue;
|
|
50
56
|
yield* walk(abs, rules);
|
|
51
57
|
} else if (s.isFile()) {
|
|
@@ -59,7 +65,7 @@ export function WalkFiles({cwd, log, ignoreFiles = [], followSymlinks = false}:
|
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
if (entry.isDirectory()) {
|
|
62
|
-
if (entry.name
|
|
68
|
+
if (isHardlySkipped(entry.name)) continue;
|
|
63
69
|
if (ig.ignores(rel + "/")) continue;
|
|
64
70
|
yield* walk(abs, rules);
|
|
65
71
|
} else if (entry.isFile()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xindex",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "Local semantic code search — index codebase, search by meaning or keywords",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "xindex.ts",
|
|
@@ -17,10 +17,13 @@
|
|
|
17
17
|
"search": "tsx apps/run.search.ts",
|
|
18
18
|
"reset": "tsx apps/run.reset.ts",
|
|
19
19
|
"test": "npm run test.functional && npm run test.compilation",
|
|
20
|
+
"dev.ci": "npm run test && npm run test.npx",
|
|
20
21
|
"mcp": "tsx apps/run.mcp.ts",
|
|
21
22
|
"watch": "tsx apps/run.watch.ts",
|
|
22
23
|
"test.functional": "bash test/functional.sh",
|
|
23
|
-
"test.compilation": "npx -y tsc --ignoreConfig --noEmit --target ES2022 --module ESNext --moduleResolution bundler --esModuleInterop --skipLibCheck --strict false $(git ls-files '*.ts')"
|
|
24
|
+
"test.compilation": "npx -y tsc --ignoreConfig --noEmit --target ES2022 --module ESNext --moduleResolution bundler --esModuleInterop --skipLibCheck --strict false $(git ls-files '*.ts')",
|
|
25
|
+
"test.npx": "docker run --rm -it -w /tmp node:22 bash -c 'npm i -g xindex && xindex-index tsx-0 && xindex-search streamx map | grep \"await mapper\" && which xindex | grep bin/xindex' ",
|
|
26
|
+
"console": "docker run --rm -it -v \"$PWD:/app\" -w /app node:22 bash"
|
|
24
27
|
},
|
|
25
28
|
"private": false,
|
|
26
29
|
"engines": {
|