@winci/local-rag 0.2.4 → 0.2.6
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.
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: local-rag
|
|
3
|
+
description: >
|
|
4
|
+
TRIGGER when: starting a new session, exploring unfamiliar code, searching for
|
|
5
|
+
functions/types/files, planning refactors, or needing context about past decisions.
|
|
6
|
+
Use local-rag MCP tools (search, read_relevant, project_map, etc.) instead of
|
|
7
|
+
manually grepping or reading files when semantic understanding is needed.
|
|
8
|
+
user-invocable: false
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Using local-rag tools
|
|
12
|
+
|
|
13
|
+
This project has a local RAG index (local-rag). Use these MCP tools:
|
|
14
|
+
|
|
15
|
+
- **`search`**: Discover which files are relevant to a topic. Returns file paths
|
|
16
|
+
with snippet previews — use this when you need to know *where* something is.
|
|
17
|
+
- **`read_relevant`**: Get the actual content of relevant semantic chunks —
|
|
18
|
+
individual functions, classes, or markdown sections — ranked by relevance.
|
|
19
|
+
Results include exact line ranges (`src/db.ts:42-67`) so you can navigate
|
|
20
|
+
directly to the edit location. Use this instead of `search` + `Read` when
|
|
21
|
+
you need the content itself. Two chunks from the same file can both appear
|
|
22
|
+
(no file deduplication).
|
|
23
|
+
- **`project_map`**: When you need to understand how files relate to each other,
|
|
24
|
+
generate a dependency graph. Use `focus` to zoom into a specific file's
|
|
25
|
+
neighborhood. This is faster than reading import statements across many files.
|
|
26
|
+
- **`search_conversation`**: Search past conversation history to recall previous
|
|
27
|
+
decisions, discussions, and tool outputs. Use this before re-investigating
|
|
28
|
+
something that may have been discussed in an earlier session.
|
|
29
|
+
- **`create_checkpoint`**: Mark important moments — decisions, milestones,
|
|
30
|
+
blockers, direction changes. Do this liberally: after completing any feature
|
|
31
|
+
or task, after adding/modifying tools, after key technical decisions, before
|
|
32
|
+
and after large refactors, or when changing direction. If in doubt, create one.
|
|
33
|
+
- **`list_checkpoints`** / **`search_checkpoints`**: Review or search past
|
|
34
|
+
checkpoints to understand project history and prior decisions.
|
|
35
|
+
- **`index_files`**: If you've created or modified files and want them searchable,
|
|
36
|
+
re-index the project directory.
|
|
37
|
+
- **`search_analytics`**: Check what queries return no results or low-relevance
|
|
38
|
+
results — this reveals documentation gaps.
|
|
39
|
+
- **`search_symbols`**: When you know a symbol name (function, class, type, etc.),
|
|
40
|
+
find it directly by name instead of using semantic search.
|
|
41
|
+
- **`find_usages`**: Before changing a function or type, find all its call sites.
|
|
42
|
+
Use this to understand the blast radius of a rename or API change. Faster and
|
|
43
|
+
more reliable than semantic search for finding usages.
|
|
44
|
+
- **`git_context`**: At the start of a session (or any time you need orientation),
|
|
45
|
+
call this to see what files have already been modified, recent commits, and
|
|
46
|
+
which changed files are in the index. Avoids redundant searches and conflicting
|
|
47
|
+
edits on already-modified files.
|
|
48
|
+
- **`annotate`**: Attach a persistent note to a file or symbol — "known race
|
|
49
|
+
condition", "don't refactor until auth rewrite lands", etc. Notes appear as
|
|
50
|
+
`[NOTE]` blocks inline in `read_relevant` results automatically.
|
|
51
|
+
- **`get_annotations`**: Retrieve all notes for a file, or search semantically
|
|
52
|
+
across all annotations to find relevant caveats before editing.
|
|
53
|
+
- **`write_relevant`**: Before adding new code or docs, find the best insertion
|
|
54
|
+
point — returns the most semantically appropriate file and anchor.
|
package/.mcp.json
CHANGED
package/package.json
CHANGED
package/src/cli/commands/init.ts
CHANGED
|
@@ -2,11 +2,12 @@ import { resolve } from "path";
|
|
|
2
2
|
import { RagDB } from "../../db";
|
|
3
3
|
import { loadConfig } from "../../config";
|
|
4
4
|
import { indexDirectory } from "../../indexing/indexer";
|
|
5
|
-
import { runSetup,
|
|
5
|
+
import { runSetup, confirm } from "../setup";
|
|
6
6
|
import { cliProgress } from "../progress";
|
|
7
7
|
|
|
8
8
|
export async function initCommand(args: string[], getFlag: (flag: string) => string | undefined) {
|
|
9
9
|
const dir = resolve(args[1] && !args[1].startsWith("--") ? args[1] : ".");
|
|
10
|
+
const autoYes = args.includes("--yes") || args.includes("-y");
|
|
10
11
|
const { actions } = await runSetup(dir);
|
|
11
12
|
if (actions.length === 0) {
|
|
12
13
|
console.log("Already set up — nothing to do.");
|
|
@@ -14,14 +15,8 @@ export async function initCommand(args: string[], getFlag: (flag: string) => str
|
|
|
14
15
|
for (const action of actions) console.log(action);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
console.log("\nAdd this to your agent's MCP config (mcpServers):\n");
|
|
18
|
-
console.log(mcpConfigSnippet(dir));
|
|
19
|
-
const hints = detectAgentHints(dir);
|
|
20
18
|
console.log();
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
console.log();
|
|
24
|
-
const shouldIndex = await confirm("Index project now? [Y/n] ");
|
|
19
|
+
const shouldIndex = autoYes || await confirm("Index project now? [Y/n] ");
|
|
25
20
|
if (shouldIndex) {
|
|
26
21
|
const db = new RagDB(dir);
|
|
27
22
|
const config = await loadConfig(dir);
|
package/src/cli/setup.ts
CHANGED
|
@@ -154,6 +154,79 @@ export function mcpConfigSnippet(projectDir: string): string {
|
|
|
154
154
|
}, null, 2);
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
function mcpServerEntry(projectDir: string) {
|
|
158
|
+
return {
|
|
159
|
+
command: "bunx",
|
|
160
|
+
args: ["@winci/local-rag@latest"],
|
|
161
|
+
env: { RAG_PROJECT_DIR: resolve(projectDir) },
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export async function ensureMcpJson(projectDir: string): Promise<string[]> {
|
|
166
|
+
const actions: string[] = [];
|
|
167
|
+
const entry = mcpServerEntry(projectDir);
|
|
168
|
+
|
|
169
|
+
// Claude Code — .mcp.json
|
|
170
|
+
const claudeMcpPath = join(projectDir, ".mcp.json");
|
|
171
|
+
if (existsSync(claudeMcpPath)) {
|
|
172
|
+
const raw = JSON.parse(await readFile(claudeMcpPath, "utf-8"));
|
|
173
|
+
if (!raw.mcpServers?.["local-rag"]) {
|
|
174
|
+
raw.mcpServers = raw.mcpServers || {};
|
|
175
|
+
raw.mcpServers["local-rag"] = entry;
|
|
176
|
+
await writeFile(claudeMcpPath, JSON.stringify(raw, null, 2) + "\n");
|
|
177
|
+
actions.push("Added local-rag to .mcp.json");
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
await writeFile(
|
|
181
|
+
claudeMcpPath,
|
|
182
|
+
JSON.stringify({ mcpServers: { "local-rag": entry } }, null, 2) + "\n"
|
|
183
|
+
);
|
|
184
|
+
actions.push("Created .mcp.json with local-rag");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Cursor — .cursor/mcp.json
|
|
188
|
+
if (existsSync(join(projectDir, ".cursor"))) {
|
|
189
|
+
const cursorMcpPath = join(projectDir, ".cursor", "mcp.json");
|
|
190
|
+
if (existsSync(cursorMcpPath)) {
|
|
191
|
+
const raw = JSON.parse(await readFile(cursorMcpPath, "utf-8"));
|
|
192
|
+
if (!raw.mcpServers?.["local-rag"]) {
|
|
193
|
+
raw.mcpServers = raw.mcpServers || {};
|
|
194
|
+
raw.mcpServers["local-rag"] = entry;
|
|
195
|
+
await writeFile(cursorMcpPath, JSON.stringify(raw, null, 2) + "\n");
|
|
196
|
+
actions.push("Added local-rag to .cursor/mcp.json");
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
await writeFile(
|
|
200
|
+
cursorMcpPath,
|
|
201
|
+
JSON.stringify({ mcpServers: { "local-rag": entry } }, null, 2) + "\n"
|
|
202
|
+
);
|
|
203
|
+
actions.push("Created .cursor/mcp.json with local-rag");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Windsurf — .windsurf/mcp.json
|
|
208
|
+
if (existsSync(join(projectDir, ".windsurf"))) {
|
|
209
|
+
const windsurfMcpPath = join(projectDir, ".windsurf", "mcp.json");
|
|
210
|
+
if (existsSync(windsurfMcpPath)) {
|
|
211
|
+
const raw = JSON.parse(await readFile(windsurfMcpPath, "utf-8"));
|
|
212
|
+
if (!raw.mcpServers?.["local-rag"]) {
|
|
213
|
+
raw.mcpServers = raw.mcpServers || {};
|
|
214
|
+
raw.mcpServers["local-rag"] = entry;
|
|
215
|
+
await writeFile(windsurfMcpPath, JSON.stringify(raw, null, 2) + "\n");
|
|
216
|
+
actions.push("Added local-rag to .windsurf/mcp.json");
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
await writeFile(
|
|
220
|
+
windsurfMcpPath,
|
|
221
|
+
JSON.stringify({ mcpServers: { "local-rag": entry } }, null, 2) + "\n"
|
|
222
|
+
);
|
|
223
|
+
actions.push("Created .windsurf/mcp.json with local-rag");
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return actions;
|
|
228
|
+
}
|
|
229
|
+
|
|
157
230
|
export function detectAgentHints(projectDir: string): string[] {
|
|
158
231
|
const hints: string[] = [];
|
|
159
232
|
if (existsSync(join(projectDir, ".mcp.json")))
|
|
@@ -186,6 +259,9 @@ export async function runSetup(projectDir: string): Promise<SetupResult> {
|
|
|
186
259
|
const instructionActions = await ensureAgentInstructions(projectDir);
|
|
187
260
|
actions.push(...instructionActions);
|
|
188
261
|
|
|
262
|
+
const mcpActions = await ensureMcpJson(projectDir);
|
|
263
|
+
actions.push(...mcpActions);
|
|
264
|
+
|
|
189
265
|
const gitignoreAction = await ensureGitignore(projectDir);
|
|
190
266
|
if (gitignoreAction) actions.push(gitignoreAction);
|
|
191
267
|
|
package/src/server/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { indexDirectory } from "../indexing/indexer";
|
|
|
8
8
|
import { startWatcher, type Watcher } from "../indexing/watcher";
|
|
9
9
|
import { discoverSessions } from "../conversation/parser";
|
|
10
10
|
import { indexConversation, startConversationTail } from "../conversation/indexer";
|
|
11
|
+
import { ensureGitignore } from "../cli/setup";
|
|
11
12
|
import { registerAllTools } from "../tools";
|
|
12
13
|
import { log } from "../utils/log";
|
|
13
14
|
|
|
@@ -54,6 +55,11 @@ export async function startServer() {
|
|
|
54
55
|
let convWatcher: Watcher | null = null;
|
|
55
56
|
|
|
56
57
|
if (!isHomeDirTrap) {
|
|
58
|
+
// Ensure .rag/ is gitignored
|
|
59
|
+
ensureGitignore(startupDir).catch((err) => {
|
|
60
|
+
log.warn(`Failed to update .gitignore: ${err instanceof Error ? err.message : err}`, "server");
|
|
61
|
+
});
|
|
62
|
+
|
|
57
63
|
// Index in background — don't block server startup
|
|
58
64
|
indexDirectory(startupDir, startupDb, startupConfig, (msg) => {
|
|
59
65
|
process.stderr.write(`[local-rag] ${msg}\n`);
|