grepmax 0.7.17 → 0.7.19

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.
@@ -41,6 +41,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
41
41
  step((generator = generator.apply(thisArg, _arguments || [])).next());
42
42
  });
43
43
  };
44
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
45
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
46
+ var m = o[Symbol.asyncIterator], i;
47
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
48
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
49
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
50
+ };
44
51
  Object.defineProperty(exports, "__esModule", { value: true });
45
52
  exports.mcp = void 0;
46
53
  exports.toStringArray = toStringArray;
@@ -57,6 +64,7 @@ const config_1 = require("../config");
57
64
  const graph_builder_1 = require("../lib/graph/graph-builder");
58
65
  const index_config_1 = require("../lib/index/index-config");
59
66
  const syncer_1 = require("../lib/index/syncer");
67
+ const meta_cache_1 = require("../lib/store/meta-cache");
60
68
  const searcher_1 = require("../lib/search/searcher");
61
69
  const retriever_1 = require("../lib/skeleton/retriever");
62
70
  const skeletonizer_1 = require("../lib/skeleton/skeletonizer");
@@ -132,6 +140,10 @@ const TOOLS = [
132
140
  type: "boolean",
133
141
  description: "Prepend the file's import/require statements to each result. Deduped per file.",
134
142
  },
143
+ name_pattern: {
144
+ type: "string",
145
+ description: "Regex to filter by symbol name (e.g. 'handle.*Auth'). Case-insensitive. Applied after search.",
146
+ },
135
147
  },
136
148
  required: ["query"],
137
149
  },
@@ -194,6 +206,10 @@ const TOOLS = [
194
206
  type: "boolean",
195
207
  description: "Prepend file's import statements to each result.",
196
208
  },
209
+ name_pattern: {
210
+ type: "string",
211
+ description: "Regex to filter by symbol name (e.g. 'handle.*Auth').",
212
+ },
197
213
  },
198
214
  required: ["query"],
199
215
  },
@@ -315,6 +331,23 @@ const TOOLS = [
315
331
  required: ["file"],
316
332
  },
317
333
  },
334
+ {
335
+ name: "recent_changes",
336
+ description: "Show recently modified files in the index. Useful after pulls or merges to see what changed.",
337
+ inputSchema: {
338
+ type: "object",
339
+ properties: {
340
+ limit: {
341
+ type: "number",
342
+ description: "Max files to return (default 20)",
343
+ },
344
+ root: {
345
+ type: "string",
346
+ description: "Project root (defaults to current project)",
347
+ },
348
+ },
349
+ },
350
+ },
318
351
  ];
319
352
  // ---------------------------------------------------------------------------
320
353
  // Helpers
@@ -699,6 +732,7 @@ exports.mcp = new commander_1.Command("mcp")
699
732
  absPath,
700
733
  text,
701
734
  score: typeof r.score === "number" ? r.score : 0,
735
+ symbols: defs,
702
736
  };
703
737
  });
704
738
  if (minScore > 0) {
@@ -714,6 +748,18 @@ exports.mcp = new commander_1.Command("mcp")
714
748
  return true;
715
749
  });
716
750
  }
751
+ const namePattern = typeof args.name_pattern === "string"
752
+ ? args.name_pattern
753
+ : "";
754
+ if (namePattern) {
755
+ try {
756
+ const regex = new RegExp(namePattern, "i");
757
+ results = results.filter((r) => r.symbols.some((s) => regex.test(s)));
758
+ }
759
+ catch (_b) {
760
+ // Invalid regex — skip filter
761
+ }
762
+ }
717
763
  let output = results.map((r) => r.text).join("\n\n");
718
764
  // Symbol mode: append call graph
719
765
  const mode = typeof args.mode === "string" ? args.mode : "default";
@@ -754,7 +800,7 @@ exports.mcp = new commander_1.Command("mcp")
754
800
  output += `\n${traceLines.join("\n")}`;
755
801
  }
756
802
  }
757
- catch (_b) {
803
+ catch (_c) {
758
804
  // Trace failed — return search results without trace
759
805
  }
760
806
  }
@@ -1405,6 +1451,76 @@ exports.mcp = new commander_1.Command("mcp")
1405
1451
  }
1406
1452
  });
1407
1453
  }
1454
+ function formatTimeAgo(ms) {
1455
+ const sec = Math.floor(ms / 1000);
1456
+ if (sec < 60)
1457
+ return `${sec}s ago`;
1458
+ const min = Math.floor(sec / 60);
1459
+ if (min < 60)
1460
+ return `${min}m ago`;
1461
+ const hr = Math.floor(min / 60);
1462
+ if (hr < 24)
1463
+ return `${hr}h ago`;
1464
+ const days = Math.floor(hr / 24);
1465
+ return `${days}d ago`;
1466
+ }
1467
+ function handleRecentChanges(args) {
1468
+ return __awaiter(this, void 0, void 0, function* () {
1469
+ var _a, e_1, _b, _c;
1470
+ const limit = Math.min(Math.max(Number(args.limit) || 20, 1), 50);
1471
+ const root = typeof args.root === "string"
1472
+ ? path.resolve(args.root)
1473
+ : projectRoot;
1474
+ const prefix = root.endsWith("/") ? root : `${root}/`;
1475
+ try {
1476
+ const metaCache = new meta_cache_1.MetaCache(config_1.PATHS.lmdbPath);
1477
+ try {
1478
+ const files = [];
1479
+ try {
1480
+ for (var _d = true, _e = __asyncValues(metaCache.entries()), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
1481
+ _c = _f.value;
1482
+ _d = false;
1483
+ const { path: p, entry, } = _c;
1484
+ if (p.startsWith(prefix)) {
1485
+ files.push({ path: p, mtimeMs: entry.mtimeMs });
1486
+ }
1487
+ }
1488
+ }
1489
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1490
+ finally {
1491
+ try {
1492
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
1493
+ }
1494
+ finally { if (e_1) throw e_1.error; }
1495
+ }
1496
+ files.sort((a, b) => b.mtimeMs - a.mtimeMs);
1497
+ const top = files.slice(0, limit);
1498
+ if (top.length === 0) {
1499
+ return ok(`No indexed files found for ${root}`);
1500
+ }
1501
+ const now = Date.now();
1502
+ const lines = [
1503
+ `Recent changes in ${path.basename(root)} (${top.length} most recent):\n`,
1504
+ ];
1505
+ for (const f of top) {
1506
+ const rel = f.path.startsWith(prefix)
1507
+ ? f.path.slice(prefix.length)
1508
+ : f.path;
1509
+ const ago = formatTimeAgo(now - f.mtimeMs);
1510
+ lines.push(` ${ago.padEnd(10)} ${rel}`);
1511
+ }
1512
+ return ok(lines.join("\n"));
1513
+ }
1514
+ finally {
1515
+ yield metaCache.close();
1516
+ }
1517
+ }
1518
+ catch (e) {
1519
+ const msg = e instanceof Error ? e.message : String(e);
1520
+ return err(`Recent changes failed: ${msg}`);
1521
+ }
1522
+ });
1523
+ }
1408
1524
  // --- MCP server setup ---
1409
1525
  const transport = new stdio_js_1.StdioServerTransport();
1410
1526
  const server = new index_js_1.Server({
@@ -1442,6 +1558,8 @@ exports.mcp = new commander_1.Command("mcp")
1442
1558
  return handleSummarizeProject(toolArgs);
1443
1559
  case "related_files":
1444
1560
  return handleRelatedFiles(toolArgs);
1561
+ case "recent_changes":
1562
+ return handleRecentChanges(toolArgs);
1445
1563
  default:
1446
1564
  return err(`Unknown tool: ${name}`);
1447
1565
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.7.17",
3
+ "version": "0.7.19",
4
4
  "author": "Robert Owens <robowens@me.com>",
5
5
  "homepage": "https://github.com/reowens/grepmax",
6
6
  "bugs": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.7.17",
3
+ "version": "0.7.19",
4
4
  "description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
5
5
  "author": {
6
6
  "name": "Robert Owens",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: grepmax
3
3
  description: Semantic code search. Use alongside grep - grep for exact strings, gmax for concepts.
4
- allowed-tools: "mcp__grepmax__semantic_search, mcp__grepmax__search_all, mcp__grepmax__code_skeleton, mcp__grepmax__trace_calls, mcp__grepmax__list_symbols, mcp__grepmax__index_status, mcp__grepmax__summarize_directory, mcp__grepmax__summarize_project, mcp__grepmax__related_files, Bash(gmax:*), Read"
4
+ allowed-tools: "mcp__grepmax__semantic_search, mcp__grepmax__search_all, mcp__grepmax__code_skeleton, mcp__grepmax__trace_calls, mcp__grepmax__list_symbols, mcp__grepmax__index_status, mcp__grepmax__summarize_directory, mcp__grepmax__summarize_project, mcp__grepmax__related_files, mcp__grepmax__recent_changes, Bash(gmax:*), Read"
5
5
  ---
6
6
 
7
7
  ## What gmax does
@@ -49,6 +49,7 @@ Parameters:
49
49
  - `role` (optional): Filter by chunk role: "ORCHESTRATION" (logic/flow), "DEFINITION" (types), or "IMPLEMENTATION"
50
50
  - `mode` (optional): `"default"` (semantic only) or `"symbol"` (semantic + call graph appended). Use "symbol" when query is a function or class name — gets search results + callers/callees in one call.
51
51
  - `include_imports` (optional): Prepend file's import/require statements to each result. Deduped per file — see dependencies at a glance.
52
+ - `name_pattern` (optional): Regex to filter by symbol name (e.g. "handle.*Auth"). Case-insensitive. Applied after search.
52
53
 
53
54
  **When to use which mode:**
54
55
  - `pointer` — navigation, finding locations, understanding architecture
@@ -93,6 +94,11 @@ Find files related to a given file by shared symbol references. Shows dependenci
93
94
  - `file` (required): File path relative to project root
94
95
  - `limit` (optional): Max results per direction (default 10)
95
96
 
97
+ ### recent_changes
98
+ Show recently modified files in the index. Useful after pulls or merges to see what changed.
99
+ - `limit` (optional): Max files (default 20)
100
+ - `root` (optional): Project root (defaults to current project)
101
+
96
102
  ### index_status
97
103
  Check centralized index health — chunks, files, indexed directories, model info, watcher status.
98
104
 
@@ -103,11 +109,13 @@ Generate LLM summaries for indexed code in a directory. Summaries are stored and
103
109
 
104
110
  ## Workflow
105
111
 
106
- 1. **Search** — `semantic_search` to find relevant code (pointers by default)
107
- 2. **Read** — `Read file:line` for the specific ranges you need
108
- 3. **Compare** — `semantic_search` with `detail: "code"` when comparing implementations
109
- 4. **Trace** — `trace_calls` to understand call flow across files
110
- 5. **Skeleton** — `code_skeleton` before reading large files
112
+ 1. **Explore** — `summarize_project` for high-level overview of a new codebase
113
+ 2. **Search** — `semantic_search` to find relevant code (pointers by default). Use `mode: "symbol"` for function/class names.
114
+ 3. **Read** — `Read file:line` for the specific ranges you need
115
+ 4. **Skeleton** — `code_skeleton` before reading large files or directories
116
+ 5. **Trace** — `trace_calls` to understand call flow, imports, and callers (use `depth: 2` for full chains)
117
+ 6. **Context** — `related_files` to see what else you need to look at when editing
118
+ 7. **Changes** — `recent_changes` after pulls to see what's been modified
111
119
 
112
120
  ## If results seem stale
113
121