@dreb/semantic-search 2.6.0 → 2.6.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "semantic-search",
3
3
  "description": "Semantic codebase search — natural language queries over code and docs using embeddings, tree-sitter parsing, and POEM multi-signal ranking",
4
- "version": "2.6.0",
4
+ "version": "2.6.2",
5
5
  "author": {
6
6
  "name": "Drew Brereton"
7
7
  },
package/README.md CHANGED
@@ -47,8 +47,8 @@ The package exposes a `search` tool over the Model Context Protocol (stdio trans
47
47
  | Parameter | Required | Description |
48
48
  | ------------ | -------- | ------------------------------------------------ |
49
49
  | `query` | yes | Natural language, identifier, or path query |
50
- | `projectDir` | yes | Absolute path to the project directory to search |
51
- | `path` | no | Restrict search to files under this path |
50
+ | `searchDir` | yes | Directory to index and search each unique value gets its own independent index |
51
+ | `restrictToDir` | no | Filter results to files under this path within the already-built index (does not affect indexing) |
52
52
  | `limit` | no | Maximum results to return (default: 20) |
53
53
  | `rebuild` | no | Force a clean index rebuild (default: false) |
54
54
 
@@ -4,7 +4,7 @@
4
4
  * Exposes the SearchEngine as a single "search" tool over the Model Context Protocol,
5
5
  * enabling any MCP-compatible client to run semantic codebase queries.
6
6
  *
7
- * The server defaults to using its CWD as the project directory. Claude Code
7
+ * The server defaults to using its CWD as the search directory. Claude Code
8
8
  * launches MCP servers with CWD set to the project root, so no configuration
9
9
  * is needed for typical per-project usage.
10
10
  */
@@ -12,14 +12,14 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
12
12
  /**
13
13
  * Create an MCP server instance configured with the semantic search tool.
14
14
  *
15
- * @param defaultProjectDir - Default project directory for searches. Used when
16
- * the client doesn't specify `projectDir` in the tool call. Typically the
15
+ * @param defaultSearchDir - Default directory to index and search. Used when
16
+ * the client doesn't specify `searchDir` in the tool call. Typically the
17
17
  * server's CWD, which Claude Code sets to the project root.
18
18
  */
19
- export declare function createMcpServer(defaultProjectDir: string): Server;
19
+ export declare function createMcpServer(defaultSearchDir: string): Server;
20
20
  /**
21
21
  * Create and start an MCP server over stdio.
22
22
  * This blocks until the transport is closed.
23
23
  */
24
- export declare function startServer(projectDir: string): Promise<void>;
24
+ export declare function startServer(searchDir: string): Promise<void>;
25
25
  //# sourceMappingURL=mcp-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAqDnE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CA6FjE;AAMD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAInE"}
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAwDnE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CA6FhE;AAMD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlE"}
@@ -4,7 +4,7 @@
4
4
  * Exposes the SearchEngine as a single "search" tool over the Model Context Protocol,
5
5
  * enabling any MCP-compatible client to run semantic codebase queries.
6
6
  *
7
- * The server defaults to using its CWD as the project directory. Claude Code
7
+ * The server defaults to using its CWD as the search directory. Claude Code
8
8
  * launches MCP servers with CWD set to the project root, so no configuration
9
9
  * is needed for typical per-project usage.
10
10
  */
@@ -27,15 +27,18 @@ const SEARCH_TOOL = {
27
27
  type: "object",
28
28
  properties: {
29
29
  query: { type: "string", description: "Search query (natural language, identifier, or path)" },
30
- projectDir: {
30
+ searchDir: {
31
31
  type: "string",
32
- description: "Absolute path to the project directory to search. Use your current working directory.",
32
+ description: "Directory to index and search. This controls which directory gets indexed.",
33
+ },
34
+ restrictToDir: {
35
+ type: "string",
36
+ description: "Restrict results to files under this path (filters the already-built index).",
33
37
  },
34
- path: { type: "string", description: "Restrict search to files under this path" },
35
38
  limit: { type: "number", description: "Maximum results to return (default: 20)" },
36
39
  rebuild: { type: "boolean", description: "Force index rebuild (default: false)" },
37
40
  },
38
- required: ["query", "projectDir"],
41
+ required: ["query", "searchDir"],
39
42
  },
40
43
  };
41
44
  // ============================================================================
@@ -57,11 +60,11 @@ function getSearchEngine(projectRoot) {
57
60
  /**
58
61
  * Create an MCP server instance configured with the semantic search tool.
59
62
  *
60
- * @param defaultProjectDir - Default project directory for searches. Used when
61
- * the client doesn't specify `projectDir` in the tool call. Typically the
63
+ * @param defaultSearchDir - Default directory to index and search. Used when
64
+ * the client doesn't specify `searchDir` in the tool call. Typically the
62
65
  * server's CWD, which Claude Code sets to the project root.
63
66
  */
64
- export function createMcpServer(defaultProjectDir) {
67
+ export function createMcpServer(defaultSearchDir) {
65
68
  const server = new Server({ name: "semantic-search", version: packageVersion }, { capabilities: { tools: {}, logging: {} } });
66
69
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
67
70
  tools: [SEARCH_TOOL],
@@ -74,9 +77,9 @@ export function createMcpServer(defaultProjectDir) {
74
77
  };
75
78
  }
76
79
  const args = (request.params.arguments ?? {});
77
- const { query, path: searchPath, rebuild = false } = args;
80
+ const { query, restrictToDir: pathFilter, rebuild = false } = args;
78
81
  const limit = typeof args.limit === "number" && args.limit > 0 ? Math.floor(args.limit) : 20;
79
- const projectDir = args.projectDir ? resolve(args.projectDir) : defaultProjectDir;
82
+ const searchDir = args.searchDir ? resolve(args.searchDir) : defaultSearchDir;
80
83
  if (!SearchEngine.isAvailable()) {
81
84
  return {
82
85
  content: [
@@ -95,14 +98,14 @@ export function createMcpServer(defaultProjectDir) {
95
98
  };
96
99
  }
97
100
  try {
98
- const engine = getSearchEngine(projectDir);
101
+ const engine = getSearchEngine(searchDir);
99
102
  if (rebuild) {
100
103
  await engine.resetIndex();
101
104
  }
102
105
  // Send progress via logging messages
103
106
  const results = await engine.search(query, {
104
107
  limit,
105
- pathFilter: searchPath,
108
+ pathFilter: pathFilter,
106
109
  onProgress: (phase, current, total) => {
107
110
  server
108
111
  .sendLoggingMessage({
@@ -141,8 +144,8 @@ export function createMcpServer(defaultProjectDir) {
141
144
  * Create and start an MCP server over stdio.
142
145
  * This blocks until the transport is closed.
143
146
  */
144
- export async function startServer(projectDir) {
145
- const server = createMcpServer(projectDir);
147
+ export async function startServer(searchDir) {
148
+ const server = createMcpServer(searchDir);
146
149
  const transport = new StdioServerTransport();
147
150
  await server.connect(transport);
148
151
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP stdio server adapter for semantic codebase search.\n *\n * Exposes the SearchEngine as a single \"search\" tool over the Model Context Protocol,\n * enabling any MCP-compatible client to run semantic codebase queries.\n *\n * The server defaults to using its CWD as the project directory. Claude Code\n * launches MCP servers with CWD set to the project root, so no configuration\n * is needed for typical per-project usage.\n */\n\nimport { createRequire } from \"node:module\";\nimport { resolve } from \"node:path\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { CallToolRequestSchema, type CallToolResult, ListToolsRequestSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport { formatResults } from \"./format.js\";\nimport { SearchEngine } from \"./search.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version: packageVersion } = require(\"../package.json\") as { version: string };\n\n// ============================================================================\n// Tool Schema (JSON Schema for MCP)\n// ============================================================================\n\nconst SEARCH_TOOL = {\n\tname: \"search\",\n\tdescription:\n\t\t\"Search the codebase using natural language queries. Returns ranked code/doc results using semantic similarity and keyword matching. First query builds the index (may take a moment); subsequent queries are fast.\",\n\tinputSchema: {\n\t\ttype: \"object\" as const,\n\t\tproperties: {\n\t\t\tquery: { type: \"string\", description: \"Search query (natural language, identifier, or path)\" },\n\t\t\tprojectDir: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Absolute path to the project directory to search. Use your current working directory.\",\n\t\t\t},\n\t\t\tpath: { type: \"string\", description: \"Restrict search to files under this path\" },\n\t\t\tlimit: { type: \"number\", description: \"Maximum results to return (default: 20)\" },\n\t\t\trebuild: { type: \"boolean\", description: \"Force index rebuild (default: false)\" },\n\t\t},\n\t\trequired: [\"query\", \"projectDir\"],\n\t},\n};\n\n// ============================================================================\n// Engine Cache\n// ============================================================================\n\n/** Cache search engines per project root to reuse index across calls. */\nconst engineCache = new Map<string, SearchEngine>();\n\nfunction getSearchEngine(projectRoot: string): SearchEngine {\n\tlet engine = engineCache.get(projectRoot);\n\tif (!engine) {\n\t\tengine = new SearchEngine(projectRoot);\n\t\tengineCache.set(projectRoot, engine);\n\t}\n\treturn engine;\n}\n\n// ============================================================================\n// Server Factory\n// ============================================================================\n\n/**\n * Create an MCP server instance configured with the semantic search tool.\n *\n * @param defaultProjectDir - Default project directory for searches. Used when\n * the client doesn't specify `projectDir` in the tool call. Typically the\n * server's CWD, which Claude Code sets to the project root.\n */\nexport function createMcpServer(defaultProjectDir: string): Server {\n\tconst server = new Server(\n\t\t{ name: \"semantic-search\", version: packageVersion },\n\t\t{ capabilities: { tools: {}, logging: {} } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: [SEARCH_TOOL],\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request): Promise<CallToolResult> => {\n\t\tif (request.params.name !== \"search\") {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Unknown tool: ${request.params.name}` }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\tconst args = (request.params.arguments ?? {}) as {\n\t\t\tquery?: string;\n\t\t\tprojectDir?: string;\n\t\t\tpath?: string;\n\t\t\tlimit?: number;\n\t\t\trebuild?: boolean;\n\t\t};\n\t\tconst { query, path: searchPath, rebuild = false } = args;\n\t\tconst limit = typeof args.limit === \"number\" && args.limit > 0 ? Math.floor(args.limit) : 20;\n\n\t\tconst projectDir = args.projectDir ? resolve(args.projectDir) : defaultProjectDir;\n\n\t\tif (!SearchEngine.isAvailable()) {\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: \"Semantic search requires Node.js 22+ (for built-in SQLite). Current version does not support node:sqlite.\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\tif (!query || query.trim().length === 0) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Search query cannot be empty.\" }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst engine = getSearchEngine(projectDir);\n\n\t\t\tif (rebuild) {\n\t\t\t\tawait engine.resetIndex();\n\t\t\t}\n\n\t\t\t// Send progress via logging messages\n\t\t\tconst results = await engine.search(query, {\n\t\t\t\tlimit,\n\t\t\t\tpathFilter: searchPath,\n\t\t\t\tonProgress: (phase, current, total) => {\n\t\t\t\t\tserver\n\t\t\t\t\t\t.sendLoggingMessage({\n\t\t\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\t\t\tlogger: \"semantic-search\",\n\t\t\t\t\t\t\tdata: `${phase}: ${current}/${total}`,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// Ignore errors sending progress — client may not support logging\n\t\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst text = formatResults(results);\n\t\t\tconst stats = engine.getStats();\n\n\t\t\tlet statsLine = \"\";\n\t\t\tif (stats) {\n\t\t\t\tstatsLine = `\\n\\n[Index: ${stats.files} files, ${stats.chunks} chunks]`;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: text + statsLine }],\n\t\t\t};\n\t\t} catch (err) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Search failed: ${err instanceof Error ? err.message : String(err)}` }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t});\n\n\treturn server;\n}\n\n// ============================================================================\n// Server Startup\n// ============================================================================\n\n/**\n * Create and start an MCP server over stdio.\n * This blocks until the transport is closed.\n */\nexport async function startServer(projectDir: string): Promise<void> {\n\tconst server = createMcpServer(projectDir);\n\tconst transport = new StdioServerTransport();\n\tawait server.connect(transport);\n}\n"]}
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP stdio server adapter for semantic codebase search.\n *\n * Exposes the SearchEngine as a single \"search\" tool over the Model Context Protocol,\n * enabling any MCP-compatible client to run semantic codebase queries.\n *\n * The server defaults to using its CWD as the search directory. Claude Code\n * launches MCP servers with CWD set to the project root, so no configuration\n * is needed for typical per-project usage.\n */\n\nimport { createRequire } from \"node:module\";\nimport { resolve } from \"node:path\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { CallToolRequestSchema, type CallToolResult, ListToolsRequestSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport { formatResults } from \"./format.js\";\nimport { SearchEngine } from \"./search.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version: packageVersion } = require(\"../package.json\") as { version: string };\n\n// ============================================================================\n// Tool Schema (JSON Schema for MCP)\n// ============================================================================\n\nconst SEARCH_TOOL = {\n\tname: \"search\",\n\tdescription:\n\t\t\"Search the codebase using natural language queries. Returns ranked code/doc results using semantic similarity and keyword matching. First query builds the index (may take a moment); subsequent queries are fast.\",\n\tinputSchema: {\n\t\ttype: \"object\" as const,\n\t\tproperties: {\n\t\t\tquery: { type: \"string\", description: \"Search query (natural language, identifier, or path)\" },\n\t\t\tsearchDir: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Directory to index and search. This controls which directory gets indexed.\",\n\t\t\t},\n\t\t\trestrictToDir: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Restrict results to files under this path (filters the already-built index).\",\n\t\t\t},\n\t\t\tlimit: { type: \"number\", description: \"Maximum results to return (default: 20)\" },\n\t\t\trebuild: { type: \"boolean\", description: \"Force index rebuild (default: false)\" },\n\t\t},\n\t\trequired: [\"query\", \"searchDir\"],\n\t},\n};\n\n// ============================================================================\n// Engine Cache\n// ============================================================================\n\n/** Cache search engines per project root to reuse index across calls. */\nconst engineCache = new Map<string, SearchEngine>();\n\nfunction getSearchEngine(projectRoot: string): SearchEngine {\n\tlet engine = engineCache.get(projectRoot);\n\tif (!engine) {\n\t\tengine = new SearchEngine(projectRoot);\n\t\tengineCache.set(projectRoot, engine);\n\t}\n\treturn engine;\n}\n\n// ============================================================================\n// Server Factory\n// ============================================================================\n\n/**\n * Create an MCP server instance configured with the semantic search tool.\n *\n * @param defaultSearchDir - Default directory to index and search. Used when\n * the client doesn't specify `searchDir` in the tool call. Typically the\n * server's CWD, which Claude Code sets to the project root.\n */\nexport function createMcpServer(defaultSearchDir: string): Server {\n\tconst server = new Server(\n\t\t{ name: \"semantic-search\", version: packageVersion },\n\t\t{ capabilities: { tools: {}, logging: {} } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: [SEARCH_TOOL],\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request): Promise<CallToolResult> => {\n\t\tif (request.params.name !== \"search\") {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Unknown tool: ${request.params.name}` }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\tconst args = (request.params.arguments ?? {}) as {\n\t\t\tquery?: string;\n\t\t\tsearchDir?: string;\n\t\t\trestrictToDir?: string;\n\t\t\tlimit?: number;\n\t\t\trebuild?: boolean;\n\t\t};\n\t\tconst { query, restrictToDir: pathFilter, rebuild = false } = args;\n\t\tconst limit = typeof args.limit === \"number\" && args.limit > 0 ? Math.floor(args.limit) : 20;\n\n\t\tconst searchDir = args.searchDir ? resolve(args.searchDir) : defaultSearchDir;\n\n\t\tif (!SearchEngine.isAvailable()) {\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: \"Semantic search requires Node.js 22+ (for built-in SQLite). Current version does not support node:sqlite.\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\tif (!query || query.trim().length === 0) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Search query cannot be empty.\" }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst engine = getSearchEngine(searchDir);\n\n\t\t\tif (rebuild) {\n\t\t\t\tawait engine.resetIndex();\n\t\t\t}\n\n\t\t\t// Send progress via logging messages\n\t\t\tconst results = await engine.search(query, {\n\t\t\t\tlimit,\n\t\t\t\tpathFilter: pathFilter,\n\t\t\t\tonProgress: (phase, current, total) => {\n\t\t\t\t\tserver\n\t\t\t\t\t\t.sendLoggingMessage({\n\t\t\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\t\t\tlogger: \"semantic-search\",\n\t\t\t\t\t\t\tdata: `${phase}: ${current}/${total}`,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// Ignore errors sending progress — client may not support logging\n\t\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst text = formatResults(results);\n\t\t\tconst stats = engine.getStats();\n\n\t\t\tlet statsLine = \"\";\n\t\t\tif (stats) {\n\t\t\t\tstatsLine = `\\n\\n[Index: ${stats.files} files, ${stats.chunks} chunks]`;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: text + statsLine }],\n\t\t\t};\n\t\t} catch (err) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Search failed: ${err instanceof Error ? err.message : String(err)}` }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t});\n\n\treturn server;\n}\n\n// ============================================================================\n// Server Startup\n// ============================================================================\n\n/**\n * Create and start an MCP server over stdio.\n * This blocks until the transport is closed.\n */\nexport async function startServer(searchDir: string): Promise<void> {\n\tconst server = createMcpServer(searchDir);\n\tconst transport = new StdioServerTransport();\n\tawait server.connect(transport);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dreb/semantic-search",
3
- "version": "2.6.0",
3
+ "version": "2.6.2",
4
4
  "description": "Semantic codebase search engine with embedding-based ranking and MCP server",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -24,8 +24,8 @@ The search tool supports three kinds of queries, automatically classified:
24
24
  | Parameter | Required | Description |
25
25
  | ------------ | -------- | --------------------------------------------------------------------------- |
26
26
  | `query` | Yes | Search query — natural language, identifier, or path |
27
- | `projectDir` | Yes | Absolute path to the project directory. Set this to your current working directory |
28
- | `path` | No | Restrict search to files under this subdirectory (relative to project root) |
27
+ | `searchDir` | Yes | Directory to index and search each unique value gets its own independent index |
28
+ | `restrictToDir` | No | Filter results to files under this subdirectory within the already-built index (does not affect which files are indexed) |
29
29
  | `limit` | No | Maximum number of results to return (default: 20) |
30
30
  | `rebuild` | No | Force a clean index rebuild — use when files have changed significantly |
31
31
 
@@ -53,7 +53,7 @@ Each result includes:
53
53
 
54
54
  ## Tips
55
55
 
56
- - Start broad, then narrow with `path` if you get too many results from different areas
56
+ - Start broad, then narrow with `restrictToDir` if you get too many results from different areas
57
57
  - Use `limit` to get more results when exploring a broad topic (e.g. `limit: 50`)
58
58
  - Use `rebuild: true` after major refactors, branch switches, or large file changes
59
59
  - Identifier queries work best for finding where something is defined or used